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 |
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.