Search code examples
pythondllctypesprocmon

Force Python to use certain set of drivers?


This is a follow-up question to a previous discussion.

Basically, I have a python code with ctypes code that is calling a vendor-supplied DLL. The code works fine when I use 32 bit python with the 32 bit DLLs. However, the code does not work when I use 64 bit Python with the 64 bit DLLs. There shouldn't be any real change for the python code, other than to specify a different place to search for the DLLs. The DLL that I call is called usb5100.dll, which has a dependency of libusb0.dll which is located in the same folder.

So, I used ProcMon, as suggested in this answer to look at DLL loading errors. The actual output of ProcMon is very long so I pared it down quite a bit. This is what the part about the DLLs looks like for the 32 bit python running 32 bit DLLs.

Time of Day Process Name PID Operation Path Result Detail
10:15:34 AM python.exe 12784 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\32bit\libusb0.dll SUCCESS Desired Access: Read Control, Disposition: Open, Options: , Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
10:15:34 AM python.exe 12784 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\32bit\usb5100.dll SUCCESS Desired Access: Read Control, Disposition: Open, Options: , Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened

That's it. Just two lines. Now, if I do the same thing for the 64 bit python/64 bit DLLs, the result, even pared down, is much longer (it is posted at the end of this question). What seems to be happening is that Python successfully loads the usb5100.dll and libusb0.dll from the correct location, which you can see near the top, but then something goes wrong and the system goes looking for other usb drivers (libusb-1.0.dll, openusb.dll, etc...) and finally settles on a libusb0.dll usb driver in C:\Windows\System32 (you can see this near the bottom) which is not the same driver that I initially specified.

The question is, is this the expected behavior? I think it isn't, because the code doesn't work in 64 bit but it does in 32 bits. Is there a way to force python to use only the set of drivers that I specify, and not go looking for other drivers? Thanks in advance.

Here is the pared down Procmon output for the 64 bit case. Yes, it is mostly garbage showing that the system is looking for different USB drivers. In fact, for every unsuccessful search, there were dozens of others that I cut out. But there were successful library loads at both the top and bottom:

Time of Day Process Name PID Operation Path Result Detail
Time of Day Process Name PID Operation Path Result Detail
10:16:28.0935968 AM python.exe 11672 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\64bit\usb5100.dll SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.0936672 AM python.exe 11672 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\64bit\usb5100.dll SUCCESS Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.0939350 AM python.exe 11672 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\64bit\usb5100.dll SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.0943315 AM python.exe 11672 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\64bit\libusb0.dll SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.0944851 AM python.exe 11672 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\64bit\libusb0.dll SUCCESS Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.1239798 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend\libusb0.py SUCCESS Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
10:16:28.1241177 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend\libusb0.py SUCCESS Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
10:16:28.1242261 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend_pycache_\libusb0.cpython-39.pyc SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
10:16:28.1253082 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend SUCCESS Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
10:16:28.1254372 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend\openusb.py SUCCESS Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
10:16:28.1255773 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend\openusb.py SUCCESS Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
10:16:28.1256754 AM python.exe 11672 CreateFile C:\Users\Ben\AppData\Roaming\Python\Python39\site-packages\usb\backend_pycache_\openusb.cpython-39.pyc SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
10:16:28.1270386 AM python.exe 11672 CreateFile C:\Program Files\Git\cmd\usb-1.0.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1273758 AM python.exe 11672 CreateFile C:\Windows\System32\usb-1.0.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1300332 AM python.exe 11672 CreateFile C:\Windows\System32\wbem\libusb-1.0.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1317197 AM python.exe 11672 CreateFile C:\Windows\usb.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1331762 AM python.exe 11672 CreateFile C:\Windows\openusb.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1348576 AM python.exe 11672 CreateFile C:\Windows\System32\usb-0.1.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1368315 AM python.exe 11672 CreateFile C:\Windows\System32\wbem\usb.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1368843 AM python.exe 11672 CreateFile C:\Windows\System32\WindowsPowerShell\v1.0\usb.dll NAME NOT FOUND Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a
10:16:28.1383914 AM python.exe 11672 CreateFile C:\Windows\System32\libusb0.dll SUCCESS Desired Access: Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Attributes: n/a, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
10:16:28.1385580 AM python.exe 11672 CreateFile C:\Windows\System32\libusb0.dll SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.1386401 AM python.exe 11672 CreateFile C:\Windows\System32\libusb0.dll SUCCESS Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.1412271 AM python.exe 11672 CreateFile C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\fw_bell_py_2.py SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
10:16:28.1459255 AM python.exe 11672 CreateFile C:\Windows\System32\kernel.appcore.dll SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:16:28.1460062 AM python.exe 11672 CreateFile C:\Windows\System32\kernel.appcore.dll SUCCESS Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened

Solution

  • When loading DLLs with ctypes.CDLL (or WinDLL, etc.) there is a winmode parameter in Python 3.8 or later:

    The winmode parameter is used on Windows to specify how the library is loaded (since mode is ignored). It takes any value that is valid for the Win32 API LoadLibraryEx flags parameter. When omitted, the default is to use the flags that result in the most secure DLL load to avoiding issues such as DLL hijacking. Passing the full path to the DLL is the safest way to ensure the correct library and dependencies are loaded.

    Changed in version 3.8: Added winmode parameter.

    Experimenting with LoadLibraryEx dwFlags values such as LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR (0x00000100) may help.