Implement SetupDiGetSelectedDriverW/SetupDiSetSelectedDriverW

Define rank of a driver as in MSDN description
Fix comments in Flags/FlagsEx description
Factorise DeviceInfoElement structure creation in CreateDeviceInfoElement().

svn path=/trunk/; revision=17244
This commit is contained in:
Hervé Poussineau 2005-08-09 16:13:50 +00:00
parent 1f19cd831e
commit ac5643191a
2 changed files with 198 additions and 65 deletions

View file

@ -152,6 +152,9 @@ struct DeviceInfoElement /* Element of DeviceInfoSet.ListHead */
/* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */ /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
/* If the driver is not searched/detected, this list is empty */ /* If the driver is not searched/detected, this list is empty */
LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */ LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */
/* Points into DriverListHead list. The pointer is NULL if no driver is
* currently chosen. */
struct DriverInfoElement *SelectedDriver;
/* List of interfaces implemented by this device */ /* List of interfaces implemented by this device */
LIST_ENTRY InterfaceHead; /* List of struct DeviceInterface */ LIST_ENTRY InterfaceHead; /* List of struct DeviceInterface */
@ -167,13 +170,9 @@ struct DeviceInfoSet /* HDEVINFO */
HKEY HKLM; /* Local or distant HKEY_LOCAL_MACHINE registry key */ HKEY HKLM; /* Local or distant HKEY_LOCAL_MACHINE registry key */
/* Flags is a combination of: /* Flags is a combination of:
* - DI_FLAGSEX_DIDINFOLIST
* - DI_DIDCLASS * - DI_DIDCLASS
* - DI_MULTMFGS * Set when the class driver list is created
* Set by SetupDiBuildDriverInfoList if drivers of * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
* multiple manufacturers found
* - DI_FLAGSEX_DIDCOMPATINFO
* - DI_COMPAT_FROM_CLASS
* Forces SetupDiBuildDriverInfoList to build a class drivers list * Forces SetupDiBuildDriverInfoList to build a class drivers list
* FlagsEx is a combination of: * FlagsEx is a combination of:
*/ */
@ -182,6 +181,9 @@ struct DeviceInfoSet /* HDEVINFO */
/* If the driver is not searched/detected, this list is empty */ /* If the driver is not searched/detected, this list is empty */
LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */ LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */
/* Points into DriverListHead list. The pointer is NULL if no driver is
* currently chosen. */
struct DriverInfoElement *SelectedDriver;
LIST_ENTRY ListHead; /* List of struct DeviceInfoElement */ LIST_ENTRY ListHead; /* List of struct DeviceInfoElement */
}; };
@ -1156,6 +1158,39 @@ end:
return ret; return ret;
} }
static BOOL
CreateDeviceInfoElement(
IN LPCWSTR InstancePath,
LPCGUID pClassGuid,
OUT struct DeviceInfoElement **pDeviceInfo)
{
struct DeviceInfoElement *deviceInfo;
*pDeviceInfo = NULL;
deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR));
if (!deviceInfo)
{
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
return FALSE;
}
wcscpy(deviceInfo->Data, InstancePath);
deviceInfo->DeviceName = deviceInfo->Data;
deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
deviceInfo->DeviceDescription = NULL;
memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
deviceInfo->CreationFlags = 0;
deviceInfo->hwndParent = NULL;
deviceInfo->Flags = 0; /* FIXME */
deviceInfo->FlagsEx = 0; /* FIXME */
deviceInfo->SelectedDriver = NULL;
InitializeListHead(&deviceInfo->DriverListHead);
InitializeListHead(&deviceInfo->InterfaceHead);
*pDeviceInfo = deviceInfo;
return TRUE;
}
static LONG SETUP_CreateDevListFromEnumerator( static LONG SETUP_CreateDevListFromEnumerator(
struct DeviceInfoSet *list, struct DeviceInfoSet *list,
LPCGUID pClassGuid OPTIONAL, LPCGUID pClassGuid OPTIONAL,
@ -1252,24 +1287,12 @@ static LONG SETUP_CreateDevListFromEnumerator(
} }
/* Add the entry to the list */ /* Add the entry to the list */
deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR)); if (!CreateDeviceInfoElement(InstancePath, pClassGuid, &deviceInfo))
if (!deviceInfo)
{ {
RegCloseKey(hDeviceIdKey); RegCloseKey(hDeviceIdKey);
return ERROR_NO_SYSTEM_RESOURCES; return GetLastError();
} }
TRACE("Adding '%S' to device info set %p\n", InstancePath, list); TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
wcscpy(deviceInfo->Data, InstancePath);
deviceInfo->DeviceName = deviceInfo->Data;
deviceInfo->UniqueId = &deviceInfo->Data[pEndOfInstancePath - InstancePath + 1];
deviceInfo->DeviceDescription = NULL;
memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
deviceInfo->CreationFlags = 0;
deviceInfo->hwndParent = NULL;
deviceInfo->Flags = 0; /* FIXME */
deviceInfo->FlagsEx = 0; /* FIXME */
InitializeListHead(&deviceInfo->DriverListHead);
InitializeListHead(&deviceInfo->InterfaceHead);
InsertTailList(&list->ListHead, &deviceInfo->ListEntry); InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
} }
RegCloseKey(hDeviceIdKey); RegCloseKey(hDeviceIdKey);
@ -2841,25 +2864,8 @@ BOOL WINAPI SetupDiCreateDeviceInfoW(
{ {
struct DeviceInfoElement *deviceInfo; struct DeviceInfoElement *deviceInfo;
deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(DeviceName) + 1) * sizeof(WCHAR)); if (CreateDeviceInfoElement(DeviceName, &GUID_NULL /* FIXME */, &deviceInfo))
if (!deviceInfo)
{ {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
else
{
/* Fill members of the new structure */
wcscpy(deviceInfo->Data, DeviceName);
deviceInfo->DeviceName = deviceInfo->Data;
deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
deviceInfo->DeviceDescription = NULL;
//FIXME memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
deviceInfo->CreationFlags = 0;
deviceInfo->hwndParent = hwndParent;
deviceInfo->Flags = 0; /* FIXME */
deviceInfo->FlagsEx = 0; /* FIXME */
InitializeListHead(&deviceInfo->DriverListHead);
InitializeListHead(&deviceInfo->InterfaceHead);
InsertTailList(&list->ListHead, &deviceInfo->ListEntry); InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
if (!DeviceInfoData) if (!DeviceInfoData)
@ -2900,8 +2906,7 @@ AddDriverToList(
IN LPCWSTR ManufacturerName, IN LPCWSTR ManufacturerName,
FILETIME DriverDate, FILETIME DriverDate,
DWORDLONG DriverVersion, DWORDLONG DriverVersion,
IN DWORD Rank, IN DWORD Rank)
IN DWORD SubRank)
{ {
struct DriverInfoElement *driverInfo; struct DriverInfoElement *driverInfo;
DWORD RequiredSize = 128; /* Initial buffer size */ DWORD RequiredSize = 128; /* Initial buffer size */
@ -2963,7 +2968,8 @@ AddDriverToList(
return FALSE; return FALSE;
} }
TRACE("Adding driver '%S' [%S/%S]\n", DeviceDescription, InfFile, InfInstallSection); TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
DeviceDescription, InfFile, InfInstallSection, Rank);
driverInfo->Info.DriverType = DriverType; driverInfo->Info.DriverType = DriverType;
driverInfo->Info.Reserved = (ULONG_PTR)driverInfo; driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
@ -3168,6 +3174,7 @@ SetupDiBuildDriverInfoList(
if (Result) if (Result)
{ {
LPCWSTR filename; LPCWSTR filename;
for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1) for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
{ {
INFCONTEXT ContextManufacturer, ContextDevice; INFCONTEXT ContextManufacturer, ContextDevice;
@ -3259,7 +3266,7 @@ SetupDiBuildDriverInfoList(
ProviderName, ProviderName,
ManufacturerName, ManufacturerName,
DriverDate, DriverVersion, DriverDate, DriverVersion,
0, 0)) 0))
{ {
break; break;
} }
@ -3299,9 +3306,8 @@ SetupDiBuildDriverInfoList(
HeapFree(GetProcessHeap(), 0, DeviceId); HeapFree(GetProcessHeap(), 0, DeviceId);
goto done; goto done;
} }
DriverRank = 0;
DriverAlreadyAdded = FALSE; DriverAlreadyAdded = FALSE;
for (currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++) for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
{ {
if (wcscmp(DeviceId, currentId) == 0) if (wcscmp(DeviceId, currentId) == 0)
{ {
@ -3313,13 +3319,13 @@ SetupDiBuildDriverInfoList(
ProviderName, ProviderName,
ManufacturerName, ManufacturerName,
DriverDate, DriverVersion, DriverDate, DriverVersion,
DriverRank, i); DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
DriverAlreadyAdded = TRUE; DriverAlreadyAdded = TRUE;
} }
} }
if (CompatibleIDs) if (CompatibleIDs)
{ {
for (currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++) for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
{ {
if (wcscmp(DeviceId, currentId) == 0) if (wcscmp(DeviceId, currentId) == 0)
{ {
@ -3331,7 +3337,7 @@ SetupDiBuildDriverInfoList(
ProviderName, ProviderName,
ManufacturerName, ManufacturerName,
DriverDate, DriverVersion, DriverDate, DriverVersion,
DriverRank, i); DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
DriverAlreadyAdded = TRUE; DriverAlreadyAdded = TRUE;
} }
} }
@ -3359,6 +3365,17 @@ SetupDiBuildDriverInfoList(
} }
done: done:
if (ret)
{
if (DeviceInfoData)
{
struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData;
deviceInfo->Flags |= DI_DIDCOMPAT;
}
else
list->Flags |= DI_DIDCLASS;
}
HeapFree(GetProcessHeap(), 0, ProviderName); HeapFree(GetProcessHeap(), 0, ProviderName);
HeapFree(GetProcessHeap(), 0, ManufacturerName); HeapFree(GetProcessHeap(), 0, ManufacturerName);
HeapFree(GetProcessHeap(), 0, ManufacturerSection); HeapFree(GetProcessHeap(), 0, ManufacturerSection);
@ -3367,6 +3384,7 @@ done:
if (hInf != INVALID_HANDLE_VALUE) if (hInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(hInf); SetupCloseInfFile(hInf);
HeapFree(GetProcessHeap(), 0, Buffer); HeapFree(GetProcessHeap(), 0, Buffer);
TRACE("Returning %d\n", ret); TRACE("Returning %d\n", ret);
return ret; return ret;
} }
@ -3522,25 +3540,11 @@ SetupDiOpenDeviceInfoW(
return FALSE; return FALSE;
} }
deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(DeviceInstanceId) + 1) * sizeof(WCHAR)); if (!CreateDeviceInfoElement(DeviceInstanceId, &GUID_NULL /* FIXME */, &deviceInfo))
if (!deviceInfo)
{ {
RegCloseKey(hKey); RegCloseKey(hKey);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE; return FALSE;
} }
wcscpy(deviceInfo->Data, DeviceInstanceId);
deviceInfo->DeviceName = deviceInfo->Data;
//FIXME deviceInfo->UniqueId = &deviceInfo->Data[pEndOfInstancePath - InstancePath + 1];
deviceInfo->DeviceDescription = NULL;
//FIXME memcpy(&deviceInfo->ClassGuid, FIXME, sizeof(GUID));
deviceInfo->CreationFlags = 0;
deviceInfo->hwndParent = hwndParent;
deviceInfo->Flags = 0; /* FIXME */
deviceInfo->FlagsEx = 0; /* FIXME */
InitializeListHead(&deviceInfo->DriverListHead);
InitializeListHead(&deviceInfo->InterfaceHead);
InsertTailList(&list->ListHead, &deviceInfo->ListEntry); InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
RegCloseKey(hKey); RegCloseKey(hKey);
@ -3688,3 +3692,133 @@ SetupDiEnumDriverInfoW(
TRACE("Returning %d\n", ret); TRACE("Returning %d\n", ret);
return ret; return ret;
} }
/***********************************************************************
* SetupDiGetSelectedDriverW (SETUPAPI.@)
*/
BOOL WINAPI
SetupDiGetSelectedDriverW(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
OUT PSP_DRVINFO_DATA_W DriverInfoData)
{
BOOL ret = FALSE;
TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
if (!DeviceInfoSet || !DriverInfoData)
SetLastError(ERROR_INVALID_PARAMETER);
else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
SetLastError(ERROR_INVALID_HANDLE);
else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
struct DriverInfoElement *driverInfo;
if (DeviceInfoData)
driverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
else
driverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
if (driverInfo == NULL)
SetLastError(ERROR_NO_DRIVER_SELECTED);
else
{
memcpy(
DriverInfoData,
&driverInfo->Info,
DriverInfoData->cbSize);
ret = TRUE;
}
}
TRACE("Returning %d\n", ret);
return ret;
}
/***********************************************************************
* SetupDiSetSelectedDriverW (SETUPAPI.@)
*/
BOOL WINAPI
SetupDiSetSelectedDriverW(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
{
BOOL ret = FALSE;
TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
if (!DeviceInfoSet)
SetLastError(ERROR_INVALID_PARAMETER);
else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
SetLastError(ERROR_INVALID_HANDLE);
else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
struct DriverInfoElement **pDriverInfo;
PLIST_ENTRY ListHead, ItemList;
if (DeviceInfoData)
{
pDriverInfo = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
}
else
{
pDriverInfo = &((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
}
if (!DriverInfoData)
{
*pDriverInfo = NULL;
ret = TRUE;
}
else
{
/* Search selected driver in list */
ItemList = ListHead->Flink;
while (ItemList != ListHead)
{
if (DriverInfoData->Reserved != 0)
{
if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
break;
}
else
{
/* The caller wants to compare only DriverType, Description and ProviderName fields */
struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
if (driverInfo->Info.DriverType == DriverInfoData->DriverType
&& wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
&& wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
{
break;
}
}
}
if (ItemList == ListHead)
SetLastError(ERROR_INVALID_PARAMETER);
else
{
*pDriverInfo = (struct DriverInfoElement *)ItemList;
DriverInfoData->Reserved = (ULONG_PTR)ItemList;
ret = TRUE;
}
}
}
TRACE("Returning %d\n", ret);
return ret;
}

View file

@ -290,7 +290,6 @@
@ stub SetupDiDeleteDevRegKey @ stub SetupDiDeleteDevRegKey
@ stdcall SetupDiDeleteDeviceInfo(long ptr) @ stdcall SetupDiDeleteDeviceInfo(long ptr)
@ stub SetupDiDeleteDeviceInterfaceData @ stub SetupDiDeleteDeviceInterfaceData
@ stub SetupDiDeleteDeviceRegKey
@ stub SetupDiDestroyClassImageList @ stub SetupDiDestroyClassImageList
@ stdcall SetupDiDestroyDeviceInfoList(long) @ stdcall SetupDiDestroyDeviceInfoList(long)
@ stdcall SetupDiDestroyDriverInfoList(long ptr long) @ stdcall SetupDiDestroyDriverInfoList(long ptr long)
@ -345,7 +344,7 @@
@ stub SetupDiGetINFClassW @ stub SetupDiGetINFClassW
@ stub SetupDiGetSelectedDevice @ stub SetupDiGetSelectedDevice
@ stub SetupDiGetSelectedDriverA @ stub SetupDiGetSelectedDriverA
@ stub SetupDiGetSelectedDriverW @ stdcall SetupDiGetSelectedDriverW(ptr ptr ptr)
@ stub SetupDiGetWizardPage @ stub SetupDiGetWizardPage
@ stdcall SetupDiInstallClassA(long str long ptr) @ stdcall SetupDiInstallClassA(long str long ptr)
@ stub SetupDiInstallClassExA @ stub SetupDiInstallClassExA
@ -379,7 +378,7 @@
@ stub SetupDiSetDriverInstallParamsW @ stub SetupDiSetDriverInstallParamsW
@ stub SetupDiSetSelectedDevice @ stub SetupDiSetSelectedDevice
@ stub SetupDiSetSelectedDriverA @ stub SetupDiSetSelectedDriverA
@ stub SetupDiSetSelectedDriverW @ stdcall SetupDiSetSelectedDriverW(ptr ptr ptr)
@ stub SetupDiUnremoveDevice @ stub SetupDiUnremoveDevice
@ stub SetupDuplicateDiskSpaceListA @ stub SetupDuplicateDiskSpaceListA
@ stub SetupDuplicateDiskSpaceListW @ stub SetupDuplicateDiskSpaceListW