setupapi: Implement SetupDiGetDriverInfoDetail().
Needed by the Windows Device Framework co-installer. Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6971dfcfc2
commit
5cff8c9e2e
|
@ -110,6 +110,7 @@ struct driver
|
|||
WCHAR manufacturer[LINE_LEN];
|
||||
WCHAR mfg_key[LINE_LEN];
|
||||
WCHAR description[LINE_LEN];
|
||||
WCHAR section[LINE_LEN];
|
||||
};
|
||||
|
||||
/* is used to identify if a DeviceInfoSet pointer is
|
||||
|
@ -4564,6 +4565,8 @@ static void enum_compat_drivers_from_file(struct device *device, const WCHAR *pa
|
|||
lstrcpyW(device->drivers[count - 1].mfg_key, mfg_key_ext);
|
||||
SetupGetStringFieldW(&ctx, 0, device->drivers[count - 1].description,
|
||||
ARRAY_SIZE(device->drivers[count - 1].description), NULL);
|
||||
SetupGetStringFieldW(&ctx, 1, device->drivers[count - 1].section,
|
||||
ARRAY_SIZE(device->drivers[count - 1].section), NULL);
|
||||
|
||||
TRACE("Found compatible driver: manufacturer %s, desc %s.\n",
|
||||
debugstr_w(mfg_name), debugstr_w(device->drivers[count - 1].description));
|
||||
|
@ -4659,6 +4662,7 @@ static BOOL copy_driver_data(SP_DRVINFO_DATA_W *data, const struct driver *drive
|
|||
wcscpy(data->Description, driver->description);
|
||||
wcscpy(data->MfgName, driver->manufacturer);
|
||||
data->DriverType = SPDIT_COMPATDRIVER;
|
||||
data->Reserved = (ULONG_PTR)driver;
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
|
||||
|
@ -4780,6 +4784,155 @@ BOOL WINAPI SetupDiGetSelectedDriverA(HDEVINFO devinfo, SP_DEVINFO_DATA *device_
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiGetDriverInfoDetailW (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupDiGetDriverInfoDetailW(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data,
|
||||
SP_DRVINFO_DATA_W *driver_data, SP_DRVINFO_DETAIL_DATA_W *detail_data, const DWORD size, DWORD *ret_size)
|
||||
{
|
||||
struct driver *driver = (struct driver *)driver_data->Reserved;
|
||||
DWORD size_needed, i, id_size = 1;
|
||||
WCHAR id[MAX_DEVICE_ID_LEN];
|
||||
INFCONTEXT ctx;
|
||||
HANDLE file;
|
||||
HINF hinf;
|
||||
|
||||
TRACE("devinfo %p, device_data %p, driver_data %p, detail_data %p, size %u, ret_size %p.\n",
|
||||
devinfo, device_data, driver_data, detail_data, size, ret_size);
|
||||
|
||||
if ((detail_data || size) && size < sizeof(SP_DRVINFO_DETAIL_DATA_W))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((hinf = SetupOpenInfFileW(driver->inf_path, NULL, INF_STYLE_WIN4, NULL)) == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
SetupFindFirstLineW(hinf, driver->mfg_key, driver->description, &ctx);
|
||||
for (i = 2; SetupGetStringFieldW(&ctx, i, id, ARRAY_SIZE(id), NULL); ++i)
|
||||
id_size += wcslen(id) + 1;
|
||||
|
||||
size_needed = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID[id_size]);
|
||||
if (ret_size)
|
||||
*ret_size = size_needed;
|
||||
if (!detail_data)
|
||||
return TRUE;
|
||||
|
||||
detail_data->CompatIDsLength = detail_data->CompatIDsOffset = 0;
|
||||
detail_data->HardwareID[0] = 0;
|
||||
|
||||
if (size >= size_needed)
|
||||
{
|
||||
id_size = 0;
|
||||
for (i = 2; SetupGetStringFieldW(&ctx, i, id, ARRAY_SIZE(id), NULL); ++i)
|
||||
{
|
||||
wcscpy(&detail_data->HardwareID[id_size], id);
|
||||
if (i == 3)
|
||||
detail_data->CompatIDsOffset = id_size;
|
||||
id_size += wcslen(id) + 1;
|
||||
}
|
||||
detail_data->HardwareID[id_size++] = 0;
|
||||
if (i > 3)
|
||||
detail_data->CompatIDsLength = id_size - detail_data->CompatIDsOffset;
|
||||
}
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
|
||||
if ((file = CreateFileW(driver->inf_path, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
GetFileTime(file, NULL, NULL, &detail_data->InfDate);
|
||||
CloseHandle(file);
|
||||
|
||||
wcscpy(detail_data->SectionName, driver->section);
|
||||
wcscpy(detail_data->InfFileName, driver->inf_path);
|
||||
wcscpy(detail_data->DrvDescription, driver->description);
|
||||
|
||||
if (size < size_needed)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiGetDriverInfoDetailA (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupDiGetDriverInfoDetailA(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data,
|
||||
SP_DRVINFO_DATA_A *driver_data, SP_DRVINFO_DETAIL_DATA_A *detail_data, const DWORD size, DWORD *ret_size)
|
||||
{
|
||||
struct driver *driver = (struct driver *)driver_data->Reserved;
|
||||
DWORD size_needed, i, id_size = 1;
|
||||
char id[MAX_DEVICE_ID_LEN];
|
||||
INFCONTEXT ctx;
|
||||
HANDLE file;
|
||||
HINF hinf;
|
||||
|
||||
TRACE("devinfo %p, device_data %p, driver_data %p, detail_data %p, size %u, ret_size %p.\n",
|
||||
devinfo, device_data, driver_data, detail_data, size, ret_size);
|
||||
|
||||
if ((detail_data || size) && size < sizeof(SP_DRVINFO_DETAIL_DATA_A))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((hinf = SetupOpenInfFileW(driver->inf_path, NULL, INF_STYLE_WIN4, NULL)) == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
SetupFindFirstLineW(hinf, driver->mfg_key, driver->description, &ctx);
|
||||
for (i = 2; SetupGetStringFieldA(&ctx, i, id, ARRAY_SIZE(id), NULL); ++i)
|
||||
id_size += strlen(id) + 1;
|
||||
|
||||
size_needed = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID[id_size]);
|
||||
if (ret_size)
|
||||
*ret_size = size_needed;
|
||||
if (!detail_data)
|
||||
return TRUE;
|
||||
|
||||
detail_data->CompatIDsLength = detail_data->CompatIDsOffset = 0;
|
||||
detail_data->HardwareID[0] = 0;
|
||||
|
||||
if (size >= size_needed)
|
||||
{
|
||||
id_size = 0;
|
||||
for (i = 2; SetupGetStringFieldA(&ctx, i, id, ARRAY_SIZE(id), NULL); ++i)
|
||||
{
|
||||
strcpy(&detail_data->HardwareID[id_size], id);
|
||||
if (i == 3)
|
||||
detail_data->CompatIDsOffset = id_size;
|
||||
id_size += strlen(id) + 1;
|
||||
}
|
||||
detail_data->HardwareID[id_size++] = 0;
|
||||
if (i > 3)
|
||||
detail_data->CompatIDsLength = id_size - detail_data->CompatIDsOffset;
|
||||
}
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
|
||||
if ((file = CreateFileW(driver->inf_path, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
GetFileTime(file, NULL, NULL, &detail_data->InfDate);
|
||||
CloseHandle(file);
|
||||
|
||||
WideCharToMultiByte(CP_ACP, 0, driver->section, -1, detail_data->SectionName,
|
||||
sizeof(detail_data->SectionName), NULL, NULL);
|
||||
WideCharToMultiByte(CP_ACP, 0, driver->inf_path, -1, detail_data->InfFileName,
|
||||
sizeof(detail_data->InfFileName), NULL, NULL);
|
||||
WideCharToMultiByte(CP_ACP, 0, driver->description, -1, detail_data->DrvDescription,
|
||||
sizeof(detail_data->InfFileName), NULL, NULL);
|
||||
|
||||
if (size < size_needed)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiInstallDriverFiles (SETUPAPI.@)
|
||||
*/
|
||||
|
|
|
@ -347,8 +347,8 @@
|
|||
@ stdcall SetupDiGetDevicePropertyW(ptr ptr ptr ptr ptr long ptr long)
|
||||
@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr)
|
||||
@ stdcall SetupDiGetDeviceRegistryPropertyW(long ptr long ptr ptr long ptr)
|
||||
@ stub SetupDiGetDriverInfoDetailA
|
||||
@ stub SetupDiGetDriverInfoDetailW
|
||||
@ stdcall SetupDiGetDriverInfoDetailA(ptr ptr ptr ptr long ptr)
|
||||
@ stdcall SetupDiGetDriverInfoDetailW(ptr ptr ptr ptr long ptr)
|
||||
@ stub SetupDiGetDriverInstallParamsA
|
||||
@ stub SetupDiGetDriverInstallParamsW
|
||||
@ stub SetupDiGetHwProfileFriendlyNameA
|
||||
|
|
|
@ -2315,13 +2315,18 @@ static void test_get_actual_section(void)
|
|||
|
||||
static void test_driver_list(void)
|
||||
{
|
||||
char inf_dir[MAX_PATH], inf_path[MAX_PATH + 10], inf_path2[MAX_PATH + 10];
|
||||
char detail_buffer[1000];
|
||||
SP_DRVINFO_DETAIL_DATA_A *detail = (SP_DRVINFO_DETAIL_DATA_A *)detail_buffer;
|
||||
char short_path[MAX_PATH], inf_dir[MAX_PATH], inf_path[MAX_PATH + 10], inf_path2[MAX_PATH + 10];
|
||||
static const char hardware_id[] = "bogus_hardware_id\0";
|
||||
static const char compat_id[] = "bogus_compat_id\0";
|
||||
SP_DEVINSTALL_PARAMS_A params = {sizeof(params)};
|
||||
SP_DRVINFO_DATA_A driver = {sizeof(driver)};
|
||||
SP_DEVINFO_DATA device = {sizeof(device)};
|
||||
DWORD size, expect_size;
|
||||
FILETIME filetime;
|
||||
HDEVINFO set;
|
||||
HANDLE file;
|
||||
BOOL ret;
|
||||
|
||||
static const char inf_data[] = "[Version]\n"
|
||||
|
@ -2334,12 +2339,12 @@ static void test_driver_list(void)
|
|||
"mfg2_wow=mfg2_key,NT" WOWEXT "\n"
|
||||
"mfg3=mfg3_key,NT" WRONGEXT "\n"
|
||||
"[mfg1_key.nt" MYEXT "]\n"
|
||||
"desc1=,bogus_hardware_id\n"
|
||||
"desc1=install1,bogus_hardware_id\n"
|
||||
"desc2=,bogus_hardware_id\n"
|
||||
"desc3=,wrong_hardware_id\n"
|
||||
"desc4=,wrong_hardware_id,bogus_compat_id\n"
|
||||
"[mfg1_key.nt" WOWEXT "]\n"
|
||||
"desc1=,bogus_hardware_id\n"
|
||||
"desc1=install1,bogus_hardware_id\n"
|
||||
"desc2=,bogus_hardware_id\n"
|
||||
"desc3=,wrong_hardware_id\n"
|
||||
"desc4=,wrong_hardware_id,bogus_compat_id\n"
|
||||
|
@ -2348,7 +2353,9 @@ static void test_driver_list(void)
|
|||
"[mfg2_key.nt" WOWEXT "]\n"
|
||||
"desc5=,bogus_hardware_id\n"
|
||||
"[mfg3_key.nt" WRONGEXT "]\n"
|
||||
"desc6=,bogus_hardware_id\n";
|
||||
"desc6=,bogus_hardware_id\n"
|
||||
"[install1.nt" MYEXT "]\n"
|
||||
"[install1.nt" WRONGEXT "]\n";
|
||||
|
||||
static const char inf_data_file1[] = "[Version]\n"
|
||||
"Signature=\"$Chicago$\"\n"
|
||||
|
@ -2371,8 +2378,14 @@ static void test_driver_list(void)
|
|||
"desc2=,bogus_hardware_id\n";
|
||||
|
||||
GetTempPathA(sizeof(inf_path), inf_path);
|
||||
GetShortPathNameA(inf_path, short_path, sizeof(short_path));
|
||||
strcat(inf_path, "setupapi_test.inf");
|
||||
strcat(short_path, "setupapi_test.inf");
|
||||
create_file(inf_path, inf_data);
|
||||
file = CreateFileA(inf_path, 0, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||
GetFileTime(file, NULL, NULL, &filetime);
|
||||
CloseHandle(file);
|
||||
|
||||
set = SetupDiCreateDeviceInfoList(NULL, NULL);
|
||||
ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
|
||||
ret = SetupDiCreateDeviceInfoA(set, "Root\\BOGUS\\0000", &GUID_NULL, NULL, NULL, 0, &device);
|
||||
|
@ -2408,6 +2421,70 @@ static void test_driver_list(void)
|
|||
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
|
||||
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
|
||||
|
||||
expect_size = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID[sizeof("bogus_hardware_id\0")]);
|
||||
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, NULL, 0, &size);
|
||||
ok(ret || GetLastError() == ERROR_INVALID_USER_BUFFER /* Win10 1809 */,
|
||||
"Failed to get driver details, error %#x.\n", GetLastError());
|
||||
ok(size == expect_size, "Got size %u.\n", size);
|
||||
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, NULL, sizeof(SP_DRVINFO_DETAIL_DATA_A) - 1, &size);
|
||||
ok(!ret, "Expected failure.\n");
|
||||
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
|
||||
ok(size == expect_size, "Got size %u.\n", size);
|
||||
|
||||
size = 0xdeadbeef;
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, detail, 0, &size);
|
||||
ok(!ret, "Expected failure.\n");
|
||||
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
|
||||
ok(size == 0xdeadbeef, "Got size %u.\n", size);
|
||||
|
||||
size = 0xdeadbeef;
|
||||
detail->CompatIDsLength = 0xdeadbeef;
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, detail, sizeof(SP_DRVINFO_DETAIL_DATA_A) - 1, &size);
|
||||
ok(!ret, "Expected failure.\n");
|
||||
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
|
||||
ok(size == 0xdeadbeef, "Got size %u.\n", size);
|
||||
ok(detail->CompatIDsLength == 0xdeadbeef, "Got wrong compat IDs length %u.\n", detail->CompatIDsLength);
|
||||
|
||||
memset(detail_buffer, 0xcc, sizeof(detail_buffer));
|
||||
detail->cbSize = sizeof(*detail);
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, detail, sizeof(SP_DRVINFO_DETAIL_DATA_A), NULL);
|
||||
ok(!ret, "Expected failure.\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
|
||||
ok(detail->InfDate.dwHighDateTime == filetime.dwHighDateTime
|
||||
&& detail->InfDate.dwLowDateTime == filetime.dwLowDateTime,
|
||||
"Expected %#x%08x, got %#x%08x.\n", filetime.dwHighDateTime, filetime.dwLowDateTime,
|
||||
detail->InfDate.dwHighDateTime, detail->InfDate.dwLowDateTime);
|
||||
ok(!strcmp(detail->SectionName, "install1"), "Got section name %s.\n", debugstr_a(detail->SectionName));
|
||||
ok(!stricmp(detail->InfFileName, short_path), "Got INF file name %s.\n", debugstr_a(detail->InfFileName));
|
||||
ok(!strcmp(detail->DrvDescription, "desc1"), "Got description %s.\n", debugstr_a(detail->DrvDescription));
|
||||
ok(!detail->CompatIDsOffset || detail->CompatIDsOffset == sizeof("bogus_hardware_id") /* Win10 1809 */,
|
||||
"Got wrong compat IDs offset %u.\n", detail->CompatIDsOffset);
|
||||
ok(!detail->CompatIDsLength, "Got wrong compat IDs length %u.\n", detail->CompatIDsLength);
|
||||
ok(!detail->HardwareID[0], "Got wrong ID list.\n");
|
||||
|
||||
size = 0xdeadbeef;
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, detail, sizeof(SP_DRVINFO_DETAIL_DATA_A), &size);
|
||||
ok(!ret, "Expected failure.\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
|
||||
ok(size == expect_size, "Got size %u.\n", size);
|
||||
|
||||
size = 0xdeadbeef;
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, detail, sizeof(detail_buffer), &size);
|
||||
ok(ret, "Failed to get driver details, error %#x.\n", GetLastError());
|
||||
ok(size == expect_size, "Got size %u.\n", size);
|
||||
ok(detail->InfDate.dwHighDateTime == filetime.dwHighDateTime
|
||||
&& detail->InfDate.dwLowDateTime == filetime.dwLowDateTime,
|
||||
"Expected %#x%08x, got %#x%08x.\n", filetime.dwHighDateTime, filetime.dwLowDateTime,
|
||||
detail->InfDate.dwHighDateTime, detail->InfDate.dwLowDateTime);
|
||||
ok(!strcmp(detail->SectionName, "install1"), "Got section name %s.\n", debugstr_a(detail->SectionName));
|
||||
ok(!stricmp(detail->InfFileName, short_path), "Got INF file name %s.\n", debugstr_a(detail->InfFileName));
|
||||
ok(!strcmp(detail->DrvDescription, "desc1"), "Got description %s.\n", debugstr_a(detail->DrvDescription));
|
||||
ok(!detail->CompatIDsOffset, "Got wrong compat IDs offset %u.\n", detail->CompatIDsOffset);
|
||||
ok(!detail->CompatIDsLength, "Got wrong compat IDs length %u.\n", detail->CompatIDsLength);
|
||||
ok(!memcmp(detail->HardwareID, "bogus_hardware_id\0", sizeof("bogus_hardware_id\0")), "Got wrong ID list.\n");
|
||||
|
||||
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 1, &driver);
|
||||
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
|
||||
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
|
||||
|
@ -2421,6 +2498,19 @@ static void test_driver_list(void)
|
|||
ok(!strcmp(driver.Description, "desc4"), "Got wrong description '%s'.\n", driver.Description);
|
||||
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
|
||||
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
|
||||
ret = SetupDiGetDriverInfoDetailA(set, &device, &driver, detail, sizeof(detail_buffer), NULL);
|
||||
ok(ret, "Failed to get driver details, error %#x.\n", GetLastError());
|
||||
ok(detail->InfDate.dwHighDateTime == filetime.dwHighDateTime
|
||||
&& detail->InfDate.dwLowDateTime == filetime.dwLowDateTime,
|
||||
"Expected %#x%08x, got %#x%08x.\n", filetime.dwHighDateTime, filetime.dwLowDateTime,
|
||||
detail->InfDate.dwHighDateTime, detail->InfDate.dwLowDateTime);
|
||||
ok(!detail->SectionName[0], "Got section name %s.\n", debugstr_a(detail->SectionName));
|
||||
ok(!stricmp(detail->InfFileName, short_path), "Got INF file name %s.\n", debugstr_a(detail->InfFileName));
|
||||
ok(!strcmp(detail->DrvDescription, "desc4"), "Got description %s.\n", debugstr_a(detail->DrvDescription));
|
||||
ok(detail->CompatIDsOffset == sizeof("wrong_hardware_id"), "Got wrong compat IDs offset %u.\n", detail->CompatIDsOffset);
|
||||
ok(detail->CompatIDsLength == sizeof("bogus_compat_id\0"), "Got wrong compat IDs length %u.\n", detail->CompatIDsLength);
|
||||
ok(!memcmp(detail->HardwareID, "wrong_hardware_id\0bogus_compat_id\0",
|
||||
sizeof("wrong_hardware_id\0bogus_compat_id\0")), "Got wrong ID list.\n");
|
||||
|
||||
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 3, &driver);
|
||||
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
|
||||
|
|
Loading…
Reference in New Issue