mirror of
https://github.com/reactos/reactos.git
synced 2024-07-06 20:55:16 +00:00
Implement SetupDiBuildDriverInfoList, SetupDiOpenDeviceInfoA/W, SetupDiEnumDriverInfoA/W, SetupDiCreateDeviceInfoW
Add stubs for SetupDiDeleteDeviceInfo, SetupDiDestroyDriverInfoList svn path=/trunk/; revision=17212
This commit is contained in:
parent
6d963834ca
commit
c4a2110e0f
|
@ -2787,8 +2787,904 @@ BOOL WINAPI SetupDiCreateDeviceInfoW(
|
|||
DWORD CreationFlags,
|
||||
PSP_DEVINFO_DATA DeviceInfoData)
|
||||
{
|
||||
FIXME("%p %s %s %s %p %lx %p\n", DeviceInfoSet, debugstr_w(DeviceName),
|
||||
debugstr_guid(ClassGuid), debugstr_w(DeviceDescription), hwndParent,
|
||||
CreationFlags, DeviceInfoData);
|
||||
struct DeviceInfoSet *list;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
|
||||
debugstr_guid(ClassGuid), DeviceDescription,
|
||||
hwndParent, CreationFlags, DeviceInfoData);
|
||||
|
||||
if (!DeviceInfoSet)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if (!ClassGuid)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
|
||||
SetLastError(ERROR_CLASS_MISMATCH);
|
||||
else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
|
||||
{
|
||||
TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
else
|
||||
{
|
||||
SP_DEVINFO_DATA DevInfo;
|
||||
|
||||
if (CreationFlags & DICD_GENERATE_ID)
|
||||
{
|
||||
/* Generate a new unique ID for this device */
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
FIXME("not implemented\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Device name is fully qualified. Try to open it */
|
||||
BOOL rc;
|
||||
|
||||
DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
rc = SetupDiOpenDeviceInfoW(
|
||||
DeviceInfoSet,
|
||||
DeviceName,
|
||||
NULL, /* hwndParent */
|
||||
CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
|
||||
&DevInfo);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
/* SetupDiOpenDeviceInfoW has already added
|
||||
* the device info to the device info set
|
||||
*/
|
||||
SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
|
||||
}
|
||||
else if (GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
struct DeviceInfoElement *deviceInfo;
|
||||
|
||||
deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(DeviceName) + 1) * sizeof(WCHAR));
|
||||
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);
|
||||
|
||||
if (!DeviceInfoData)
|
||||
ret = TRUE;
|
||||
else
|
||||
{
|
||||
if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
|
||||
DeviceInfoData->DevInst = 0; /* FIXME */
|
||||
DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Helper functions for SetupDiBuildDriverInfoList
|
||||
*/
|
||||
static BOOL
|
||||
AddDriverToList(
|
||||
IN PLIST_ENTRY DriverListHead,
|
||||
IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
|
||||
IN INFCONTEXT ContextDevice,
|
||||
IN LPCWSTR InfFile,
|
||||
IN LPCWSTR ProviderName,
|
||||
IN LPCWSTR ManufacturerName,
|
||||
FILETIME DriverDate,
|
||||
DWORDLONG DriverVersion,
|
||||
IN DWORD Rank,
|
||||
IN DWORD SubRank)
|
||||
{
|
||||
struct DriverInfoElement *driverInfo;
|
||||
DWORD RequiredSize = 128; /* Initial buffer size */
|
||||
BOOL Result = FALSE;
|
||||
LPWSTR DeviceDescription = NULL;
|
||||
LPWSTR InfInstallSection = NULL;
|
||||
|
||||
driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
|
||||
if (!driverInfo)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, DeviceDescription);
|
||||
DeviceDescription = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!DeviceDescription)
|
||||
return FALSE;
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextDevice,
|
||||
0, /* Field index */
|
||||
DeviceDescription, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
if (!Result)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, driverInfo);
|
||||
HeapFree(GetProcessHeap(), 0, DeviceDescription);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Result = FALSE;
|
||||
RequiredSize = 128; /* Initial buffer size */
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, InfInstallSection);
|
||||
InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!InfInstallSection)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, driverInfo);
|
||||
HeapFree(GetProcessHeap(), 0, DeviceDescription);
|
||||
return FALSE;
|
||||
}
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextDevice,
|
||||
1, /* Field index */
|
||||
InfInstallSection, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
if (!Result)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, driverInfo);
|
||||
HeapFree(GetProcessHeap(), 0, DeviceDescription);
|
||||
HeapFree(GetProcessHeap(), 0, InfInstallSection);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TRACE("Adding driver '%S' [%S/%S]\n", DeviceDescription, InfFile, InfInstallSection);
|
||||
|
||||
driverInfo->Info.DriverType = DriverType;
|
||||
driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
|
||||
wcsncpy(driverInfo->Info.Description, DeviceDescription, LINE_LEN - 1);
|
||||
driverInfo->Info.Description[LINE_LEN - 1] = '\0';
|
||||
wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
|
||||
driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
|
||||
if (ProviderName)
|
||||
{
|
||||
wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
|
||||
driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
|
||||
}
|
||||
else
|
||||
driverInfo->Info.ProviderName[0] = '\0';
|
||||
driverInfo->Info.DriverDate = DriverDate;
|
||||
driverInfo->Info.DriverVersion = DriverVersion;
|
||||
InsertTailList(DriverListHead, &driverInfo->ListEntry);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, DeviceDescription);
|
||||
HeapFree(GetProcessHeap(), 0, InfInstallSection);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
GetVersionInformationFromInfFile(
|
||||
IN HINF hInf,
|
||||
OUT LPGUID ClassGuid,
|
||||
OUT LPWSTR* pProviderName,
|
||||
OUT FILETIME* DriverDate,
|
||||
OUT DWORDLONG* DriverVersion)
|
||||
{
|
||||
DWORD RequiredSize;
|
||||
WCHAR guidW[MAX_GUID_STRING_LEN + 1];
|
||||
LPWSTR ProviderName = NULL;
|
||||
BOOL Result;
|
||||
|
||||
if (!SetupGetLineTextW(
|
||||
NULL, /* Context */
|
||||
hInf,
|
||||
L"Version", L"ClassGUID",
|
||||
guidW, sizeof(guidW),
|
||||
NULL /* Required size */))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get Provider name, driver date, and driver version */
|
||||
|
||||
guidW[37] = '\0'; /* Replace the } by a NULL character */
|
||||
if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
Result = SetupGetLineTextW(
|
||||
NULL, /* Context */
|
||||
hInf, L"Version", L"Provider",
|
||||
NULL, 0,
|
||||
&RequiredSize);
|
||||
if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!ProviderName)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
Result = SetupGetLineTextW(
|
||||
NULL, /* Context */
|
||||
hInf, L"Version", L"Provider",
|
||||
ProviderName, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
//FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
|
||||
//FIXME: DriverVersion = Version.DriverVer => invalid = 0
|
||||
|
||||
*pProviderName = ProviderName;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiBuildDriverInfoList (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiBuildDriverInfoList(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
|
||||
IN DWORD DriverType)
|
||||
{
|
||||
struct DeviceInfoSet *list;
|
||||
PVOID Buffer = NULL;
|
||||
HINF hInf = INVALID_HANDLE_VALUE;
|
||||
LPWSTR ProviderName = NULL;
|
||||
LPWSTR ManufacturerName = NULL;
|
||||
LPWSTR ManufacturerSection = NULL;
|
||||
LPWSTR HardwareIDs = NULL;
|
||||
LPWSTR CompatibleIDs = NULL;
|
||||
FILETIME DriverDate;
|
||||
DWORDLONG DriverVersion;
|
||||
DWORD RequiredSize;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
|
||||
|
||||
if (!DeviceInfoSet)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if (list->HKLM != HKEY_LOCAL_MACHINE)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
|
||||
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||
else
|
||||
{
|
||||
BOOL Result = FALSE;
|
||||
|
||||
if (DriverType == SPDIT_COMPATDRIVER)
|
||||
{
|
||||
/* Get hardware IDs list */
|
||||
Result = FALSE;
|
||||
RequiredSize = 512; /* Initial buffer size */
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, HardwareIDs);
|
||||
HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!HardwareIDs)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
Result = SetupDiGetDeviceRegistryPropertyW(
|
||||
DeviceInfoSet,
|
||||
DeviceInfoData,
|
||||
SPDRP_HARDWAREID,
|
||||
NULL,
|
||||
(PBYTE)HardwareIDs,
|
||||
RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
if (!Result)
|
||||
goto done;
|
||||
|
||||
/* Get compatible IDs list */
|
||||
Result = FALSE;
|
||||
RequiredSize = 512; /* Initial buffer size */
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, CompatibleIDs);
|
||||
CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!CompatibleIDs)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
Result = SetupDiGetDeviceRegistryPropertyW(
|
||||
DeviceInfoSet,
|
||||
DeviceInfoData,
|
||||
SPDRP_COMPATIBLEIDS,
|
||||
NULL,
|
||||
(PBYTE)CompatibleIDs,
|
||||
RequiredSize,
|
||||
&RequiredSize);
|
||||
if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
/* No compatible ID for this device */
|
||||
HeapFree(GetProcessHeap(), 0, CompatibleIDs);
|
||||
CompatibleIDs = NULL;
|
||||
Result = TRUE;
|
||||
}
|
||||
}
|
||||
if (!Result)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Enumerate .inf files */
|
||||
Result = FALSE;
|
||||
RequiredSize = 32768; /* Initial buffer size */
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, Buffer);
|
||||
Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!Buffer)
|
||||
{
|
||||
Result = FALSE;
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
break;
|
||||
}
|
||||
Result = SetupGetInfFileListW(
|
||||
NULL, /* Directory path */
|
||||
INF_STYLE_WIN4,
|
||||
Buffer, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
if (Result)
|
||||
{
|
||||
LPCWSTR filename;
|
||||
for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
|
||||
{
|
||||
INFCONTEXT ContextManufacturer, ContextDevice;
|
||||
GUID ClassGuid;
|
||||
TRACE("Opening file %S\n", filename);
|
||||
|
||||
hInf = SetupOpenInfFileW(filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
if (hInf == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
|
||||
if (!GetVersionInformationFromInfFile(
|
||||
hInf,
|
||||
&ClassGuid,
|
||||
&ProviderName,
|
||||
&DriverDate,
|
||||
&DriverVersion))
|
||||
{
|
||||
SetupCloseInfFile(hInf);
|
||||
hInf = INVALID_HANDLE_VALUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DriverType == SPDIT_CLASSDRIVER)
|
||||
{
|
||||
/* Check if the ClassGuid in this .inf file is corresponding with our needs */
|
||||
if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
|
||||
{
|
||||
SetupCloseInfFile(hInf);
|
||||
hInf = INVALID_HANDLE_VALUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the manufacturers list */
|
||||
Result = SetupFindFirstLineW(hInf, L"Manufacturer", NULL, &ContextManufacturer);
|
||||
while (Result)
|
||||
{
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextManufacturer,
|
||||
0, /* Field index */
|
||||
NULL, 0,
|
||||
&RequiredSize);
|
||||
if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!ManufacturerName)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextManufacturer,
|
||||
0, /* Field index */
|
||||
ManufacturerName, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextManufacturer,
|
||||
1, /* Field index */
|
||||
NULL, 0,
|
||||
&RequiredSize);
|
||||
if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
ManufacturerSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!ManufacturerSection)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextManufacturer,
|
||||
1, /* Field index */
|
||||
ManufacturerSection, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
|
||||
TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
|
||||
Result = SetupFindFirstLineW(hInf, ManufacturerSection, NULL, &ContextDevice);
|
||||
while (Result)
|
||||
{
|
||||
if (DriverType == SPDIT_CLASSDRIVER)
|
||||
{
|
||||
/* FIXME: read [ControlFlags] / ExcludeFromSelect */
|
||||
if (!AddDriverToList(
|
||||
&list->DriverListHead,
|
||||
DriverType,
|
||||
ContextDevice,
|
||||
filename,
|
||||
ProviderName,
|
||||
ManufacturerName,
|
||||
DriverDate, DriverVersion,
|
||||
0, 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* DriverType = SPDIT_COMPATDRIVER */
|
||||
{
|
||||
/* 1. Get all fields */
|
||||
DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
|
||||
DWORD DriverRank;
|
||||
DWORD i;
|
||||
LPCWSTR currentId;
|
||||
BOOL DriverAlreadyAdded;
|
||||
|
||||
for (i = 2; i <= FieldCount; i++)
|
||||
{
|
||||
LPWSTR DeviceId = NULL;
|
||||
Result = FALSE;
|
||||
RequiredSize = 128; /* Initial buffer size */
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, DeviceId);
|
||||
DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
|
||||
if (!DeviceId)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
Result = SetupGetStringFieldW(
|
||||
&ContextDevice,
|
||||
i,
|
||||
DeviceId, RequiredSize,
|
||||
&RequiredSize);
|
||||
}
|
||||
if (!Result)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, DeviceId);
|
||||
goto done;
|
||||
}
|
||||
DriverRank = 0;
|
||||
DriverAlreadyAdded = FALSE;
|
||||
for (currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
|
||||
{
|
||||
if (wcscmp(DeviceId, currentId) == 0)
|
||||
{
|
||||
AddDriverToList(
|
||||
&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
|
||||
DriverType,
|
||||
ContextDevice,
|
||||
filename,
|
||||
ProviderName,
|
||||
ManufacturerName,
|
||||
DriverDate, DriverVersion,
|
||||
DriverRank, i);
|
||||
DriverAlreadyAdded = TRUE;
|
||||
}
|
||||
}
|
||||
if (CompatibleIDs)
|
||||
{
|
||||
for (currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
|
||||
{
|
||||
if (wcscmp(DeviceId, currentId) == 0)
|
||||
{
|
||||
AddDriverToList(
|
||||
&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
|
||||
DriverType,
|
||||
ContextDevice,
|
||||
filename,
|
||||
ProviderName,
|
||||
ManufacturerName,
|
||||
DriverDate, DriverVersion,
|
||||
DriverRank, i);
|
||||
DriverAlreadyAdded = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, DeviceId);
|
||||
}
|
||||
}
|
||||
Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, ManufacturerName);
|
||||
HeapFree(GetProcessHeap(), 0, ManufacturerSection);
|
||||
ManufacturerName = ManufacturerSection = NULL;
|
||||
Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, ProviderName);
|
||||
ProviderName = NULL;
|
||||
ret = TRUE;
|
||||
|
||||
SetupCloseInfFile(hInf);
|
||||
hInf = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
HeapFree(GetProcessHeap(), 0, ProviderName);
|
||||
HeapFree(GetProcessHeap(), 0, ManufacturerName);
|
||||
HeapFree(GetProcessHeap(), 0, ManufacturerSection);
|
||||
HeapFree(GetProcessHeap(), 0, HardwareIDs);
|
||||
HeapFree(GetProcessHeap(), 0, CompatibleIDs);
|
||||
if (hInf != INVALID_HANDLE_VALUE)
|
||||
SetupCloseInfFile(hInf);
|
||||
HeapFree(GetProcessHeap(), 0, Buffer);
|
||||
TRACE("Returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiDeleteDeviceInfo (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiDeleteDeviceInfo(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN PSP_DEVINFO_DATA DeviceInfoData)
|
||||
{
|
||||
TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
|
||||
|
||||
FIXME("not implemented\n");
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiDestroyDriverInfoList (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiDestroyDriverInfoList(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN PSP_DEVINFO_DATA DeviceInfoData,
|
||||
IN DWORD DriverType)
|
||||
{
|
||||
TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
|
||||
|
||||
FIXME("not implemented\n");
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiOpenDeviceInfoA (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiOpenDeviceInfoA(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN PCSTR DeviceInstanceId,
|
||||
IN HWND hwndParent OPTIONAL,
|
||||
IN DWORD OpenFlags,
|
||||
OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
|
||||
{
|
||||
LPWSTR DeviceInstanceIdW = NULL;
|
||||
BOOL bResult;
|
||||
|
||||
TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
|
||||
|
||||
DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
|
||||
if (DeviceInstanceIdW == NULL)
|
||||
return FALSE;
|
||||
|
||||
bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
|
||||
DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
|
||||
|
||||
MyFree(DeviceInstanceIdW);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiOpenDeviceInfoW (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiOpenDeviceInfoW(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN PCWSTR DeviceInstanceId,
|
||||
IN HWND hwndParent OPTIONAL,
|
||||
IN DWORD OpenFlags,
|
||||
OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
|
||||
{
|
||||
struct DeviceInfoSet *list;
|
||||
HKEY hEnumKey, hKey;
|
||||
DWORD rc;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
|
||||
|
||||
if (OpenFlags & DIOD_CANCEL_REMOVE)
|
||||
FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
|
||||
|
||||
if (!DeviceInfoSet)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
else if (!DeviceInstanceId)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
|
||||
{
|
||||
TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
|
||||
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||
else
|
||||
{
|
||||
struct DeviceInfoElement *deviceInfo = NULL;
|
||||
/* Search if device already exists in DeviceInfoSet.
|
||||
* If yes, return the existing element
|
||||
* If no, create a new element using informations in registry
|
||||
*/
|
||||
PLIST_ENTRY ItemList = list->ListHead.Flink;
|
||||
while (ItemList != &list->ListHead)
|
||||
{
|
||||
// TODO
|
||||
//if (good one)
|
||||
// break;
|
||||
FIXME("not implemented\n");
|
||||
ItemList = ItemList->Flink;
|
||||
}
|
||||
|
||||
if (deviceInfo)
|
||||
{
|
||||
// good one found
|
||||
if (DeviceInfoData)
|
||||
{
|
||||
memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
|
||||
DeviceInfoData->DevInst = 0; /* FIXME */
|
||||
DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
|
||||
}
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Open supposed registry key */
|
||||
rc = RegOpenKeyExW(
|
||||
list->HKLM,
|
||||
EnumKeyName,
|
||||
0, /* Options */
|
||||
KEY_ENUMERATE_SUB_KEYS,
|
||||
&hEnumKey);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(rc);
|
||||
return FALSE;
|
||||
}
|
||||
rc = RegOpenKeyExW(
|
||||
hEnumKey,
|
||||
DeviceInstanceId,
|
||||
0, /* Options */
|
||||
KEY_QUERY_VALUE,
|
||||
&hKey);
|
||||
RegCloseKey(hEnumKey);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(rc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(DeviceInstanceId) + 1) * sizeof(WCHAR));
|
||||
if (!deviceInfo)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
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);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
if (ret && deviceInfo && DeviceInfoData)
|
||||
{
|
||||
memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
|
||||
DeviceInfoData->DevInst = 0; /* FIXME */
|
||||
DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiEnumDriverInfoA (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiEnumDriverInfoA(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
|
||||
IN DWORD DriverType,
|
||||
IN DWORD MemberIndex,
|
||||
OUT PSP_DRVINFO_DATA_A DriverInfoData)
|
||||
{
|
||||
SP_DRVINFO_DATA_V2_W driverInfoData2W;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
|
||||
DriverType, MemberIndex, DriverInfoData);
|
||||
|
||||
if (DriverInfoData == NULL)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
|
||||
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||
else
|
||||
{
|
||||
driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
|
||||
ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
|
||||
DriverType, MemberIndex, &driverInfoData2W);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
/* Do W->A conversion */
|
||||
DriverInfoData->DriverType = driverInfoData2W.DriverType;
|
||||
DriverInfoData->Reserved = driverInfoData2W.Reserved;
|
||||
if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
|
||||
DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
|
||||
{
|
||||
DriverInfoData->Description[0] = '\0';
|
||||
ret = FALSE;
|
||||
}
|
||||
if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
|
||||
DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
|
||||
{
|
||||
DriverInfoData->MfgName[0] = '\0';
|
||||
ret = FALSE;
|
||||
}
|
||||
if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
|
||||
DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
|
||||
{
|
||||
DriverInfoData->ProviderName[0] = '\0';
|
||||
ret = FALSE;
|
||||
}
|
||||
if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
|
||||
{
|
||||
/* Copy more fields */
|
||||
DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
|
||||
DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiEnumDriverInfoW (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SetupDiEnumDriverInfoW(
|
||||
IN HDEVINFO DeviceInfoSet,
|
||||
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
|
||||
IN DWORD DriverType,
|
||||
IN DWORD MemberIndex,
|
||||
OUT PSP_DRVINFO_DATA_W DriverInfoData)
|
||||
{
|
||||
PLIST_ENTRY ListHead;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
|
||||
DriverType, MemberIndex, 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 (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
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 DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
|
||||
PLIST_ENTRY ItemList;
|
||||
if (DriverType == SPDIT_CLASSDRIVER ||
|
||||
devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
|
||||
{
|
||||
ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
|
||||
}
|
||||
else
|
||||
{
|
||||
ListHead = &devInfo->DriverListHead;
|
||||
}
|
||||
|
||||
ItemList = ListHead->Flink;
|
||||
while (ItemList != ListHead && MemberIndex-- > 0)
|
||||
ItemList = ItemList->Flink;
|
||||
if (ItemList == ListHead)
|
||||
SetLastError(ERROR_NO_MORE_ITEMS);
|
||||
else
|
||||
{
|
||||
struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
|
||||
|
||||
memcpy(
|
||||
DriverInfoData,
|
||||
&DrvInfo->Info,
|
||||
DriverInfoData->cbSize);
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@
|
|||
@ stdcall SetupDiBuildClassInfoList(long ptr long ptr)
|
||||
@ stdcall SetupDiBuildClassInfoListExA(long ptr long ptr str ptr)
|
||||
@ stdcall SetupDiBuildClassInfoListExW(long ptr long ptr wstr ptr)
|
||||
@ stub SetupDiBuildDriverInfoList
|
||||
@ stdcall SetupDiBuildDriverInfoList(long ptr long)
|
||||
@ stdcall SetupDiCallClassInstaller(long ptr ptr)
|
||||
@ stub SetupDiCancelDriverInfoSearch
|
||||
@ stub SetupDiChangeState
|
||||
|
@ -293,12 +293,12 @@
|
|||
@ stub SetupDiDeleteDeviceRegKey
|
||||
@ stub SetupDiDestroyClassImageList
|
||||
@ stdcall SetupDiDestroyDeviceInfoList(long)
|
||||
@ stub SetupDiDestroyDriverInfoList
|
||||
@ stdcall SetupDiDestroyDriverInfoList(long ptr long)
|
||||
@ stub SetupDiDrawMiniIcon
|
||||
@ stdcall SetupDiEnumDeviceInfo(long long ptr)
|
||||
@ stdcall SetupDiEnumDeviceInterfaces(long ptr ptr long ptr)
|
||||
@ stub SetupDiEnumDriverInfoA
|
||||
@ stub SetupDiEnumDriverInfoW
|
||||
@ stdcall SetupDiEnumDriverInfoA(long ptr long long ptr)
|
||||
@ stdcall SetupDiEnumDriverInfoW(long ptr long long ptr)
|
||||
@ stdcall SetupDiGetActualSectionToInstallA(long str str long ptr ptr)
|
||||
@ stdcall SetupDiGetActualSectionToInstallW(long wstr wstr long ptr ptr)
|
||||
@ stub SetupDiGetClassBitmapIndex
|
||||
|
@ -359,8 +359,8 @@
|
|||
@ stdcall SetupDiOpenClassRegKeyExA(ptr long long str ptr)
|
||||
@ stdcall SetupDiOpenClassRegKeyExW(ptr long long wstr ptr)
|
||||
@ stdcall SetupDiOpenDevRegKey(ptr ptr long long long long)
|
||||
@ stub SetupDiOpenDeviceInfoA
|
||||
@ stub SetupDiOpenDeviceInfoW
|
||||
@ stdcall SetupDiOpenDeviceInfoA(ptr str long long ptr)
|
||||
@ stdcall SetupDiOpenDeviceInfoW(ptr wstr long long ptr)
|
||||
@ stdcall SetupDiOpenDeviceInterfaceA(ptr str long ptr)
|
||||
@ stub SetupDiOpenDeviceInterfaceRegKey
|
||||
@ stdcall SetupDiOpenDeviceInterfaceW(ptr wstr long ptr)
|
||||
|
|
Loading…
Reference in a new issue