338 lines
8.1 KiB
C
338 lines
8.1 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1998-2011 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
DEVNODE.C
|
||
|
|
||
|
--*/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
I N C L U D E S
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include "enum.h"
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
DriverNameToDeviceInst()
|
||
|
|
||
|
Finds the Device instance of the DevNode with the matching DriverName.
|
||
|
Returns FALSE if the matching DevNode is not found and TRUE if found
|
||
|
|
||
|
*****************************************************************************/
|
||
|
BOOL
|
||
|
DriverNameToDeviceInst(
|
||
|
_In_reads_bytes_(cbDriverName) PCHAR DriverName,
|
||
|
_In_ size_t cbDriverName,
|
||
|
_Out_ HDEVINFO *pDevInfo,
|
||
|
_Out_writes_bytes_(sizeof(SP_DEVINFO_DATA)) PSP_DEVINFO_DATA pDevInfoData
|
||
|
)
|
||
|
{
|
||
|
HDEVINFO deviceInfo = INVALID_HANDLE_VALUE;
|
||
|
BOOL status = TRUE;
|
||
|
ULONG deviceIndex;
|
||
|
SP_DEVINFO_DATA deviceInfoData;
|
||
|
BOOL bResult = FALSE;
|
||
|
PCHAR pDriverName = NULL;
|
||
|
PSTR buf = NULL;
|
||
|
BOOL done = FALSE;
|
||
|
|
||
|
if (pDevInfo == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (pDevInfoData == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
memset(pDevInfoData, 0, sizeof(SP_DEVINFO_DATA));
|
||
|
|
||
|
*pDevInfo = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
// Use local string to guarantee zero termination
|
||
|
pDriverName = (PCHAR) ALLOC((DWORD) cbDriverName + 1);
|
||
|
if (NULL == pDriverName)
|
||
|
{
|
||
|
status = FALSE;
|
||
|
goto Done;
|
||
|
}
|
||
|
StringCbCopyN(pDriverName, cbDriverName + 1, DriverName, cbDriverName);
|
||
|
|
||
|
//
|
||
|
// We cannot walk the device tree with CM_Get_Sibling etc. unless we assume
|
||
|
// the device tree will stabilize. Any devnode removal (even outside of USB)
|
||
|
// would force us to retry. Instead we use Setup API to snapshot all
|
||
|
// devices.
|
||
|
//
|
||
|
|
||
|
// Examine all present devices to see if any match the given DriverName
|
||
|
//
|
||
|
deviceInfo = SetupDiGetClassDevs(NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
DIGCF_ALLCLASSES | DIGCF_PRESENT);
|
||
|
|
||
|
if (deviceInfo == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
status = FALSE;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
deviceIndex = 0;
|
||
|
deviceInfoData.cbSize = sizeof(deviceInfoData);
|
||
|
|
||
|
while (done == FALSE)
|
||
|
{
|
||
|
//
|
||
|
// Get devinst of the next device
|
||
|
//
|
||
|
|
||
|
status = SetupDiEnumDeviceInfo(deviceInfo,
|
||
|
deviceIndex,
|
||
|
&deviceInfoData);
|
||
|
|
||
|
deviceIndex++;
|
||
|
|
||
|
if (!status)
|
||
|
{
|
||
|
//
|
||
|
// This could be an error, or indication that all devices have been
|
||
|
// processed. Either way the desired device was not found.
|
||
|
//
|
||
|
|
||
|
done = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the DriverName value
|
||
|
//
|
||
|
|
||
|
bResult = GetDeviceProperty(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
SPDRP_DRIVER,
|
||
|
&buf);
|
||
|
|
||
|
// If the DriverName value matches, return the DeviceInstance
|
||
|
//
|
||
|
if (bResult == TRUE && buf != NULL && _stricmp(pDriverName, buf) == 0)
|
||
|
{
|
||
|
done = TRUE;
|
||
|
*pDevInfo = deviceInfo;
|
||
|
deviceInfo = INVALID_HANDLE_VALUE;
|
||
|
CopyMemory(pDevInfoData, &deviceInfoData, sizeof(deviceInfoData));
|
||
|
FREE(buf);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(buf != NULL)
|
||
|
{
|
||
|
FREE(buf);
|
||
|
buf = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Done:
|
||
|
|
||
|
//if (bResult == FALSE)
|
||
|
{
|
||
|
if (deviceInfo != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pDriverName != NULL)
|
||
|
{
|
||
|
FREE(pDriverName);
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
DriverNameToDeviceProperties()
|
||
|
|
||
|
Returns the Device properties of the DevNode with the matching DriverName.
|
||
|
Returns NULL if the matching DevNode is not found.
|
||
|
|
||
|
The caller should free the returned structure using FREE() macro
|
||
|
|
||
|
*****************************************************************************/
|
||
|
PUSB_DEVICE_PNP_STRINGS
|
||
|
DriverNameToDeviceProperties(
|
||
|
_In_reads_bytes_(cbDriverName) PCHAR DriverName,
|
||
|
_In_ size_t cbDriverName
|
||
|
)
|
||
|
{
|
||
|
HDEVINFO deviceInfo = INVALID_HANDLE_VALUE;
|
||
|
SP_DEVINFO_DATA deviceInfoData = {0};
|
||
|
ULONG len;
|
||
|
BOOL status;
|
||
|
PUSB_DEVICE_PNP_STRINGS DevProps = NULL;
|
||
|
DWORD lastError;
|
||
|
|
||
|
// Allocate device propeties structure
|
||
|
DevProps = (PUSB_DEVICE_PNP_STRINGS) ALLOC(sizeof(USB_DEVICE_PNP_STRINGS));
|
||
|
|
||
|
if(NULL == DevProps)
|
||
|
{
|
||
|
status = FALSE;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
// Get device instance
|
||
|
status = DriverNameToDeviceInst(DriverName, cbDriverName, &deviceInfo, &deviceInfoData);
|
||
|
if (status == FALSE)
|
||
|
{
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
len = 0;
|
||
|
status = SetupDiGetDeviceInstanceId(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
NULL,
|
||
|
0,
|
||
|
&len);
|
||
|
lastError = GetLastError();
|
||
|
|
||
|
|
||
|
if (status != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
status = FALSE;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// An extra byte is required for the terminating character
|
||
|
//
|
||
|
|
||
|
len++;
|
||
|
DevProps->DeviceId = ALLOC(len * 2);
|
||
|
|
||
|
if (DevProps->DeviceId == NULL)
|
||
|
{
|
||
|
status = FALSE;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
status = SetupDiGetDeviceInstanceId(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
DevProps->DeviceId,
|
||
|
len,
|
||
|
&len);
|
||
|
if (status == FALSE)
|
||
|
{
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
status = GetDeviceProperty(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
SPDRP_DEVICEDESC,
|
||
|
&DevProps->DeviceDesc);
|
||
|
|
||
|
if (status == FALSE)
|
||
|
{
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// We don't fail if the following registry query fails as these fields are additional information only
|
||
|
//
|
||
|
|
||
|
GetDeviceProperty(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
SPDRP_HARDWAREID,
|
||
|
&DevProps->HwId);
|
||
|
|
||
|
GetDeviceProperty(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
SPDRP_SERVICE,
|
||
|
&DevProps->Service);
|
||
|
|
||
|
GetDeviceProperty(deviceInfo,
|
||
|
&deviceInfoData,
|
||
|
SPDRP_CLASS,
|
||
|
&DevProps->DeviceClass);
|
||
|
Done:
|
||
|
|
||
|
if (deviceInfo != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||
|
}
|
||
|
|
||
|
if (status == FALSE)
|
||
|
{
|
||
|
if (DevProps != NULL)
|
||
|
{
|
||
|
FreeDeviceProperties(&DevProps);
|
||
|
}
|
||
|
}
|
||
|
return DevProps;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
FreeDeviceProperties()
|
||
|
|
||
|
Free the device properties structure
|
||
|
|
||
|
*****************************************************************************/
|
||
|
VOID FreeDeviceProperties(_In_ PUSB_DEVICE_PNP_STRINGS *ppDevProps)
|
||
|
{
|
||
|
if(ppDevProps == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(*ppDevProps == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ((*ppDevProps)->DeviceId != NULL)
|
||
|
{
|
||
|
FREE((*ppDevProps)->DeviceId);
|
||
|
}
|
||
|
|
||
|
if ((*ppDevProps)->DeviceDesc != NULL)
|
||
|
{
|
||
|
FREE((*ppDevProps)->DeviceDesc);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The following are not necessary, but left in case
|
||
|
// in the future there is a later failure where these
|
||
|
// pointer fields would be allocated.
|
||
|
//
|
||
|
|
||
|
if ((*ppDevProps)->HwId != NULL)
|
||
|
{
|
||
|
FREE((*ppDevProps)->HwId);
|
||
|
}
|
||
|
|
||
|
if ((*ppDevProps)->Service != NULL)
|
||
|
{
|
||
|
FREE((*ppDevProps)->Service);
|
||
|
}
|
||
|
|
||
|
if ((*ppDevProps)->DeviceClass != NULL)
|
||
|
{
|
||
|
FREE((*ppDevProps)->DeviceClass);
|
||
|
}
|
||
|
|
||
|
if ((*ppDevProps)->PowerState != NULL)
|
||
|
{
|
||
|
FREE((*ppDevProps)->PowerState);
|
||
|
}
|
||
|
|
||
|
FREE(*ppDevProps);
|
||
|
*ppDevProps = NULL;
|
||
|
}
|