WinUSB.DLL and Python: Specifically WinUsb_Initialize

大兔子大兔子 提交于 2020-01-03 04:47:26

问题


I've been following the WinUsb MSDN HowTo here and so far it's worked pretty well. I've made it to the point in the guide where I have to call the WinUsb_Initialize() function from the WinUsb DLL. And that's where I'm stuck. My code so far is this, and you will doubtlessly ascertain that I've ripped a great deal of it screaming from the WinAPI.py module of PyWinUSB. Insert gratuitous thanks and giving credit to the creator of PyWinUSB here.

import ctypes
import platform
from ctypes import byref, POINTER, Structure, sizeof, c_ulong
from ctypes.wintypes import DWORD, WORD, BYTE, HANDLE, LPCWSTR, ULONG, WCHAR, \
BOOL
TCHAR = WCHAR

winUSB          = ctypes.windll.winusb
winHID          = ctypes.windll.hid
kernel32        = ctypes.windll.kernel32
setupAPI        = ctypes.windll.setupapi

GENERIC_READ    = (-2147483648)
GENERIC_WRITE   = (1073741824)
FILE_SHARE_READ = 1
FILE_SHARE_WRITE = 2
OPEN_EXISTING   = 3
FILE_FLAG_OVERLAPPED    = 1073741824

if platform.architecture()[0].startswith('64'):
    WIN_PACK = 8
else:
    WIN_PACK = 1

class GUID(ctypes.Structure):
    """GUID Windows OS Structure"""
    _pack_ = 1
    _fields_ = [("data1", DWORD),
                ("data2", WORD),
                ("data3", WORD),
                ("data4", BYTE * 8)]

    def __init__(self, data1 = None, data2 = None, data3 = None, data4 = None):
        if data1 is not None:
            self.data1 = data1
        if data2 is not None:
            self.data2 = data2
        if data3 is not None:
            self.data3 = data3
        if data4 is not None:
            self.data4 = data4

class SP_DEVICE_INTERFACE_DATA(Structure):
    """
    typedef struct _SP_DEVICE_INTERFACE_DATA {
        DWORD       cbSize;
        GUID        InterfaceClassGuid;
        DWORD       Flags;
        ULONG_PTR   Reserved;
        } SP_DEVICE_INTERFACE_DATA,  *PSP_DEVICE_INTERFACE_DATA
    """
    _pack_ = WIN_PACK
    _fields_ = [("cb_size",                 DWORD),
                ("interface_class_guid",    GUID),
                ("flags",                   DWORD),
                ("reserved",                POINTER(ULONG))]

    def __init__(self):
        self.cb_size = sizeof(SP_DEVICE_INTERFACE_DATA)


class SP_DEVICE_INTERFACE_DETAIL_DATA(Structure):
    """
    typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA {
        DWORD cbSize;
        TCHAR DevicePath[ANYSIZE_ARRAY];
    } SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;
    """

    _pack_ = WIN_PACK
    _fields_ = [("cb_size", DWORD),
                ("device_path", TCHAR * 1)] #device_path[1]

    def __init__(self):
        self.cb_size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)

    def get_string(self):
        """Retreive stored string"""
        return ctypes.wstring_at(byref(self, sizeof(DWORD)))


class SP_DEVINFO_DATA(Structure):
    """
    typedef struct _SP_DEVINFO_DATA {
      DWORD     cbSize;
      GUID      ClassGuid;
      DWORD     DevInst;
      ULONG_PTR Reserved;
    } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
    """
    _pack_ = WIN_PACK
    _fields_ = [("cb_size",     DWORD),
                ("class_guid",  GUID),
                ("dev_inst",    DWORD),
                ("reserved",    POINTER(ULONG))]

    def __init__(self):
        self.cb_size = sizeof(SP_DEVINFO_DATA)

class DIGCF:
    """
    Flags controlling what is included in the device information set
    built by SetupDiGetClassDevs
    """
    DEFAULT         = 0x00000001
    PRESENT         = 0x00000002
    ALLCLASSES      = 0x00000004
    PROFILE         = 0x00000008
    DEVICEINTERFACE = 0x00000010

def GetHidGuid():
    "Get system-defined GUID for HIDClass devices"
    hid_guid = GUID()
    winHID.HidD_GetHidGuid(byref(hid_guid))
    return hid_guid

SetupDiGetClassDevs             = setupAPI.SetupDiGetClassDevsW
SetupDiGetClassDevs.restype     = HANDLE
SetupDiGetClassDevs.argtypes    = [
    # __in_opt      const GUID *ClassGuid,
    # __in_opt      PCTSTR Enumerator,
    # __in_opt      HWND hwndParent,
    # __in          DWORD Flags,
    POINTER(GUID),
    LPCWSTR,
    HANDLE,
    DWORD]

SetupDiGetDeviceInterfaceDetail             = setupAPI.SetupDiGetDeviceInterfaceDetailW
SetupDiGetDeviceInterfaceDetail.restype     = BOOL
SetupDiGetDeviceInterfaceDetail.argtypes    = [
    # __in          HDEVINFO DeviceInfoSet,
    # __in          PSP_DEVICE_INTERFACE_DATA DeviceIn,
    # __out_opt     PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,
    # __in          DWORD DeviceInterfaceDetailDataSize,
    # __out_opt     PDWORD RequiredSize
    # __out_opt     PSP_DEVINFO_DATA DeviceInfoData
    HANDLE,
    POINTER(SP_DEVICE_INTERFACE_DATA),
    POINTER(SP_DEVICE_INTERFACE_DETAIL_DATA),
    DWORD,
    POINTER(DWORD),
    POINTER(SP_DEVINFO_DATA)]                                   

devGuid     = GUID(0x2518E22E, 0x0F35, 0x11E2, (BYTE * 8)(0xB1, 0xD5, 0x6C, 0xF0,
                                                          0x49, 0x73, 0x78, 0x72))
classGuid   = GetHidGuid()
                #GUID(0x745A17A0, 0x74D3, 0x11D0, (BYTE * 8)(0xB6, 0xFE, 0x00, 0xA0,
                #                                            0xC9, 0x0F, 0x57, 0xDA))

derp        = SetupDiGetClassDevs(
                byref(classGuid), None, None,
                (DIGCF.PRESENT | DIGCF.DEVICEINTERFACE))

def stepDevices(herp, index = 0):
    devInterfaceData = SP_DEVICE_INTERFACE_DATA()
    if setupAPI.SetupDiEnumDeviceInterfaces(
        herp, None, byref(classGuid), index, byref(devInterfaceData)):
        yield devInterfaceData
        del devInterfaceData
    else:
        print(kernel32.GetLastError())

def enumDevices(herp):
    index               = 0    
    devInterfaceData    = SP_DEVICE_INTERFACE_DATA()
    while setupAPI.SetupDiEnumDeviceInterfaces(
        herp, None, byref(classGuid), index, byref(devInterfaceData)):        
        print(kernel32.GetLastError())
        yield devInterfaceData
        index += 1
    del devInterfaceData

def getDetail(herp, devData, devInfo = None):

    reqSize     = c_ulong(0)
    devDetail   = SP_DEVICE_INTERFACE_DETAIL_DATA()

    SetupDiGetDeviceInterfaceDetail(
        herp, byref(devData), None, 0, byref(reqSize), None)

    ctypes.resize(devDetail, reqSize.value)

    SetupDiGetDeviceInterfaceDetail(
        herp, byref(devData), byref(devDetail),
        reqSize, None, byref(devInfo))

    return devDetail.get_string()

dev = stepDevices(derp).next()
devInfo = SP_DEVINFO_DATA()
devString = getDetail(derp, dev, devInfo)

winUSBHandle = kernel32.CreateFileW(
    devString, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, None)

#winUSB.WinUsb_Initialize(winUSBHandle, <what goes here?>)

I've tried creating a simple handle and passing that byref(handle) as the second parameter to the function, but the handle value stays as None. I don't know how much has been done with Python and WinUSB.DLL but if anyone can point me in the correct direction I'd be sincerely grateful.

Thanks in advance.


回答1:


The documentation says it is a PWINUSB_INTERFACE_HANDLE, which is a PVOID, which is a c_void_p in ctypes, so this should work:

h = ctypes.c_void_p()
winUSB.WinUsb_Initialize(winUSBHandle, ctypes.byref(h))

Does the winUSBHandle look valid (not 0 or -1 or 0xFFFFFFFF)?

Edit

If it is failing, make sure to use the ctypes copy of GetLastError or it may be incorrect. Make the library references with:

winUSB = ctypes.WinDLL('winusb',use_last_error=True)

and use:

ctypes.get_last_error()


来源:https://stackoverflow.com/questions/12926923/winusb-dll-and-python-specifically-winusb-initialize

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!