in XInput_Scp/pnp.cpp [3:156]
BOOLEAN FindKnownHidDevices(OUT PHID_DEVICE* HidDevices, OUT PULONG NumberDevices)
{
HDEVINFO hardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInfoData;
ULONG i = 0;
BOOLEAN done;
PHID_DEVICE hidDeviceInst;
GUID hidGuid;
PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = NULL;
ULONG predictedLength = 0;
ULONG requiredLength = 0;
PHID_DEVICE newHidDevices;
HidD_GetHidGuid(&hidGuid);
*HidDevices = NULL;
*NumberDevices = 0;
//
// Open a handle to the plug and play dev node.
//
hardwareDeviceInfo = SetupDiGetClassDevs(&hidGuid,
NULL, // Define no enumerator (global)
NULL, // Define no
(DIGCF_PRESENT | // Only Devices present
DIGCF_DEVICEINTERFACE)); // Function class devices.
if (hardwareDeviceInfo == INVALID_HANDLE_VALUE)
{
return FALSE;
}
//
// Take a wild guess to start
//
*NumberDevices = 4;
done = FALSE;
deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (!done)
{
*NumberDevices *= 2;
if (*HidDevices)
{
newHidDevices = (PHID_DEVICE) realloc(*HidDevices, (*NumberDevices * sizeof(HID_DEVICE)));
if (newHidDevices == NULL)
{
free(*HidDevices);
}
*HidDevices = newHidDevices;
}
else
{
*HidDevices = (PHID_DEVICE) calloc(*NumberDevices, sizeof(HID_DEVICE));
}
if (*HidDevices == NULL)
{
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
return FALSE;
}
hidDeviceInst = *HidDevices + i;
for (; i < *NumberDevices; i++, hidDeviceInst++)
{
if (SetupDiEnumDeviceInterfaces(hardwareDeviceInfo,
0, // No care about specific PDOs
&hidGuid,
i,
&deviceInfoData))
{
//
// allocate a function class device data structure to receive the
// goods about this particular device.
//
SetupDiGetDeviceInterfaceDetail(
hardwareDeviceInfo,
&deviceInfoData,
NULL, // probing so no output buffer yet
0, // probing so output buffer length of zero
&requiredLength,
NULL); // not interested in the specific dev-node
predictedLength = requiredLength;
functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(predictedLength);
if (functionClassDeviceData)
{
functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
ZeroMemory(functionClassDeviceData->DevicePath, sizeof(functionClassDeviceData->DevicePath));
}
else
{
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
return FALSE;
}
//
// Retrieve the information from Plug and Play.
//
if (! SetupDiGetDeviceInterfaceDetail(
hardwareDeviceInfo,
&deviceInfoData,
functionClassDeviceData,
predictedLength,
&requiredLength,
NULL))
{
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
free(functionClassDeviceData);
return FALSE;
}
//
// Open device with just generic query abilities to begin with
//
if (! OpenHidDevice(functionClassDeviceData->DevicePath,
FALSE, // ReadAccess - none
FALSE, // WriteAccess - none
FALSE, // Overlapped - no
FALSE, // Exclusive - no
hidDeviceInst))
{
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
free(functionClassDeviceData);
return FALSE;
}
}
else
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
done = TRUE;
break;
}
}
}
}
*NumberDevices = i;
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
free(functionClassDeviceData);
return TRUE;
}