3

I am trying to read usb devices on Windows 10, following this two pages using-winusb-api-to-communicate-with-a-usb-device and WinUSBCommTest.cpp, but when I try to run this code, WinUsb_Initialize fails for windows error 8, ERROR_NOT_ENOUGH_MEMORY. And I don't know how to fix it, could anyone please help me out?

BOOL GetWinUSBHandle(HANDLE hDeviceHandle, PWINUSB_INTERFACE_HANDLE phWinUSBHandle)
{
  if (hDeviceHandle == INVALID_HANDLE_VALUE)
  {
    return FALSE;
  }

  BOOL bResult = WinUsb_Initialize(hDeviceHandle, phWinUSBHandle);
  if(!bResult)
  {
    //Error.
    printf("WinUsb_Initialize Error %d.", GetLastError());
    return FALSE;
  }

  return bResult;
}

BOOL GetDeviceHandle (GUID guidDeviceInterface, PHANDLE hDeviceHandle)
{
  if (guidDeviceInterface==GUID_NULL)
  {
    return FALSE;
  }

  BOOL bResult = TRUE;
  HDEVINFO hDeviceInfo;
  SP_DEVINFO_DATA DeviceInfoData;

  SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;

  ULONG requiredLength=0;

  LPTSTR lpDevicePath = NULL;

  DWORD index = 0;

  // Get information about all the installed devices for the specified
  // device interface class.
  hDeviceInfo = SetupDiGetClassDevs( 
    &guidDeviceInterface,
    NULL, 
    NULL,
    DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

  if (hDeviceInfo == INVALID_HANDLE_VALUE) 
  { 
    // ERROR 
    PTRACE("Error SetupDiGetClassDevs: %d.\n", GetLastError());
    goto done;
  }

  //Enumerate all the device interfaces in the device information set.
  DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

  for (index = 0; SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData); index++)
  {
    //Reset for this iteration
    if (lpDevicePath)
    {
      LocalFree(lpDevicePath);
    }
    if (pInterfaceDetailData)
    {
      LocalFree(pInterfaceDetailData);
    }

    deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

    //Get information about the device interface.
    bResult = SetupDiEnumDeviceInterfaces( 
      hDeviceInfo,
      &DeviceInfoData,
      &guidDeviceInterface,
      0, 
      &deviceInterfaceData);

    // Check if last item
    if (GetLastError () == ERROR_NO_MORE_ITEMS)
    {
      break;
    }

    //Check for some other error
    if (!bResult) 
    {
      printf("Error SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
      goto done;
    }

    //Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA
    //which we need to allocate, so we have to call this function twice.
    //First to get the size so that we know how much to allocate
    //Second, the actual call with the allocated buffer

    bResult = SetupDiGetDeviceInterfaceDetail(
      hDeviceInfo,
      &deviceInterfaceData,
      NULL, 0,
      &requiredLength,
      NULL);


    //Check for some other error
    if (!bResult) 
    {
      if ((ERROR_INSUFFICIENT_BUFFER==GetLastError()) && (requiredLength>0))
      {
        //we got the size, allocate buffer
        pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength);

        if (!pInterfaceDetailData) 
        { 
          // ERROR 
          printf("Error allocating memory for the device detail buffer.\n");
          goto done;
        }
      }
      else
      {
        printf("Error SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
        goto done;
      }
    }

    //get the interface detailed data
    pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    //Now call it with the correct size and allocated buffer
    bResult = SetupDiGetDeviceInterfaceDetail(
      hDeviceInfo,
      &deviceInterfaceData,
      pInterfaceDetailData,
      requiredLength,
      NULL,
      &DeviceInfoData);

    //Check for some other error
    if (!bResult) 
    {
      printf("Error SetupDiGetDeviceInterfaceDetail: %d.\n", GetLastError());
      goto done;
    }

    //copy device path

    size_t nLength = _tcslen(pInterfaceDetailData->DevicePath) + 1;  
    lpDevicePath = (TCHAR *) LocalAlloc (LPTR, nLength * sizeof(TCHAR));
    StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData->DevicePath);
    lpDevicePath[nLength-1] = 0;

    printf("Device path:  %s\n", lpDevicePath);

  }

  if (!lpDevicePath)
  {
    //Error.
    printf("Error %d.", GetLastError());
    goto done;
  }

  //Open the device
  *hDeviceHandle = CreateFile (
    lpDevicePath,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);

  if (*hDeviceHandle == INVALID_HANDLE_VALUE)
  {
    //Error.
    printf("Error %d.", GetLastError());
    goto done;
  }



done:
  LocalFree(lpDevicePath);
  LocalFree(pInterfaceDetailData);    
  bResult = SetupDiDestroyDeviceInfoList(hDeviceInfo);

  return bResult;
}
3
  • Please make a minimal reproducible example so we can see with what arguments GetWinUSBHandle is called etc. Commented May 11, 2020 at 12:22
  • Did you open the Task Manager to check how much memory your computer is using? And how much memory your USB program is using? Commented May 11, 2020 at 17:01
  • The computer take about 39% of all memory and the program used 0.8M memory. Commented May 12, 2020 at 3:46

1 Answer 1

6

If you enumerate on GUID_DEVINTERFACE_USB_DEVICE you will get a device (vs a specific interface). If your thingy has multiple interfaces the WinUsb_Initialize will fail with an 8 - ERROR_NOT_ENOUGH_MEMORY. You need to enumerate on something specific like GUID_DEVINTERFACE_ANDROID. When you get the path, print it and you will see that it is not interface specific.

This is a GUID_DEVINTERFACE_USB_DEVICE (whole device)
\\?\usb#vid_1004&pid_62c6#vs12345678#{a5dcbf10-6530-11d2-901f-00c04fb951ed

This is a GUID_DEVINTERFACE_ANDROID (specific interface, #1)
\\?\usb#vid_1004&pid_62c6&mi_01#6&987654&1&0001#{f72fe0d4-cbcb-407d-8814-9ed673d0dd6b}
Sign up to request clarification or add additional context in comments.

3 Comments

sorry, how is this related to Trezor? Can you point me to the Trezor question?
ah! interesting. I will try to investigate this at some point

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.