0

I want to get the Device ID of a USB stick by using the Setup API, but first I am trying to understand some of the functions I have to use. The SetupDiGetDeviceRegistryProperty documentation says I can send NULL to the buffer and buffer size to get the required size, but I am getting the 122 error code, which means:

The data area passed to a system call is too small

Can anyone tell me what am I doing wrong?

Here is my code so far:

#include <Windows.h>
#include <wchar.h>
#include <SetupAPI.h>

#pragma comment(lib, "Setupapi.lib")

int wmain(int argc, wchar_t *arv[])
{
    // SetupDiGetClassDevs
    HDEVINFO hDeviceInfo;
    DWORD filterDevInfo = DIGCF_ALLCLASSES;

    hDeviceInfo = SetupDiGetClassDevsW(NULL, NULL, NULL, filterDevInfo);

    if (hDeviceInfo != INVALID_HANDLE_VALUE)
    {
        // SetupDiEnumDeviceInfo
        DWORD memberIndex = 0;
        SP_DEVINFO_DATA devInfoData;

        devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        if (!SetupDiEnumDeviceInfo(
            hDeviceInfo,
            memberIndex,
            &devInfoData))
        {
            fwprintf(stderr, L"Error on enum: %u\n", GetLastError());
            return 1;

        }

        // SetupDiGetDeviceRegistryProperty
        DWORD propertyRetrieved = SPDRP_DEVICEDESC;
        DWORD requiredSize;

        // First call to get the required size for the buffer

        if (!SetupDiGetDeviceRegistryPropertyW(
            hDeviceInfo,
            &devInfoData,
            propertyRetrieved,
            NULL,
            NULL,
            0,
            &requiredSize))
        {
            fwprintf(stderr, L"Error on registry property: %u\n", GetLastError());
            return 1;

        }

    }
    else
    {
        wprintf(L"Error code: %u\n", GetLastError());
        return 1;
    }

    return 0;
}
Sergio Calderon
  • 837
  • 1
  • 13
  • 32
  • 2
    It is supposed to fail with that error. You now know the *requiredSize* so you allocate a buffer big enough to call it again, now passing a non-NULL value for the 5th argument. Feature, not a bug. – Hans Passant Jun 19 '18 at 21:28
  • 1
    To add to what @HansPassant said, this is a fairly common Windows API pattern. Let's say that instead of passing `NULL` and zero you passed a valid pointer and the length 200 **but** the requested data required 400 bytes. You would get the same "too small" error and `requiredSize` would be set to 400. Passing in `NULL` and zero is just an easy way of triggering this error so you get the `requiredSize` variable set. – Frank Boyne Jun 19 '18 at 21:36
  • Oh, I get it. I thought I would get a different error code as a result when it was called with `NULL` and `0`. Thanks a lot, no errors then. – Sergio Calderon Jun 19 '18 at 21:40
  • You may be calling `GetLastError` too late. You need to call it immediately after entering a state, where it returns a meaningful value, and no later. – IInspectable Jun 19 '18 at 23:04
  • @IInspectable, would you show me where I should put the `GetLastError`? – Sergio Calderon Jun 20 '18 at 02:05
  • Make it a single statement, and move it outside your `fwprintf` calls. – IInspectable Jun 20 '18 at 02:32

0 Answers0