From 7b66dbbc92156ac7cc2cb43cae77ff1ed2f3463b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Fri, 2 Jun 2006 09:06:05 +0000 Subject: [PATCH] Extract some code from devinst.c to new files: devclass.c (device class functions), driver.c (Driver install/enumeration functions), interface.c (Interface install/enumeration functions) devinst.c is now 123 Kb instead of 285 Kb. No code change. svn path=/trunk/; revision=22172 --- reactos/dll/win32/setupapi/devclass.c | 2219 ++++++++ reactos/dll/win32/setupapi/devinst.c | 4742 +---------------- reactos/dll/win32/setupapi/driver.c | 1852 +++++++ reactos/dll/win32/setupapi/interface.c | 689 +++ reactos/dll/win32/setupapi/misc.c | 74 + reactos/dll/win32/setupapi/setupapi.rbuild | 3 + reactos/dll/win32/setupapi/setupapi_private.h | 55 +- 7 files changed, 4892 insertions(+), 4742 deletions(-) create mode 100644 reactos/dll/win32/setupapi/devclass.c create mode 100644 reactos/dll/win32/setupapi/driver.c create mode 100644 reactos/dll/win32/setupapi/interface.c diff --git a/reactos/dll/win32/setupapi/devclass.c b/reactos/dll/win32/setupapi/devclass.c new file mode 100644 index 00000000000..d4979089337 --- /dev/null +++ b/reactos/dll/win32/setupapi/devclass.c @@ -0,0 +1,2219 @@ +/* + * SetupAPI device class-related functions + * + * Copyright 2000 Andreas Mohr for CodeWeavers + * 2005-2006 Hervé Poussineau (hpoussin@reactos.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "setupapi_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/* Unicode constants */ +static const WCHAR BackSlash[] = {'\\',0}; +static const WCHAR Class[] = {'C','l','a','s','s',0}; +static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; +static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0}; +static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0}; +static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0}; +static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; + +typedef BOOL +(WINAPI* PROPERTY_PAGE_PROVIDER) ( + IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest, + IN LPFNADDPROPSHEETPAGE fAddFunc, + IN LPARAM lParam); +typedef BOOL +(*UPDATE_CLASS_PARAM_HANDLER) ( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, + IN DWORD ClassInstallParamsSize); + +static BOOL +PropertyChangeHandler( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, + IN DWORD ClassInstallParamsSize); + +static const UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = { + NULL, /* DIF_SELECTDEVICE */ + NULL, /* DIF_INSTALLDEVICE */ + NULL, /* DIF_ASSIGNRESOURCES */ + NULL, /* DIF_PROPERTIES */ + NULL, /* DIF_REMOVE */ + NULL, /* DIF_FIRSTTIMESETUP */ + NULL, /* DIF_FOUNDDEVICE */ + NULL, /* DIF_SELECTCLASSDRIVERS */ + NULL, /* DIF_VALIDATECLASSDRIVERS */ + NULL, /* DIF_INSTALLCLASSDRIVERS */ + NULL, /* DIF_CALCDISKSPACE */ + NULL, /* DIF_DESTROYPRIVATEDATA */ + NULL, /* DIF_VALIDATEDRIVER */ + NULL, /* DIF_MOVEDEVICE */ + NULL, /* DIF_DETECT */ + NULL, /* DIF_INSTALLWIZARD */ + NULL, /* DIF_DESTROYWIZARDDATA */ + PropertyChangeHandler, /* DIF_PROPERTYCHANGE */ + NULL, /* DIF_ENABLECLASS */ + NULL, /* DIF_DETECTVERIFY */ + NULL, /* DIF_INSTALLDEVICEFILES */ + NULL, /* DIF_UNREMOVE */ + NULL, /* DIF_SELECTBESTCOMPATDRV */ + NULL, /* DIF_ALLOW_INSTALL */ + NULL, /* DIF_REGISTERDEVICE */ + NULL, /* DIF_NEWDEVICEWIZARD_PRESELECT */ + NULL, /* DIF_NEWDEVICEWIZARD_SELECT */ + NULL, /* DIF_NEWDEVICEWIZARD_PREANALYZE */ + NULL, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */ + NULL, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */ + NULL, /* DIF_UNUSED1 */ + NULL, /* DIF_INSTALLINTERFACES */ + NULL, /* DIF_DETECTCANCEL */ + NULL, /* DIF_REGISTER_COINSTALLERS */ + NULL, /* DIF_ADDPROPERTYPAGE_ADVANCED */ + NULL, /* DIF_ADDPROPERTYPAGE_BASIC */ + NULL, /* DIF_RESERVED1 */ + NULL, /* DIF_TROUBLESHOOTER */ + NULL, /* DIF_POWERMESSAGEWAKE */ + NULL, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */ + NULL, /* DIF_UPDATEDRIVER_UI */ + NULL /* DIF_RESERVED2 */ +}; + + +/*********************************************************************** + * SetupDiBuildClassInfoList (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiBuildClassInfoList( + IN DWORD Flags, + OUT LPGUID ClassGuidList OPTIONAL, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize) +{ + TRACE("\n"); + return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiBuildClassInfoListExA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiBuildClassInfoListExA( + IN DWORD Flags, + OUT LPGUID ClassGuidList OPTIONAL, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + LPWSTR MachineNameW = NULL; + BOOL bResult; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) return FALSE; + } + + bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, + ClassGuidListSize, RequiredSize, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return bResult; +} + +/*********************************************************************** + * SetupDiBuildClassInfoListExW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiBuildClassInfoListExW( + IN DWORD Flags, + OUT LPGUID ClassGuidList OPTIONAL, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + WCHAR szKeyName[MAX_GUID_STRING_LEN + 1]; + HKEY hClassesKey = INVALID_HANDLE_VALUE; + HKEY hClassKey = NULL; + DWORD dwLength; + DWORD dwIndex; + LONG lError; + DWORD dwGuidListIndex = 0; + BOOL ret = FALSE; + + TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList, + ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); + + if (RequiredSize != NULL) + *RequiredSize = 0; + + hClassesKey = SetupDiOpenClassRegKeyExW(NULL, + KEY_ENUMERATE_SUB_KEYS, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hClassesKey == INVALID_HANDLE_VALUE) + goto cleanup; + + for (dwIndex = 0; ; dwIndex++) + { + dwLength = MAX_GUID_STRING_LEN + 1; + lError = RegEnumKeyExW(hClassesKey, + dwIndex, + szKeyName, + &dwLength, + NULL, + NULL, + NULL, + NULL); + TRACE("RegEnumKeyExW() returns %ld\n", lError); + if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) + { + TRACE("Key name: %s\n", debugstr_w(szKeyName)); + + if (hClassKey != NULL) + RegCloseKey(hClassKey); + if (RegOpenKeyExW(hClassesKey, + szKeyName, + 0, + KEY_QUERY_VALUE, + &hClassKey) != ERROR_SUCCESS) + { + goto cleanup; + } + + if (RegQueryValueExW(hClassKey, + REGSTR_VAL_NOUSECLASS, + NULL, + NULL, + NULL, + NULL) == ERROR_SUCCESS) + { + TRACE("'NoUseClass' value found!\n"); + continue; + } + + if ((Flags & DIBCI_NOINSTALLCLASS) && + (!RegQueryValueExW(hClassKey, + REGSTR_VAL_NOINSTALLCLASS, + NULL, + NULL, + NULL, + NULL))) + { + TRACE("'NoInstallClass' value found!\n"); + continue; + } + + if ((Flags & DIBCI_NODISPLAYCLASS) && + (!RegQueryValueExW(hClassKey, + REGSTR_VAL_NODISPLAYCLASS, + NULL, + NULL, + NULL, + NULL))) + { + TRACE("'NoDisplayClass' value found!\n"); + continue; + } + + TRACE("Guid: %s\n", debugstr_w(szKeyName)); + if (dwGuidListIndex < ClassGuidListSize) + { + if (szKeyName[0] == L'{' && szKeyName[37] == L'}') + szKeyName[37] = 0; + TRACE("Guid: %s\n", debugstr_w(&szKeyName[1])); + + UuidFromStringW(&szKeyName[1], + &ClassGuidList[dwGuidListIndex]); + } + + dwGuidListIndex++; + } + + if (lError != ERROR_SUCCESS) + break; + } + + if (RequiredSize != NULL) + *RequiredSize = dwGuidListIndex; + + if (ClassGuidListSize < dwGuidListIndex) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + else + ret = TRUE; + +cleanup: + if (hClassesKey != INVALID_HANDLE_VALUE) + RegCloseKey(hClassesKey); + if (hClassKey != NULL) + RegCloseKey(hClassKey); + return ret; +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassGuidsFromNameA( + IN PCSTR ClassName, + OUT LPGUID ClassGuidList, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize) +{ + return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassGuidsFromNameW( + IN PCWSTR ClassName, + OUT LPGUID ClassGuidList, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize) +{ + return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameExA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassGuidsFromNameExA( + IN PCSTR ClassName, + OUT LPGUID ClassGuidList, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + LPWSTR ClassNameW = NULL; + LPWSTR MachineNameW = NULL; + BOOL bResult; + + TRACE("\n"); + + ClassNameW = MultiByteToUnicode(ClassName, CP_ACP); + if (ClassNameW == NULL) + return FALSE; + + if (MachineNameW) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + { + MyFree(ClassNameW); + return FALSE; + } + } + + bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, + ClassGuidListSize, RequiredSize, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + MyFree(ClassNameW); + + return bResult; +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameExW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassGuidsFromNameExW( + IN PCWSTR ClassName, + OUT LPGUID ClassGuidList, + IN DWORD ClassGuidListSize, + OUT PDWORD RequiredSize, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + WCHAR szKeyName[MAX_GUID_STRING_LEN + 1]; + WCHAR szClassName[256]; + HKEY hClassesKey = INVALID_HANDLE_VALUE; + HKEY hClassKey = NULL; + DWORD dwLength; + DWORD dwIndex; + LONG lError; + DWORD dwGuidListIndex = 0; + BOOL ret = FALSE; + + TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList, + ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); + + if (RequiredSize != NULL) + *RequiredSize = 0; + + hClassesKey = SetupDiOpenClassRegKeyExW(NULL, + KEY_ENUMERATE_SUB_KEYS, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hClassesKey == INVALID_HANDLE_VALUE) + goto cleanup; + + for (dwIndex = 0; ; dwIndex++) + { + dwLength = MAX_GUID_STRING_LEN + 1; + lError = RegEnumKeyExW(hClassesKey, + dwIndex, + szKeyName, + &dwLength, + NULL, + NULL, + NULL, + NULL); + TRACE("RegEnumKeyExW() returns %ld\n", lError); + if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) + { + TRACE("Key name: %s\n", debugstr_w(szKeyName)); + + if (hClassKey != NULL) + RegCloseKey(hClassKey); + if (RegOpenKeyExW(hClassesKey, + szKeyName, + 0, + KEY_QUERY_VALUE, + &hClassKey) != ERROR_SUCCESS) + { + goto cleanup; + } + + dwLength = 256 * sizeof(WCHAR); + if (RegQueryValueExW(hClassKey, + Class, + NULL, + NULL, + (LPBYTE)szClassName, + &dwLength) == ERROR_SUCCESS) + { + TRACE("Class name: %s\n", debugstr_w(szClassName)); + + if (strcmpiW(szClassName, ClassName) == 0) + { + TRACE("Found matching class name\n"); + + TRACE("Guid: %s\n", debugstr_w(szKeyName)); + if (dwGuidListIndex < ClassGuidListSize) + { + if (szKeyName[0] == L'{' && szKeyName[37] == L'}') + szKeyName[37] = 0; + TRACE("Guid: %s\n", debugstr_w(&szKeyName[1])); + + UuidFromStringW(&szKeyName[1], + &ClassGuidList[dwGuidListIndex]); + } + + dwGuidListIndex++; + } + } + } + + if (lError != ERROR_SUCCESS) + break; + } + + if (RequiredSize != NULL) + *RequiredSize = dwGuidListIndex; + + if (ClassGuidListSize < dwGuidListIndex) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + else + ret = TRUE; + +cleanup: + if (hClassesKey != INVALID_HANDLE_VALUE) + RegCloseKey(hClassesKey); + if (hClassKey != NULL) + RegCloseKey(hClassKey); + return ret; +} + +/*********************************************************************** + * SetupDiClassNameFromGuidA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassNameFromGuidA( + IN CONST GUID* ClassGuid, + OUT PSTR ClassName, + IN DWORD ClassNameSize, + OUT PDWORD RequiredSize OPTIONAL) +{ + return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, + ClassNameSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassNameFromGuidW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassNameFromGuidW( + IN CONST GUID* ClassGuid, + OUT PWSTR ClassName, + IN DWORD ClassNameSize, + OUT PDWORD RequiredSize OPTIONAL) +{ + return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, + ClassNameSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassNameFromGuidExA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassNameFromGuidExA( + IN CONST GUID* ClassGuid, + OUT PSTR ClassName, + IN DWORD ClassNameSize, + OUT PDWORD RequiredSize OPTIONAL, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; + LPWSTR MachineNameW = NULL; + BOOL ret; + + if (MachineName) + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, + NULL, MachineNameW, Reserved); + if (ret) + { + int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, + ClassNameSize, NULL, NULL); + + if (!ClassNameSize && RequiredSize) + *RequiredSize = len; + } + MyFree(MachineNameW); + return ret; +} + +/*********************************************************************** + * SetupDiClassNameFromGuidExW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiClassNameFromGuidExW( + IN CONST GUID* ClassGuid, + OUT PWSTR ClassName, + IN DWORD ClassNameSize, + OUT PDWORD RequiredSize OPTIONAL, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + HKEY hKey; + DWORD dwLength; + LONG rc; + BOOL ret = FALSE; + + TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName, + ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved); + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, + KEY_QUERY_VALUE, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hKey == INVALID_HANDLE_VALUE) + goto cleanup; + + if (RequiredSize != NULL) + { + dwLength = 0; + rc = RegQueryValueExW(hKey, + Class, + NULL, + NULL, + NULL, + &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + + *RequiredSize = dwLength / sizeof(WCHAR); + } + + dwLength = ClassNameSize * sizeof(WCHAR); + rc = RegQueryValueExW(hKey, + Class, + NULL, + NULL, + (LPBYTE)ClassName, + &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + + ret = TRUE; + +cleanup: + if (hKey != INVALID_HANDLE_VALUE) + RegCloseKey(hKey); + return ret; +} + +/*********************************************************************** + * SetupDiGetClassDescriptionA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassDescriptionA( + IN CONST GUID *ClassGuid, + OUT PSTR ClassDescription, + IN DWORD ClassDescriptionSize, + OUT PDWORD RequiredSize OPTIONAL) +{ + return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, + ClassDescriptionSize, + RequiredSize, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassDescriptionW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassDescriptionW( + IN CONST GUID *ClassGuid, + OUT PWSTR ClassDescription, + IN DWORD ClassDescriptionSize, + OUT PDWORD RequiredSize OPTIONAL) +{ + return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, + ClassDescriptionSize, + RequiredSize, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassDescriptionExA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassDescriptionExA( + IN CONST GUID *ClassGuid, + OUT PSTR ClassDescription, + IN DWORD ClassDescriptionSize, + OUT PDWORD RequiredSize OPTIONAL, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + PWCHAR ClassDescriptionW; + LPWSTR MachineNameW = NULL; + BOOL ret; + + TRACE("\n"); + if (ClassDescriptionSize > 0) + { + ClassDescriptionW = HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize * sizeof(WCHAR)); + if (!ClassDescriptionW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = FALSE; + goto end; + } + } + else + ClassDescriptionW = NULL; + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (!MachineNameW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = FALSE; + goto end; + } + } + + ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, ClassDescriptionSize * sizeof(WCHAR), + NULL, MachineNameW, Reserved); + if (ret) + { + int len = WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription, + ClassDescriptionSize, NULL, NULL); + + if (!ClassDescriptionSize && RequiredSize) + *RequiredSize = len; + } + +end: + HeapFree(GetProcessHeap(), 0, ClassDescriptionW); + MyFree(MachineNameW); + return ret; +} + +/*********************************************************************** + * SetupDiGetClassDescriptionExW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassDescriptionExW( + IN CONST GUID *ClassGuid, + OUT PWSTR ClassDescription, + IN DWORD ClassDescriptionSize, + OUT PDWORD RequiredSize OPTIONAL, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + HKEY hKey = INVALID_HANDLE_VALUE; + DWORD dwLength; + BOOL ret = FALSE; + + TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription, + ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved); + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, + KEY_QUERY_VALUE, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hKey == INVALID_HANDLE_VALUE) + { + WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError()); + goto cleanup; + } + + if (RequiredSize != NULL) + { + dwLength = 0; + if (RegQueryValueExW(hKey, + NULL, + NULL, + NULL, + NULL, + &dwLength) != ERROR_SUCCESS) + { + goto cleanup; + } + + *RequiredSize = dwLength / sizeof(WCHAR); + } + + dwLength = ClassDescriptionSize * sizeof(WCHAR); + if (RegQueryValueExW(hKey, + NULL, + NULL, + NULL, + (LPBYTE)ClassDescription, + &dwLength) != ERROR_SUCCESS) + { + goto cleanup; + } + + ret = TRUE; + +cleanup: + if (hKey != INVALID_HANDLE_VALUE) + RegCloseKey(hKey); + + return ret; +} + +/*********************************************************************** + * SetupDiGetClassDevsA (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiGetClassDevsA( + IN CONST GUID *ClassGuid OPTIONAL, + IN PCSTR Enumerator OPTIONAL, + IN HWND hwndParent OPTIONAL, + IN DWORD Flags) +{ + return SetupDiGetClassDevsExA(ClassGuid, Enumerator, hwndParent, + Flags, NULL, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassDevsW (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiGetClassDevsW( + IN CONST GUID *ClassGuid OPTIONAL, + IN PCWSTR Enumerator OPTIONAL, + IN HWND hwndParent OPTIONAL, + IN DWORD Flags) +{ + return SetupDiGetClassDevsExW(ClassGuid, Enumerator, hwndParent, + Flags, NULL, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassDevsExA (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiGetClassDevsExA( + IN CONST GUID *ClassGuid OPTIONAL, + IN PCSTR Enumerator OPTIONAL, + IN HWND hwndParent OPTIONAL, + IN DWORD Flags, + IN HDEVINFO DeviceInfoSet OPTIONAL, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + HDEVINFO ret; + LPWSTR enumstrW = NULL; + LPWSTR machineW = NULL; + + if (Enumerator) + { + int len = MultiByteToWideChar(CP_ACP, 0, Enumerator, -1, NULL, 0); + enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!enumstrW) + { + ret = (HDEVINFO)INVALID_HANDLE_VALUE; + goto end; + } + MultiByteToWideChar(CP_ACP, 0, Enumerator, -1, enumstrW, len); + } + if (MachineName) + { + int len = MultiByteToWideChar(CP_ACP, 0, MachineName, -1, NULL, 0); + machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!machineW) + { + ret = (HDEVINFO)INVALID_HANDLE_VALUE; + goto end; + } + MultiByteToWideChar(CP_ACP, 0, MachineName, -1, machineW, len); + } + ret = SetupDiGetClassDevsExW(ClassGuid, enumstrW, hwndParent, Flags, DeviceInfoSet, machineW, Reserved); + +end: + HeapFree(GetProcessHeap(), 0, enumstrW); + HeapFree(GetProcessHeap(), 0, machineW); + return ret; +} + +/*********************************************************************** + * Helper functions for SetupDiGetClassDevsExW + */ +static LONG +SETUP_CreateDevListFromEnumerator( + struct DeviceInfoSet *list, + CONST GUID *pClassGuid OPTIONAL, + LPCWSTR Enumerator, + HKEY hEnumeratorKey) /* handle to Enumerator registry key */ +{ + HKEY hDeviceIdKey = NULL, hInstanceIdKey; + WCHAR KeyBuffer[MAX_PATH]; + WCHAR InstancePath[MAX_PATH]; + LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */ + struct DeviceInfoElement *deviceInfo; + DWORD i = 0, j; + DWORD dwLength, dwRegType; + DWORD rc; + + /* Enumerate device IDs (subkeys of hEnumeratorKey) */ + while (TRUE) + { + dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); + rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); + if (rc == ERROR_NO_MORE_ITEMS) + break; + if (rc != ERROR_SUCCESS) + goto cleanup; + i++; + + /* Open device id sub key */ + if (hDeviceIdKey != NULL) + RegCloseKey(hDeviceIdKey); + rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + strcpyW(InstancePath, Enumerator); + strcatW(InstancePath, BackSlash); + strcatW(InstancePath, KeyBuffer); + strcatW(InstancePath, BackSlash); + pEndOfInstancePath = &InstancePath[strlenW(InstancePath)]; + + /* Enumerate instance IDs (subkeys of hDeviceIdKey) */ + j = 0; + while (TRUE) + { + GUID KeyGuid; + + dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); + rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); + if (rc == ERROR_NO_MORE_ITEMS) + break; + if (rc != ERROR_SUCCESS) + goto cleanup; + j++; + + /* Open instance id sub key */ + rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + *pEndOfInstancePath = '\0'; + strcatW(InstancePath, KeyBuffer); + + /* Read ClassGUID value */ + dwLength = sizeof(KeyBuffer) - sizeof(WCHAR); + rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength); + RegCloseKey(hInstanceIdKey); + if (rc == ERROR_FILE_NOT_FOUND) + { + if (pClassGuid) + /* Skip this bad entry as we can't verify it */ + continue; + /* Set a default GUID for this device */ + memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID)); + } + else if (rc != ERROR_SUCCESS) + { + goto cleanup; + } + else if (dwRegType != REG_SZ) + { + rc = ERROR_GEN_FAILURE; + goto cleanup; + } + else + { + KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */ + if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK) + /* Bad GUID, skip the entry */ + continue; + } + + if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid)) + { + /* Skip this entry as it is not the right device class */ + continue; + } + + /* Add the entry to the list */ + if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo)) + { + rc = GetLastError(); + goto cleanup; + } + TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath), list); + InsertTailList(&list->ListHead, &deviceInfo->ListEntry); + } + } + + rc = ERROR_SUCCESS; + +cleanup: + if (hDeviceIdKey != NULL) + RegCloseKey(hDeviceIdKey); + return rc; +} + +static LONG +SETUP_CreateDevList( + struct DeviceInfoSet *list, + PCWSTR MachineName OPTIONAL, + CONST GUID *class OPTIONAL, + PCWSTR Enumerator OPTIONAL) +{ + HKEY HKLM = HKEY_LOCAL_MACHINE; + HKEY hEnumKey = NULL; + HKEY hEnumeratorKey = NULL; + WCHAR KeyBuffer[MAX_PATH]; + DWORD i; + DWORD dwLength; + DWORD rc; + + if (class && IsEqualIID(class, &GUID_NULL)) + class = NULL; + + /* Open Enum key (if applicable) */ + if (MachineName != NULL) + { + rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); + if (rc != ERROR_SUCCESS) + goto cleanup; + } + + rc = RegOpenKeyExW( + HKLM, + REGSTR_PATH_SYSTEMENUM, + 0, + KEY_ENUMERATE_SUB_KEYS, + &hEnumKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + + /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator. + * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator + * for each one. + */ + if (Enumerator) + { + rc = RegOpenKeyExW( + hEnumKey, + Enumerator, + 0, + KEY_ENUMERATE_SUB_KEYS, + &hEnumeratorKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey); + } + else + { + /* Enumerate enumerators */ + i = 0; + while (TRUE) + { + dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); + rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); + if (rc == ERROR_NO_MORE_ITEMS) + break; + else if (rc != ERROR_SUCCESS) + goto cleanup; + i++; + + /* Open sub key */ + if (hEnumeratorKey != NULL) + RegCloseKey(hEnumeratorKey); + rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + + /* Call SETUP_CreateDevListFromEnumerator */ + rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + } + rc = ERROR_SUCCESS; + } + +cleanup: + if (HKLM != HKEY_LOCAL_MACHINE) + RegCloseKey(HKLM); + if (hEnumKey != NULL) + RegCloseKey(hEnumKey); + if (hEnumeratorKey != NULL) + RegCloseKey(hEnumeratorKey); + return rc; +} + +/*********************************************************************** + * SetupDiGetClassDevsExW (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiGetClassDevsExW( + IN CONST GUID *ClassGuid OPTIONAL, + IN PCWSTR Enumerator OPTIONAL, + IN HWND hwndParent OPTIONAL, + IN DWORD Flags, + IN HDEVINFO DeviceInfoSet OPTIONAL, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; + struct DeviceInfoSet *list; + CONST GUID *pClassGuid; + LONG rc; + HDEVINFO ret = INVALID_HANDLE_VALUE; + + TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(ClassGuid), debugstr_w(Enumerator), + hwndParent, Flags, DeviceInfoSet, debugstr_w(MachineName), Reserved); + + /* Create the deviceset if not set */ + if (DeviceInfoSet) + { + list = (struct DeviceInfoSet *)DeviceInfoSet; + if (list->magic != SETUP_DEV_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + goto cleanup; + } + hDeviceInfo = DeviceInfoSet; + } + else + { + hDeviceInfo = SetupDiCreateDeviceInfoListExW( + Flags & DIGCF_DEVICEINTERFACE ? NULL : ClassGuid, + NULL, MachineName, NULL); + if (hDeviceInfo == INVALID_HANDLE_VALUE) + goto cleanup; + list = (struct DeviceInfoSet *)hDeviceInfo; + } + + if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) + pClassGuid = NULL; + else + pClassGuid = &list->ClassGuid; + + if (Flags & DIGCF_PROFILE) + FIXME(": flag DIGCF_PROFILE ignored\n"); + + if (Flags & DIGCF_ALLCLASSES) + { + rc = SETUP_CreateDevList(list, MachineName, pClassGuid, Enumerator); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + ret = hDeviceInfo; + } + else if (Flags & DIGCF_DEVICEINTERFACE) + { + if (ClassGuid == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + goto cleanup; + } + + rc = SETUP_CreateInterfaceList(list, MachineName, ClassGuid, Enumerator, Flags & DIGCF_PRESENT); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + ret = hDeviceInfo; + } + else + { + rc = SETUP_CreateDevList(list, MachineName, ClassGuid, Enumerator); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + ret = hDeviceInfo; + } + +cleanup: + if (!DeviceInfoSet && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != ret) + SetupDiDestroyDeviceInfoList(hDeviceInfo); + return ret; +} + +/*********************************************************************** + * SetupDiGetClassImageIndex (SETUPAPI.@) + */ +static BOOL +GetIconIndex( + IN HKEY hClassKey, + OUT PINT ImageIndex) +{ + LPWSTR Buffer = NULL; + DWORD dwRegType, dwLength; + LONG rc; + BOOL ret = FALSE; + + /* Read icon registry key */ + rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } else if (dwRegType != REG_SZ) + { + SetLastError(ERROR_INVALID_INDEX); + goto cleanup; + } + Buffer = MyMalloc(dwLength + sizeof(WCHAR)); + if (!Buffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + /* make sure the returned buffer is NULL-terminated */ + Buffer[dwLength / sizeof(WCHAR)] = 0; + + /* Transform icon value to a INT */ + *ImageIndex = atoiW(Buffer); + ret = TRUE; + +cleanup: + MyFree(Buffer); + return ret; +} + +BOOL WINAPI +SetupDiGetClassImageIndex( + IN PSP_CLASSIMAGELIST_DATA ClassImageListData, + IN CONST GUID *ClassGuid, + OUT PINT ImageIndex) +{ + struct ClassImageList *list; + BOOL ret = FALSE; + + TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex); + + if (!ClassImageListData || !ClassGuid || !ImageIndex) + SetLastError(ERROR_INVALID_PARAMETER); + else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (!ImageIndex) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + HKEY hKey = INVALID_HANDLE_VALUE; + INT iconIndex; + + /* Read Icon registry entry into Buffer */ + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL); + if (hKey == INVALID_HANDLE_VALUE) + goto cleanup; + if (!GetIconIndex(hKey, &iconIndex)) + goto cleanup; + + if (iconIndex >= 0) + { + SetLastError(ERROR_INVALID_INDEX); + goto cleanup; + } + + *ImageIndex = -iconIndex; + ret = TRUE; + +cleanup: + if (hKey != INVALID_HANDLE_VALUE) + RegCloseKey(hKey); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetClassImageList(SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassImageList( + OUT PSP_CLASSIMAGELIST_DATA ClassImageListData) +{ + return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassImageListExA(SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassImageListExA( + OUT PSP_CLASSIMAGELIST_DATA ClassImageListData, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + PWSTR MachineNameW = NULL; + BOOL ret; + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return FALSE; + } + + ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return ret; +} + +/*********************************************************************** + * SetupDiGetClassImageListExW(SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassImageListExW( + OUT PSP_CLASSIMAGELIST_DATA ClassImageListData, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + BOOL ret = FALSE; + + TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved); + + if (!ClassImageListData) + SetLastError(ERROR_INVALID_PARAMETER); + else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (Reserved) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + struct ClassImageList *list = NULL; + DWORD size; + + size = FIELD_OFFSET(struct ClassImageList, szData); + if (MachineName) + size += (strlenW(MachineName) + 3) * sizeof(WCHAR); + list = HeapAlloc(GetProcessHeap(), 0, size); + if (!list) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC; + if (MachineName) + { + list->szData[0] = list->szData[1] = '\\'; + strcpyW(list->szData + 2, MachineName); + list->MachineName = list->szData; + } + else + { + list->MachineName = NULL; + } + + ClassImageListData->Reserved = (ULONG_PTR)list; + ret = TRUE; + +cleanup: + if (!ret) + MyFree(list); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiLoadClassIcon(SETUPAPI.@) + */ +BOOL WINAPI +SetupDiLoadClassIcon( + IN CONST GUID *ClassGuid, + OUT HICON *LargeIcon OPTIONAL, + OUT PINT MiniIconIndex OPTIONAL) +{ + BOOL ret = FALSE; + + if (!ClassGuid) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + LPWSTR Buffer = NULL; + LPCWSTR DllName; + INT iconIndex; + HKEY hKey = INVALID_HANDLE_VALUE; + + hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE); + if (hKey == INVALID_HANDLE_VALUE) + goto cleanup; + + if (!GetIconIndex(hKey, &iconIndex)) + goto cleanup; + + if (iconIndex > 0) + { + /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */ + PWCHAR Comma; + LONG rc; + DWORD dwRegType, dwLength; + rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); + if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) + { + Buffer = MyMalloc(dwLength + sizeof(WCHAR)); + if (Buffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + /* make sure the returned buffer is NULL-terminated */ + Buffer[dwLength / sizeof(WCHAR)] = 0; + } + else if + (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength)) + && dwRegType == REG_SZ) + { + Buffer = MyMalloc(dwLength + sizeof(WCHAR)); + if (Buffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + /* make sure the returned buffer is NULL-terminated */ + Buffer[dwLength / sizeof(WCHAR)] = 0; + } + else + { + /* Unable to find where to load the icon */ + SetLastError(ERROR_FILE_NOT_FOUND); + goto cleanup; + } + Comma = strchrW(Buffer, ','); + if (!Comma) + { + SetLastError(ERROR_GEN_FAILURE); + goto cleanup; + } + *Comma = '\0'; + DllName = Buffer; + } + else + { + /* Look up icon in setupapi.dll */ + DllName = L"setupapi.dll"; + iconIndex = -iconIndex; + } + + TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName)); + if (LargeIcon) + { + if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1)) + { + SetLastError(ERROR_INVALID_INDEX); + goto cleanup; + } + } + if (MiniIconIndex) + *MiniIconIndex = iconIndex; + ret = TRUE; + +cleanup: + if (hKey != INVALID_HANDLE_VALUE) + RegCloseKey(hKey); + MyFree(Buffer); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiInstallClassA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallClassA( + IN HWND hwndParent OPTIONAL, + IN PCSTR InfFileName, + IN DWORD Flags, + IN HSPFILEQ FileQueue OPTIONAL) +{ + return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); +} + +/*********************************************************************** + * SetupDiInstallClassW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallClassW( + IN HWND hwndParent OPTIONAL, + IN PCWSTR InfFileName, + IN DWORD Flags, + IN HSPFILEQ FileQueue OPTIONAL) +{ + return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); +} + +/*********************************************************************** + * SetupDiInstallClassExA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallClassExA( + IN HWND hwndParent OPTIONAL, + IN PCSTR InfFileName OPTIONAL, + IN DWORD Flags, + IN HSPFILEQ FileQueue OPTIONAL, + IN CONST GUID *InterfaceClassGuid OPTIONAL, + IN PVOID Reserved1, + IN PVOID Reserved2) +{ + PWSTR InfFileNameW = NULL; + BOOL Result; + + if (InfFileName) + { + InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP); + if (InfFileNameW == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + } + + Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags, + FileQueue, InterfaceClassGuid, Reserved1, Reserved2); + + MyFree(InfFileNameW); + + return Result; +} + +/*********************************************************************** + * Helper function for SetupDiInstallClassExW + */ +static HKEY +CreateClassKey(HINF hInf) +{ + WCHAR FullBuffer[MAX_PATH]; + WCHAR Buffer[MAX_PATH]; + DWORD RequiredSize; + HKEY hClassKey = NULL; + HKEY ret = INVALID_HANDLE_VALUE; + + FullBuffer[0] = '\0'; + Buffer[0] = '\\'; + if (!SetupGetLineTextW(NULL, + hInf, + Version, + ClassGUID, + &Buffer[1], + MAX_PATH - 1, + &RequiredSize)) + { + goto cleanup; + } + + lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT); + lstrcatW(FullBuffer, Buffer); + + if (!SetupGetLineTextW(NULL, + hInf, + Version, + Class, + Buffer, + MAX_PATH, + &RequiredSize)) + { + RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer); + goto cleanup; + } + + if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE, + FullBuffer, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, + NULL, + &hClassKey, + NULL)) + { + goto cleanup; + } + + if (ERROR_SUCCESS != RegSetValueExW(hClassKey, + Class, + 0, + REG_SZ, + (LPBYTE)Buffer, + RequiredSize * sizeof(WCHAR))) + { + goto cleanup; + } + + ret = hClassKey; + +cleanup: + if (hClassKey != NULL && hClassKey != ret) + RegCloseKey(hClassKey); + if (ret == INVALID_HANDLE_VALUE && FullBuffer[0] != '\0') + RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer); + return ret; +} + +/*********************************************************************** + * SetupDiInstallClassExW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallClassExW( + IN HWND hwndParent OPTIONAL, + IN PCWSTR InfFileName OPTIONAL, + IN DWORD Flags, + IN HSPFILEQ FileQueue OPTIONAL, + IN CONST GUID *InterfaceClassGuid OPTIONAL, + IN PVOID Reserved1, + IN PVOID Reserved2) +{ + BOOL ret = FALSE; + + TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags, + FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2); + + if (!InfFileName) + { + FIXME("Case not implemented: InfFileName NULL\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + } + else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)) + { + TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)); + SetLastError(ERROR_INVALID_FLAGS); + } + else if ((Flags & DI_NOVCP) && FileQueue == NULL) + SetLastError(ERROR_INVALID_PARAMETER); + else if (Reserved1 != NULL) + SetLastError(ERROR_INVALID_PARAMETER); + else if (Reserved2 != NULL) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; + SP_DEVINSTALL_PARAMS_W InstallParams; + WCHAR SectionName[MAX_PATH]; + HINF hInf = INVALID_HANDLE_VALUE; + HKEY hRootKey = INVALID_HANDLE_VALUE; + PVOID callback_context = NULL; + + hDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL); + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); + if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams)) + goto cleanup; + InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL); + InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL); + if (Flags & DI_NOVCP) + InstallParams.FileQueue = FileQueue; + if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams)) + goto cleanup; + + /* Open the .inf file */ + hInf = SetupOpenInfFileW( + InfFileName, + NULL, + INF_STYLE_WIN4, + NULL); + if (hInf == INVALID_HANDLE_VALUE) + goto cleanup; + + /* Try to append a layout file */ + ret = SetupOpenAppendInfFileW(NULL, hInf, NULL); + if (!ret) + goto cleanup; + + if (InterfaceClassGuid) + { + /* Retrieve the actual section name */ + ret = SetupDiGetActualSectionToInstallW( + hInf, + InterfaceInstall32, + SectionName, + MAX_PATH, + NULL, + NULL); + if (!ret) + goto cleanup; + + /* Open registry key related to this interface */ + /* FIXME: What happens if the key doesn't exist? */ + hRootKey = SetupDiOpenClassRegKeyExW(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL); + if (hRootKey == INVALID_HANDLE_VALUE) + goto cleanup; + + /* SetupDiCreateDeviceInterface??? */ + FIXME("Installing an interface is not implemented\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + } + else + { + /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */ + hRootKey = CreateClassKey(hInf); + if (hRootKey == INVALID_HANDLE_VALUE) + goto cleanup; + + /* Retrieve the actual section name */ + ret = SetupDiGetActualSectionToInstallW( + hInf, + ClassInstall32, + SectionName, + MAX_PATH - strlenW(DotServices), + NULL, + NULL); + if (!ret) + goto cleanup; + + callback_context = SetupInitDefaultQueueCallback(hwndParent); + if (!callback_context) + goto cleanup; + + ret = SetupInstallFromInfSectionW( + hwndParent, + hInf, + SectionName, + SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG, + hRootKey, + NULL, /* FIXME: SourceRootPath */ + !(Flags & DI_NOVCP) && (Flags & DI_FORCECOPY) ? SP_COPY_FORCE_IN_USE : 0, /* CopyFlags */ + SetupDefaultQueueCallbackW, + callback_context, + hDeviceInfo, + NULL); + if (!ret) + goto cleanup; + + /* Install .Services section */ + lstrcatW(SectionName, DotServices); + ret = SetupInstallServicesFromInfSectionExW( + hInf, + SectionName, + 0, + hDeviceInfo, + NULL, + NULL, + NULL); + if (!ret) + goto cleanup; + + ret = TRUE; + } + +cleanup: + if (hDeviceInfo != INVALID_HANDLE_VALUE) + SetupDiDestroyDeviceInfoList(hDeviceInfo); + if (hInf != INVALID_HANDLE_VALUE) + SetupCloseInfFile(hInf); + if (hRootKey != INVALID_HANDLE_VALUE) + RegCloseKey(hRootKey); + SetupTermDefaultQueueCallback(callback_context); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiOpenClassRegKey (SETUPAPI.@) + */ +HKEY WINAPI +SetupDiOpenClassRegKey( + IN CONST GUID *ClassGuid OPTIONAL, + IN REGSAM samDesired) +{ + return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, + DIOCR_INSTALLER, NULL, NULL); +} + +/*********************************************************************** + * SetupDiOpenClassRegKeyExA (SETUPAPI.@) + */ +HKEY WINAPI +SetupDiOpenClassRegKeyExA( + IN CONST GUID *ClassGuid OPTIONAL, + IN REGSAM samDesired, + IN DWORD Flags, + IN PCSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + PWSTR MachineNameW = NULL; + HKEY hKey; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return INVALID_HANDLE_VALUE; + } + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, + Flags, MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return hKey; +} + +/*********************************************************************** + * SetupDiOpenClassRegKeyExW (SETUPAPI.@) + */ +HKEY WINAPI +SetupDiOpenClassRegKeyExW( + IN CONST GUID* ClassGuid OPTIONAL, + IN REGSAM samDesired, + IN DWORD Flags, + IN PCWSTR MachineName OPTIONAL, + IN PVOID Reserved) +{ + LPWSTR lpGuidString = NULL; + LPWSTR lpFullGuidString = NULL; + DWORD dwLength; + HKEY HKLM; + HKEY hClassesKey = NULL; + HKEY hClassKey = NULL; + HKEY ret = INVALID_HANDLE_VALUE; + DWORD rc; + LPCWSTR lpKeyName; + + TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired, + Flags, debugstr_w(MachineName), Reserved); + + if (Flags == DIOCR_INSTALLER) + lpKeyName = REGSTR_PATH_CLASS_NT; + else if (Flags == DIOCR_INTERFACE) + lpKeyName = REGSTR_PATH_DEVICE_CLASSES; + else + { + ERR("Invalid Flags parameter!\n"); + SetLastError(ERROR_INVALID_FLAGS); + goto cleanup; + } + + if (MachineName != NULL) + { + rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + } + else + HKLM = HKEY_LOCAL_MACHINE; + + rc = RegOpenKeyExW(HKLM, + lpKeyName, + 0, + ClassGuid ? 0 : samDesired, + &hClassesKey); + if (MachineName != NULL) RegCloseKey(HKLM); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + + if (ClassGuid == NULL) + { + /* Stop here. We don't need to open a subkey */ + ret = hClassesKey; + goto cleanup; + } + + if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK) + { + SetLastError(ERROR_GEN_FAILURE); + goto cleanup; + } + + dwLength = lstrlenW(lpGuidString); + lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR)); + if (!lpFullGuidString) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + lpFullGuidString[0] = '{'; + memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR)); + lpFullGuidString[dwLength + 1] = '}'; + lpFullGuidString[dwLength + 2] = '\0'; + + rc = RegOpenKeyExW(hClassesKey, + lpFullGuidString, + 0, + samDesired, + &hClassKey); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + ret = hClassKey; + +cleanup: + if (hClassKey != NULL && hClassKey != ret) + RegCloseKey(hClassKey); + if (hClassesKey != NULL && hClassesKey != ret) + RegCloseKey(hClassesKey); + if (lpGuidString) + RpcStringFreeW(&lpGuidString); + HeapFree(GetProcessHeap(), 0, lpFullGuidString); + + return ret; +} + +/*********************************************************************** + * SetupDiSetClassInstallParamsA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiSetClassInstallParamsA( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, + IN DWORD ClassInstallParamsSize) +{ + FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData, + ClassInstallParams->InstallFunction, ClassInstallParamsSize); + return FALSE; +} + +/*********************************************************************** + * Helper functions for SetupDiSetClassInstallParamsW + */ +static BOOL +PropertyChangeHandler( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData, + IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, + IN DWORD ClassInstallParamsSize) +{ + PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams; + BOOL ret = FALSE; + + if (!DeviceInfoData) + SetLastError(ERROR_INVALID_PARAMETER); + else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS)) + SetLastError(ERROR_INVALID_PARAMETER); + else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE + && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE + && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP) + SetLastError(ERROR_INVALID_FLAGS); + else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL + && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC) + SetLastError(ERROR_INVALID_FLAGS); + else if (PropChangeParams + && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP) + && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC) + SetLastError(ERROR_INVALID_USER_BUFFER); + else + { + PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams; + if (!DeviceInfoData) + { + struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet; + CurrentPropChangeParams = &list->ClassInstallParams.PropChange; + } + else + { + struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; + CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChange; + } + if (*CurrentPropChangeParams) + { + MyFree(*CurrentPropChangeParams); + *CurrentPropChangeParams = NULL; + } + if (PropChangeParams) + { + *CurrentPropChangeParams = MyMalloc(sizeof(SP_PROPCHANGE_PARAMS)); + if (!*CurrentPropChangeParams) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS)); + } + ret = TRUE; + } + +done: + return ret; +} + +/*********************************************************************** + * SetupDiSetClassInstallParamsW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiSetClassInstallParamsW( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, + IN DWORD ClassInstallParamsSize) +{ + struct DeviceInfoSet *list; + BOOL ret = FALSE; + + TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData, + ClassInstallParams, ClassInstallParamsSize); + + if (!DeviceInfoSet) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) + SetLastError(ERROR_INVALID_HANDLE); + else if ((list = (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 (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER)) + SetLastError(ERROR_INVALID_PARAMETER); + else if (!ClassInstallParams && ClassInstallParamsSize != 0) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + SP_DEVINSTALL_PARAMS_W InstallParams; + BOOL Result; + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + if (!Result) + goto done; + + if (ClassInstallParams) + { + /* Check parameters in ClassInstallParams */ + if (ClassInstallParams->InstallFunction < DIF_SELECTDEVICE + || ClassInstallParams->InstallFunction - DIF_SELECTDEVICE >= sizeof(UpdateClassInstallParamHandlers)/sizeof(UpdateClassInstallParamHandlers[0])) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + goto done; + } + else if (UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE] == NULL) + { + ERR("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams->InstallFunction); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + goto done; + } + ret = UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE](DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize); + if (!ret) + goto done; + InstallParams.Flags |= DI_CLASSINSTALLPARAMS; + } + else + { + InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS; + } + + ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + } + +done: + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassDevPropertySheetsA( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN LPPROPSHEETHEADERA PropertySheetHeader, + IN DWORD PropertySheetHeaderPageListSize, + OUT PDWORD RequiredSize OPTIONAL, + IN DWORD PropertySheetType) +{ + PROPSHEETHEADERW psh; + BOOL ret = FALSE; + + TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, + PropertySheetHeader, PropertySheetHeaderPageListSize, + RequiredSize, PropertySheetType); + + psh.dwFlags = PropertySheetHeader->dwFlags; + psh.phpage = PropertySheetHeader->phpage; + psh.nPages = PropertySheetHeader->nPages; + + ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL, + PropertySheetHeaderPageListSize, RequiredSize, + PropertySheetType); + if (ret) + { + PropertySheetHeader->nPages = psh.nPages; + } + + TRACE("Returning %d\n", ret); + return ret; +} + +struct ClassDevPropertySheetsData +{ + HPROPSHEETPAGE *PropertySheetPages; + DWORD MaximumNumberOfPages; + DWORD NumberOfPages; +}; + +static BOOL WINAPI +GetClassDevPropertySheetsCallback( + IN HPROPSHEETPAGE hPropSheetPage, + IN OUT LPARAM lParam) +{ + struct ClassDevPropertySheetsData *PropPageData; + + PropPageData = (struct ClassDevPropertySheetsData *)lParam; + + if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages) + { + *PropPageData->PropertySheetPages = hPropSheetPage; + PropPageData->PropertySheetPages++; + } + + PropPageData->NumberOfPages++; + return TRUE; +} + +/*********************************************************************** + * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetClassDevPropertySheetsW( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN OUT LPPROPSHEETHEADERW PropertySheetHeader, + IN DWORD PropertySheetHeaderPageListSize, + OUT PDWORD RequiredSize OPTIONAL, + IN DWORD PropertySheetType) +{ + struct DeviceInfoSet *list; + BOOL ret = FALSE; + + TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, + PropertySheetHeader, PropertySheetHeaderPageListSize, + RequiredSize, PropertySheetType); + + if (!DeviceInfoSet) + SetLastError(ERROR_INVALID_HANDLE); + else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) + SetLastError(ERROR_INVALID_HANDLE); + else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) + SetLastError(ERROR_INVALID_HANDLE); + else if (!PropertySheetHeader) + SetLastError(ERROR_INVALID_PARAMETER); + else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE) + SetLastError(ERROR_INVALID_FLAGS); + else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL)) + SetLastError(ERROR_INVALID_PARAMETER); + else if (!PropertySheetHeader) + SetLastError(ERROR_INVALID_PARAMETER); + else if (PropertySheetType != DIGCDP_FLAG_ADVANCED + && PropertySheetType != DIGCDP_FLAG_BASIC + && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED + && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + HKEY hKey = INVALID_HANDLE_VALUE; + SP_PROPSHEETPAGE_REQUEST Request; + LPWSTR PropPageProvider = NULL; + HMODULE hModule = NULL; + PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL; + struct ClassDevPropertySheetsData PropPageData; + DWORD dwLength, dwRegType; + DWORD rc; + + if (DeviceInfoData) + hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE); + else + { + hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE, + DIOCR_INSTALLER, list->MachineName + 2, NULL); + } + if (hKey == INVALID_HANDLE_VALUE) + goto cleanup; + + rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength); + if (rc == ERROR_FILE_NOT_FOUND) + { + /* No registry key. As it is optional, don't say it's a bad error */ + if (RequiredSize) + *RequiredSize = 0; + ret = TRUE; + goto cleanup; + } + else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ) + { + SetLastError(rc); + goto cleanup; + } + + PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR)); + if (!PropPageProvider) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength); + if (rc != ERROR_SUCCESS) + { + SetLastError(rc); + goto cleanup; + } + PropPageProvider[dwLength / sizeof(WCHAR)] = 0; + + rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider); + if (rc != ERROR_SUCCESS) + { + SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER); + goto cleanup; + } + + Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST); + Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES; + Request.DeviceInfoSet = DeviceInfoSet; + Request.DeviceInfoData = DeviceInfoData; + PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages]; + PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages; + PropPageData.NumberOfPages = 0; + ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData); + if (!ret) + goto cleanup; + + if (RequiredSize) + *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages; + if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages) + { + PropertySheetHeader->nPages += PropPageData.NumberOfPages; + ret = TRUE; + } + else + { + PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + +cleanup: + if (hKey != INVALID_HANDLE_VALUE) + RegCloseKey(hKey); + HeapFree(GetProcessHeap(), 0, PropPageProvider); + FreeFunctionPointer(hModule, pPropPageProvider); + } + + TRACE("Returning %d\n", ret); + return ret; +} diff --git a/reactos/dll/win32/setupapi/devinst.c b/reactos/dll/win32/setupapi/devinst.c index 3a17477617e..15c14ad9dd4 100644 --- a/reactos/dll/win32/setupapi/devinst.c +++ b/reactos/dll/win32/setupapi/devinst.c @@ -24,22 +24,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(setupapi); /* Unicode constants */ -static const WCHAR AddInterface[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0}; static const WCHAR BackSlash[] = {'\\',0}; static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; static const WCHAR Class[] = {'C','l','a','s','s',0}; -static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0}; -static const WCHAR Control[] = {'C','o','n','t','r','o','l',0}; -static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0}; static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0}; static const WCHAR DotHW[] = {'.','H','W',0}; -static const WCHAR DotInterfaces[] = {'.','I','n','t','e','r','f','a','c','e','s',0}; static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0}; static const WCHAR InfDirectory[] = {'i','n','f','\\',0}; -static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0}; -static const WCHAR Linked[] = {'L','i','n','k','e','d',0}; -static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; -static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0}; static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0}; @@ -47,10 +38,6 @@ static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e',' static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0}; static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0}; -static const WCHAR INF_MANUFACTURER[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; -static const WCHAR INF_PROVIDER[] = {'P','r','o','v','i','d','e','r',0}; -static const WCHAR INF_DRIVER_VER[] = {'D','r','i','v','e','r','V','e','r',0}; - typedef DWORD (CALLBACK* CLASS_INSTALL_PROC) ( IN DI_FUNCTION InstallFunction, @@ -66,17 +53,6 @@ typedef DWORD IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, IN OUT PCOINSTALLER_CONTEXT_DATA Context); -typedef BOOL -(WINAPI* PROPERTY_PAGE_PROVIDER) ( - IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest, - IN LPFNADDPROPSHEETPAGE fAddFunc, - IN LPARAM lParam); -typedef BOOL -(*UPDATE_CLASS_PARAM_HANDLER) ( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, - IN DWORD ClassInstallParamsSize); struct CoInstallerElement { @@ -98,552 +74,6 @@ struct GetSectionCallbackInfo DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5; }; -static BOOL -PropertyChangeHandler( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, - IN DWORD ClassInstallParamsSize); - -static const UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = { - NULL, /* DIF_SELECTDEVICE */ - NULL, /* DIF_INSTALLDEVICE */ - NULL, /* DIF_ASSIGNRESOURCES */ - NULL, /* DIF_PROPERTIES */ - NULL, /* DIF_REMOVE */ - NULL, /* DIF_FIRSTTIMESETUP */ - NULL, /* DIF_FOUNDDEVICE */ - NULL, /* DIF_SELECTCLASSDRIVERS */ - NULL, /* DIF_VALIDATECLASSDRIVERS */ - NULL, /* DIF_INSTALLCLASSDRIVERS */ - NULL, /* DIF_CALCDISKSPACE */ - NULL, /* DIF_DESTROYPRIVATEDATA */ - NULL, /* DIF_VALIDATEDRIVER */ - NULL, /* DIF_MOVEDEVICE */ - NULL, /* DIF_DETECT */ - NULL, /* DIF_INSTALLWIZARD */ - NULL, /* DIF_DESTROYWIZARDDATA */ - PropertyChangeHandler, /* DIF_PROPERTYCHANGE */ - NULL, /* DIF_ENABLECLASS */ - NULL, /* DIF_DETECTVERIFY */ - NULL, /* DIF_INSTALLDEVICEFILES */ - NULL, /* DIF_UNREMOVE */ - NULL, /* DIF_SELECTBESTCOMPATDRV */ - NULL, /* DIF_ALLOW_INSTALL */ - NULL, /* DIF_REGISTERDEVICE */ - NULL, /* DIF_NEWDEVICEWIZARD_PRESELECT */ - NULL, /* DIF_NEWDEVICEWIZARD_SELECT */ - NULL, /* DIF_NEWDEVICEWIZARD_PREANALYZE */ - NULL, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */ - NULL, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */ - NULL, /* DIF_UNUSED1 */ - NULL, /* DIF_INSTALLINTERFACES */ - NULL, /* DIF_DETECTCANCEL */ - NULL, /* DIF_REGISTER_COINSTALLERS */ - NULL, /* DIF_ADDPROPERTYPAGE_ADVANCED */ - NULL, /* DIF_ADDPROPERTYPAGE_BASIC */ - NULL, /* DIF_RESERVED1 */ - NULL, /* DIF_TROUBLESHOOTER */ - NULL, /* DIF_POWERMESSAGEWAKE */ - NULL, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */ - NULL, /* DIF_UPDATEDRIVER_UI */ - NULL /* DIF_RESERVED2 */ -}; - -/*********************************************************************** - * SetupDiBuildClassInfoList (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiBuildClassInfoList( - IN DWORD Flags, - OUT LPGUID ClassGuidList OPTIONAL, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize) -{ - TRACE("\n"); - return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiBuildClassInfoListExA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiBuildClassInfoListExA( - IN DWORD Flags, - OUT LPGUID ClassGuidList OPTIONAL, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - LPWSTR MachineNameW = NULL; - BOOL bResult; - - TRACE("\n"); - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) return FALSE; - } - - bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, - ClassGuidListSize, RequiredSize, - MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - return bResult; -} - -/*********************************************************************** - * SetupDiBuildClassInfoListExW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiBuildClassInfoListExW( - IN DWORD Flags, - OUT LPGUID ClassGuidList OPTIONAL, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - WCHAR szKeyName[MAX_GUID_STRING_LEN + 1]; - HKEY hClassesKey = INVALID_HANDLE_VALUE; - HKEY hClassKey = NULL; - DWORD dwLength; - DWORD dwIndex; - LONG lError; - DWORD dwGuidListIndex = 0; - BOOL ret = FALSE; - - TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList, - ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); - - if (RequiredSize != NULL) - *RequiredSize = 0; - - hClassesKey = SetupDiOpenClassRegKeyExW(NULL, - KEY_ENUMERATE_SUB_KEYS, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hClassesKey == INVALID_HANDLE_VALUE) - goto cleanup; - - for (dwIndex = 0; ; dwIndex++) - { - dwLength = MAX_GUID_STRING_LEN + 1; - lError = RegEnumKeyExW(hClassesKey, - dwIndex, - szKeyName, - &dwLength, - NULL, - NULL, - NULL, - NULL); - TRACE("RegEnumKeyExW() returns %ld\n", lError); - if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) - { - TRACE("Key name: %s\n", debugstr_w(szKeyName)); - - if (hClassKey != NULL) - RegCloseKey(hClassKey); - if (RegOpenKeyExW(hClassesKey, - szKeyName, - 0, - KEY_QUERY_VALUE, - &hClassKey) != ERROR_SUCCESS) - { - goto cleanup; - } - - if (RegQueryValueExW(hClassKey, - REGSTR_VAL_NOUSECLASS, - NULL, - NULL, - NULL, - NULL) == ERROR_SUCCESS) - { - TRACE("'NoUseClass' value found!\n"); - continue; - } - - if ((Flags & DIBCI_NOINSTALLCLASS) && - (!RegQueryValueExW(hClassKey, - REGSTR_VAL_NOINSTALLCLASS, - NULL, - NULL, - NULL, - NULL))) - { - TRACE("'NoInstallClass' value found!\n"); - continue; - } - - if ((Flags & DIBCI_NODISPLAYCLASS) && - (!RegQueryValueExW(hClassKey, - REGSTR_VAL_NODISPLAYCLASS, - NULL, - NULL, - NULL, - NULL))) - { - TRACE("'NoDisplayClass' value found!\n"); - continue; - } - - TRACE("Guid: %s\n", debugstr_w(szKeyName)); - if (dwGuidListIndex < ClassGuidListSize) - { - if (szKeyName[0] == L'{' && szKeyName[37] == L'}') - szKeyName[37] = 0; - TRACE("Guid: %s\n", debugstr_w(&szKeyName[1])); - - UuidFromStringW(&szKeyName[1], - &ClassGuidList[dwGuidListIndex]); - } - - dwGuidListIndex++; - } - - if (lError != ERROR_SUCCESS) - break; - } - - if (RequiredSize != NULL) - *RequiredSize = dwGuidListIndex; - - if (ClassGuidListSize < dwGuidListIndex) - SetLastError(ERROR_INSUFFICIENT_BUFFER); - else - ret = TRUE; - -cleanup: - if (hClassesKey != INVALID_HANDLE_VALUE) - RegCloseKey(hClassesKey); - if (hClassKey != NULL) - RegCloseKey(hClassKey); - return ret; -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassGuidsFromNameA( - IN PCSTR ClassName, - OUT LPGUID ClassGuidList, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize) -{ - return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassGuidsFromNameW( - IN PCWSTR ClassName, - OUT LPGUID ClassGuidList, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize) -{ - return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameExA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassGuidsFromNameExA( - IN PCSTR ClassName, - OUT LPGUID ClassGuidList, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - LPWSTR ClassNameW = NULL; - LPWSTR MachineNameW = NULL; - BOOL bResult; - - TRACE("\n"); - - ClassNameW = MultiByteToUnicode(ClassName, CP_ACP); - if (ClassNameW == NULL) - return FALSE; - - if (MachineNameW) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) - { - MyFree(ClassNameW); - return FALSE; - } - } - - bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, - ClassGuidListSize, RequiredSize, - MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - MyFree(ClassNameW); - - return bResult; -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameExW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassGuidsFromNameExW( - IN PCWSTR ClassName, - OUT LPGUID ClassGuidList, - IN DWORD ClassGuidListSize, - OUT PDWORD RequiredSize, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - WCHAR szKeyName[MAX_GUID_STRING_LEN + 1]; - WCHAR szClassName[256]; - HKEY hClassesKey = INVALID_HANDLE_VALUE; - HKEY hClassKey = NULL; - DWORD dwLength; - DWORD dwIndex; - LONG lError; - DWORD dwGuidListIndex = 0; - BOOL ret = FALSE; - - TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList, - ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); - - if (RequiredSize != NULL) - *RequiredSize = 0; - - hClassesKey = SetupDiOpenClassRegKeyExW(NULL, - KEY_ENUMERATE_SUB_KEYS, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hClassesKey == INVALID_HANDLE_VALUE) - goto cleanup; - - for (dwIndex = 0; ; dwIndex++) - { - dwLength = MAX_GUID_STRING_LEN + 1; - lError = RegEnumKeyExW(hClassesKey, - dwIndex, - szKeyName, - &dwLength, - NULL, - NULL, - NULL, - NULL); - TRACE("RegEnumKeyExW() returns %ld\n", lError); - if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) - { - TRACE("Key name: %s\n", debugstr_w(szKeyName)); - - if (hClassKey != NULL) - RegCloseKey(hClassKey); - if (RegOpenKeyExW(hClassesKey, - szKeyName, - 0, - KEY_QUERY_VALUE, - &hClassKey) != ERROR_SUCCESS) - { - goto cleanup; - } - - dwLength = 256 * sizeof(WCHAR); - if (RegQueryValueExW(hClassKey, - Class, - NULL, - NULL, - (LPBYTE)szClassName, - &dwLength) == ERROR_SUCCESS) - { - TRACE("Class name: %s\n", debugstr_w(szClassName)); - - if (strcmpiW(szClassName, ClassName) == 0) - { - TRACE("Found matching class name\n"); - - TRACE("Guid: %s\n", debugstr_w(szKeyName)); - if (dwGuidListIndex < ClassGuidListSize) - { - if (szKeyName[0] == L'{' && szKeyName[37] == L'}') - szKeyName[37] = 0; - TRACE("Guid: %s\n", debugstr_w(&szKeyName[1])); - - UuidFromStringW(&szKeyName[1], - &ClassGuidList[dwGuidListIndex]); - } - - dwGuidListIndex++; - } - } - } - - if (lError != ERROR_SUCCESS) - break; - } - - if (RequiredSize != NULL) - *RequiredSize = dwGuidListIndex; - - if (ClassGuidListSize < dwGuidListIndex) - SetLastError(ERROR_INSUFFICIENT_BUFFER); - else - ret = TRUE; - -cleanup: - if (hClassesKey != INVALID_HANDLE_VALUE) - RegCloseKey(hClassesKey); - if (hClassKey != NULL) - RegCloseKey(hClassKey); - return ret; -} - -/*********************************************************************** - * SetupDiClassNameFromGuidA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassNameFromGuidA( - IN CONST GUID* ClassGuid, - OUT PSTR ClassName, - IN DWORD ClassNameSize, - OUT PDWORD RequiredSize OPTIONAL) -{ - return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, - ClassNameSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassNameFromGuidW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassNameFromGuidW( - IN CONST GUID* ClassGuid, - OUT PWSTR ClassName, - IN DWORD ClassNameSize, - OUT PDWORD RequiredSize OPTIONAL) -{ - return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, - ClassNameSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassNameFromGuidExA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassNameFromGuidExA( - IN CONST GUID* ClassGuid, - OUT PSTR ClassName, - IN DWORD ClassNameSize, - OUT PDWORD RequiredSize OPTIONAL, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; - LPWSTR MachineNameW = NULL; - BOOL ret; - - if (MachineName) - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, - NULL, MachineNameW, Reserved); - if (ret) - { - int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, - ClassNameSize, NULL, NULL); - - if (!ClassNameSize && RequiredSize) - *RequiredSize = len; - } - MyFree(MachineNameW); - return ret; -} - -/*********************************************************************** - * SetupDiClassNameFromGuidExW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiClassNameFromGuidExW( - IN CONST GUID* ClassGuid, - OUT PWSTR ClassName, - IN DWORD ClassNameSize, - OUT PDWORD RequiredSize OPTIONAL, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - HKEY hKey; - DWORD dwLength; - LONG rc; - BOOL ret = FALSE; - - TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName, - ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved); - - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, - KEY_QUERY_VALUE, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hKey == INVALID_HANDLE_VALUE) - goto cleanup; - - if (RequiredSize != NULL) - { - dwLength = 0; - rc = RegQueryValueExW(hKey, - Class, - NULL, - NULL, - NULL, - &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - - *RequiredSize = dwLength / sizeof(WCHAR); - } - - dwLength = ClassNameSize * sizeof(WCHAR); - rc = RegQueryValueExW(hKey, - Class, - NULL, - NULL, - (LPBYTE)ClassName, - &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - - ret = TRUE; - -cleanup: - if (hKey != INVALID_HANDLE_VALUE) - RegCloseKey(hKey); - return ret; -} /*********************************************************************** * SetupDiCreateDeviceInfoList (SETUPAPI.@) @@ -1367,236 +797,7 @@ done: } -/*********************************************************************** - * SetupDiGetClassDescriptionA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassDescriptionA( - IN CONST GUID *ClassGuid, - OUT PSTR ClassDescription, - IN DWORD ClassDescriptionSize, - OUT PDWORD RequiredSize OPTIONAL) -{ - return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, - ClassDescriptionSize, - RequiredSize, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassDescriptionW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassDescriptionW( - IN CONST GUID *ClassGuid, - OUT PWSTR ClassDescription, - IN DWORD ClassDescriptionSize, - OUT PDWORD RequiredSize OPTIONAL) -{ - return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, - ClassDescriptionSize, - RequiredSize, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassDescriptionExA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassDescriptionExA( - IN CONST GUID *ClassGuid, - OUT PSTR ClassDescription, - IN DWORD ClassDescriptionSize, - OUT PDWORD RequiredSize OPTIONAL, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - PWCHAR ClassDescriptionW; - LPWSTR MachineNameW = NULL; - BOOL ret; - - TRACE("\n"); - if (ClassDescriptionSize > 0) - { - ClassDescriptionW = HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize * sizeof(WCHAR)); - if (!ClassDescriptionW) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - ret = FALSE; - goto end; - } - } - else - ClassDescriptionW = NULL; - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (!MachineNameW) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - ret = FALSE; - goto end; - } - } - - ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, ClassDescriptionSize * sizeof(WCHAR), - NULL, MachineNameW, Reserved); - if (ret) - { - int len = WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription, - ClassDescriptionSize, NULL, NULL); - - if (!ClassDescriptionSize && RequiredSize) - *RequiredSize = len; - } - -end: - HeapFree(GetProcessHeap(), 0, ClassDescriptionW); - MyFree(MachineNameW); - return ret; -} - -/*********************************************************************** - * SetupDiGetClassDescriptionExW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassDescriptionExW( - IN CONST GUID *ClassGuid, - OUT PWSTR ClassDescription, - IN DWORD ClassDescriptionSize, - OUT PDWORD RequiredSize OPTIONAL, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - HKEY hKey = INVALID_HANDLE_VALUE; - DWORD dwLength; - BOOL ret = FALSE; - - TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription, - ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved); - - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, - KEY_QUERY_VALUE, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hKey == INVALID_HANDLE_VALUE) - { - WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError()); - goto cleanup; - } - - if (RequiredSize != NULL) - { - dwLength = 0; - if (RegQueryValueExW(hKey, - NULL, - NULL, - NULL, - NULL, - &dwLength) != ERROR_SUCCESS) - { - goto cleanup; - } - - *RequiredSize = dwLength / sizeof(WCHAR); - } - - dwLength = ClassDescriptionSize * sizeof(WCHAR); - if (RegQueryValueExW(hKey, - NULL, - NULL, - NULL, - (LPBYTE)ClassDescription, - &dwLength) != ERROR_SUCCESS) - { - goto cleanup; - } - - ret = TRUE; - -cleanup: - if (hKey != INVALID_HANDLE_VALUE) - RegCloseKey(hKey); - - return ret; -} - -/*********************************************************************** - * SetupDiGetClassDevsA (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiGetClassDevsA( - IN CONST GUID *ClassGuid OPTIONAL, - IN PCSTR Enumerator OPTIONAL, - IN HWND hwndParent OPTIONAL, - IN DWORD Flags) -{ - return SetupDiGetClassDevsExA(ClassGuid, Enumerator, hwndParent, - Flags, NULL, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassDevsW (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiGetClassDevsW( - IN CONST GUID *ClassGuid OPTIONAL, - IN PCWSTR Enumerator OPTIONAL, - IN HWND hwndParent OPTIONAL, - IN DWORD Flags) -{ - return SetupDiGetClassDevsExW(ClassGuid, Enumerator, hwndParent, - Flags, NULL, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassDevsExA (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiGetClassDevsExA( - IN CONST GUID *ClassGuid OPTIONAL, - IN PCSTR Enumerator OPTIONAL, - IN HWND hwndParent OPTIONAL, - IN DWORD Flags, - IN HDEVINFO DeviceInfoSet OPTIONAL, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - HDEVINFO ret; - LPWSTR enumstrW = NULL; - LPWSTR machineW = NULL; - - if (Enumerator) - { - int len = MultiByteToWideChar(CP_ACP, 0, Enumerator, -1, NULL, 0); - enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (!enumstrW) - { - ret = (HDEVINFO)INVALID_HANDLE_VALUE; - goto end; - } - MultiByteToWideChar(CP_ACP, 0, Enumerator, -1, enumstrW, len); - } - if (MachineName) - { - int len = MultiByteToWideChar(CP_ACP, 0, MachineName, -1, NULL, 0); - machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (!machineW) - { - ret = (HDEVINFO)INVALID_HANDLE_VALUE; - goto end; - } - MultiByteToWideChar(CP_ACP, 0, MachineName, -1, machineW, len); - } - ret = SetupDiGetClassDevsExW(ClassGuid, enumstrW, hwndParent, Flags, DeviceInfoSet, machineW, Reserved); - -end: - HeapFree(GetProcessHeap(), 0, enumstrW); - HeapFree(GetProcessHeap(), 0, machineW); - return ret; -} - -static BOOL +BOOL CreateDeviceInfoElement( IN struct DeviceInfoSet *list, IN LPCWSTR InstancePath, @@ -1639,969 +840,6 @@ CreateDeviceInfoElement( return TRUE; } -static BOOL -CreateDeviceInterface( - IN struct DeviceInfoElement* deviceInfo, - IN LPCWSTR SymbolicLink, - IN LPCGUID pInterfaceGuid, - OUT struct DeviceInterface **pDeviceInterface) -{ - struct DeviceInterface *deviceInterface; - - *pDeviceInterface = NULL; - - deviceInterface = HeapAlloc(GetProcessHeap(), 0, - FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (strlenW(SymbolicLink) + 1) * sizeof(WCHAR)); - if (!deviceInterface) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - deviceInterface->DeviceInfo = deviceInfo; - strcpyW(deviceInterface->SymbolicLink, SymbolicLink); - deviceInterface->Flags = 0; /* Flags will be updated later */ - memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID)); - - *pDeviceInterface = deviceInterface; - return TRUE; -} - -static LONG -SETUP_CreateDevListFromEnumerator( - struct DeviceInfoSet *list, - CONST GUID *pClassGuid OPTIONAL, - LPCWSTR Enumerator, - HKEY hEnumeratorKey) /* handle to Enumerator registry key */ -{ - HKEY hDeviceIdKey = NULL, hInstanceIdKey; - WCHAR KeyBuffer[MAX_PATH]; - WCHAR InstancePath[MAX_PATH]; - LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */ - struct DeviceInfoElement *deviceInfo; - DWORD i = 0, j; - DWORD dwLength, dwRegType; - DWORD rc; - - /* Enumerate device IDs (subkeys of hEnumeratorKey) */ - while (TRUE) - { - dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); - rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - goto cleanup; - i++; - - /* Open device id sub key */ - if (hDeviceIdKey != NULL) - RegCloseKey(hDeviceIdKey); - rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - strcpyW(InstancePath, Enumerator); - strcatW(InstancePath, BackSlash); - strcatW(InstancePath, KeyBuffer); - strcatW(InstancePath, BackSlash); - pEndOfInstancePath = &InstancePath[strlenW(InstancePath)]; - - /* Enumerate instance IDs (subkeys of hDeviceIdKey) */ - j = 0; - while (TRUE) - { - GUID KeyGuid; - - dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); - rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - goto cleanup; - j++; - - /* Open instance id sub key */ - rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - *pEndOfInstancePath = '\0'; - strcatW(InstancePath, KeyBuffer); - - /* Read ClassGUID value */ - dwLength = sizeof(KeyBuffer) - sizeof(WCHAR); - rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength); - RegCloseKey(hInstanceIdKey); - if (rc == ERROR_FILE_NOT_FOUND) - { - if (pClassGuid) - /* Skip this bad entry as we can't verify it */ - continue; - /* Set a default GUID for this device */ - memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID)); - } - else if (rc != ERROR_SUCCESS) - { - goto cleanup; - } - else if (dwRegType != REG_SZ) - { - rc = ERROR_GEN_FAILURE; - goto cleanup; - } - else - { - KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */ - if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK) - /* Bad GUID, skip the entry */ - continue; - } - - if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid)) - { - /* Skip this entry as it is not the right device class */ - continue; - } - - /* Add the entry to the list */ - if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo)) - { - rc = GetLastError(); - goto cleanup; - } - TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath), list); - InsertTailList(&list->ListHead, &deviceInfo->ListEntry); - } - } - - rc = ERROR_SUCCESS; - -cleanup: - if (hDeviceIdKey != NULL) - RegCloseKey(hDeviceIdKey); - return rc; -} - -static LONG -SETUP_CreateDevList( - struct DeviceInfoSet *list, - PCWSTR MachineName OPTIONAL, - CONST GUID *class OPTIONAL, - PCWSTR Enumerator OPTIONAL) -{ - HKEY HKLM = HKEY_LOCAL_MACHINE; - HKEY hEnumKey = NULL; - HKEY hEnumeratorKey = NULL; - WCHAR KeyBuffer[MAX_PATH]; - DWORD i; - DWORD dwLength; - DWORD rc; - - if (class && IsEqualIID(class, &GUID_NULL)) - class = NULL; - - /* Open Enum key (if applicable) */ - if (MachineName != NULL) - { - rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); - if (rc != ERROR_SUCCESS) - goto cleanup; - } - - rc = RegOpenKeyExW( - HKLM, - REGSTR_PATH_SYSTEMENUM, - 0, - KEY_ENUMERATE_SUB_KEYS, - &hEnumKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - - /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator. - * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator - * for each one. - */ - if (Enumerator) - { - rc = RegOpenKeyExW( - hEnumKey, - Enumerator, - 0, - KEY_ENUMERATE_SUB_KEYS, - &hEnumeratorKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey); - } - else - { - /* Enumerate enumerators */ - i = 0; - while (TRUE) - { - dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); - rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); - if (rc == ERROR_NO_MORE_ITEMS) - break; - else if (rc != ERROR_SUCCESS) - goto cleanup; - i++; - - /* Open sub key */ - if (hEnumeratorKey != NULL) - RegCloseKey(hEnumeratorKey); - rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - - /* Call SETUP_CreateDevListFromEnumerator */ - rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - } - rc = ERROR_SUCCESS; - } - -cleanup: - if (HKLM != HKEY_LOCAL_MACHINE) - RegCloseKey(HKLM); - if (hEnumKey != NULL) - RegCloseKey(hEnumKey); - if (hEnumeratorKey != NULL) - RegCloseKey(hEnumeratorKey); - return rc; -} - -static BOOL -DestroyDeviceInterface( - struct DeviceInterface* deviceInterface) -{ - return HeapFree(GetProcessHeap(), 0, deviceInterface); -} - -static LONG -SETUP_CreateInterfaceList( - struct DeviceInfoSet *list, - PCWSTR MachineName, - CONST GUID *InterfaceGuid, - PCWSTR DeviceInstanceW /* OPTIONAL */, - BOOL OnlyPresentInterfaces) -{ - HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */ - HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */ - HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */ - HKEY hControlKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */ - HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */ - HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */ - LONG rc; - WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1]; - PWSTR pSymbolicLink = NULL; - PWSTR InstancePath = NULL; - DWORD i, j; - DWORD dwLength, dwInstancePathLength; - DWORD dwRegType; - DWORD LinkedValue; - GUID ClassGuid; - struct DeviceInfoElement *deviceInfo; - - hInterfaceKey = INVALID_HANDLE_VALUE; - hDeviceInstanceKey = NULL; - hReferenceKey = NULL; - - /* Open registry key related to this interface */ - hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL); - if (hInterfaceKey == INVALID_HANDLE_VALUE) - { - rc = GetLastError(); - goto cleanup; - } - - /* Enumerate sub keys of hInterfaceKey */ - i = 0; - while (TRUE) - { - dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); - rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - goto cleanup; - i++; - - /* Open sub key */ - if (hDeviceInstanceKey != NULL) - RegCloseKey(hDeviceInstanceKey); - rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - - /* Read DeviceInstance */ - rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength); - if (rc != ERROR_SUCCESS) - goto cleanup; - if (dwRegType != REG_SZ) - { - rc = ERROR_GEN_FAILURE; - goto cleanup; - } - HeapFree(GetProcessHeap(), 0, InstancePath); - InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR)); - if (!InstancePath) - { - rc = ERROR_NOT_ENOUGH_MEMORY; - goto cleanup; - } - rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength); - if (rc != ERROR_SUCCESS) - goto cleanup; - InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0'; - TRACE("DeviceInstance %s\n", debugstr_w(InstancePath)); - - if (DeviceInstanceW) - { - /* Check if device enumerator is not the right one */ - if (strcmpW(DeviceInstanceW, InstancePath) != 0) - continue; - } - - /* Find class GUID associated to the device instance */ - rc = RegOpenKeyExW( - list->HKLM, - REGSTR_PATH_SYSTEMENUM, - 0, /* Options */ - 0, - &hEnumKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - rc = RegOpenKeyExW( - hEnumKey, - InstancePath, - 0, /* Options */ - KEY_QUERY_VALUE, - &hKey); - RegCloseKey(hEnumKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - dwLength = sizeof(KeyBuffer) - sizeof(WCHAR); - rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); - RegCloseKey(hKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - KeyBuffer[dwLength / sizeof(WCHAR)] = '\0'; - KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */ - if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK) - { - rc = ERROR_GEN_FAILURE; - goto cleanup; - } - TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid)); - - /* If current device doesn't match the list GUID (if any), skip this entry */ - if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid)) - continue; - - /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */ - j = 0; - while (TRUE) - { - struct DeviceInterface *interfaceInfo; - - dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); - rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - goto cleanup; - j++; - if (KeyBuffer[0] != '#') - /* This entry doesn't represent an interesting entry */ - continue; - - /* Open sub key */ - if (hReferenceKey != NULL) - RegCloseKey(hReferenceKey); - rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey); - if (rc != ERROR_SUCCESS) - goto cleanup; - - /* Read SymbolicLink value */ - rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength); - if (rc != ERROR_SUCCESS ) - goto cleanup; - if (dwRegType != REG_SZ) - { - rc = ERROR_GEN_FAILURE; - goto cleanup; - } - - /* We have found a device */ - /* Step 1. Create a device info element */ - if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo)) - { - rc = GetLastError(); - goto cleanup; - } - TRACE("Adding device %s to list\n", debugstr_w(InstancePath)); - InsertTailList(&list->ListHead, &deviceInfo->ListEntry); - - /* Step 2. Create an interface list for this element */ - HeapFree(GetProcessHeap(), 0, pSymbolicLink); - pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR)); - if (!pSymbolicLink) - { - rc = ERROR_NOT_ENOUGH_MEMORY; - goto cleanup; - } - rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength); - pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0'; - if (rc != ERROR_SUCCESS) - goto cleanup; - if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo)) - { - rc = GetLastError(); - goto cleanup; - } - - /* Step 3. Update flags */ - if (KeyBuffer[1] == '\0') - interfaceInfo->Flags |= SPINT_DEFAULT; - rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey); - if (rc != ERROR_SUCCESS) - { - if (OnlyPresentInterfaces) - { - DestroyDeviceInterface(interfaceInfo); - continue; - } - else - interfaceInfo->Flags |= SPINT_REMOVED; - } - else - { - dwLength = sizeof(DWORD); - if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength) - && dwRegType == REG_DWORD && LinkedValue) - interfaceInfo->Flags |= SPINT_ACTIVE; - RegCloseKey(hControlKey); - } - - TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink)); - InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry); - } - } - rc = ERROR_SUCCESS; - -cleanup: - if (hReferenceKey != NULL) - RegCloseKey(hReferenceKey); - if (hDeviceInstanceKey != NULL) - RegCloseKey(hDeviceInstanceKey); - if (hInterfaceKey != INVALID_HANDLE_VALUE) - RegCloseKey(hInterfaceKey); - HeapFree(GetProcessHeap(), 0, InstancePath); - HeapFree(GetProcessHeap(), 0, pSymbolicLink); - return rc; -} - -/*********************************************************************** - * SetupDiGetClassDevsExW (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiGetClassDevsExW( - IN CONST GUID *ClassGuid OPTIONAL, - IN PCWSTR Enumerator OPTIONAL, - IN HWND hwndParent OPTIONAL, - IN DWORD Flags, - IN HDEVINFO DeviceInfoSet OPTIONAL, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; - struct DeviceInfoSet *list; - CONST GUID *pClassGuid; - LONG rc; - HDEVINFO ret = INVALID_HANDLE_VALUE; - - TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(ClassGuid), debugstr_w(Enumerator), - hwndParent, Flags, DeviceInfoSet, debugstr_w(MachineName), Reserved); - - /* Create the deviceset if not set */ - if (DeviceInfoSet) - { - list = (struct DeviceInfoSet *)DeviceInfoSet; - if (list->magic != SETUP_DEV_INFO_SET_MAGIC) - { - SetLastError(ERROR_INVALID_HANDLE); - goto cleanup; - } - hDeviceInfo = DeviceInfoSet; - } - else - { - hDeviceInfo = SetupDiCreateDeviceInfoListExW( - Flags & DIGCF_DEVICEINTERFACE ? NULL : ClassGuid, - NULL, MachineName, NULL); - if (hDeviceInfo == INVALID_HANDLE_VALUE) - goto cleanup; - list = (struct DeviceInfoSet *)hDeviceInfo; - } - - if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) - pClassGuid = NULL; - else - pClassGuid = &list->ClassGuid; - - if (Flags & DIGCF_PROFILE) - FIXME(": flag DIGCF_PROFILE ignored\n"); - - if (Flags & DIGCF_ALLCLASSES) - { - rc = SETUP_CreateDevList(list, MachineName, pClassGuid, Enumerator); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - ret = hDeviceInfo; - } - else if (Flags & DIGCF_DEVICEINTERFACE) - { - if (ClassGuid == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - goto cleanup; - } - - rc = SETUP_CreateInterfaceList(list, MachineName, ClassGuid, Enumerator, Flags & DIGCF_PRESENT); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - ret = hDeviceInfo; - } - else - { - rc = SETUP_CreateDevList(list, MachineName, ClassGuid, Enumerator); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - ret = hDeviceInfo; - } - -cleanup: - if (!DeviceInfoSet && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != ret) - SetupDiDestroyDeviceInfoList(hDeviceInfo); - return ret; -} - -/*********************************************************************** - * SetupDiGetClassImageIndex (SETUPAPI.@) - */ - -static BOOL -GetIconIndex( - IN HKEY hClassKey, - OUT PINT ImageIndex) -{ - LPWSTR Buffer = NULL; - DWORD dwRegType, dwLength; - LONG rc; - BOOL ret = FALSE; - - /* Read icon registry key */ - rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } else if (dwRegType != REG_SZ) - { - SetLastError(ERROR_INVALID_INDEX); - goto cleanup; - } - Buffer = MyMalloc(dwLength + sizeof(WCHAR)); - if (!Buffer) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - /* make sure the returned buffer is NULL-terminated */ - Buffer[dwLength / sizeof(WCHAR)] = 0; - - /* Transform icon value to a INT */ - *ImageIndex = atoiW(Buffer); - ret = TRUE; - -cleanup: - MyFree(Buffer); - return ret; -} - -BOOL WINAPI -SetupDiGetClassImageIndex( - IN PSP_CLASSIMAGELIST_DATA ClassImageListData, - IN CONST GUID *ClassGuid, - OUT PINT ImageIndex) -{ - struct ClassImageList *list; - BOOL ret = FALSE; - - TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex); - - if (!ClassImageListData || !ClassGuid || !ImageIndex) - SetLastError(ERROR_INVALID_PARAMETER); - else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (!ImageIndex) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - HKEY hKey = INVALID_HANDLE_VALUE; - INT iconIndex; - - /* Read Icon registry entry into Buffer */ - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL); - if (hKey == INVALID_HANDLE_VALUE) - goto cleanup; - if (!GetIconIndex(hKey, &iconIndex)) - goto cleanup; - - if (iconIndex >= 0) - { - SetLastError(ERROR_INVALID_INDEX); - goto cleanup; - } - - *ImageIndex = -iconIndex; - ret = TRUE; - -cleanup: - if (hKey != INVALID_HANDLE_VALUE) - RegCloseKey(hKey); - } - - TRACE("Returning %d\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiGetClassImageList(SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassImageList( - OUT PSP_CLASSIMAGELIST_DATA ClassImageListData) -{ - return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassImageListExA(SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassImageListExA( - OUT PSP_CLASSIMAGELIST_DATA ClassImageListData, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - PWSTR MachineNameW = NULL; - BOOL ret; - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) - return FALSE; - } - - ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - return ret; -} - -/*********************************************************************** - * SetupDiGetClassImageListExW(SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassImageListExW( - OUT PSP_CLASSIMAGELIST_DATA ClassImageListData, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - BOOL ret = FALSE; - - TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved); - - if (!ClassImageListData) - SetLastError(ERROR_INVALID_PARAMETER); - else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (Reserved) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - struct ClassImageList *list = NULL; - DWORD size; - - size = FIELD_OFFSET(struct ClassImageList, szData); - if (MachineName) - size += (strlenW(MachineName) + 3) * sizeof(WCHAR); - list = HeapAlloc(GetProcessHeap(), 0, size); - if (!list) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC; - if (MachineName) - { - list->szData[0] = list->szData[1] = '\\'; - strcpyW(list->szData + 2, MachineName); - list->MachineName = list->szData; - } - else - { - list->MachineName = NULL; - } - - ClassImageListData->Reserved = (ULONG_PTR)list; - ret = TRUE; - -cleanup: - if (!ret) - MyFree(list); - } - - TRACE("Returning %d\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiLoadClassIcon(SETUPAPI.@) - */ -BOOL WINAPI -SetupDiLoadClassIcon( - IN CONST GUID *ClassGuid, - OUT HICON *LargeIcon OPTIONAL, - OUT PINT MiniIconIndex OPTIONAL) -{ - BOOL ret = FALSE; - - if (!ClassGuid) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - LPWSTR Buffer = NULL; - LPCWSTR DllName; - INT iconIndex; - HKEY hKey = INVALID_HANDLE_VALUE; - - hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE); - if (hKey == INVALID_HANDLE_VALUE) - goto cleanup; - - if (!GetIconIndex(hKey, &iconIndex)) - goto cleanup; - - if (iconIndex > 0) - { - /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */ - PWCHAR Comma; - LONG rc; - DWORD dwRegType, dwLength; - rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); - if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) - { - Buffer = MyMalloc(dwLength + sizeof(WCHAR)); - if (Buffer == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - /* make sure the returned buffer is NULL-terminated */ - Buffer[dwLength / sizeof(WCHAR)] = 0; - } - else if - (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength)) - && dwRegType == REG_SZ) - { - Buffer = MyMalloc(dwLength + sizeof(WCHAR)); - if (Buffer == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - /* make sure the returned buffer is NULL-terminated */ - Buffer[dwLength / sizeof(WCHAR)] = 0; - } - else - { - /* Unable to find where to load the icon */ - SetLastError(ERROR_FILE_NOT_FOUND); - goto cleanup; - } - Comma = strchrW(Buffer, ','); - if (!Comma) - { - SetLastError(ERROR_GEN_FAILURE); - goto cleanup; - } - *Comma = '\0'; - DllName = Buffer; - } - else - { - /* Look up icon in setupapi.dll */ - DllName = L"setupapi.dll"; - iconIndex = -iconIndex; - } - - TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName)); - if (LargeIcon) - { - if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1)) - { - SetLastError(ERROR_INVALID_INDEX); - goto cleanup; - } - } - if (MiniIconIndex) - *MiniIconIndex = iconIndex; - ret = TRUE; - -cleanup: - if (hKey != INVALID_HANDLE_VALUE) - RegCloseKey(hKey); - MyFree(Buffer); - } - - TRACE("Returning %d\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiEnumDeviceInterfaces (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiEnumDeviceInterfaces( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN CONST GUID *InterfaceClassGuid, - IN DWORD MemberIndex, - OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) -{ - BOOL ret = FALSE; - - TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData, - debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); - - if (!DeviceInterfaceData) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) - { - struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet; - - if (list->magic == SETUP_DEV_INFO_SET_MAGIC) - { - PLIST_ENTRY ItemList = list->ListHead.Flink; - BOOL Found = FALSE; - while (ItemList != &list->ListHead && !Found) - { - PLIST_ENTRY InterfaceListEntry; - struct DeviceInfoElement *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfoElement, ListEntry); - if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo) - { - /* We are not searching for this element */ - ItemList = ItemList->Flink; - continue; - } - InterfaceListEntry = DevInfo->InterfaceListHead.Flink; - while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found) - { - struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); - if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) - { - InterfaceListEntry = InterfaceListEntry->Flink; - continue; - } - if (MemberIndex-- == 0) - { - /* return this item */ - memcpy(&DeviceInterfaceData->InterfaceClassGuid, - &DevItf->InterfaceClassGuid, - sizeof(GUID)); - DeviceInterfaceData->Flags = DevItf->Flags; - DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; - Found = TRUE; - } - InterfaceListEntry = InterfaceListEntry->Flink; - } - ItemList = ItemList->Flink; - } - if (!Found) - SetLastError(ERROR_NO_MORE_ITEMS); - else - ret = TRUE; - } - else - SetLastError(ERROR_INVALID_HANDLE); - } - else - SetLastError(ERROR_INVALID_HANDLE); - return ret; -} - -static VOID -ReferenceInfFile(struct InfFileDetails* infFile) -{ - InterlockedIncrement(&infFile->References); -} - -static VOID -DereferenceInfFile(struct InfFileDetails* infFile) -{ - if (InterlockedDecrement(&infFile->References) == 0) - { - SetupCloseInfFile(infFile->hInf); - HeapFree(GetProcessHeap(), 0, infFile); - } -} - -static BOOL -DestroyDriverInfoElement(struct DriverInfoElement* driverInfo) -{ - DereferenceInfFile(driverInfo->InfFileDetails); - HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); - HeapFree(GetProcessHeap(), 0, driverInfo); - return TRUE; -} static BOOL DestroyClassInstallParams(struct ClassInstallParams* installParams) @@ -2680,144 +918,6 @@ SetupDiDestroyDeviceInfoList( return ret; } -/*********************************************************************** - * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetDeviceInterfaceDetailA( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, - OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL, - IN DWORD DeviceInterfaceDetailDataSize, - OUT PDWORD RequiredSize OPTIONAL, - OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) -{ - PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL; - DWORD sizeW = 0, sizeA; - BOOL ret = FALSE; - - TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet, - DeviceInterfaceData, DeviceInterfaceDetailData, - DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); - - if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - if (DeviceInterfaceDetailData != NULL) - { - sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) - + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR); - DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW); - if (!DeviceInterfaceDetailDataW) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - } - if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW)) - { - DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); - ret = SetupDiGetDeviceInterfaceDetailW( - DeviceInfoSet, - DeviceInterfaceData, - DeviceInterfaceDetailDataW, - sizeW, - &sizeW, - DeviceInfoData); - sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR) - + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath); - if (RequiredSize) - *RequiredSize = sizeA; - if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA) - { - if (!WideCharToMultiByte( - CP_ACP, 0, - DeviceInterfaceDetailDataW->DevicePath, -1, - DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath), - NULL, NULL)) - { - ret = FALSE; - } - } - } - HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW); - } - - TRACE("Returning %d\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetDeviceInterfaceDetailW( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, - OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL, - IN DWORD DeviceInterfaceDetailDataSize, - OUT PDWORD RequiredSize OPTIONAL, - OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) -{ - BOOL ret = FALSE; - - TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet, - DeviceInterfaceData, DeviceInterfaceDetailData, - DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); - - if (!DeviceInfoSet || !DeviceInterfaceData) - 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 (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved; - LPCWSTR devName = deviceInterface->SymbolicLink; - DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + - (lstrlenW(devName) + 1) * sizeof(WCHAR); - - if (sizeRequired > DeviceInterfaceDetailDataSize) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - if (RequiredSize) - *RequiredSize = sizeRequired; - } - else - { - strcpyW(DeviceInterfaceDetailData->DevicePath, devName); - TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath)); - if (DeviceInfoData) - { - memcpy(&DeviceInfoData->ClassGuid, - &deviceInterface->DeviceInfo->ClassGuid, - sizeof(GUID)); - DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst; - DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo; - } - ret = TRUE; - } - } - - TRACE("Returning %d\n", ret); - return ret; -} - /*********************************************************************** * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) */ @@ -3256,718 +1356,6 @@ SetupDiSetDeviceRegistryPropertyW( } -/*********************************************************************** - * SetupDiInstallClassA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiInstallClassA( - IN HWND hwndParent OPTIONAL, - IN PCSTR InfFileName, - IN DWORD Flags, - IN HSPFILEQ FileQueue OPTIONAL) -{ - return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); -} - - -/*********************************************************************** - * SetupDiInstallClassW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiInstallClassW( - IN HWND hwndParent OPTIONAL, - IN PCWSTR InfFileName, - IN DWORD Flags, - IN HSPFILEQ FileQueue OPTIONAL) -{ - return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); -} - - -/*********************************************************************** - * SetupDiInstallClassExA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiInstallClassExA( - IN HWND hwndParent OPTIONAL, - IN PCSTR InfFileName OPTIONAL, - IN DWORD Flags, - IN HSPFILEQ FileQueue OPTIONAL, - IN CONST GUID *InterfaceClassGuid OPTIONAL, - IN PVOID Reserved1, - IN PVOID Reserved2) -{ - PWSTR InfFileNameW = NULL; - BOOL Result; - - if (InfFileName) - { - InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP); - if (InfFileNameW == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - } - - Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags, - FileQueue, InterfaceClassGuid, Reserved1, Reserved2); - - MyFree(InfFileNameW); - - return Result; -} - - -static HKEY -CreateClassKey(HINF hInf) -{ - WCHAR FullBuffer[MAX_PATH]; - WCHAR Buffer[MAX_PATH]; - DWORD RequiredSize; - HKEY hClassKey = NULL; - HKEY ret = INVALID_HANDLE_VALUE; - - FullBuffer[0] = '\0'; - Buffer[0] = '\\'; - if (!SetupGetLineTextW(NULL, - hInf, - Version, - ClassGUID, - &Buffer[1], - MAX_PATH - 1, - &RequiredSize)) - { - goto cleanup; - } - - lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT); - lstrcatW(FullBuffer, Buffer); - - if (!SetupGetLineTextW(NULL, - hInf, - Version, - Class, - Buffer, - MAX_PATH, - &RequiredSize)) - { - RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer); - goto cleanup; - } - - if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE, - FullBuffer, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_SET_VALUE, - NULL, - &hClassKey, - NULL)) - { - goto cleanup; - } - - if (ERROR_SUCCESS != RegSetValueExW(hClassKey, - Class, - 0, - REG_SZ, - (LPBYTE)Buffer, - RequiredSize * sizeof(WCHAR))) - { - goto cleanup; - } - - ret = hClassKey; - -cleanup: - if (hClassKey != NULL && hClassKey != ret) - RegCloseKey(hClassKey); - if (ret == INVALID_HANDLE_VALUE && FullBuffer[0] != '\0') - RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer); - return ret; -} - - -/*********************************************************************** - * SetupDiInstallClassExW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiInstallClassExW( - IN HWND hwndParent OPTIONAL, - IN PCWSTR InfFileName OPTIONAL, - IN DWORD Flags, - IN HSPFILEQ FileQueue OPTIONAL, - IN CONST GUID *InterfaceClassGuid OPTIONAL, - IN PVOID Reserved1, - IN PVOID Reserved2) -{ - BOOL ret = FALSE; - - TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags, - FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2); - - if (!InfFileName) - { - FIXME("Case not implemented: InfFileName NULL\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - } - else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)) - { - TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)); - SetLastError(ERROR_INVALID_FLAGS); - } - else if ((Flags & DI_NOVCP) && FileQueue == NULL) - SetLastError(ERROR_INVALID_PARAMETER); - else if (Reserved1 != NULL) - SetLastError(ERROR_INVALID_PARAMETER); - else if (Reserved2 != NULL) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; - SP_DEVINSTALL_PARAMS_W InstallParams; - WCHAR SectionName[MAX_PATH]; - HINF hInf = INVALID_HANDLE_VALUE; - HKEY hRootKey = INVALID_HANDLE_VALUE; - PVOID callback_context = NULL; - - hDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL); - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); - if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams)) - goto cleanup; - InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL); - InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL); - if (Flags & DI_NOVCP) - InstallParams.FileQueue = FileQueue; - if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams)) - goto cleanup; - - /* Open the .inf file */ - hInf = SetupOpenInfFileW( - InfFileName, - NULL, - INF_STYLE_WIN4, - NULL); - if (hInf == INVALID_HANDLE_VALUE) - goto cleanup; - - /* Try to append a layout file */ - ret = SetupOpenAppendInfFileW(NULL, hInf, NULL); - if (!ret) - goto cleanup; - - if (InterfaceClassGuid) - { - /* Retrieve the actual section name */ - ret = SetupDiGetActualSectionToInstallW( - hInf, - InterfaceInstall32, - SectionName, - MAX_PATH, - NULL, - NULL); - if (!ret) - goto cleanup; - - /* Open registry key related to this interface */ - /* FIXME: What happens if the key doesn't exist? */ - hRootKey = SetupDiOpenClassRegKeyExW(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL); - if (hRootKey == INVALID_HANDLE_VALUE) - goto cleanup; - - /* SetupDiCreateDeviceInterface??? */ - FIXME("Installing an interface is not implemented\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - } - else - { - /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */ - hRootKey = CreateClassKey(hInf); - if (hRootKey == INVALID_HANDLE_VALUE) - goto cleanup; - - /* Retrieve the actual section name */ - ret = SetupDiGetActualSectionToInstallW( - hInf, - ClassInstall32, - SectionName, - MAX_PATH - strlenW(DotServices), - NULL, - NULL); - if (!ret) - goto cleanup; - - callback_context = SetupInitDefaultQueueCallback(hwndParent); - if (!callback_context) - goto cleanup; - - ret = SetupInstallFromInfSectionW( - hwndParent, - hInf, - SectionName, - SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG, - hRootKey, - NULL, /* FIXME: SourceRootPath */ - !(Flags & DI_NOVCP) && (Flags & DI_FORCECOPY) ? SP_COPY_FORCE_IN_USE : 0, /* CopyFlags */ - SetupDefaultQueueCallbackW, - callback_context, - hDeviceInfo, - NULL); - if (!ret) - goto cleanup; - - /* Install .Services section */ - lstrcatW(SectionName, DotServices); - ret = SetupInstallServicesFromInfSectionExW( - hInf, - SectionName, - 0, - hDeviceInfo, - NULL, - NULL, - NULL); - if (!ret) - goto cleanup; - - ret = TRUE; - } - -cleanup: - if (hDeviceInfo != INVALID_HANDLE_VALUE) - SetupDiDestroyDeviceInfoList(hDeviceInfo); - if (hInf != INVALID_HANDLE_VALUE) - SetupCloseInfFile(hInf); - if (hRootKey != INVALID_HANDLE_VALUE) - RegCloseKey(hRootKey); - SetupTermDefaultQueueCallback(callback_context); - } - - TRACE("Returning %d\n", ret); - return ret; -} - - -/*********************************************************************** - * SetupDiOpenClassRegKey (SETUPAPI.@) - */ -HKEY WINAPI -SetupDiOpenClassRegKey( - IN CONST GUID *ClassGuid OPTIONAL, - IN REGSAM samDesired) -{ - return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, - DIOCR_INSTALLER, NULL, NULL); -} - - -/*********************************************************************** - * SetupDiOpenClassRegKeyExA (SETUPAPI.@) - */ -HKEY WINAPI -SetupDiOpenClassRegKeyExA( - IN CONST GUID *ClassGuid OPTIONAL, - IN REGSAM samDesired, - IN DWORD Flags, - IN PCSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - PWSTR MachineNameW = NULL; - HKEY hKey; - - TRACE("\n"); - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) - return INVALID_HANDLE_VALUE; - } - - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, - Flags, MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - return hKey; -} - - -/*********************************************************************** - * SetupDiOpenClassRegKeyExW (SETUPAPI.@) - */ -HKEY WINAPI -SetupDiOpenClassRegKeyExW( - IN CONST GUID* ClassGuid OPTIONAL, - IN REGSAM samDesired, - IN DWORD Flags, - IN PCWSTR MachineName OPTIONAL, - IN PVOID Reserved) -{ - LPWSTR lpGuidString = NULL; - LPWSTR lpFullGuidString = NULL; - DWORD dwLength; - HKEY HKLM; - HKEY hClassesKey = NULL; - HKEY hClassKey = NULL; - HKEY ret = INVALID_HANDLE_VALUE; - DWORD rc; - LPCWSTR lpKeyName; - - TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired, - Flags, debugstr_w(MachineName), Reserved); - - if (Flags == DIOCR_INSTALLER) - lpKeyName = REGSTR_PATH_CLASS_NT; - else if (Flags == DIOCR_INTERFACE) - lpKeyName = REGSTR_PATH_DEVICE_CLASSES; - else - { - ERR("Invalid Flags parameter!\n"); - SetLastError(ERROR_INVALID_FLAGS); - goto cleanup; - } - - if (MachineName != NULL) - { - rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - } - else - HKLM = HKEY_LOCAL_MACHINE; - - rc = RegOpenKeyExW(HKLM, - lpKeyName, - 0, - ClassGuid ? 0 : samDesired, - &hClassesKey); - if (MachineName != NULL) RegCloseKey(HKLM); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - - if (ClassGuid == NULL) - { - /* Stop here. We don't need to open a subkey */ - ret = hClassesKey; - goto cleanup; - } - - if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK) - { - SetLastError(ERROR_GEN_FAILURE); - goto cleanup; - } - - dwLength = lstrlenW(lpGuidString); - lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR)); - if (!lpFullGuidString) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - lpFullGuidString[0] = '{'; - memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR)); - lpFullGuidString[dwLength + 1] = '}'; - lpFullGuidString[dwLength + 2] = '\0'; - - rc = RegOpenKeyExW(hClassesKey, - lpFullGuidString, - 0, - samDesired, - &hClassKey); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - ret = hClassKey; - -cleanup: - if (hClassKey != NULL && hClassKey != ret) - RegCloseKey(hClassKey); - if (hClassesKey != NULL && hClassesKey != ret) - RegCloseKey(hClassesKey); - if (lpGuidString) - RpcStringFreeW(&lpGuidString); - HeapFree(GetProcessHeap(), 0, lpFullGuidString); - - return ret; -} - -/*********************************************************************** - * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiOpenDeviceInterfaceW( - IN HDEVINFO DeviceInfoSet, - IN PCWSTR DevicePath, - IN DWORD OpenFlags, - OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL) -{ - FIXME("%p %s %08lx %p\n", - DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); - return FALSE; -} - -/*********************************************************************** - * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiOpenDeviceInterfaceA( - IN HDEVINFO DeviceInfoSet, - IN PCSTR DevicePath, - IN DWORD OpenFlags, - OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL) -{ - LPWSTR DevicePathW = NULL; - BOOL bResult; - - TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); - - DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP); - if (DevicePathW == NULL) - return FALSE; - - bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet, - DevicePathW, OpenFlags, DeviceInterfaceData); - - MyFree(DevicePathW); - - return bResult; -} - -/*********************************************************************** - * SetupDiSetClassInstallParamsA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiSetClassInstallParamsA( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, - IN DWORD ClassInstallParamsSize) -{ - FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData, - ClassInstallParams->InstallFunction, ClassInstallParamsSize); - return FALSE; -} - -/*********************************************************************** - * SetupDiSetClassInstallParamsW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiSetClassInstallParamsW( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, - IN DWORD ClassInstallParamsSize) -{ - struct DeviceInfoSet *list; - BOOL ret = FALSE; - - TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData, - ClassInstallParams, ClassInstallParamsSize); - - if (!DeviceInfoSet) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) - SetLastError(ERROR_INVALID_HANDLE); - else if ((list = (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 (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER)) - SetLastError(ERROR_INVALID_PARAMETER); - else if (!ClassInstallParams && ClassInstallParamsSize != 0) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - SP_DEVINSTALL_PARAMS_W InstallParams; - BOOL Result; - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - if (!Result) - goto done; - - if (ClassInstallParams) - { - /* Check parameters in ClassInstallParams */ - if (ClassInstallParams->InstallFunction < DIF_SELECTDEVICE - || ClassInstallParams->InstallFunction - DIF_SELECTDEVICE >= sizeof(UpdateClassInstallParamHandlers)/sizeof(UpdateClassInstallParamHandlers[0])) - { - SetLastError(ERROR_INVALID_USER_BUFFER); - goto done; - } - else if (UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE] == NULL) - { - ERR("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams->InstallFunction); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - goto done; - } - ret = UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE](DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize); - if (!ret) - goto done; - InstallParams.Flags |= DI_CLASSINSTALLPARAMS; - } - else - { - InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS; - } - - ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - } - -done: - TRACE("Returning %d\n", ret); - return ret; -} - -static BOOL -PropertyChangeHandler( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL, - IN DWORD ClassInstallParamsSize) -{ - PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams; - BOOL ret = FALSE; - - if (!DeviceInfoData) - SetLastError(ERROR_INVALID_PARAMETER); - else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS)) - SetLastError(ERROR_INVALID_PARAMETER); - else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE - && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE - && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP) - SetLastError(ERROR_INVALID_FLAGS); - else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL - && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC) - SetLastError(ERROR_INVALID_FLAGS); - else if (PropChangeParams - && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP) - && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC) - SetLastError(ERROR_INVALID_USER_BUFFER); - else - { - PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams; - if (!DeviceInfoData) - { - struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet; - CurrentPropChangeParams = &list->ClassInstallParams.PropChange; - } - else - { - struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; - CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChange; - } - if (*CurrentPropChangeParams) - { - MyFree(*CurrentPropChangeParams); - *CurrentPropChangeParams = NULL; - } - if (PropChangeParams) - { - *CurrentPropChangeParams = MyMalloc(sizeof(SP_PROPCHANGE_PARAMS)); - if (!*CurrentPropChangeParams) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS)); - } - ret = TRUE; - } - -done: - return ret; -} - -static DWORD -GetFunctionPointer( - IN PWSTR InstallerName, - OUT HMODULE* ModulePointer, - OUT PVOID* FunctionPointer) -{ - HMODULE hModule = NULL; - LPSTR FunctionNameA = NULL; - PWCHAR Comma; - DWORD rc; - - *ModulePointer = NULL; - *FunctionPointer = NULL; - - Comma = strchrW(InstallerName, ','); - if (!Comma) - { - rc = ERROR_INVALID_PARAMETER; - goto cleanup; - } - - /* Load library */ - *Comma = '\0'; - hModule = LoadLibraryW(InstallerName); - *Comma = ','; - if (!hModule) - { - rc = GetLastError(); - goto cleanup; - } - - /* Skip comma spaces */ - while (*Comma == ',' || isspaceW(*Comma)) - Comma++; - - /* W->A conversion for function name */ - FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP); - if (!FunctionNameA) - { - rc = GetLastError(); - goto cleanup; - } - - /* Search function */ - *FunctionPointer = GetProcAddress(hModule, FunctionNameA); - if (!*FunctionPointer) - { - rc = GetLastError(); - goto cleanup; - } - - *ModulePointer = hModule; - rc = ERROR_SUCCESS; - -cleanup: - if (rc != ERROR_SUCCESS && hModule) - FreeLibrary(hModule); - MyFree(FunctionNameA); - return rc; -} - -static DWORD -FreeFunctionPointer( - IN HMODULE ModulePointer, - IN PVOID FunctionPointer) -{ - if (ModulePointer == NULL) - return ERROR_SUCCESS; - if (FreeLibrary(ModulePointer)) - return ERROR_SUCCESS; - else - return GetLastError(); -} - static BOOL WINAPI IntSetupDiRegisterDeviceInfo( IN HDEVINFO DeviceInfoSet, @@ -4677,198 +2065,6 @@ SetupDiGetDeviceInstanceIdW( return ret; } -/*********************************************************************** - * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassDevPropertySheetsA( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN LPPROPSHEETHEADERA PropertySheetHeader, - IN DWORD PropertySheetHeaderPageListSize, - OUT PDWORD RequiredSize OPTIONAL, - IN DWORD PropertySheetType) -{ - PROPSHEETHEADERW psh; - BOOL ret = FALSE; - - TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, - PropertySheetHeader, PropertySheetHeaderPageListSize, - RequiredSize, PropertySheetType); - - psh.dwFlags = PropertySheetHeader->dwFlags; - psh.phpage = PropertySheetHeader->phpage; - psh.nPages = PropertySheetHeader->nPages; - - ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL, - PropertySheetHeaderPageListSize, RequiredSize, - PropertySheetType); - if (ret) - { - PropertySheetHeader->nPages = psh.nPages; - } - - TRACE("Returning %d\n", ret); - return ret; -} - -struct ClassDevPropertySheetsData -{ - HPROPSHEETPAGE *PropertySheetPages; - DWORD MaximumNumberOfPages; - DWORD NumberOfPages; -}; - -static BOOL WINAPI -GetClassDevPropertySheetsCallback( - IN HPROPSHEETPAGE hPropSheetPage, - IN OUT LPARAM lParam) -{ - struct ClassDevPropertySheetsData *PropPageData; - - PropPageData = (struct ClassDevPropertySheetsData *)lParam; - - if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages) - { - *PropPageData->PropertySheetPages = hPropSheetPage; - PropPageData->PropertySheetPages++; - } - - PropPageData->NumberOfPages++; - return TRUE; -} - -/*********************************************************************** - * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetClassDevPropertySheetsW( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN OUT LPPROPSHEETHEADERW PropertySheetHeader, - IN DWORD PropertySheetHeaderPageListSize, - OUT PDWORD RequiredSize OPTIONAL, - IN DWORD PropertySheetType) -{ - struct DeviceInfoSet *list; - BOOL ret = FALSE; - - TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, - PropertySheetHeader, PropertySheetHeaderPageListSize, - RequiredSize, PropertySheetType); - - if (!DeviceInfoSet) - SetLastError(ERROR_INVALID_HANDLE); - else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) - SetLastError(ERROR_INVALID_HANDLE); - else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) - SetLastError(ERROR_INVALID_HANDLE); - else if (!PropertySheetHeader) - SetLastError(ERROR_INVALID_PARAMETER); - else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE) - SetLastError(ERROR_INVALID_FLAGS); - else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL)) - SetLastError(ERROR_INVALID_PARAMETER); - else if (!PropertySheetHeader) - SetLastError(ERROR_INVALID_PARAMETER); - else if (PropertySheetType != DIGCDP_FLAG_ADVANCED - && PropertySheetType != DIGCDP_FLAG_BASIC - && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED - && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - HKEY hKey = INVALID_HANDLE_VALUE; - SP_PROPSHEETPAGE_REQUEST Request; - LPWSTR PropPageProvider = NULL; - HMODULE hModule = NULL; - PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL; - struct ClassDevPropertySheetsData PropPageData; - DWORD dwLength, dwRegType; - DWORD rc; - - if (DeviceInfoData) - hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE); - else - { - hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE, - DIOCR_INSTALLER, list->MachineName + 2, NULL); - } - if (hKey == INVALID_HANDLE_VALUE) - goto cleanup; - - rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength); - if (rc == ERROR_FILE_NOT_FOUND) - { - /* No registry key. As it is optional, don't say it's a bad error */ - if (RequiredSize) - *RequiredSize = 0; - ret = TRUE; - goto cleanup; - } - else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ) - { - SetLastError(rc); - goto cleanup; - } - - PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR)); - if (!PropPageProvider) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength); - if (rc != ERROR_SUCCESS) - { - SetLastError(rc); - goto cleanup; - } - PropPageProvider[dwLength / sizeof(WCHAR)] = 0; - - rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider); - if (rc != ERROR_SUCCESS) - { - SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER); - goto cleanup; - } - - Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST); - Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES; - Request.DeviceInfoSet = DeviceInfoSet; - Request.DeviceInfoData = DeviceInfoData; - PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages]; - PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages; - PropPageData.NumberOfPages = 0; - ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData); - if (!ret) - goto cleanup; - - if (RequiredSize) - *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages; - if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages) - { - PropertySheetHeader->nPages += PropPageData.NumberOfPages; - ret = TRUE; - } - else - { - PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages; - SetLastError(ERROR_INSUFFICIENT_BUFFER); - } - -cleanup: - if (hKey != INVALID_HANDLE_VALUE) - RegCloseKey(hKey); - HeapFree(GetProcessHeap(), 0, PropPageProvider); - FreeFunctionPointer(hModule, pPropPageProvider); - } - - TRACE("Returning %d\n", ret); - return ret; -} /*********************************************************************** * SetupDiCreateDevRegKeyA (SETUPAPI.@) @@ -5451,862 +2647,6 @@ SetupDiCreateDeviceInfoW( return ret; } -/*********************************************************************** - * Helper functions for SetupDiBuildDriverInfoList - */ -static BOOL -AddDriverToList( - IN PLIST_ENTRY DriverListHead, - IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */ - IN LPGUID ClassGuid, - IN INFCONTEXT ContextDevice, - IN struct InfFileDetails *InfFileDetails, - IN LPCWSTR InfFile, - IN LPCWSTR ProviderName, - IN LPCWSTR ManufacturerName, - IN LPCWSTR MatchingId, - FILETIME DriverDate, - DWORDLONG DriverVersion, - IN DWORD Rank) -{ - struct DriverInfoElement *driverInfo = NULL; - HANDLE hFile = INVALID_HANDLE_VALUE; - DWORD RequiredSize = 128; /* Initial buffer size */ - BOOL Result = FALSE; - PLIST_ENTRY PreviousEntry; - LPWSTR InfInstallSection = NULL; - BOOL ret = FALSE; - - driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement)); - if (!driverInfo) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - memset(driverInfo, 0, sizeof(struct DriverInfoElement)); - - driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); - driverInfo->Details.Reserved = (ULONG_PTR)driverInfo; - - /* Copy InfFileName field */ - strncpyW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1); - driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0'; - - /* Fill InfDate field */ - hFile = CreateFile( - InfFile, - GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) - goto cleanup; - Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate); - if (!Result) - goto cleanup; - - /* Fill SectionName field */ - Result = SetupGetStringFieldW( - &ContextDevice, - 1, - driverInfo->Details.SectionName, LINE_LEN, - NULL); - if (!Result) - goto cleanup; - - /* Fill DrvDescription field */ - Result = SetupGetStringFieldW( - &ContextDevice, - 0, /* Field index */ - driverInfo->Details.DrvDescription, LINE_LEN, - NULL); - - /* Copy MatchingId information */ - if (MatchingId) - { - driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); - if (!driverInfo->MatchingId) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); - } - else - driverInfo->MatchingId = NULL; - - /* Get inf install section */ - 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) - goto cleanup; - Result = SetupGetStringFieldW( - &ContextDevice, - 1, /* Field index */ - InfInstallSection, RequiredSize, - &RequiredSize); - } - if (!Result) - goto cleanup; - - TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n", - debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile), - debugstr_w(InfInstallSection), Rank); - - driverInfo->DriverRank = Rank; - memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME)); - memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID)); - driverInfo->Info.DriverType = DriverType; - driverInfo->Info.Reserved = (ULONG_PTR)driverInfo; - strncpyW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1); - driverInfo->Info.Description[LINE_LEN - 1] = '\0'; - strncpyW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1); - driverInfo->Info.MfgName[LINE_LEN - 1] = '\0'; - if (ProviderName) - { - strncpyW(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; - ReferenceInfFile(InfFileDetails); - driverInfo->InfFileDetails = InfFileDetails; - - /* Insert current driver in driver list, according to its rank */ - PreviousEntry = DriverListHead->Flink; - while (PreviousEntry != DriverListHead) - { - struct DriverInfoElement *CurrentDriver; - CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry); - if (CurrentDriver->DriverRank > Rank || - (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart)) - { - /* Insert before the current item */ - InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry); - break; - } - PreviousEntry = PreviousEntry->Flink; - } - if (PreviousEntry == DriverListHead) - { - /* Insert at the end of the list */ - InsertTailList(DriverListHead, &driverInfo->ListEntry); - } - - ret = TRUE; - -cleanup: - if (!ret) - { - if (driverInfo) - HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); - HeapFree(GetProcessHeap(), 0, driverInfo); - } - if (hFile != INVALID_HANDLE_VALUE) - CloseHandle(hFile); - HeapFree(GetProcessHeap(), 0, InfInstallSection); - - return ret; -} - -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 DriverVer = NULL; - LPWSTR ProviderName = NULL; - LPWSTR pComma; /* Points into DriverVer */ - LPWSTR pVersion = NULL; /* Points into DriverVer */ - SYSTEMTIME SystemTime; - BOOL Result; - BOOL ret = FALSE; /* Final result */ - - /* Get class Guid */ - if (!SetupGetLineTextW( - NULL, /* Context */ - hInf, - Version, ClassGUID, - guidW, sizeof(guidW), - NULL /* Required size */)) - { - goto cleanup; - } - guidW[37] = '\0'; /* Replace the } by a NULL character */ - if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK) - { - SetLastError(ERROR_GEN_FAILURE); - goto cleanup; - } - - /* Get provider name */ - Result = SetupGetLineTextW( - NULL, /* Context */ - hInf, Version, INF_PROVIDER, - NULL, 0, - &RequiredSize); - if (Result) - { - /* We know know the needed buffer size */ - ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); - if (!ProviderName) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - Result = SetupGetLineTextW( - NULL, /* Context */ - hInf, Version, INF_PROVIDER, - ProviderName, RequiredSize, - &RequiredSize); - } - if (!Result) - goto cleanup; - *pProviderName = ProviderName; - - /* Read the "DriverVer" value */ - Result = SetupGetLineTextW( - NULL, /* Context */ - hInf, Version, INF_DRIVER_VER, - NULL, 0, - &RequiredSize); - if (Result) - { - /* We know know the needed buffer size */ - DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); - if (!DriverVer) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - Result = SetupGetLineTextW( - NULL, /* Context */ - hInf, Version, INF_DRIVER_VER, - DriverVer, RequiredSize, - &RequiredSize); - } - if (!Result) - goto cleanup; - - /* Get driver date and driver version, by analyzing the "DriverVer" value */ - pComma = strchrW(DriverVer, ','); - if (pComma != NULL) - { - *pComma = UNICODE_NULL; - pVersion = pComma + 1; - } - /* Get driver date version. Invalid date = 00/00/00 */ - memset(DriverDate, 0, sizeof(FILETIME)); - if (strlenW(DriverVer) == 10 - && (DriverVer[2] == '-' || DriverVer[2] == '/') - && (DriverVer[5] == '-' || DriverVer[5] == '/')) - { - memset(&SystemTime, 0, sizeof(SYSTEMTIME)); - DriverVer[2] = DriverVer[5] = UNICODE_NULL; - SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0'; - SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0'; - SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0'; - SystemTimeToFileTime(&SystemTime, DriverDate); - } - /* Get driver version. Invalid version = 0.0.0.0 */ - *DriverVersion = 0; - if (pVersion) - { - WORD Major, Minor = 0, Revision = 0, Build = 0; - LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL; - LARGE_INTEGER fullVersion; - - pMinor = strchrW(pVersion, '.'); - if (pMinor) - { - *pMinor = 0; - pRevision = strchrW(++pMinor, '.'); - Minor = atoiW(pMinor); - } - if (pRevision) - { - *pRevision = 0; - pBuild = strchrW(++pRevision, '.'); - Revision = atoiW(pRevision); - } - if (pBuild) - { - *pBuild = 0; - pBuild++; - Build = atoiW(pBuild); - } - Major = atoiW(pVersion); - fullVersion.u.HighPart = Major << 16 | Minor; - fullVersion.u.LowPart = Revision << 16 | Build; - memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER)); - } - - ret = TRUE; - -cleanup: - if (!ret) - HeapFree(GetProcessHeap(), 0, ProviderName); - HeapFree(GetProcessHeap(), 0, DriverVer); - - return ret; -} - -static BOOL -GetHardwareAndCompatibleIDsLists( - IN HDEVINFO DeviceInfoSet, - IN OUT PSP_DEVINFO_DATA DeviceInfoData, - OUT LPWSTR *pHardwareIDs OPTIONAL, - OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL, - OUT LPWSTR *pCompatibleIDs OPTIONAL, - OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL) -{ - LPWSTR HardwareIDs = NULL; - LPWSTR CompatibleIDs = NULL; - DWORD RequiredSize; - BOOL Result; - - /* Get hardware IDs list */ - Result = FALSE; - RequiredSize = 512; /* Initial buffer size */ - SetLastError(ERROR_INSUFFICIENT_BUFFER); - while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - MyFree(HardwareIDs); - HardwareIDs = MyMalloc(RequiredSize); - if (!HardwareIDs) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - Result = SetupDiGetDeviceRegistryPropertyW( - DeviceInfoSet, - DeviceInfoData, - SPDRP_HARDWAREID, - NULL, - (PBYTE)HardwareIDs, - RequiredSize, - &RequiredSize); - } - if (!Result) - { - if (GetLastError() == ERROR_FILE_NOT_FOUND) - { - /* No hardware ID for this device */ - MyFree(HardwareIDs); - HardwareIDs = NULL; - RequiredSize = 0; - } - else - goto done; - } - if (pHardwareIDs) - *pHardwareIDs = HardwareIDs; - if (pHardwareIDsRequiredSize) - *pHardwareIDsRequiredSize = RequiredSize; - - /* Get compatible IDs list */ - Result = FALSE; - RequiredSize = 512; /* Initial buffer size */ - SetLastError(ERROR_INSUFFICIENT_BUFFER); - while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - MyFree(CompatibleIDs); - CompatibleIDs = MyMalloc(RequiredSize); - if (!CompatibleIDs) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - Result = SetupDiGetDeviceRegistryPropertyW( - DeviceInfoSet, - DeviceInfoData, - SPDRP_COMPATIBLEIDS, - NULL, - (PBYTE)CompatibleIDs, - RequiredSize, - &RequiredSize); - } - if (!Result) - { - if (GetLastError() == ERROR_FILE_NOT_FOUND) - { - /* No compatible ID for this device */ - MyFree(CompatibleIDs); - CompatibleIDs = NULL; - RequiredSize = 0; - } - else - goto done; - } - if (pCompatibleIDs) - *pCompatibleIDs = CompatibleIDs; - if (pCompatibleIDsRequiredSize) - *pCompatibleIDsRequiredSize = RequiredSize; - - Result = TRUE; - -done: - if (!Result) - { - MyFree(HardwareIDs); - MyFree(CompatibleIDs); - } - return Result; -} - -static struct InfFileDetails * -CreateInfFileDetails( - IN LPCWSTR FullInfFileName) -{ - struct InfFileDetails *details; - PWCHAR last; - DWORD Needed; - - Needed = FIELD_OFFSET(struct InfFileDetails, szData) - + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL); - - details = HeapAlloc(GetProcessHeap(), 0, Needed); - if (!details) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } - - memset(details, 0, Needed); - strcpyW(details->szData, FullInfFileName); - last = strrchrW(details->szData, '\\'); - if (last) - { - details->DirectoryName = details->szData; - details->FileName = last + 1; - *last = '\0'; - } - else - details->FileName = details->szData; - ReferenceInfFile(details); - details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL); - if (details->hInf == INVALID_HANDLE_VALUE) - { - HeapFree(GetProcessHeap(), 0, details); - return NULL; - } - return details; -} - -/*********************************************************************** - * SetupDiBuildDriverInfoList (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiBuildDriverInfoList( - IN HDEVINFO DeviceInfoSet, - IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN DWORD DriverType) -{ - struct DeviceInfoSet *list; - SP_DEVINSTALL_PARAMS_W InstallParams; - PVOID Buffer = NULL; - struct InfFileDetails *currentInfFileDetails = NULL; - LPWSTR ProviderName = NULL; - LPWSTR ManufacturerName = NULL; - WCHAR ManufacturerSection[LINE_LEN + 1]; - LPWSTR HardwareIDs = NULL; - LPWSTR CompatibleIDs = NULL; - LPWSTR FullInfFileName = NULL; - LPWSTR ExcludeFromSelect = NULL; - FILETIME DriverDate; - DWORDLONG DriverVersion = 0; - 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_COMPATDRIVER && !DeviceInfoData) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else - { - PLIST_ENTRY pDriverListHead = &list->DriverListHead; - BOOL Result; - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - if (!Result) - goto done; - - if (DeviceInfoData) - { - struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; - if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)) - pDriverListHead = &devInfo->DriverListHead; - } - - if (DriverType == SPDIT_COMPATDRIVER) - { - /* Get hardware and compatible IDs lists */ - Result = GetHardwareAndCompatibleIDsLists( - DeviceInfoSet, - DeviceInfoData, - &HardwareIDs, - NULL, - &CompatibleIDs, - NULL); - if (!Result) - goto done; - if (!HardwareIDs && !CompatibleIDs) - { - SetLastError(ERROR_FILE_NOT_FOUND); - goto done; - } - } - - if (InstallParams.Flags & DI_ENUMSINGLEINF) - { - /* InstallParams.DriverPath contains the name of a .inf file */ - RequiredSize = strlenW(InstallParams.DriverPath) + 2; - Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); - if (!Buffer) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - strcpyW(Buffer, InstallParams.DriverPath); - ((LPWSTR)Buffer)[RequiredSize - 1] = 0; - Result = TRUE; - } - else - { - /* 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( - *InstallParams.DriverPath ? InstallParams.DriverPath : NULL, - INF_STYLE_WIN4, - Buffer, RequiredSize, - &RequiredSize); - } - if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND) - { - /* No .inf file in specified directory. So, we should - * success as we created an empty driver info list. - */ - ret = TRUE; - goto done; - } - } - if (Result) - { - LPCWSTR filename; - LPWSTR pFullFilename; - - if (InstallParams.Flags & DI_ENUMSINGLEINF) - { - /* Only a filename */ - FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); - if (!FullInfFileName) - goto done; - pFullFilename = &FullInfFileName[0]; - } - else if (*InstallParams.DriverPath) - { - /* Directory name specified */ - DWORD len; - len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL); - if (len == 0) - goto done; - FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR)); - if (!FullInfFileName) - goto done; - len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL); - if (len == 0) - goto done; - if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') - strcatW(FullInfFileName, BackSlash); - pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; - } - else - { - /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */ - DWORD len; - len = GetSystemWindowsDirectoryW(NULL, 0); - if (len == 0) - goto done; - FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + strlenW(InfDirectory) + MAX_PATH) * sizeof(WCHAR)); - if (!FullInfFileName) - goto done; - len = GetSystemWindowsDirectoryW(FullInfFileName, len); - if (len == 0) - goto done; - if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') - strcatW(FullInfFileName, BackSlash); - strcatW(FullInfFileName, InfDirectory); - pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; - } - - for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1) - { - INFCONTEXT ContextManufacturer, ContextDevice; - GUID ClassGuid; - - strcpyW(pFullFilename, filename); - TRACE("Opening file %s\n", debugstr_w(FullInfFileName)); - - currentInfFileDetails = CreateInfFileDetails(FullInfFileName); - if (!currentInfFileDetails) - continue; - - if (!GetVersionInformationFromInfFile( - currentInfFileDetails->hInf, - &ClassGuid, - &ProviderName, - &DriverDate, - &DriverVersion)) - { - DereferenceInfFile(currentInfFileDetails); - currentInfFileDetails = NULL; - 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)) - { - goto next; - } - } - - if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS) - { - /* Read ExcludeFromSelect control flags */ - /* FIXME */ - } - else - FIXME("ExcludeFromSelect list ignored\n"); - - /* Get the manufacturers list */ - Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer); - while (Result) - { - Result = SetupGetStringFieldW( - &ContextManufacturer, - 0, /* Field index */ - NULL, 0, - &RequiredSize); - if (Result) - { - /* We got the needed size for the 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); - } - /* Get manufacturer section name */ - Result = SetupGetStringFieldW( - &ContextManufacturer, - 1, /* Field index */ - ManufacturerSection, LINE_LEN, - &RequiredSize); - if (Result) - { - ManufacturerSection[RequiredSize] = 0; /* Final NULL char */ - /* Add (possible) extension to manufacturer section name */ - Result = SetupDiGetActualSectionToInstallW( - currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL); - if (Result) - { - TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection)); - Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice); - } - } - while (Result) - { - if (DriverType == SPDIT_CLASSDRIVER) - { - /* FIXME: Check ExcludeFromSelect list */ - if (!AddDriverToList( - pDriverListHead, - DriverType, - &ClassGuid, - ContextDevice, - currentInfFileDetails, - FullInfFileName, - ProviderName, - ManufacturerName, - NULL, - DriverDate, DriverVersion, - 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; - } - /* FIXME: Check ExcludeFromSelect list */ - DriverAlreadyAdded = FALSE; - for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) - { - if (strcmpiW(DeviceId, currentId) == 0) - { - AddDriverToList( - pDriverListHead, - DriverType, - &ClassGuid, - ContextDevice, - currentInfFileDetails, - FullInfFileName, - ProviderName, - ManufacturerName, - currentId, - DriverDate, DriverVersion, - DriverRank + (i == 2 ? 0 : 0x1000 + i - 3)); - DriverAlreadyAdded = TRUE; - } - } - if (CompatibleIDs) - { - for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) - { - if (strcmpiW(DeviceId, currentId) == 0) - { - AddDriverToList( - pDriverListHead, - DriverType, - &ClassGuid, - ContextDevice, - currentInfFileDetails, - FullInfFileName, - ProviderName, - ManufacturerName, - currentId, - DriverDate, DriverVersion, - DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3)); - DriverAlreadyAdded = TRUE; - } - } - } - HeapFree(GetProcessHeap(), 0, DeviceId); - } - } - Result = SetupFindNextLine(&ContextDevice, &ContextDevice); - } - - HeapFree(GetProcessHeap(), 0, ManufacturerName); - ManufacturerName = NULL; - Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer); - } - - ret = TRUE; -next: - HeapFree(GetProcessHeap(), 0, ProviderName); - HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); - ProviderName = ExcludeFromSelect = NULL; - - DereferenceInfFile(currentInfFileDetails); - currentInfFileDetails = NULL; - } - ret = TRUE; - } - } - -done: - if (ret) - { - if (DeviceInfoData) - { - InstallParams.Flags |= DI_DIDCOMPAT; - InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO; - } - else - { - InstallParams.Flags |= DI_DIDCLASS; - InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST; - } - ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - } - - HeapFree(GetProcessHeap(), 0, ProviderName); - HeapFree(GetProcessHeap(), 0, ManufacturerName); - MyFree(HardwareIDs); - MyFree(CompatibleIDs); - HeapFree(GetProcessHeap(), 0, FullInfFileName); - HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); - if (currentInfFileDetails) - DereferenceInfFile(currentInfFileDetails); - HeapFree(GetProcessHeap(), 0, Buffer); - - TRACE("Returning %d\n", ret); - return ret; -} /*********************************************************************** * SetupDiDeleteDeviceInfo (SETUPAPI.@) @@ -6324,90 +2664,6 @@ SetupDiDeleteDeviceInfo( } -/*********************************************************************** - * SetupDiDestroyDriverInfoList (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiDestroyDriverInfoList( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN DWORD DriverType) -{ - struct DeviceInfoSet *list; - BOOL ret = FALSE; - - TRACE("%p %p 0x%lx\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 (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) - 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 - { - PLIST_ENTRY ListEntry; - struct DriverInfoElement *driverInfo; - SP_DEVINSTALL_PARAMS_W InstallParams; - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) - goto done; - - if (!DeviceInfoData) - /* Fall back to destroying class driver list */ - DriverType = SPDIT_CLASSDRIVER; - - if (DriverType == SPDIT_CLASSDRIVER) - { - while (!IsListEmpty(&list->DriverListHead)) - { - ListEntry = RemoveHeadList(&list->DriverListHead); - driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); - DestroyDriverInfoElement(driverInfo); - } - InstallParams.Reserved = 0; - InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS); - InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST; - ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams); - } - else - { - SP_DEVINSTALL_PARAMS_W InstallParamsSet; - struct DeviceInfoElement *deviceInfo; - - InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet)) - goto done; - deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; - while (!IsListEmpty(&deviceInfo->DriverListHead)) - { - ListEntry = RemoveHeadList(&deviceInfo->DriverListHead); - driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); - if ((PVOID)InstallParamsSet.Reserved == driverInfo) - { - InstallParamsSet.Reserved = 0; - SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet); - } - DestroyDriverInfoElement(driverInfo); - } - InstallParams.Reserved = 0; - InstallParams.Flags &= ~DI_DIDCOMPAT; - InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO; - ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - } - } - -done: - TRACE("Returning %d\n", ret); - return ret; -} - - /*********************************************************************** * SetupDiOpenDeviceInfoA (SETUPAPI.@) */ @@ -6549,136 +2805,6 @@ cleanup: } -/*********************************************************************** - * 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_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 = NULL; - PLIST_ENTRY ItemList; - if (DeviceInfoData) - devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; - if (!devInfo || (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 = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); - - memcpy( - &DriverInfoData->DriverType, - &DrvInfo->Info.DriverType, - DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); - ret = TRUE; - } - } - - TRACE("Returning %d\n", ret); - return ret; -} - - /*********************************************************************** * SetupDiGetSelectedDevice (SETUPAPI.@) */ @@ -6717,116 +2843,6 @@ SetupDiGetSelectedDevice( } -/*********************************************************************** - * SetupDiGetSelectedDriverA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetSelectedDriverA( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - OUT PSP_DRVINFO_DATA_A DriverInfoData) -{ - SP_DRVINFO_DATA_V2_W driverInfoData2W; - BOOL ret = FALSE; - - 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 = SetupDiGetSelectedDriverW(DeviceInfoSet, - DeviceInfoData, - &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; - } - } - } - - 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 - { - SP_DEVINSTALL_PARAMS InstallParams; - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) - { - struct DriverInfoElement *driverInfo; - driverInfo = (struct DriverInfoElement *)InstallParams.Reserved; - if (driverInfo == NULL) - SetLastError(ERROR_NO_DRIVER_SELECTED); - else - { - memcpy( - &DriverInfoData->DriverType, - &driverInfo->Info.DriverType, - DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); - ret = TRUE; - } - } - } - - TRACE("Returning %d\n", ret); - return ret; -} - - /*********************************************************************** * SetupDiSetSelectedDevice (SETUPAPI.@) */ @@ -6861,484 +2877,6 @@ SetupDiSetSelectedDevice( } -/*********************************************************************** - * SetupDiSetSelectedDriverA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiSetSelectedDriverA( - IN HDEVINFO DeviceInfoSet, - IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL) -{ - SP_DRVINFO_DATA_V1_W DriverInfoDataW; - PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL; - BOOL ret = FALSE; - - if (DriverInfoData != NULL) - { - if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) && - DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A)); - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); - DriverInfoDataW.Reserved = DriverInfoData->Reserved; - - if (DriverInfoDataW.Reserved == 0) - { - DriverInfoDataW.DriverType = DriverInfoData->DriverType; - - /* convert the strings to unicode */ - if (!MultiByteToWideChar(CP_ACP, - 0, - DriverInfoData->Description, - LINE_LEN, - DriverInfoDataW.Description, - LINE_LEN) || - !MultiByteToWideChar(CP_ACP, - 0, - DriverInfoData->ProviderName, - LINE_LEN, - DriverInfoDataW.ProviderName, - LINE_LEN)) - { - return FALSE; - } - } - - pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW; - } - - ret = SetupDiSetSelectedDriverW(DeviceInfoSet, - DeviceInfoData, - pDriverInfoDataW); - - if (ret && pDriverInfoDataW != NULL) - { - DriverInfoData->Reserved = DriverInfoDataW.Reserved; - } - - return ret; -} - - -/*********************************************************************** - * SetupDiSetSelectedDriverW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiSetSelectedDriverW( - IN HDEVINFO DeviceInfoSet, - IN OUT 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 DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved; - ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead; - } - else - { - pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved; - 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 = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); - if (driverInfo->Info.DriverType == DriverInfoData->DriverType - && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0 - && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0) - { - break; - } - } - ItemList = ItemList->Flink; - } - if (ItemList == ListHead) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); - DriverInfoData->Reserved = (ULONG_PTR)ItemList; - ret = TRUE; - TRACE("Choosing driver whose rank is 0x%lx\n", - (*pDriverInfo)->DriverRank); - if (DeviceInfoData) - memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID)); - } - } - } - - TRACE("Returning %d\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiGetDriverInfoDetailA (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetDriverInfoDetailA( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN PSP_DRVINFO_DATA_A DriverInfoData, - IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL, - IN DWORD DriverInfoDetailDataSize, - OUT PDWORD RequiredSize OPTIONAL) -{ - SP_DRVINFO_DATA_V2_W DriverInfoDataW; - PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL; - DWORD BufSize = 0; - DWORD HardwareIDLen = 0; - BOOL ret = FALSE; - - /* do some sanity checks, the unicode version might do more thorough checks */ - if (DriverInfoData == NULL || - (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) || - (DriverInfoDetailData != NULL && - (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) || - DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A)))) - { - SetLastError(ERROR_INVALID_PARAMETER); - goto Cleanup; - } - - /* make sure we support both versions of the SP_DRVINFO_DATA structure */ - if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A)) - { - DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); - } - else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) - { - DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); - } - else - { - SetLastError(ERROR_INVALID_PARAMETER); - goto Cleanup; - } - DriverInfoDataW.DriverType = DriverInfoData->DriverType; - DriverInfoDataW.Reserved = DriverInfoData->Reserved; - - /* convert the strings to unicode */ - if (MultiByteToWideChar(CP_ACP, - 0, - DriverInfoData->Description, - LINE_LEN, - DriverInfoDataW.Description, - LINE_LEN) && - MultiByteToWideChar(CP_ACP, - 0, - DriverInfoData->MfgName, - LINE_LEN, - DriverInfoDataW.MfgName, - LINE_LEN) && - MultiByteToWideChar(CP_ACP, - 0, - DriverInfoData->ProviderName, - LINE_LEN, - DriverInfoDataW.ProviderName, - LINE_LEN)) - { - if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W)) - { - DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate; - DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion; - } - - if (DriverInfoDetailData != NULL) - { - /* calculate the unicode buffer size from the ansi buffer size */ - HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID); - BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) + - (HardwareIDLen * sizeof(WCHAR)); - - DriverInfoDetailDataW = MyMalloc(BufSize); - if (DriverInfoDetailDataW == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto Cleanup; - } - - /* initialize the buffer */ - ZeroMemory(DriverInfoDetailDataW, - BufSize); - DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); - } - - /* call the unicode version */ - ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet, - DeviceInfoData, - &DriverInfoDataW, - DriverInfoDetailDataW, - BufSize, - RequiredSize); - - if (ret) - { - if (DriverInfoDetailDataW != NULL) - { - /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */ - DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A); - DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate; - DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved; - if (WideCharToMultiByte(CP_ACP, - 0, - DriverInfoDetailDataW->SectionName, - LINE_LEN, - DriverInfoDetailData->SectionName, - LINE_LEN, - NULL, - NULL) && - WideCharToMultiByte(CP_ACP, - 0, - DriverInfoDetailDataW->InfFileName, - MAX_PATH, - DriverInfoDetailData->InfFileName, - MAX_PATH, - NULL, - NULL) && - WideCharToMultiByte(CP_ACP, - 0, - DriverInfoDetailDataW->DrvDescription, - LINE_LEN, - DriverInfoDetailData->DrvDescription, - LINE_LEN, - NULL, - NULL) && - WideCharToMultiByte(CP_ACP, - 0, - DriverInfoDetailDataW->HardwareID, - HardwareIDLen, - DriverInfoDetailData->HardwareID, - HardwareIDLen, - NULL, - NULL)) - { - DWORD len, cnt = 0; - DWORD hwidlen = HardwareIDLen; - CHAR *s = DriverInfoDetailData->HardwareID; - - /* count the strings in the list */ - while (*s != '\0') - { - len = lstrlenA(s) + 1; - if (hwidlen > len) - { - cnt++; - s += len; - hwidlen -= len; - } - else - { - /* looks like the string list wasn't terminated... */ - SetLastError(ERROR_INVALID_USER_BUFFER); - ret = FALSE; - break; - } - } - - /* make sure CompatIDsOffset points to the second string in the - list, if present */ - if (cnt > 1) - { - DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1; - DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) - - DriverInfoDetailData->CompatIDsOffset + 1; - } - else - { - DriverInfoDetailData->CompatIDsOffset = 0; - DriverInfoDetailData->CompatIDsLength = 0; - } - } - else - { - ret = FALSE; - } - } - - if (RequiredSize != NULL) - { - *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + - (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR)); - } - } - } - -Cleanup: - if (DriverInfoDetailDataW != NULL) - { - MyFree(DriverInfoDetailDataW); - } - - return ret; -} - -/*********************************************************************** - * SetupDiGetDriverInfoDetailW (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiGetDriverInfoDetailW( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, - IN PSP_DRVINFO_DATA_W DriverInfoData, - IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL, - IN DWORD DriverInfoDetailDataSize, - OUT PDWORD RequiredSize OPTIONAL) -{ - BOOL ret = FALSE; - - TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData, - DriverInfoData, DriverInfoDetailData, - DriverInfoDetailDataSize, RequiredSize); - - 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) - SetLastError(ERROR_INVALID_PARAMETER); - else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W)) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else if (DriverInfoData->Reserved == 0) - SetLastError(ERROR_NO_DRIVER_SELECTED); - else - { - struct DriverInfoElement *driverInfoElement; - LPWSTR HardwareIDs = NULL; - LPWSTR CompatibleIDs = NULL; - LPWSTR pBuffer = NULL; - LPCWSTR DeviceID = NULL; - ULONG HardwareIDsSize, CompatibleIDsSize; - ULONG sizeNeeded, sizeLeft, size; - BOOL Result; - - driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved; - - /* Get hardware and compatible IDs lists */ - Result = GetHardwareAndCompatibleIDsLists( - DeviceInfoSet, - DeviceInfoData, - &HardwareIDs, &HardwareIDsSize, - &CompatibleIDs, &CompatibleIDsSize); - if (!Result) - goto done; - - sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) - + HardwareIDsSize + CompatibleIDsSize; - if (RequiredSize) - *RequiredSize = sizeNeeded; - - if (!DriverInfoDetailData) - { - ret = TRUE; - goto done; - } - - memcpy( - DriverInfoDetailData, - &driverInfoElement->Details, - driverInfoElement->Details.cbSize); - DriverInfoDetailData->CompatIDsOffset = 0; - DriverInfoDetailData->CompatIDsLength = 0; - - sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR); - pBuffer = DriverInfoDetailData->HardwareID; - /* Add as many as possible HardwareIDs in the list */ - DeviceID = HardwareIDs; - while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) - { - TRACE("Adding %s to list\n", debugstr_w(DeviceID)); - wcscpy(pBuffer, DeviceID); - DeviceID += size + 1; - pBuffer += size + 1; - sizeLeft -= size + 1; - DriverInfoDetailData->CompatIDsOffset += size + 1; - } - if (sizeLeft > 0) - { - *pBuffer = UNICODE_NULL; - sizeLeft--; - DriverInfoDetailData->CompatIDsOffset++; - } - /* Add as many as possible CompatibleIDs in the list */ - DeviceID = CompatibleIDs; - while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) - { - TRACE("Adding %s to list\n", debugstr_w(DeviceID)); - wcscpy(pBuffer, DeviceID); - DeviceID += size + 1; - pBuffer += size + 1; - sizeLeft -= size + 1; - DriverInfoDetailData->CompatIDsLength += size + 1; - } - if (sizeLeft > 0) - { - *pBuffer = UNICODE_NULL; - sizeLeft--; - DriverInfoDetailData->CompatIDsLength++; - } - - if (sizeNeeded > DriverInfoDetailDataSize) - SetLastError(ERROR_INSUFFICIENT_BUFFER); - else - ret = TRUE; - -done: - MyFree(HardwareIDs); - MyFree(CompatibleIDs); - } - - TRACE("Returning %d\n", ret); - return ret; -} - /* Return the current hardware profile id, or -1 if error */ static DWORD GetCurrentHwProfile( @@ -7536,42 +3074,6 @@ cleanup: return ret; } -/*********************************************************************** - * SetupDiSelectBestCompatDrv (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiSelectBestCompatDrv( - IN HDEVINFO DeviceInfoSet, - IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) -{ - SP_DRVINFO_DATA_W drvInfoData; - BOOL ret; - - TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); - - /* Drivers are sorted by rank in the driver list, so - * the first driver in the list is the best one. - */ - drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W); - ret = SetupDiEnumDriverInfoW( - DeviceInfoSet, - DeviceInfoData, - SPDIT_COMPATDRIVER, - 0, /* Member index */ - &drvInfoData); - - if (ret) - { - ret = SetupDiSetSelectedDriverW( - DeviceInfoSet, - DeviceInfoData, - &drvInfoData); - } - - TRACE("Returning %d\n", ret); - return ret; -} - /*********************************************************************** * SetupDiSelectDevice (SETUPAPI.@) */ @@ -7585,104 +3087,6 @@ SetupDiSelectDevice( return FALSE; } -/*********************************************************************** - * SetupDiInstallDriverFiles (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiInstallDriverFiles( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData) -{ - BOOL ret = FALSE; - - TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); - - 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 (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0) - SetLastError(ERROR_NO_DRIVER_SELECTED); - else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0) - SetLastError(ERROR_NO_DRIVER_SELECTED); - else - { - SP_DEVINSTALL_PARAMS_W InstallParams; - struct DriverInfoElement *SelectedDriver; - WCHAR SectionName[MAX_PATH]; - DWORD SectionNameLength = 0; - PVOID InstallMsgHandler; - PVOID InstallMsgHandlerContext; - PVOID Context = NULL; - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - if (!ret) - goto done; - - SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; - if (!SelectedDriver) - { - SetLastError(ERROR_NO_DRIVER_SELECTED); - goto done; - } - - ret = SetupDiGetActualSectionToInstallW( - SelectedDriver->InfFileDetails->hInf, - SelectedDriver->Details.SectionName, - SectionName, MAX_PATH, &SectionNameLength, NULL); - if (!ret) - goto done; - - if (InstallParams.InstallMsgHandler) - { - InstallMsgHandler = InstallParams.InstallMsgHandler; - InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext; - } - else - { - Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); - if (!Context) - goto cleanup; - InstallMsgHandler = SetupDefaultQueueCallback; - InstallMsgHandlerContext = Context; - } - ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, - SelectedDriver->InfFileDetails->hInf, SectionName, - SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, - InstallMsgHandler, InstallMsgHandlerContext, - DeviceInfoSet, DeviceInfoData); - if (!ret) - goto done; - - /* Install files from .CoInstallers section */ - lstrcatW(SectionName, DotCoInstallers); - ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, - SelectedDriver->InfFileDetails->hInf, SectionName, - SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, - InstallMsgHandler, InstallMsgHandlerContext, - DeviceInfoSet, DeviceInfoData); - if (!ret) - goto done; - - /* Set the DI_NOFILECOPY flag to prevent another - * installation during SetupDiInstallDevice */ - InstallParams.Flags |= DI_NOFILECOPY; - ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - -cleanup: - if (Context) - SetupTermDefaultQueueCallback(Context); - } - -done: - TRACE("Returning %d\n", ret); - return ret; -} /*********************************************************************** * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@) @@ -7779,150 +3183,6 @@ cleanup: return ret; } -static BOOL -InstallOneInterface( - IN LPGUID InterfaceGuid, - IN LPCWSTR ReferenceString, - IN LPCWSTR InterfaceSection, - IN UINT InterfaceFlags) -{ - if (InterfaceFlags != 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid), - debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags); - return TRUE; -} - -/*********************************************************************** - * SetupDiInstallDeviceInterfaces (SETUPAPI.@) - */ -BOOL WINAPI -SetupDiInstallDeviceInterfaces( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData) -{ - struct DeviceInfoSet *list = NULL; - BOOL ret = FALSE; - - TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); - - if (!DeviceInfoSet) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) - SetLastError(ERROR_INVALID_HANDLE); - else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) - SetLastError(ERROR_INVALID_HANDLE); - else if (!DeviceInfoData) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) - SetLastError(ERROR_INVALID_USER_BUFFER); - else - { - struct DriverInfoElement *SelectedDriver; - SP_DEVINSTALL_PARAMS_W InstallParams; - WCHAR SectionName[MAX_PATH]; - DWORD SectionNameLength = 0; - INFCONTEXT ContextInterface; - LPWSTR InterfaceGuidString = NULL; - LPWSTR ReferenceString = NULL; - LPWSTR InterfaceSection = NULL; - INT InterfaceFlags; - GUID InterfaceGuid; - BOOL Result; - - InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); - Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); - if (!Result) - goto cleanup; - - SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; - if (SelectedDriver == NULL) - { - SetLastError(ERROR_NO_DRIVER_SELECTED); - ret = FALSE; - goto cleanup; - } - - /* Get .Interfaces section name */ - Result = SetupDiGetActualSectionToInstallW( - SelectedDriver->InfFileDetails->hInf, - SelectedDriver->Details.SectionName, - SectionName, MAX_PATH, &SectionNameLength, NULL); - if (!Result || SectionNameLength > MAX_PATH - strlenW(DotInterfaces) - 1) - goto cleanup; - strcatW(SectionName, DotInterfaces); - - ret = TRUE; - Result = SetupFindFirstLineW( - SelectedDriver->InfFileDetails->hInf, - SectionName, - AddInterface, - &ContextInterface); - while (ret && Result) - { - ret = GetStringField(&ContextInterface, 1, &InterfaceGuidString); - if (!ret) - goto cleanup; - else if (strlenW(InterfaceGuidString) != MAX_GUID_STRING_LEN - 1) - { - SetLastError(ERROR_INVALID_PARAMETER); - ret = FALSE; - goto cleanup; - } - - InterfaceGuidString[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */ - if (UuidFromStringW(&InterfaceGuidString[1], &InterfaceGuid) != RPC_S_OK) - { - /* Bad GUID, skip the entry */ - SetLastError(ERROR_INVALID_PARAMETER); - ret = FALSE; - goto cleanup; - } - - ret = GetStringField(&ContextInterface, 2, &ReferenceString); - if (!ret) - goto cleanup; - - ret = GetStringField(&ContextInterface, 3, &InterfaceSection); - if (!ret) - goto cleanup; - - ret = SetupGetIntField( - &ContextInterface, - 4, /* Field index */ - &InterfaceFlags); - if (!ret) - { - if (GetLastError() == ERROR_INVALID_PARAMETER) - { - /* The field may be empty. Ignore the error */ - InterfaceFlags = 0; - ret = TRUE; - } - else - goto cleanup; - } - - /* Install Interface */ - ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags); - -cleanup: - MyFree(InterfaceGuidString); - MyFree(ReferenceString); - MyFree(InterfaceSection); - InterfaceGuidString = ReferenceString = InterfaceSection = NULL; - Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface); - } - } - - TRACE("Returning %d\n", ret); - return ret; -} - static BOOL InfIsFromOEMLocation( IN PCWSTR FullName, diff --git a/reactos/dll/win32/setupapi/driver.c b/reactos/dll/win32/setupapi/driver.c new file mode 100644 index 00000000000..609e774dee6 --- /dev/null +++ b/reactos/dll/win32/setupapi/driver.c @@ -0,0 +1,1852 @@ +/* + * SetupAPI driver-related functions + * + * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "setupapi_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/* Unicode constants */ +static const WCHAR BackSlash[] = {'\\',0}; +static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; +static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0}; +static const WCHAR InfDirectory[] = {'i','n','f','\\',0}; +static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; + +static const WCHAR INF_MANUFACTURER[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; +static const WCHAR INF_PROVIDER[] = {'P','r','o','v','i','d','e','r',0}; +static const WCHAR INF_DRIVER_VER[] = {'D','r','i','v','e','r','V','e','r',0}; + + +/*********************************************************************** + * struct InfFileDetails management + */ +static VOID +ReferenceInfFile(struct InfFileDetails* infFile) +{ + InterlockedIncrement(&infFile->References); +} + +VOID +DereferenceInfFile(struct InfFileDetails* infFile) +{ + if (InterlockedDecrement(&infFile->References) == 0) + { + SetupCloseInfFile(infFile->hInf); + HeapFree(GetProcessHeap(), 0, infFile); + } +} + +struct InfFileDetails * +CreateInfFileDetails( + IN LPCWSTR FullInfFileName) +{ + struct InfFileDetails *details; + PWCHAR last; + DWORD Needed; + + Needed = FIELD_OFFSET(struct InfFileDetails, szData) + + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL); + + details = HeapAlloc(GetProcessHeap(), 0, Needed); + if (!details) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + memset(details, 0, Needed); + strcpyW(details->szData, FullInfFileName); + last = strrchrW(details->szData, '\\'); + if (last) + { + details->DirectoryName = details->szData; + details->FileName = last + 1; + *last = '\0'; + } + else + details->FileName = details->szData; + ReferenceInfFile(details); + details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL); + if (details->hInf == INVALID_HANDLE_VALUE) + { + HeapFree(GetProcessHeap(), 0, details); + return NULL; + } + return details; +} + +BOOL +DestroyDriverInfoElement(struct DriverInfoElement* driverInfo) +{ + DereferenceInfFile(driverInfo->InfFileDetails); + HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); + HeapFree(GetProcessHeap(), 0, driverInfo); + return TRUE; +} + +/*********************************************************************** + * Helper functions for SetupDiBuildDriverInfoList + */ +static BOOL +AddDriverToList( + IN PLIST_ENTRY DriverListHead, + IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */ + IN LPGUID ClassGuid, + IN INFCONTEXT ContextDevice, + IN struct InfFileDetails *InfFileDetails, + IN LPCWSTR InfFile, + IN LPCWSTR ProviderName, + IN LPCWSTR ManufacturerName, + IN LPCWSTR MatchingId, + FILETIME DriverDate, + DWORDLONG DriverVersion, + IN DWORD Rank) +{ + struct DriverInfoElement *driverInfo = NULL; + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD RequiredSize = 128; /* Initial buffer size */ + BOOL Result = FALSE; + PLIST_ENTRY PreviousEntry; + LPWSTR InfInstallSection = NULL; + BOOL ret = FALSE; + + driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement)); + if (!driverInfo) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + memset(driverInfo, 0, sizeof(struct DriverInfoElement)); + + driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + driverInfo->Details.Reserved = (ULONG_PTR)driverInfo; + + /* Copy InfFileName field */ + strncpyW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1); + driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0'; + + /* Fill InfDate field */ + hFile = CreateFile( + InfFile, + GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + goto cleanup; + Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate); + if (!Result) + goto cleanup; + + /* Fill SectionName field */ + Result = SetupGetStringFieldW( + &ContextDevice, + 1, + driverInfo->Details.SectionName, LINE_LEN, + NULL); + if (!Result) + goto cleanup; + + /* Fill DrvDescription field */ + Result = SetupGetStringFieldW( + &ContextDevice, + 0, /* Field index */ + driverInfo->Details.DrvDescription, LINE_LEN, + NULL); + + /* Copy MatchingId information */ + if (MatchingId) + { + driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); + if (!driverInfo->MatchingId) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); + } + else + driverInfo->MatchingId = NULL; + + /* Get inf install section */ + 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) + goto cleanup; + Result = SetupGetStringFieldW( + &ContextDevice, + 1, /* Field index */ + InfInstallSection, RequiredSize, + &RequiredSize); + } + if (!Result) + goto cleanup; + + TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n", + debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile), + debugstr_w(InfInstallSection), Rank); + + driverInfo->DriverRank = Rank; + memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME)); + memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID)); + driverInfo->Info.DriverType = DriverType; + driverInfo->Info.Reserved = (ULONG_PTR)driverInfo; + strncpyW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1); + driverInfo->Info.Description[LINE_LEN - 1] = '\0'; + strncpyW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1); + driverInfo->Info.MfgName[LINE_LEN - 1] = '\0'; + if (ProviderName) + { + strncpyW(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; + ReferenceInfFile(InfFileDetails); + driverInfo->InfFileDetails = InfFileDetails; + + /* Insert current driver in driver list, according to its rank */ + PreviousEntry = DriverListHead->Flink; + while (PreviousEntry != DriverListHead) + { + struct DriverInfoElement *CurrentDriver; + CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry); + if (CurrentDriver->DriverRank > Rank || + (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart)) + { + /* Insert before the current item */ + InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry); + break; + } + PreviousEntry = PreviousEntry->Flink; + } + if (PreviousEntry == DriverListHead) + { + /* Insert at the end of the list */ + InsertTailList(DriverListHead, &driverInfo->ListEntry); + } + + ret = TRUE; + +cleanup: + if (!ret) + { + if (driverInfo) + HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); + HeapFree(GetProcessHeap(), 0, driverInfo); + } + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + HeapFree(GetProcessHeap(), 0, InfInstallSection); + + return ret; +} + +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 DriverVer = NULL; + LPWSTR ProviderName = NULL; + LPWSTR pComma; /* Points into DriverVer */ + LPWSTR pVersion = NULL; /* Points into DriverVer */ + SYSTEMTIME SystemTime; + BOOL Result; + BOOL ret = FALSE; /* Final result */ + + /* Get class Guid */ + if (!SetupGetLineTextW( + NULL, /* Context */ + hInf, + Version, ClassGUID, + guidW, sizeof(guidW), + NULL /* Required size */)) + { + goto cleanup; + } + guidW[37] = '\0'; /* Replace the } by a NULL character */ + if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK) + { + SetLastError(ERROR_GEN_FAILURE); + goto cleanup; + } + + /* Get provider name */ + Result = SetupGetLineTextW( + NULL, /* Context */ + hInf, Version, INF_PROVIDER, + NULL, 0, + &RequiredSize); + if (Result) + { + /* We know know the needed buffer size */ + ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); + if (!ProviderName) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + Result = SetupGetLineTextW( + NULL, /* Context */ + hInf, Version, INF_PROVIDER, + ProviderName, RequiredSize, + &RequiredSize); + } + if (!Result) + goto cleanup; + *pProviderName = ProviderName; + + /* Read the "DriverVer" value */ + Result = SetupGetLineTextW( + NULL, /* Context */ + hInf, Version, INF_DRIVER_VER, + NULL, 0, + &RequiredSize); + if (Result) + { + /* We know know the needed buffer size */ + DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); + if (!DriverVer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + Result = SetupGetLineTextW( + NULL, /* Context */ + hInf, Version, INF_DRIVER_VER, + DriverVer, RequiredSize, + &RequiredSize); + } + if (!Result) + goto cleanup; + + /* Get driver date and driver version, by analyzing the "DriverVer" value */ + pComma = strchrW(DriverVer, ','); + if (pComma != NULL) + { + *pComma = UNICODE_NULL; + pVersion = pComma + 1; + } + /* Get driver date version. Invalid date = 00/00/00 */ + memset(DriverDate, 0, sizeof(FILETIME)); + if (strlenW(DriverVer) == 10 + && (DriverVer[2] == '-' || DriverVer[2] == '/') + && (DriverVer[5] == '-' || DriverVer[5] == '/')) + { + memset(&SystemTime, 0, sizeof(SYSTEMTIME)); + DriverVer[2] = DriverVer[5] = UNICODE_NULL; + SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0'; + SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0'; + SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0'; + SystemTimeToFileTime(&SystemTime, DriverDate); + } + /* Get driver version. Invalid version = 0.0.0.0 */ + *DriverVersion = 0; + if (pVersion) + { + WORD Major, Minor = 0, Revision = 0, Build = 0; + LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL; + LARGE_INTEGER fullVersion; + + pMinor = strchrW(pVersion, '.'); + if (pMinor) + { + *pMinor = 0; + pRevision = strchrW(++pMinor, '.'); + Minor = atoiW(pMinor); + } + if (pRevision) + { + *pRevision = 0; + pBuild = strchrW(++pRevision, '.'); + Revision = atoiW(pRevision); + } + if (pBuild) + { + *pBuild = 0; + pBuild++; + Build = atoiW(pBuild); + } + Major = atoiW(pVersion); + fullVersion.u.HighPart = Major << 16 | Minor; + fullVersion.u.LowPart = Revision << 16 | Build; + memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER)); + } + + ret = TRUE; + +cleanup: + if (!ret) + HeapFree(GetProcessHeap(), 0, ProviderName); + HeapFree(GetProcessHeap(), 0, DriverVer); + + return ret; +} + +static BOOL +GetHardwareAndCompatibleIDsLists( + IN HDEVINFO DeviceInfoSet, + IN OUT PSP_DEVINFO_DATA DeviceInfoData, + OUT LPWSTR *pHardwareIDs OPTIONAL, + OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL, + OUT LPWSTR *pCompatibleIDs OPTIONAL, + OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL) +{ + LPWSTR HardwareIDs = NULL; + LPWSTR CompatibleIDs = NULL; + DWORD RequiredSize; + BOOL Result; + + /* Get hardware IDs list */ + Result = FALSE; + RequiredSize = 512; /* Initial buffer size */ + SetLastError(ERROR_INSUFFICIENT_BUFFER); + while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + MyFree(HardwareIDs); + HardwareIDs = MyMalloc(RequiredSize); + if (!HardwareIDs) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + Result = SetupDiGetDeviceRegistryPropertyW( + DeviceInfoSet, + DeviceInfoData, + SPDRP_HARDWAREID, + NULL, + (PBYTE)HardwareIDs, + RequiredSize, + &RequiredSize); + } + if (!Result) + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + { + /* No hardware ID for this device */ + MyFree(HardwareIDs); + HardwareIDs = NULL; + RequiredSize = 0; + } + else + goto done; + } + if (pHardwareIDs) + *pHardwareIDs = HardwareIDs; + if (pHardwareIDsRequiredSize) + *pHardwareIDsRequiredSize = RequiredSize; + + /* Get compatible IDs list */ + Result = FALSE; + RequiredSize = 512; /* Initial buffer size */ + SetLastError(ERROR_INSUFFICIENT_BUFFER); + while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + MyFree(CompatibleIDs); + CompatibleIDs = MyMalloc(RequiredSize); + if (!CompatibleIDs) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + Result = SetupDiGetDeviceRegistryPropertyW( + DeviceInfoSet, + DeviceInfoData, + SPDRP_COMPATIBLEIDS, + NULL, + (PBYTE)CompatibleIDs, + RequiredSize, + &RequiredSize); + } + if (!Result) + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + { + /* No compatible ID for this device */ + MyFree(CompatibleIDs); + CompatibleIDs = NULL; + RequiredSize = 0; + } + else + goto done; + } + if (pCompatibleIDs) + *pCompatibleIDs = CompatibleIDs; + if (pCompatibleIDsRequiredSize) + *pCompatibleIDsRequiredSize = RequiredSize; + + Result = TRUE; + +done: + if (!Result) + { + MyFree(HardwareIDs); + MyFree(CompatibleIDs); + } + return Result; +} + +/*********************************************************************** + * SetupDiBuildDriverInfoList (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiBuildDriverInfoList( + IN HDEVINFO DeviceInfoSet, + IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN DWORD DriverType) +{ + struct DeviceInfoSet *list; + SP_DEVINSTALL_PARAMS_W InstallParams; + PVOID Buffer = NULL; + struct InfFileDetails *currentInfFileDetails = NULL; + LPWSTR ProviderName = NULL; + LPWSTR ManufacturerName = NULL; + WCHAR ManufacturerSection[LINE_LEN + 1]; + LPWSTR HardwareIDs = NULL; + LPWSTR CompatibleIDs = NULL; + LPWSTR FullInfFileName = NULL; + LPWSTR ExcludeFromSelect = NULL; + FILETIME DriverDate; + DWORDLONG DriverVersion = 0; + 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_COMPATDRIVER && !DeviceInfoData) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else + { + PLIST_ENTRY pDriverListHead = &list->DriverListHead; + BOOL Result; + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + if (!Result) + goto done; + + if (DeviceInfoData) + { + struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; + if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)) + pDriverListHead = &devInfo->DriverListHead; + } + + if (DriverType == SPDIT_COMPATDRIVER) + { + /* Get hardware and compatible IDs lists */ + Result = GetHardwareAndCompatibleIDsLists( + DeviceInfoSet, + DeviceInfoData, + &HardwareIDs, + NULL, + &CompatibleIDs, + NULL); + if (!Result) + goto done; + if (!HardwareIDs && !CompatibleIDs) + { + SetLastError(ERROR_FILE_NOT_FOUND); + goto done; + } + } + + if (InstallParams.Flags & DI_ENUMSINGLEINF) + { + /* InstallParams.DriverPath contains the name of a .inf file */ + RequiredSize = strlenW(InstallParams.DriverPath) + 2; + Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); + if (!Buffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + strcpyW(Buffer, InstallParams.DriverPath); + ((LPWSTR)Buffer)[RequiredSize - 1] = 0; + Result = TRUE; + } + else + { + /* 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( + *InstallParams.DriverPath ? InstallParams.DriverPath : NULL, + INF_STYLE_WIN4, + Buffer, RequiredSize, + &RequiredSize); + } + if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND) + { + /* No .inf file in specified directory. So, we should + * success as we created an empty driver info list. + */ + ret = TRUE; + goto done; + } + } + if (Result) + { + LPCWSTR filename; + LPWSTR pFullFilename; + + if (InstallParams.Flags & DI_ENUMSINGLEINF) + { + /* Only a filename */ + FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + if (!FullInfFileName) + goto done; + pFullFilename = &FullInfFileName[0]; + } + else if (*InstallParams.DriverPath) + { + /* Directory name specified */ + DWORD len; + len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL); + if (len == 0) + goto done; + FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR)); + if (!FullInfFileName) + goto done; + len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL); + if (len == 0) + goto done; + if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') + strcatW(FullInfFileName, BackSlash); + pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; + } + else + { + /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */ + DWORD len; + len = GetSystemWindowsDirectoryW(NULL, 0); + if (len == 0) + goto done; + FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + strlenW(InfDirectory) + MAX_PATH) * sizeof(WCHAR)); + if (!FullInfFileName) + goto done; + len = GetSystemWindowsDirectoryW(FullInfFileName, len); + if (len == 0) + goto done; + if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') + strcatW(FullInfFileName, BackSlash); + strcatW(FullInfFileName, InfDirectory); + pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; + } + + for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1) + { + INFCONTEXT ContextManufacturer, ContextDevice; + GUID ClassGuid; + + strcpyW(pFullFilename, filename); + TRACE("Opening file %s\n", debugstr_w(FullInfFileName)); + + currentInfFileDetails = CreateInfFileDetails(FullInfFileName); + if (!currentInfFileDetails) + continue; + + if (!GetVersionInformationFromInfFile( + currentInfFileDetails->hInf, + &ClassGuid, + &ProviderName, + &DriverDate, + &DriverVersion)) + { + DereferenceInfFile(currentInfFileDetails); + currentInfFileDetails = NULL; + 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)) + { + goto next; + } + } + + if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS) + { + /* Read ExcludeFromSelect control flags */ + /* FIXME */ + } + else + FIXME("ExcludeFromSelect list ignored\n"); + + /* Get the manufacturers list */ + Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer); + while (Result) + { + Result = SetupGetStringFieldW( + &ContextManufacturer, + 0, /* Field index */ + NULL, 0, + &RequiredSize); + if (Result) + { + /* We got the needed size for the 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); + } + /* Get manufacturer section name */ + Result = SetupGetStringFieldW( + &ContextManufacturer, + 1, /* Field index */ + ManufacturerSection, LINE_LEN, + &RequiredSize); + if (Result) + { + ManufacturerSection[RequiredSize] = 0; /* Final NULL char */ + /* Add (possible) extension to manufacturer section name */ + Result = SetupDiGetActualSectionToInstallW( + currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL); + if (Result) + { + TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection)); + Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice); + } + } + while (Result) + { + if (DriverType == SPDIT_CLASSDRIVER) + { + /* FIXME: Check ExcludeFromSelect list */ + if (!AddDriverToList( + pDriverListHead, + DriverType, + &ClassGuid, + ContextDevice, + currentInfFileDetails, + FullInfFileName, + ProviderName, + ManufacturerName, + NULL, + DriverDate, DriverVersion, + 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; + } + /* FIXME: Check ExcludeFromSelect list */ + DriverAlreadyAdded = FALSE; + for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) + { + if (strcmpiW(DeviceId, currentId) == 0) + { + AddDriverToList( + pDriverListHead, + DriverType, + &ClassGuid, + ContextDevice, + currentInfFileDetails, + FullInfFileName, + ProviderName, + ManufacturerName, + currentId, + DriverDate, DriverVersion, + DriverRank + (i == 2 ? 0 : 0x1000 + i - 3)); + DriverAlreadyAdded = TRUE; + } + } + if (CompatibleIDs) + { + for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) + { + if (strcmpiW(DeviceId, currentId) == 0) + { + AddDriverToList( + pDriverListHead, + DriverType, + &ClassGuid, + ContextDevice, + currentInfFileDetails, + FullInfFileName, + ProviderName, + ManufacturerName, + currentId, + DriverDate, DriverVersion, + DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3)); + DriverAlreadyAdded = TRUE; + } + } + } + HeapFree(GetProcessHeap(), 0, DeviceId); + } + } + Result = SetupFindNextLine(&ContextDevice, &ContextDevice); + } + + HeapFree(GetProcessHeap(), 0, ManufacturerName); + ManufacturerName = NULL; + Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer); + } + + ret = TRUE; +next: + HeapFree(GetProcessHeap(), 0, ProviderName); + HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); + ProviderName = ExcludeFromSelect = NULL; + + DereferenceInfFile(currentInfFileDetails); + currentInfFileDetails = NULL; + } + ret = TRUE; + } + } + +done: + if (ret) + { + if (DeviceInfoData) + { + InstallParams.Flags |= DI_DIDCOMPAT; + InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO; + } + else + { + InstallParams.Flags |= DI_DIDCLASS; + InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST; + } + ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + } + + HeapFree(GetProcessHeap(), 0, ProviderName); + HeapFree(GetProcessHeap(), 0, ManufacturerName); + MyFree(HardwareIDs); + MyFree(CompatibleIDs); + HeapFree(GetProcessHeap(), 0, FullInfFileName); + HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); + if (currentInfFileDetails) + DereferenceInfFile(currentInfFileDetails); + HeapFree(GetProcessHeap(), 0, Buffer); + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiDestroyDriverInfoList (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiDestroyDriverInfoList( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN DWORD DriverType) +{ + struct DeviceInfoSet *list; + BOOL ret = FALSE; + + TRACE("%p %p 0x%lx\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 (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) + 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 + { + PLIST_ENTRY ListEntry; + struct DriverInfoElement *driverInfo; + SP_DEVINSTALL_PARAMS_W InstallParams; + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) + goto done; + + if (!DeviceInfoData) + /* Fall back to destroying class driver list */ + DriverType = SPDIT_CLASSDRIVER; + + if (DriverType == SPDIT_CLASSDRIVER) + { + while (!IsListEmpty(&list->DriverListHead)) + { + ListEntry = RemoveHeadList(&list->DriverListHead); + driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); + DestroyDriverInfoElement(driverInfo); + } + InstallParams.Reserved = 0; + InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS); + InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST; + ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams); + } + else + { + SP_DEVINSTALL_PARAMS_W InstallParamsSet; + struct DeviceInfoElement *deviceInfo; + + InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet)) + goto done; + deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; + while (!IsListEmpty(&deviceInfo->DriverListHead)) + { + ListEntry = RemoveHeadList(&deviceInfo->DriverListHead); + driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); + if ((PVOID)InstallParamsSet.Reserved == driverInfo) + { + InstallParamsSet.Reserved = 0; + SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet); + } + DestroyDriverInfoElement(driverInfo); + } + InstallParams.Reserved = 0; + InstallParams.Flags &= ~DI_DIDCOMPAT; + InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO; + ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + } + } + +done: + TRACE("Returning %d\n", ret); + 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_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 = NULL; + PLIST_ENTRY ItemList; + if (DeviceInfoData) + devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved; + if (!devInfo || (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 = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); + + memcpy( + &DriverInfoData->DriverType, + &DrvInfo->Info.DriverType, + DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); + ret = TRUE; + } + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetSelectedDriverA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetSelectedDriverA( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + OUT PSP_DRVINFO_DATA_A DriverInfoData) +{ + SP_DRVINFO_DATA_V2_W driverInfoData2W; + BOOL ret = FALSE; + + 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 = SetupDiGetSelectedDriverW(DeviceInfoSet, + DeviceInfoData, + &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; + } + } + } + + 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 + { + SP_DEVINSTALL_PARAMS InstallParams; + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) + { + struct DriverInfoElement *driverInfo; + driverInfo = (struct DriverInfoElement *)InstallParams.Reserved; + if (driverInfo == NULL) + SetLastError(ERROR_NO_DRIVER_SELECTED); + else + { + memcpy( + &DriverInfoData->DriverType, + &driverInfo->Info.DriverType, + DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); + ret = TRUE; + } + } + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiSetSelectedDriverA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiSetSelectedDriverA( + IN HDEVINFO DeviceInfoSet, + IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL) +{ + SP_DRVINFO_DATA_V1_W DriverInfoDataW; + PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL; + BOOL ret = FALSE; + + if (DriverInfoData != NULL) + { + if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) && + DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A)); + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); + DriverInfoDataW.Reserved = DriverInfoData->Reserved; + + if (DriverInfoDataW.Reserved == 0) + { + DriverInfoDataW.DriverType = DriverInfoData->DriverType; + + /* convert the strings to unicode */ + if (!MultiByteToWideChar(CP_ACP, + 0, + DriverInfoData->Description, + LINE_LEN, + DriverInfoDataW.Description, + LINE_LEN) || + !MultiByteToWideChar(CP_ACP, + 0, + DriverInfoData->ProviderName, + LINE_LEN, + DriverInfoDataW.ProviderName, + LINE_LEN)) + { + return FALSE; + } + } + + pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW; + } + + ret = SetupDiSetSelectedDriverW(DeviceInfoSet, + DeviceInfoData, + pDriverInfoDataW); + + if (ret && pDriverInfoDataW != NULL) + { + DriverInfoData->Reserved = DriverInfoDataW.Reserved; + } + + return ret; +} + +/*********************************************************************** + * SetupDiSetSelectedDriverW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiSetSelectedDriverW( + IN HDEVINFO DeviceInfoSet, + IN OUT 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 DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved; + ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead; + } + else + { + pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved; + 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 = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); + if (driverInfo->Info.DriverType == DriverInfoData->DriverType + && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0 + && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0) + { + break; + } + } + ItemList = ItemList->Flink; + } + if (ItemList == ListHead) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); + DriverInfoData->Reserved = (ULONG_PTR)ItemList; + ret = TRUE; + TRACE("Choosing driver whose rank is 0x%lx\n", + (*pDriverInfo)->DriverRank); + if (DeviceInfoData) + memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID)); + } + } + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetDriverInfoDetailA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetDriverInfoDetailA( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN PSP_DRVINFO_DATA_A DriverInfoData, + IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL, + IN DWORD DriverInfoDetailDataSize, + OUT PDWORD RequiredSize OPTIONAL) +{ + SP_DRVINFO_DATA_V2_W DriverInfoDataW; + PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL; + DWORD BufSize = 0; + DWORD HardwareIDLen = 0; + BOOL ret = FALSE; + + /* do some sanity checks, the unicode version might do more thorough checks */ + if (DriverInfoData == NULL || + (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) || + (DriverInfoDetailData != NULL && + (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) || + DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A)))) + { + SetLastError(ERROR_INVALID_PARAMETER); + goto Cleanup; + } + + /* make sure we support both versions of the SP_DRVINFO_DATA structure */ + if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A)) + { + DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); + } + else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) + { + DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + goto Cleanup; + } + DriverInfoDataW.DriverType = DriverInfoData->DriverType; + DriverInfoDataW.Reserved = DriverInfoData->Reserved; + + /* convert the strings to unicode */ + if (MultiByteToWideChar(CP_ACP, + 0, + DriverInfoData->Description, + LINE_LEN, + DriverInfoDataW.Description, + LINE_LEN) && + MultiByteToWideChar(CP_ACP, + 0, + DriverInfoData->MfgName, + LINE_LEN, + DriverInfoDataW.MfgName, + LINE_LEN) && + MultiByteToWideChar(CP_ACP, + 0, + DriverInfoData->ProviderName, + LINE_LEN, + DriverInfoDataW.ProviderName, + LINE_LEN)) + { + if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W)) + { + DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate; + DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion; + } + + if (DriverInfoDetailData != NULL) + { + /* calculate the unicode buffer size from the ansi buffer size */ + HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID); + BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) + + (HardwareIDLen * sizeof(WCHAR)); + + DriverInfoDetailDataW = MyMalloc(BufSize); + if (DriverInfoDetailDataW == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto Cleanup; + } + + /* initialize the buffer */ + ZeroMemory(DriverInfoDetailDataW, + BufSize); + DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); + } + + /* call the unicode version */ + ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet, + DeviceInfoData, + &DriverInfoDataW, + DriverInfoDetailDataW, + BufSize, + RequiredSize); + + if (ret) + { + if (DriverInfoDetailDataW != NULL) + { + /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */ + DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A); + DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate; + DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved; + if (WideCharToMultiByte(CP_ACP, + 0, + DriverInfoDetailDataW->SectionName, + LINE_LEN, + DriverInfoDetailData->SectionName, + LINE_LEN, + NULL, + NULL) && + WideCharToMultiByte(CP_ACP, + 0, + DriverInfoDetailDataW->InfFileName, + MAX_PATH, + DriverInfoDetailData->InfFileName, + MAX_PATH, + NULL, + NULL) && + WideCharToMultiByte(CP_ACP, + 0, + DriverInfoDetailDataW->DrvDescription, + LINE_LEN, + DriverInfoDetailData->DrvDescription, + LINE_LEN, + NULL, + NULL) && + WideCharToMultiByte(CP_ACP, + 0, + DriverInfoDetailDataW->HardwareID, + HardwareIDLen, + DriverInfoDetailData->HardwareID, + HardwareIDLen, + NULL, + NULL)) + { + DWORD len, cnt = 0; + DWORD hwidlen = HardwareIDLen; + CHAR *s = DriverInfoDetailData->HardwareID; + + /* count the strings in the list */ + while (*s != '\0') + { + len = lstrlenA(s) + 1; + if (hwidlen > len) + { + cnt++; + s += len; + hwidlen -= len; + } + else + { + /* looks like the string list wasn't terminated... */ + SetLastError(ERROR_INVALID_USER_BUFFER); + ret = FALSE; + break; + } + } + + /* make sure CompatIDsOffset points to the second string in the + list, if present */ + if (cnt > 1) + { + DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1; + DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) - + DriverInfoDetailData->CompatIDsOffset + 1; + } + else + { + DriverInfoDetailData->CompatIDsOffset = 0; + DriverInfoDetailData->CompatIDsLength = 0; + } + } + else + { + ret = FALSE; + } + } + + if (RequiredSize != NULL) + { + *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + + (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR)); + } + } + } + +Cleanup: + if (DriverInfoDetailDataW != NULL) + { + MyFree(DriverInfoDetailDataW); + } + + return ret; +} + +/*********************************************************************** + * SetupDiGetDriverInfoDetailW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetDriverInfoDetailW( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN PSP_DRVINFO_DATA_W DriverInfoData, + IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL, + IN DWORD DriverInfoDetailDataSize, + OUT PDWORD RequiredSize OPTIONAL) +{ + BOOL ret = FALSE; + + TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData, + DriverInfoData, DriverInfoDetailData, + DriverInfoDetailDataSize, RequiredSize); + + 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) + SetLastError(ERROR_INVALID_PARAMETER); + else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W)) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (DriverInfoData->Reserved == 0) + SetLastError(ERROR_NO_DRIVER_SELECTED); + else + { + struct DriverInfoElement *driverInfoElement; + LPWSTR HardwareIDs = NULL; + LPWSTR CompatibleIDs = NULL; + LPWSTR pBuffer = NULL; + LPCWSTR DeviceID = NULL; + ULONG HardwareIDsSize, CompatibleIDsSize; + ULONG sizeNeeded, sizeLeft, size; + BOOL Result; + + driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved; + + /* Get hardware and compatible IDs lists */ + Result = GetHardwareAndCompatibleIDsLists( + DeviceInfoSet, + DeviceInfoData, + &HardwareIDs, &HardwareIDsSize, + &CompatibleIDs, &CompatibleIDsSize); + if (!Result) + goto done; + + sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) + + HardwareIDsSize + CompatibleIDsSize; + if (RequiredSize) + *RequiredSize = sizeNeeded; + + if (!DriverInfoDetailData) + { + ret = TRUE; + goto done; + } + + memcpy( + DriverInfoDetailData, + &driverInfoElement->Details, + driverInfoElement->Details.cbSize); + DriverInfoDetailData->CompatIDsOffset = 0; + DriverInfoDetailData->CompatIDsLength = 0; + + sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR); + pBuffer = DriverInfoDetailData->HardwareID; + /* Add as many as possible HardwareIDs in the list */ + DeviceID = HardwareIDs; + while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) + { + TRACE("Adding %s to list\n", debugstr_w(DeviceID)); + wcscpy(pBuffer, DeviceID); + DeviceID += size + 1; + pBuffer += size + 1; + sizeLeft -= size + 1; + DriverInfoDetailData->CompatIDsOffset += size + 1; + } + if (sizeLeft > 0) + { + *pBuffer = UNICODE_NULL; + sizeLeft--; + DriverInfoDetailData->CompatIDsOffset++; + } + /* Add as many as possible CompatibleIDs in the list */ + DeviceID = CompatibleIDs; + while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) + { + TRACE("Adding %s to list\n", debugstr_w(DeviceID)); + wcscpy(pBuffer, DeviceID); + DeviceID += size + 1; + pBuffer += size + 1; + sizeLeft -= size + 1; + DriverInfoDetailData->CompatIDsLength += size + 1; + } + if (sizeLeft > 0) + { + *pBuffer = UNICODE_NULL; + sizeLeft--; + DriverInfoDetailData->CompatIDsLength++; + } + + if (sizeNeeded > DriverInfoDetailDataSize) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + else + ret = TRUE; + +done: + MyFree(HardwareIDs); + MyFree(CompatibleIDs); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiSelectBestCompatDrv (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiSelectBestCompatDrv( + IN HDEVINFO DeviceInfoSet, + IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) +{ + SP_DRVINFO_DATA_W drvInfoData; + BOOL ret; + + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + /* Drivers are sorted by rank in the driver list, so + * the first driver in the list is the best one. + */ + drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W); + ret = SetupDiEnumDriverInfoW( + DeviceInfoSet, + DeviceInfoData, + SPDIT_COMPATDRIVER, + 0, /* Member index */ + &drvInfoData); + + if (ret) + { + ret = SetupDiSetSelectedDriverW( + DeviceInfoSet, + DeviceInfoData, + &drvInfoData); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiInstallDriverFiles (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallDriverFiles( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData) +{ + BOOL ret = FALSE; + + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + 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 (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0) + SetLastError(ERROR_NO_DRIVER_SELECTED); + else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0) + SetLastError(ERROR_NO_DRIVER_SELECTED); + else + { + SP_DEVINSTALL_PARAMS_W InstallParams; + struct DriverInfoElement *SelectedDriver; + WCHAR SectionName[MAX_PATH]; + DWORD SectionNameLength = 0; + PVOID InstallMsgHandler; + PVOID InstallMsgHandlerContext; + PVOID Context = NULL; + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + if (!ret) + goto done; + + SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; + if (!SelectedDriver) + { + SetLastError(ERROR_NO_DRIVER_SELECTED); + goto done; + } + + ret = SetupDiGetActualSectionToInstallW( + SelectedDriver->InfFileDetails->hInf, + SelectedDriver->Details.SectionName, + SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL); + if (!ret) + goto done; + + if (InstallParams.InstallMsgHandler) + { + InstallMsgHandler = InstallParams.InstallMsgHandler; + InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext; + } + else + { + Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); + if (!Context) + goto cleanup; + InstallMsgHandler = SetupDefaultQueueCallback; + InstallMsgHandlerContext = Context; + } + ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, + SelectedDriver->InfFileDetails->hInf, SectionName, + SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, + InstallMsgHandler, InstallMsgHandlerContext, + DeviceInfoSet, DeviceInfoData); + if (!ret) + goto done; + + /* Install files from .CoInstallers section */ + lstrcatW(SectionName, DotCoInstallers); + ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, + SelectedDriver->InfFileDetails->hInf, SectionName, + SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, + InstallMsgHandler, InstallMsgHandlerContext, + DeviceInfoSet, DeviceInfoData); + if (!ret) + goto done; + + /* Set the DI_NOFILECOPY flag to prevent another + * installation during SetupDiInstallDevice */ + InstallParams.Flags |= DI_NOFILECOPY; + ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + +cleanup: + if (Context) + SetupTermDefaultQueueCallback(Context); + } + +done: + TRACE("Returning %d\n", ret); + return ret; +} diff --git a/reactos/dll/win32/setupapi/interface.c b/reactos/dll/win32/setupapi/interface.c new file mode 100644 index 00000000000..fa6d22165a5 --- /dev/null +++ b/reactos/dll/win32/setupapi/interface.c @@ -0,0 +1,689 @@ +/* + * SetupAPI interface-related functions + * + * Copyright 2000 Andreas Mohr for CodeWeavers + * 2005-2006 Hervé Poussineau (hpoussin@reactos.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "setupapi_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/* Unicode constants */ +static const WCHAR AddInterface[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0}; +static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; +static const WCHAR Control[] = {'C','o','n','t','r','o','l',0}; +static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0}; +static const WCHAR DotInterfaces[] = {'.','I','n','t','e','r','f','a','c','e','s',0}; +static const WCHAR Linked[] = {'L','i','n','k','e','d',0}; +static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; + +static BOOL +CreateDeviceInterface( + IN struct DeviceInfoElement* deviceInfo, + IN LPCWSTR SymbolicLink, + IN LPCGUID pInterfaceGuid, + OUT struct DeviceInterface **pDeviceInterface) +{ + struct DeviceInterface *deviceInterface; + + *pDeviceInterface = NULL; + + deviceInterface = HeapAlloc(GetProcessHeap(), 0, + FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (strlenW(SymbolicLink) + 1) * sizeof(WCHAR)); + if (!deviceInterface) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + deviceInterface->DeviceInfo = deviceInfo; + strcpyW(deviceInterface->SymbolicLink, SymbolicLink); + deviceInterface->Flags = 0; /* Flags will be updated later */ + memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID)); + + *pDeviceInterface = deviceInterface; + return TRUE; +} + +BOOL +DestroyDeviceInterface( + struct DeviceInterface* deviceInterface) +{ + return HeapFree(GetProcessHeap(), 0, deviceInterface); +} + +LONG +SETUP_CreateInterfaceList( + struct DeviceInfoSet *list, + PCWSTR MachineName, + CONST GUID *InterfaceGuid, + PCWSTR DeviceInstanceW /* OPTIONAL */, + BOOL OnlyPresentInterfaces) +{ + HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */ + HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */ + HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */ + HKEY hControlKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */ + HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */ + HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */ + LONG rc; + WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1]; + PWSTR pSymbolicLink = NULL; + PWSTR InstancePath = NULL; + DWORD i, j; + DWORD dwLength, dwInstancePathLength; + DWORD dwRegType; + DWORD LinkedValue; + GUID ClassGuid; + struct DeviceInfoElement *deviceInfo; + + hInterfaceKey = INVALID_HANDLE_VALUE; + hDeviceInstanceKey = NULL; + hReferenceKey = NULL; + + /* Open registry key related to this interface */ + hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL); + if (hInterfaceKey == INVALID_HANDLE_VALUE) + { + rc = GetLastError(); + goto cleanup; + } + + /* Enumerate sub keys of hInterfaceKey */ + i = 0; + while (TRUE) + { + dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); + rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); + if (rc == ERROR_NO_MORE_ITEMS) + break; + if (rc != ERROR_SUCCESS) + goto cleanup; + i++; + + /* Open sub key */ + if (hDeviceInstanceKey != NULL) + RegCloseKey(hDeviceInstanceKey); + rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + + /* Read DeviceInstance */ + rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength); + if (rc != ERROR_SUCCESS) + goto cleanup; + if (dwRegType != REG_SZ) + { + rc = ERROR_GEN_FAILURE; + goto cleanup; + } + HeapFree(GetProcessHeap(), 0, InstancePath); + InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR)); + if (!InstancePath) + { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength); + if (rc != ERROR_SUCCESS) + goto cleanup; + InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0'; + TRACE("DeviceInstance %s\n", debugstr_w(InstancePath)); + + if (DeviceInstanceW) + { + /* Check if device enumerator is not the right one */ + if (strcmpW(DeviceInstanceW, InstancePath) != 0) + continue; + } + + /* Find class GUID associated to the device instance */ + rc = RegOpenKeyExW( + list->HKLM, + REGSTR_PATH_SYSTEMENUM, + 0, /* Options */ + 0, + &hEnumKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + rc = RegOpenKeyExW( + hEnumKey, + InstancePath, + 0, /* Options */ + KEY_QUERY_VALUE, + &hKey); + RegCloseKey(hEnumKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + dwLength = sizeof(KeyBuffer) - sizeof(WCHAR); + rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); + RegCloseKey(hKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + KeyBuffer[dwLength / sizeof(WCHAR)] = '\0'; + KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */ + if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK) + { + rc = ERROR_GEN_FAILURE; + goto cleanup; + } + TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid)); + + /* If current device doesn't match the list GUID (if any), skip this entry */ + if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid)) + continue; + + /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */ + j = 0; + while (TRUE) + { + struct DeviceInterface *interfaceInfo; + + dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); + rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); + if (rc == ERROR_NO_MORE_ITEMS) + break; + if (rc != ERROR_SUCCESS) + goto cleanup; + j++; + if (KeyBuffer[0] != '#') + /* This entry doesn't represent an interesting entry */ + continue; + + /* Open sub key */ + if (hReferenceKey != NULL) + RegCloseKey(hReferenceKey); + rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey); + if (rc != ERROR_SUCCESS) + goto cleanup; + + /* Read SymbolicLink value */ + rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength); + if (rc != ERROR_SUCCESS ) + goto cleanup; + if (dwRegType != REG_SZ) + { + rc = ERROR_GEN_FAILURE; + goto cleanup; + } + + /* We have found a device */ + /* Step 1. Create a device info element */ + if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo)) + { + rc = GetLastError(); + goto cleanup; + } + TRACE("Adding device %s to list\n", debugstr_w(InstancePath)); + InsertTailList(&list->ListHead, &deviceInfo->ListEntry); + + /* Step 2. Create an interface list for this element */ + HeapFree(GetProcessHeap(), 0, pSymbolicLink); + pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR)); + if (!pSymbolicLink) + { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength); + pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0'; + if (rc != ERROR_SUCCESS) + goto cleanup; + if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo)) + { + rc = GetLastError(); + goto cleanup; + } + + /* Step 3. Update flags */ + if (KeyBuffer[1] == '\0') + interfaceInfo->Flags |= SPINT_DEFAULT; + rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey); + if (rc != ERROR_SUCCESS) + { + if (OnlyPresentInterfaces) + { + DestroyDeviceInterface(interfaceInfo); + continue; + } + else + interfaceInfo->Flags |= SPINT_REMOVED; + } + else + { + dwLength = sizeof(DWORD); + if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength) + && dwRegType == REG_DWORD && LinkedValue) + interfaceInfo->Flags |= SPINT_ACTIVE; + RegCloseKey(hControlKey); + } + + TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink)); + InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry); + } + } + rc = ERROR_SUCCESS; + +cleanup: + if (hReferenceKey != NULL) + RegCloseKey(hReferenceKey); + if (hDeviceInstanceKey != NULL) + RegCloseKey(hDeviceInstanceKey); + if (hInterfaceKey != INVALID_HANDLE_VALUE) + RegCloseKey(hInterfaceKey); + HeapFree(GetProcessHeap(), 0, InstancePath); + HeapFree(GetProcessHeap(), 0, pSymbolicLink); + return rc; +} + +/*********************************************************************** + * SetupDiEnumDeviceInterfaces (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiEnumDeviceInterfaces( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN CONST GUID *InterfaceClassGuid, + IN DWORD MemberIndex, + OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + BOOL ret = FALSE; + + TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData, + debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); + + if (!DeviceInterfaceData) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) + { + struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet; + + if (list->magic == SETUP_DEV_INFO_SET_MAGIC) + { + PLIST_ENTRY ItemList = list->ListHead.Flink; + BOOL Found = FALSE; + while (ItemList != &list->ListHead && !Found) + { + PLIST_ENTRY InterfaceListEntry; + struct DeviceInfoElement *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfoElement, ListEntry); + if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo) + { + /* We are not searching for this element */ + ItemList = ItemList->Flink; + continue; + } + InterfaceListEntry = DevInfo->InterfaceListHead.Flink; + while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found) + { + struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); + if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) + { + InterfaceListEntry = InterfaceListEntry->Flink; + continue; + } + if (MemberIndex-- == 0) + { + /* return this item */ + memcpy(&DeviceInterfaceData->InterfaceClassGuid, + &DevItf->InterfaceClassGuid, + sizeof(GUID)); + DeviceInterfaceData->Flags = DevItf->Flags; + DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; + Found = TRUE; + } + InterfaceListEntry = InterfaceListEntry->Flink; + } + ItemList = ItemList->Flink; + } + if (!Found) + SetLastError(ERROR_NO_MORE_ITEMS); + else + ret = TRUE; + } + else + SetLastError(ERROR_INVALID_HANDLE); + } + else + SetLastError(ERROR_INVALID_HANDLE); + return ret; +} + +/*********************************************************************** + * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetDeviceInterfaceDetailW( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL, + IN DWORD DeviceInterfaceDetailDataSize, + OUT PDWORD RequiredSize OPTIONAL, + OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) +{ + BOOL ret = FALSE; + + TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet, + DeviceInterfaceData, DeviceInterfaceDetailData, + DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); + + if (!DeviceInfoSet || !DeviceInterfaceData) + 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 (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved; + LPCWSTR devName = deviceInterface->SymbolicLink; + DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + + (lstrlenW(devName) + 1) * sizeof(WCHAR); + + if (sizeRequired > DeviceInterfaceDetailDataSize) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + if (RequiredSize) + *RequiredSize = sizeRequired; + } + else + { + strcpyW(DeviceInterfaceDetailData->DevicePath, devName); + TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath)); + if (DeviceInfoData) + { + memcpy(&DeviceInfoData->ClassGuid, + &deviceInterface->DeviceInfo->ClassGuid, + sizeof(GUID)); + DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst; + DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo; + } + ret = TRUE; + } + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiGetDeviceInterfaceDetailA( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL, + IN DWORD DeviceInterfaceDetailDataSize, + OUT PDWORD RequiredSize OPTIONAL, + OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) +{ + PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL; + DWORD sizeW = 0, sizeA; + BOOL ret = FALSE; + + TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet, + DeviceInterfaceData, DeviceInterfaceDetailData, + DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); + + if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + if (DeviceInterfaceDetailData != NULL) + { + sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR); + DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW); + if (!DeviceInterfaceDetailDataW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + } + if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW)) + { + DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + ret = SetupDiGetDeviceInterfaceDetailW( + DeviceInfoSet, + DeviceInterfaceData, + DeviceInterfaceDetailDataW, + sizeW, + &sizeW, + DeviceInfoData); + sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR) + + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath); + if (RequiredSize) + *RequiredSize = sizeA; + if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA) + { + if (!WideCharToMultiByte( + CP_ACP, 0, + DeviceInterfaceDetailDataW->DevicePath, -1, + DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath), + NULL, NULL)) + { + ret = FALSE; + } + } + } + HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiOpenDeviceInterfaceA( + IN HDEVINFO DeviceInfoSet, + IN PCSTR DevicePath, + IN DWORD OpenFlags, + OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL) +{ + LPWSTR DevicePathW = NULL; + BOOL bResult; + + TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); + + DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP); + if (DevicePathW == NULL) + return FALSE; + + bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet, + DevicePathW, OpenFlags, DeviceInterfaceData); + + MyFree(DevicePathW); + + return bResult; +} + +/*********************************************************************** + * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiOpenDeviceInterfaceW( + IN HDEVINFO DeviceInfoSet, + IN PCWSTR DevicePath, + IN DWORD OpenFlags, + OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL) +{ + FIXME("%p %s %08lx %p\n", + DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); + return FALSE; +} + +static BOOL +InstallOneInterface( + IN LPGUID InterfaceGuid, + IN LPCWSTR ReferenceString, + IN LPCWSTR InterfaceSection, + IN UINT InterfaceFlags) +{ + if (InterfaceFlags != 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid), + debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags); + return TRUE; +} + +/*********************************************************************** + * SetupDiInstallDeviceInterfaces (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallDeviceInterfaces( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData) +{ + struct DeviceInfoSet *list = NULL; + BOOL ret = FALSE; + + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + if (!DeviceInfoSet) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) + SetLastError(ERROR_INVALID_HANDLE); + else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) + SetLastError(ERROR_INVALID_HANDLE); + else if (!DeviceInfoData) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else + { + struct DriverInfoElement *SelectedDriver; + SP_DEVINSTALL_PARAMS_W InstallParams; + WCHAR SectionName[MAX_PATH]; + DWORD SectionNameLength = 0; + INFCONTEXT ContextInterface; + LPWSTR InterfaceGuidString = NULL; + LPWSTR ReferenceString = NULL; + LPWSTR InterfaceSection = NULL; + INT InterfaceFlags; + GUID InterfaceGuid; + BOOL Result; + + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); + if (!Result) + goto cleanup; + + SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; + if (SelectedDriver == NULL) + { + SetLastError(ERROR_NO_DRIVER_SELECTED); + ret = FALSE; + goto cleanup; + } + + /* Get .Interfaces section name */ + Result = SetupDiGetActualSectionToInstallW( + SelectedDriver->InfFileDetails->hInf, + SelectedDriver->Details.SectionName, + SectionName, MAX_PATH, &SectionNameLength, NULL); + if (!Result || SectionNameLength > MAX_PATH - strlenW(DotInterfaces) - 1) + goto cleanup; + strcatW(SectionName, DotInterfaces); + + ret = TRUE; + Result = SetupFindFirstLineW( + SelectedDriver->InfFileDetails->hInf, + SectionName, + AddInterface, + &ContextInterface); + while (ret && Result) + { + ret = GetStringField(&ContextInterface, 1, &InterfaceGuidString); + if (!ret) + goto cleanup; + else if (strlenW(InterfaceGuidString) != MAX_GUID_STRING_LEN - 1) + { + SetLastError(ERROR_INVALID_PARAMETER); + ret = FALSE; + goto cleanup; + } + + InterfaceGuidString[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */ + if (UuidFromStringW(&InterfaceGuidString[1], &InterfaceGuid) != RPC_S_OK) + { + /* Bad GUID, skip the entry */ + SetLastError(ERROR_INVALID_PARAMETER); + ret = FALSE; + goto cleanup; + } + + ret = GetStringField(&ContextInterface, 2, &ReferenceString); + if (!ret) + goto cleanup; + + ret = GetStringField(&ContextInterface, 3, &InterfaceSection); + if (!ret) + goto cleanup; + + ret = SetupGetIntField( + &ContextInterface, + 4, /* Field index */ + &InterfaceFlags); + if (!ret) + { + if (GetLastError() == ERROR_INVALID_PARAMETER) + { + /* The field may be empty. Ignore the error */ + InterfaceFlags = 0; + ret = TRUE; + } + else + goto cleanup; + } + + /* Install Interface */ + ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags); + +cleanup: + MyFree(InterfaceGuidString); + MyFree(ReferenceString); + MyFree(InterfaceSection); + InterfaceGuidString = ReferenceString = InterfaceSection = NULL; + Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface); + } + } + + TRACE("Returning %d\n", ret); + return ret; +} diff --git a/reactos/dll/win32/setupapi/misc.c b/reactos/dll/win32/setupapi/misc.c index 2f92718d32d..7ab8567dc3b 100644 --- a/reactos/dll/win32/setupapi/misc.c +++ b/reactos/dll/win32/setupapi/misc.c @@ -22,6 +22,80 @@ WINE_DEFAULT_DEBUG_CHANNEL(setupapi); +DWORD +GetFunctionPointer( + IN PWSTR InstallerName, + OUT HMODULE* ModulePointer, + OUT PVOID* FunctionPointer) +{ + HMODULE hModule = NULL; + LPSTR FunctionNameA = NULL; + PWCHAR Comma; + DWORD rc; + + *ModulePointer = NULL; + *FunctionPointer = NULL; + + Comma = strchrW(InstallerName, ','); + if (!Comma) + { + rc = ERROR_INVALID_PARAMETER; + goto cleanup; + } + + /* Load library */ + *Comma = '\0'; + hModule = LoadLibraryW(InstallerName); + *Comma = ','; + if (!hModule) + { + rc = GetLastError(); + goto cleanup; + } + + /* Skip comma spaces */ + while (*Comma == ',' || isspaceW(*Comma)) + Comma++; + + /* W->A conversion for function name */ + FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP); + if (!FunctionNameA) + { + rc = GetLastError(); + goto cleanup; + } + + /* Search function */ + *FunctionPointer = GetProcAddress(hModule, FunctionNameA); + if (!*FunctionPointer) + { + rc = GetLastError(); + goto cleanup; + } + + *ModulePointer = hModule; + rc = ERROR_SUCCESS; + +cleanup: + if (rc != ERROR_SUCCESS && hModule) + FreeLibrary(hModule); + MyFree(FunctionNameA); + return rc; +} + +DWORD +FreeFunctionPointer( + IN HMODULE ModulePointer, + IN PVOID FunctionPointer) +{ + if (ModulePointer == NULL) + return ERROR_SUCCESS; + if (FreeLibrary(ModulePointer)) + return ERROR_SUCCESS; + else + return GetLastError(); +} + /************************************************************************** * MyFree [SETUPAPI.@] * diff --git a/reactos/dll/win32/setupapi/setupapi.rbuild b/reactos/dll/win32/setupapi/setupapi.rbuild index e99105ba295..b4e4d6f1830 100644 --- a/reactos/dll/win32/setupapi/setupapi.rbuild +++ b/reactos/dll/win32/setupapi/setupapi.rbuild @@ -23,10 +23,13 @@ rpcrt4 version cfgmgr.c + devclass.c devinst.c dirid.c diskspace.c + driver.c install.c + interface.c misc.c parser.c query.c diff --git a/reactos/dll/win32/setupapi/setupapi_private.h b/reactos/dll/win32/setupapi/setupapi_private.h index b2c7e6f6d18..f83c8b15c53 100644 --- a/reactos/dll/win32/setupapi/setupapi_private.h +++ b/reactos/dll/win32/setupapi/setupapi_private.h @@ -227,9 +227,62 @@ UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, U extern HINSTANCE hInstance; extern OSVERSIONINFOW OsVersionInfo; +/* devinst.c */ + +BOOL +CreateDeviceInfoElement( + IN struct DeviceInfoSet *list, + IN LPCWSTR InstancePath, + IN LPCGUID pClassGuid, + OUT struct DeviceInfoElement **pDeviceInfo); + +/* driver.c */ + +struct InfFileDetails * +CreateInfFileDetails( + IN LPCWSTR FullInfFileName); + +VOID +DereferenceInfFile(struct InfFileDetails* infFile); + +BOOL +DestroyDriverInfoElement(struct DriverInfoElement* driverInfo); + +/* install.c */ + +BOOL +GetStringField( PINFCONTEXT context, DWORD index, PWSTR *value); + +/* interface.c */ + +BOOL +DestroyDeviceInterface( + struct DeviceInterface* deviceInterface); + +LONG +SETUP_CreateInterfaceList( + struct DeviceInfoSet *list, + PCWSTR MachineName, + CONST GUID *InterfaceGuid, + PCWSTR DeviceInstanceW /* OPTIONAL */, + BOOL OnlyPresentInterfaces); + +/* misc.c */ + +DWORD +GetFunctionPointer( + IN PWSTR InstallerName, + OUT HMODULE* ModulePointer, + OUT PVOID* FunctionPointer); + +DWORD +FreeFunctionPointer( + IN HMODULE ModulePointer, + IN PVOID FunctionPointer); + DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst); -BOOL GetStringField( PINFCONTEXT context, DWORD index, PWSTR *value); +/* parser.c */ typedef BOOL (*FIND_CALLBACK)(LPCWSTR SectionName, PVOID Context); BOOL EnumerateSectionsStartingWith(HINF hInf, LPCWSTR pStr, FIND_CALLBACK Callback, PVOID Context);