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);