From: Tuomas Räsänen tuomas.rasanen@opinsys.fi
Previously, SetupDiGetINFClassW read INF files withGetPrivateProfileString, which does not substitute %strkey% tokens.
This caused device installation to fail for devices which had driver INF files using %strkey% tokens in Version section.
An example of such device is Vernier LabQuest Mini (08f7:0008) for which Vernier's LoggerPro application includes a driver.
The INF file in question adds a new device setup class and has following entries in Version section:
Class = %ClassName% ClassGuid = %DeviceClassGUID%
Strings section includes following entries:
DeviceClassGUID = "{6B8429BF-10AD-4b66-9FBA-2FE72B891721}" ClassName = "VST_WinUSB"
Previously, when LoggerPro was installed and LabQuest Mini was hotplugged, device installation failed with the following error:
fixme:setupapi:SetupDiGetINFClassW failed to convert "L"%DeviceClassGUID"" into a guid
This caused GUID_NULL to be used and Class was not set to the registry for the device.
With this commit, correct class GUID and names are set to the device registry entry.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56579 --- dlls/setupapi/devinst.c | 68 ++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 14 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 7e2d683daa6..95edec17137 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -4280,8 +4280,11 @@ BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name, DWORD size, PDWORD required_size) { BOOL have_guid, have_name; - DWORD dret; + DWORD class_name_len; WCHAR buffer[MAX_PATH]; + INFCONTEXT inf_ctx; + HINF hinf; + BOOL retval = FALSE;
if (!inf) { @@ -4302,30 +4305,64 @@ BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name, return FALSE; }
- if (!GetPrivateProfileStringW(Version, Signature, NULL, buffer, MAX_PATH, inf)) + if ((hinf = SetupOpenInfFileW(inf, NULL, INF_STYLE_WIN4, NULL)) == INVALID_HANDLE_VALUE) + { + ERR("failed to open INF file %s\n", debugstr_w(inf)); return FALSE; + } + + if (!SetupFindFirstLineW(hinf, Version, Signature, &inf_ctx)) + { + ERR("INF file %s does not have mandatory [Version].Signature\n", debugstr_w(inf)); + goto out; + } + + if (!SetupGetStringFieldW(&inf_ctx, 1, buffer, ARRAY_SIZE(buffer), NULL)) + { + ERR("failed to get [Version].Signature string from %s\n", debugstr_w(inf)); + goto out; + }
if (lstrcmpiW(buffer, Chicago) && lstrcmpiW(buffer, WindowsNT)) - return FALSE; + { + ERR("INF file %s has invalid [Version].Signature: %s\n", debugstr_w(inf), debugstr_w(buffer)); + goto out; + } + + have_guid = SetupFindFirstLineW(hinf, Version, ClassGUID, &inf_ctx);
- buffer[0] = '\0'; - have_guid = 0 < GetPrivateProfileStringW(Version, ClassGUID, NULL, buffer, MAX_PATH, inf); if (have_guid) { + if (!SetupGetStringFieldW(&inf_ctx, 1, buffer, ARRAY_SIZE(buffer), NULL)) + { + ERR("failed to get [Version].ClassGUID as a string from '%s'\n", debugstr_w(inf)); + goto out; + } + buffer[lstrlenW(buffer)-1] = 0; if (RPC_S_OK != UuidFromStringW(buffer + 1, class_guid)) { - FIXME("failed to convert "%s" into a guid\n", debugstr_w(buffer)); + ERR("INF file %s has invalid [Version].ClassGUID: %s\n", debugstr_w(inf), debugstr_w(buffer)); SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + goto out; } }
- buffer[0] = '\0'; - dret = GetPrivateProfileStringW(Version, Class, NULL, buffer, MAX_PATH, inf); - have_name = 0 < dret; + have_name = SetupFindFirstLineW(hinf, Version, Class, &inf_ctx);
- if (dret >= MAX_PATH -1) FIXME("buffer might be too small\n"); + class_name_len = 0; + if (have_name) + { + if (!SetupGetStringFieldW(&inf_ctx, 1, buffer, ARRAY_SIZE(buffer), NULL)) + { + ERR("failed to get [Version].Class as a string from '%s'\n", debugstr_w(inf)); + goto out; + } + + class_name_len = lstrlenW(buffer); + } + + if (class_name_len >= MAX_PATH - 1) FIXME("buffer might be too small\n"); if (have_guid && !have_name) { class_name[0] = '\0'; @@ -4334,7 +4371,7 @@ BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name,
if (have_name) { - if (dret < size) lstrcpyW(class_name, buffer); + if (class_name_len < size) lstrcpyW(class_name, buffer); else { SetLastError(ERROR_INSUFFICIENT_BUFFER); @@ -4342,9 +4379,12 @@ BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name, } }
- if (required_size) *required_size = dret + ((dret) ? 1 : 0); + if (required_size) *required_size = class_name_len + ((class_name_len) ? 1 : 0);
- return (have_guid || have_name); + retval = (have_guid || have_name); +out: + SetupCloseInfFile(hinf); + return retval; }
static LSTATUS get_device_property(struct device *device, const DEVPROPKEY *prop_key, DEVPROPTYPE *prop_type,