WinUsb_Initialize returning ERROR_INVALID_FUNCTION RRS feed

  • Question

  • Using VS2013 and WDK 8.1 I created a template WinUSB Application following the instructions on

    I modified the code and inf file to specify my device's VID/PID and interface GUID.

    I installed the driver using the inf file and verified using DeviceManager that my device shows up as USB Input Device.

    I can read and write to the USB device fine using the file handle and file I/O calls, but if I call WinUSB_Initialize() to get a handle for doing WinUSB operations it fails with ERROR_INVALID_FUNCTION

    Here is the code

        _Out_     PDEVICE_DATA DeviceData,
        _Out_opt_ PBOOL        FailureDeviceNotFound

    Routine description:

        Open all needed handles to interact with the device.

        If the device has multiple USB interfaces, this function grants access to
        only the first interface.

        If multiple devices have the same device interface GUID, there is no
        guarantee of which one will be returned.


        DeviceData - Struct filled in by this function. The caller should use the
            WinusbHandle to interact with the device, and must pass the struct to
            CloseDevice when finished.

        FailureDeviceNotFound - TRUE when failure is returned due to no devices
            found with the correct device interface (device not connected, driver
            not installed, or device is disabled in Device Manager); FALSE

    Return value:


        HRESULT hr = S_OK;
        BOOL    bResult;

        DeviceData->HandlesOpen = FALSE;

        hr = RetrieveDevicePath(DeviceData->DevicePath,

        if (FAILED(hr)) {

            return hr;

        DeviceData->DeviceHandle = CreateFile(DeviceData->DevicePath,
                                              GENERIC_WRITE | GENERIC_READ,
                                              FILE_SHARE_WRITE | FILE_SHARE_READ,
                                              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,

        if (INVALID_HANDLE_VALUE == DeviceData->DeviceHandle) {

            hr = HRESULT_FROM_WIN32(GetLastError());
            return hr;

        bResult = WinUsb_Initialize(DeviceData->DeviceHandle,

        if (FALSE == bResult) {

            hr = HRESULT_FROM_WIN32(GetLastError());
            return hr;

        DeviceData->HandlesOpen = TRUE;
        return hr;

    Thursday, August 28, 2014 7:57 PM

All replies

  • how are you initiating IO outside of winusb? you can't use winusb.dll if you don't also install winusb.sys as the driver. Having the device show up as an input device is a little suspicious, typically that is a HID device.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, August 28, 2014 9:10 PM
  • Well I suspect I'm doing it wrong, although I attempted to follow the instructions.  I do have an HID device and I was hoping to assign winusb.sys as the driver for it. 

    VS2013 generated a template inf file for me.  I edited the inf for my VID/PID and interface Guid.  I built the template code.  Following the steps listed under "Single Computer Debugging:  I located the device using Device Manager, clicked "Update Driver" and selected my inf. (My device was connected at this time) I don't think Windows indicated any problem - I don't recall.  I tried testing my code and the WinUsb_Initialize() call failed.  I tried installing the inf again and Device Manager replied the driver was up to date.  I disconnected the device and after a minute or so reconnected.  Windows displayed the "Installing driver..." message and after a long (2 min?) delay Windows indicated the driver was sucessfully installed.  However, the WinUsb_Initialize() call still fails.

    Thursday, August 28, 2014 10:59 PM
  • open the driver details tab in the device properties in device manager and see what drivers are listed. are you matching against the USB\XXX HW ID or the HID\XXX HW ID?

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, August 29, 2014 3:22 AM
  • Thank you for your help with this.  As you suggested, the device is using hidusb.sys instead of winusb.sys

    Either I have something wrong with my inf file, or I am installing it incorrectly.  Or am I misunderstanding something basic - does the fact that I have a HID device mean that it is incompatible with WinUSB?

    Here is how I am detecting the device.

    // These are the identifiers for the XXT XL51 USB device, as of August 2014
    DEFINE_GUID(InterfaceClassGuid, 0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
    static WCHAR *pDeviceKey = _T("VID_04D8&PID_003F");
    //FUNCTION:    CheckIfPresentAndGetUSBDevicePath()
    //PURPOSE:    Check if a USB device is currently plugged in with a matching VID and PID
    //INPUT:    Uses globally declared String DevicePath, globally declared GUID, and the MY_DEVICE_ID constant.
    //OUTPUT:    Returns BOOL.  TRUE when device with matching VID/PID found.  FALSE if device with VID/PID could not be found.
    //            When returns TRUE, the globally accessable "DetailedInterfaceDataStructure" will contain the device path
    //            to the USB device with the matching VID/PID.
    bool CTest_XL51_USBDlg::CheckIfPresentAndGetUSBDevicePath()
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    int i;

        hDevInfo = SetupDiGetClassDevs(NULL,
            0, // Enumerator
        if (hDevInfo == INVALID_HANDLE_VALUE)
            m_USB.Status.Format(_T("SetupDiGetClassDevs() returned error %ld"), GetLastError());
            WriteDebugString (m_USB.Status);
            return false;

    // Enumerate through all devices in Set.
        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i,
            DWORD DataT;
            LPTSTR buffer = NULL;
            DWORD buffersize = 0;
            // Call function with null to begin with,
            // then use the returned buffer size (doubled)
            // to Alloc the buffer. Keep calling until
            // success or an unknown failure.
            //  Double the returned buffersize to correct
            //  for underlying legacy CM functions that
            //  return an incorrect buffersize value on
            //  DBCS/MBCS systems.
            while (!SetupDiGetDeviceRegistryProperty(
                if (GetLastError() ==
                    // Change the buffer size.
                    if (buffer) LocalFree(buffer);
                    buffer = (LPTSTR) LocalAlloc(LPTR,buffersize);
                    m_USB.Status.Format(_T("SetupDiGetDeviceRegistryProperty() returned error %ld"), GetLastError());
                    WriteDebugString (m_USB.Status);
            CString strResult;
            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
            DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
            strResult.Format(_T("Result:[%s]\n"), buffer);
            if (buffer) LocalFree(buffer);
            buffer = NULL;
    //        WriteDebugString (strResult);   
            strResult = strResult.MakeUpper();
            if (-1 != strResult.Find(pDeviceKey))
    //            OutputDebugString ("Bingo!\n");
                int MemberIndex  = 0;
                while (SetupDiEnumDeviceInterfaces(hDevInfo,
                    DWORD dwRequiredSize = 0;
                    SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
                    DeviceInterfaceDetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                    SP_DEVINFO_DATA DeviceInfoData;
                    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                    //Get the details with null values to get the required size of the buffer
                    SetupDiGetDeviceInterfaceDetail (hDevInfo,
                                                     NULL, //interfaceDetail,
                                                     0, //interfaceDetailSize,
                                                     0); //infoData))

                    //Allocate the buffer
                    PSP_INTERFACE_DEVICE_DETAIL_DATA deviceDetail;
                    deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(dwRequiredSize);
                    deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

                    //Fill the buffer with the device details
                    if (!SetupDiGetDeviceInterfaceDetail (hDevInfo,
                        SetupDiDestroyDeviceInfoList (hDevInfo);
                        free (deviceDetail);
                        m_USB.Status.Format(_T("SetupDiGetDeviceInterfaceDetail() returned error %ld"), GetLastError());
                        WriteDebugString (m_USB.Status);
                        return false;
                    m_USB.DevicePath.Format(_T("%s"), deviceDetail->DevicePath);
                    free (deviceDetail);
                if (ERROR_NO_MORE_ITEMS != GetLastError())
                    m_USB.Status.Format(_T("SetupDiEnumDeviceInterfaces() returned error %ld"), GetLastError());
                    WriteDebugString (m_USB.Status);
                    return false;
        if ( GetLastError()!=NO_ERROR &&
            GetLastError()!=ERROR_NO_MORE_ITEMS )
            DWORD dwError = GetLastError();
            return false;
        //  Cleanup
        // launch the USB thread, if necessary
        if (INVALID_HANDLE_VALUE == hUSBCommunicationsThread)
            ResetEvent (m_USB.hUSBCommunicationsEvent);
            hUSBCommunicationsThread = CreateThread (NULL,8192,&USBCommunicationsThread,(void *)&m_USB,0,&m_dwUSBCommunicationsThreadID);
        return true;

    Friday, August 29, 2014 3:23 PM