2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
43 #include "setupapi_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
48 /* Unicode constants */
49 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
50 static const WCHAR Class[] = {'C','l','a','s','s',0};
51 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
52 static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
53 static const WCHAR NoInstallClass[] = {'N','o','I','n','s','t','a','l','l','C','l','a','s','s',0};
54 static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
55 static const WCHAR NtExtension[] = {'.','N','T',0};
56 static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
57 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
58 static const WCHAR WinExtension[] = {'.','W','i','n',0};
60 /* Registry key and value names */
61 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
62 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
63 'C','o','n','t','r','o','l','\\',
64 'C','l','a','s','s',0};
66 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
67 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
68 'C','o','n','t','r','o','l','\\',
69 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
70 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
71 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
73 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
74 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
75 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
76 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
77 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
78 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
79 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
80 static const WCHAR Mfg[] = {'M','f','g',0};
81 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
82 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
83 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
84 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
85 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
86 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
87 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
89 /* is used to identify if a DeviceInfoSet pointer is
91 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
95 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
99 SP_DEVINFO_DATA *devices;
102 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
110 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId,
113 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
114 sizeof(struct DeviceInfo));
118 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
119 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
120 if (devInfo->instanceId)
125 devInfo->key = INVALID_HANDLE_VALUE;
126 devInfo->phantom = phantom;
127 lstrcpyW(devInfo->instanceId, instanceId);
128 struprW(devInfo->instanceId);
129 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
130 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
133 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
134 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
136 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
137 (LPBYTE)&phantom, sizeof(phantom));
138 RegCloseKey(enumKey);
143 HeapFree(GetProcessHeap(), 0, devInfo);
150 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
152 if (devInfo->key != INVALID_HANDLE_VALUE)
153 RegCloseKey(devInfo->key);
154 if (devInfo->phantom)
159 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
160 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
163 RegDeleteTreeW(enumKey, devInfo->instanceId);
164 RegCloseKey(enumKey);
167 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
168 HeapFree(GetProcessHeap(), 0, devInfo);
171 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
173 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
174 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
175 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
178 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
179 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
180 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
183 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
184 * struct DeviceInfo, and points the returned device info's Reserved member
185 * to it. "Phantom" devices are deleted from the registry when closed.
186 * Returns a pointer to the newly allocated device info.
188 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
193 SP_DEVINFO_DATA **dev)
196 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(instanceId,
199 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
200 debugstr_w(instanceId), phantom);
205 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
206 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
208 set->devices = HeapAlloc(GetProcessHeap(), 0,
209 sizeof(SP_DEVINFO_DATA));
212 WCHAR classGuidStr[39];
214 *dev = &set->devices[set->cDevices++];
215 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
216 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
217 (*dev)->DevInst = devInst;
218 (*dev)->Reserved = (ULONG_PTR)devInfo;
219 SETUPDI_GuidToString(guid, classGuidStr);
220 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
221 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
222 lstrlenW(classGuidStr) * sizeof(WCHAR));
227 HeapFree(GetProcessHeap(), 0, devInfo);
228 SetLastError(ERROR_OUTOFMEMORY);
234 /***********************************************************************
235 * SetupDiBuildClassInfoList (SETUPAPI.@)
237 * Returns a list of setup class GUIDs that identify the classes
238 * that are installed on a local machine.
241 * Flags [I] control exclusion of classes from the list.
242 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
243 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
244 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
250 BOOL WINAPI SetupDiBuildClassInfoList(
252 LPGUID ClassGuidList,
253 DWORD ClassGuidListSize,
257 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
258 ClassGuidListSize, RequiredSize,
262 /***********************************************************************
263 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
265 * Returns a list of setup class GUIDs that identify the classes
266 * that are installed on a local or remote macine.
269 * Flags [I] control exclusion of classes from the list.
270 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
271 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
272 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
273 * MachineName [I] name of a remote machine.
274 * Reserved [I] must be NULL.
280 BOOL WINAPI SetupDiBuildClassInfoListExA(
282 LPGUID ClassGuidList,
283 DWORD ClassGuidListSize,
288 LPWSTR MachineNameW = NULL;
295 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
296 if (MachineNameW == NULL) return FALSE;
299 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
300 ClassGuidListSize, RequiredSize,
301 MachineNameW, Reserved);
303 MyFree(MachineNameW);
308 /***********************************************************************
309 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
311 * Returns a list of setup class GUIDs that identify the classes
312 * that are installed on a local or remote macine.
315 * Flags [I] control exclusion of classes from the list.
316 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
317 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
318 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
319 * MachineName [I] name of a remote machine.
320 * Reserved [I] must be NULL.
326 BOOL WINAPI SetupDiBuildClassInfoListExW(
328 LPGUID ClassGuidList,
329 DWORD ClassGuidListSize,
340 DWORD dwGuidListIndex = 0;
344 if (RequiredSize != NULL)
347 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
352 if (hClassesKey == INVALID_HANDLE_VALUE)
357 for (dwIndex = 0; ; dwIndex++)
360 lError = RegEnumKeyExW(hClassesKey,
368 TRACE("RegEnumKeyExW() returns %d\n", lError);
369 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
371 TRACE("Key name: %p\n", szKeyName);
373 if (RegOpenKeyExW(hClassesKey,
379 RegCloseKey(hClassesKey);
383 if (!RegQueryValueExW(hClassKey,
390 TRACE("'NoUseClass' value found!\n");
391 RegCloseKey(hClassKey);
395 if ((Flags & DIBCI_NOINSTALLCLASS) &&
396 (!RegQueryValueExW(hClassKey,
403 TRACE("'NoInstallClass' value found!\n");
404 RegCloseKey(hClassKey);
408 if ((Flags & DIBCI_NODISPLAYCLASS) &&
409 (!RegQueryValueExW(hClassKey,
416 TRACE("'NoDisplayClass' value found!\n");
417 RegCloseKey(hClassKey);
421 RegCloseKey(hClassKey);
423 TRACE("Guid: %p\n", szKeyName);
424 if (dwGuidListIndex < ClassGuidListSize)
426 if (szKeyName[0] == '{' && szKeyName[37] == '}')
430 TRACE("Guid: %p\n", &szKeyName[1]);
432 UuidFromStringW(&szKeyName[1],
433 &ClassGuidList[dwGuidListIndex]);
439 if (lError != ERROR_SUCCESS)
443 RegCloseKey(hClassesKey);
445 if (RequiredSize != NULL)
446 *RequiredSize = dwGuidListIndex;
448 if (ClassGuidListSize < dwGuidListIndex)
450 SetLastError(ERROR_INSUFFICIENT_BUFFER);
457 /***********************************************************************
458 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
460 BOOL WINAPI SetupDiClassGuidsFromNameA(
462 LPGUID ClassGuidList,
463 DWORD ClassGuidListSize,
466 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
467 ClassGuidListSize, RequiredSize,
471 /***********************************************************************
472 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
474 BOOL WINAPI SetupDiClassGuidsFromNameW(
476 LPGUID ClassGuidList,
477 DWORD ClassGuidListSize,
480 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
481 ClassGuidListSize, RequiredSize,
485 /***********************************************************************
486 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
488 BOOL WINAPI SetupDiClassGuidsFromNameExA(
490 LPGUID ClassGuidList,
491 DWORD ClassGuidListSize,
496 LPWSTR ClassNameW = NULL;
497 LPWSTR MachineNameW = NULL;
502 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
503 if (ClassNameW == NULL)
508 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
509 if (MachineNameW == NULL)
516 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
517 ClassGuidListSize, RequiredSize,
518 MachineNameW, Reserved);
520 MyFree(MachineNameW);
526 /***********************************************************************
527 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
529 BOOL WINAPI SetupDiClassGuidsFromNameExW(
531 LPGUID ClassGuidList,
532 DWORD ClassGuidListSize,
538 WCHAR szClassName[256];
544 DWORD dwGuidListIndex = 0;
546 if (RequiredSize != NULL)
549 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
554 if (hClassesKey == INVALID_HANDLE_VALUE)
559 for (dwIndex = 0; ; dwIndex++)
562 lError = RegEnumKeyExW(hClassesKey,
570 TRACE("RegEnumKeyExW() returns %d\n", lError);
571 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
573 TRACE("Key name: %p\n", szKeyName);
575 if (RegOpenKeyExW(hClassesKey,
581 RegCloseKey(hClassesKey);
585 dwLength = 256 * sizeof(WCHAR);
586 if (!RegQueryValueExW(hClassKey,
593 TRACE("Class name: %p\n", szClassName);
595 if (strcmpiW(szClassName, ClassName) == 0)
597 TRACE("Found matching class name\n");
599 TRACE("Guid: %p\n", szKeyName);
600 if (dwGuidListIndex < ClassGuidListSize)
602 if (szKeyName[0] == '{' && szKeyName[37] == '}')
606 TRACE("Guid: %p\n", &szKeyName[1]);
608 UuidFromStringW(&szKeyName[1],
609 &ClassGuidList[dwGuidListIndex]);
616 RegCloseKey(hClassKey);
619 if (lError != ERROR_SUCCESS)
623 RegCloseKey(hClassesKey);
625 if (RequiredSize != NULL)
626 *RequiredSize = dwGuidListIndex;
628 if (ClassGuidListSize < dwGuidListIndex)
630 SetLastError(ERROR_INSUFFICIENT_BUFFER);
637 /***********************************************************************
638 * SetupDiClassNameFromGuidA (SETUPAPI.@)
640 BOOL WINAPI SetupDiClassNameFromGuidA(
641 const GUID* ClassGuid,
646 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
647 ClassNameSize, RequiredSize,
651 /***********************************************************************
652 * SetupDiClassNameFromGuidW (SETUPAPI.@)
654 BOOL WINAPI SetupDiClassNameFromGuidW(
655 const GUID* ClassGuid,
660 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
661 ClassNameSize, RequiredSize,
665 /***********************************************************************
666 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
668 BOOL WINAPI SetupDiClassNameFromGuidExA(
669 const GUID* ClassGuid,
676 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
677 LPWSTR MachineNameW = NULL;
681 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
682 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
683 NULL, MachineNameW, Reserved);
686 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
687 ClassNameSize, NULL, NULL);
689 if (!ClassNameSize && RequiredSize)
692 MyFree(MachineNameW);
696 /***********************************************************************
697 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
699 BOOL WINAPI SetupDiClassNameFromGuidExW(
700 const GUID* ClassGuid,
710 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
715 if (hKey == INVALID_HANDLE_VALUE)
720 if (RequiredSize != NULL)
723 if (RegQueryValueExW(hKey,
734 *RequiredSize = dwLength / sizeof(WCHAR);
737 dwLength = ClassNameSize * sizeof(WCHAR);
738 if (RegQueryValueExW(hKey,
754 /***********************************************************************
755 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
758 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
761 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
764 /***********************************************************************
765 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
768 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
773 LPWSTR MachineNameW = NULL;
780 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
781 if (MachineNameW == NULL)
782 return (HDEVINFO)INVALID_HANDLE_VALUE;
785 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
786 MachineNameW, Reserved);
788 MyFree(MachineNameW);
793 /***********************************************************************
794 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
796 * Create an empty DeviceInfoSet list.
799 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
801 * hwndParent [I] hwnd needed for interface related actions.
802 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
803 * local registry will be used.
804 * Reserved [I] must be NULL
807 * Success: empty list.
808 * Failure: INVALID_HANDLE_VALUE.
811 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
816 struct DeviceInfoSet *list = NULL;
817 DWORD size = sizeof(struct DeviceInfoSet);
819 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
820 debugstr_w(MachineName), Reserved);
822 if (MachineName != NULL)
824 FIXME("remote support is not implemented\n");
825 SetLastError(ERROR_INVALID_MACHINENAME);
826 return (HDEVINFO)INVALID_HANDLE_VALUE;
829 if (Reserved != NULL)
831 SetLastError(ERROR_INVALID_PARAMETER);
832 return (HDEVINFO)INVALID_HANDLE_VALUE;
835 list = HeapAlloc(GetProcessHeap(), 0, size);
838 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
839 return (HDEVINFO)INVALID_HANDLE_VALUE;
842 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
843 list->hwndParent = hwndParent;
844 memcpy(&list->ClassGuid,
845 ClassGuid ? ClassGuid : &GUID_NULL,
846 sizeof(list->ClassGuid));
848 list->devices = NULL;
850 return (HDEVINFO)list;
853 /***********************************************************************
854 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
856 BOOL WINAPI SetupDiCreateDeviceInfoA(
857 HDEVINFO DeviceInfoSet,
859 CONST GUID *ClassGuid,
860 PCSTR DeviceDescription,
863 PSP_DEVINFO_DATA DeviceInfoData)
866 LPWSTR DeviceNameW = NULL;
867 LPWSTR DeviceDescriptionW = NULL;
871 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
872 if (DeviceNameW == NULL) return FALSE;
874 if (DeviceDescription)
876 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
877 if (DeviceDescriptionW == NULL)
884 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
885 hwndParent, CreationFlags, DeviceInfoData);
888 MyFree(DeviceDescriptionW);
893 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
896 DWORD devNameLen = lstrlenW(devName), devInst = 0;
899 TRACE("%s\n", debugstr_w(devName));
900 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
905 devInst |= *ptr - '0';
911 TRACE("%d\n", valid ? devInst : 0xffffffff);
912 return valid ? devInst : 0xffffffff;
915 /***********************************************************************
916 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
918 BOOL WINAPI SetupDiCreateDeviceInfoW(
919 HDEVINFO DeviceInfoSet,
921 CONST GUID *ClassGuid,
922 PCWSTR DeviceDescription,
925 PSP_DEVINFO_DATA DeviceInfoData)
927 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
928 BOOL ret = FALSE, allocatedInstanceId = FALSE;
929 LPCWSTR instanceId = NULL;
931 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
932 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
933 hwndParent, CreationFlags, DeviceInfoData);
937 SetLastError(ERROR_INVALID_DEVINST_NAME);
940 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
942 SetLastError(ERROR_INVALID_HANDLE);
947 SetLastError(ERROR_INVALID_PARAMETER);
950 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
952 SetLastError(ERROR_INVALID_HANDLE);
955 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
956 !IsEqualGUID(ClassGuid, &set->ClassGuid))
958 SetLastError(ERROR_CLASS_MISMATCH);
961 if ((CreationFlags & DICD_GENERATE_ID))
963 if (strchrW(DeviceName, '\\'))
964 SetLastError(ERROR_INVALID_DEVINST_NAME);
967 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
968 '\\','%','0','4','d',0};
973 DWORD i, highestDevID = 0;
975 for (i = 0; i < set->cDevices; i++)
977 struct DeviceInfo *devInfo =
978 (struct DeviceInfo *)set->devices[i].Reserved;
979 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
985 devName = devInfo->instanceId;
986 id = SETUPDI_DevNameToDevID(devName);
987 if (id != 0xffffffff && id > highestDevID)
990 devId = highestDevID + 1;
994 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
995 instanceId = HeapAlloc(GetProcessHeap(), 0,
996 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
999 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1001 allocatedInstanceId = TRUE;
1013 instanceId = DeviceName;
1014 for (i = 0; ret && i < set->cDevices; i++)
1016 struct DeviceInfo *devInfo =
1017 (struct DeviceInfo *)set->devices[i].Reserved;
1019 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1021 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1028 SP_DEVINFO_DATA *dev = NULL;
1030 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1031 instanceId, TRUE, &dev);
1034 if (DeviceDescription)
1035 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1036 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1037 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1040 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1042 SetLastError(ERROR_INVALID_USER_BUFFER);
1046 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1050 if (allocatedInstanceId)
1051 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1056 /***********************************************************************
1057 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1059 BOOL WINAPI SetupDiRegisterDeviceInfo(
1060 HDEVINFO DeviceInfoSet,
1061 PSP_DEVINFO_DATA DeviceInfoData,
1063 PSP_DETSIG_CMPPROC CompareProc,
1064 PVOID CompareContext,
1065 PSP_DEVINFO_DATA DupDeviceInfoData)
1067 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1068 struct DeviceInfo *devInfo;
1070 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1071 CompareProc, CompareContext, DupDeviceInfoData);
1073 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1075 SetLastError(ERROR_INVALID_HANDLE);
1078 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1080 SetLastError(ERROR_INVALID_HANDLE);
1083 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1084 || !DeviceInfoData->Reserved)
1086 SetLastError(ERROR_INVALID_PARAMETER);
1089 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1090 if (devInfo->phantom)
1092 devInfo->phantom = FALSE;
1093 RegDeleteValueW(devInfo->key, Phantom);
1098 /***********************************************************************
1099 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1101 BOOL WINAPI SetupDiEnumDeviceInfo(
1104 PSP_DEVINFO_DATA info)
1108 TRACE("%p %d %p\n", devinfo, index, info);
1112 if(info->cbSize < sizeof(*info))
1114 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1116 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1117 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1119 if (index < list->cDevices)
1121 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1123 memcpy(info, &list->devices[index], info->cbSize);
1127 SetLastError(ERROR_INVALID_USER_BUFFER);
1130 SetLastError(ERROR_NO_MORE_ITEMS);
1133 SetLastError(ERROR_INVALID_HANDLE);
1136 SetLastError(ERROR_INVALID_HANDLE);
1140 /***********************************************************************
1141 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1143 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1144 HDEVINFO DeviceInfoSet,
1145 PSP_DEVINFO_DATA DeviceInfoData,
1146 PSTR DeviceInstanceId,
1147 DWORD DeviceInstanceIdSize,
1148 PDWORD RequiredSize)
1154 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1155 DeviceInstanceIdSize, RequiredSize);
1157 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1162 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1164 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1167 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1174 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1176 DeviceInstanceIdSize, NULL, NULL);
1182 if (len > DeviceInstanceIdSize)
1184 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1188 *RequiredSize = len;
1191 HeapFree(GetProcessHeap(), 0, instanceId);
1196 /***********************************************************************
1197 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1199 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1200 HDEVINFO DeviceInfoSet,
1201 PSP_DEVINFO_DATA DeviceInfoData,
1202 PWSTR DeviceInstanceId,
1203 DWORD DeviceInstanceIdSize,
1204 PDWORD RequiredSize)
1206 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1207 struct DeviceInfo *devInfo;
1209 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1210 DeviceInstanceIdSize, RequiredSize);
1212 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1214 SetLastError(ERROR_INVALID_HANDLE);
1217 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1219 SetLastError(ERROR_INVALID_HANDLE);
1222 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1223 || !DeviceInfoData->Reserved)
1225 SetLastError(ERROR_INVALID_PARAMETER);
1228 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1229 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1230 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1232 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1234 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1237 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1239 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1243 /***********************************************************************
1244 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1246 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1248 PCSTR InfSectionName,
1249 PSTR InfSectionWithExt,
1250 DWORD InfSectionWithExtSize,
1251 PDWORD RequiredSize,
1258 /***********************************************************************
1259 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1261 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1263 PCWSTR InfSectionName,
1264 PWSTR InfSectionWithExt,
1265 DWORD InfSectionWithExtSize,
1266 PDWORD RequiredSize,
1269 WCHAR szBuffer[MAX_PATH];
1272 LONG lLineCount = -1;
1274 lstrcpyW(szBuffer, InfSectionName);
1275 dwLength = lstrlenW(szBuffer);
1277 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1279 /* Test section name with '.NTx86' extension */
1280 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1281 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1283 if (lLineCount == -1)
1285 /* Test section name with '.NT' extension */
1286 lstrcpyW(&szBuffer[dwLength], NtExtension);
1287 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1292 /* Test section name with '.Win' extension */
1293 lstrcpyW(&szBuffer[dwLength], WinExtension);
1294 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1297 if (lLineCount == -1)
1299 /* Test section name without extension */
1300 szBuffer[dwLength] = 0;
1301 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1304 if (lLineCount == -1)
1306 SetLastError(ERROR_INVALID_PARAMETER);
1310 dwFullLength = lstrlenW(szBuffer);
1312 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1314 if (InfSectionWithExtSize < (dwFullLength + 1))
1316 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1320 lstrcpyW(InfSectionWithExt, szBuffer);
1321 if (Extension != NULL)
1323 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1327 if (RequiredSize != NULL)
1329 *RequiredSize = dwFullLength + 1;
1335 /***********************************************************************
1336 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1338 BOOL WINAPI SetupDiGetClassDescriptionA(
1339 const GUID* ClassGuid,
1340 PSTR ClassDescription,
1341 DWORD ClassDescriptionSize,
1342 PDWORD RequiredSize)
1344 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1345 ClassDescriptionSize,
1346 RequiredSize, NULL, NULL);
1349 /***********************************************************************
1350 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1352 BOOL WINAPI SetupDiGetClassDescriptionW(
1353 const GUID* ClassGuid,
1354 PWSTR ClassDescription,
1355 DWORD ClassDescriptionSize,
1356 PDWORD RequiredSize)
1358 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1359 ClassDescriptionSize,
1360 RequiredSize, NULL, NULL);
1363 /***********************************************************************
1364 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1366 BOOL WINAPI SetupDiGetClassDescriptionExA(
1367 const GUID* ClassGuid,
1368 PSTR ClassDescription,
1369 DWORD ClassDescriptionSize,
1370 PDWORD RequiredSize,
1378 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1383 if (hKey == INVALID_HANDLE_VALUE)
1385 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1389 dwLength = ClassDescriptionSize;
1390 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1391 (LPBYTE)ClassDescription, &dwLength );
1392 if (RequiredSize) *RequiredSize = dwLength;
1397 /***********************************************************************
1398 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1400 BOOL WINAPI SetupDiGetClassDescriptionExW(
1401 const GUID* ClassGuid,
1402 PWSTR ClassDescription,
1403 DWORD ClassDescriptionSize,
1404 PDWORD RequiredSize,
1412 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1417 if (hKey == INVALID_HANDLE_VALUE)
1419 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1423 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1424 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1425 (LPBYTE)ClassDescription, &dwLength );
1426 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1431 /***********************************************************************
1432 * SetupDiGetClassDevsA (SETUPAPI.@)
1434 HDEVINFO WINAPI SetupDiGetClassDevsA(
1441 LPWSTR enumstrW = NULL;
1445 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1446 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1449 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1452 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1454 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
1455 HeapFree(GetProcessHeap(), 0, enumstrW);
1461 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1462 HKEY key, const GUID *interface, LPCWSTR enumstr)
1464 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1466 WCHAR subKeyName[MAX_PATH];
1468 HKEY enumKey = INVALID_HANDLE_VALUE;
1470 TRACE("%s\n", debugstr_w(enumstr));
1472 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1474 for (i = 0; !l; i++)
1476 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1477 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1482 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1485 WCHAR deviceInst[MAX_PATH * 3];
1488 len = sizeof(deviceInst);
1489 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1490 (BYTE *)deviceInst, &len);
1491 if (!l && dataType == REG_SZ)
1493 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1494 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1498 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1502 WCHAR deviceClassStr[40];
1504 len = sizeof(deviceClassStr);
1505 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1506 &dataType, (BYTE *)deviceClassStr, &len);
1507 if (!l && dataType == REG_SZ &&
1508 deviceClassStr[0] == '{' &&
1509 deviceClassStr[37] == '}')
1512 SP_DEVINFO_DATA *dev;
1514 deviceClassStr[37] = 0;
1515 UuidFromStringW(&deviceClassStr[1],
1517 SETUPDI_AddDeviceToSet(set, &deviceClass,
1518 0 /* FIXME: DevInst */, deviceInst,
1520 /* FIXME: add this interface, and all the
1521 * device's interfaces, to the device
1524 RegCloseKey(deviceKey);
1528 RegCloseKey(subKey);
1532 if (enumKey != INVALID_HANDLE_VALUE)
1533 RegCloseKey(enumKey);
1536 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1537 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1539 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1540 DIOCR_INTERFACE, NULL, NULL);
1542 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1543 debugstr_w(enumstr), flags);
1545 if (interfacesKey != INVALID_HANDLE_VALUE)
1547 if (flags & DIGCF_ALLCLASSES)
1550 WCHAR interfaceGuidStr[40];
1551 LONG l = ERROR_SUCCESS;
1553 for (i = 0; !l; i++)
1555 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
1556 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
1557 NULL, NULL, NULL, NULL);
1560 if (interfaceGuidStr[0] == '{' &&
1561 interfaceGuidStr[37] == '}')
1566 interfaceGuidStr[37] = 0;
1567 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
1568 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
1569 KEY_READ, &interfaceKey);
1572 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1573 interfaceKey, &interfaceGuid, enumstr);
1574 RegCloseKey(interfaceKey);
1582 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
1583 * interface's key, so just pass that long
1585 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1586 interfacesKey, interface, enumstr);
1588 RegCloseKey(interfacesKey);
1592 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
1593 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
1595 struct DeviceInfoSet *set = (struct DeviceInfoSet *)set;
1597 WCHAR subKeyName[MAX_PATH];
1598 LONG l = ERROR_SUCCESS;
1600 TRACE("%s\n", debugstr_w(parent));
1602 for (i = 0; !l; i++)
1604 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1605 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1610 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1613 WCHAR classGuid[40];
1616 len = sizeof(classGuid);
1617 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
1618 (BYTE *)classGuid, &len);
1619 if (!l && dataType == REG_SZ)
1621 if (classGuid[0] == '{' && classGuid[37] == '}')
1626 UuidFromStringW(&classGuid[1], &deviceClass);
1627 if ((flags & DIGCF_ALLCLASSES) ||
1628 IsEqualGUID(class, &deviceClass))
1630 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
1633 instanceId = HeapAlloc(GetProcessHeap(), 0,
1634 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
1638 SP_DEVINFO_DATA *dev;
1640 sprintfW(instanceId, fmt, parent, subKeyName);
1641 SETUPDI_AddDeviceToSet(set, &deviceClass,
1642 0 /* FIXME: DevInst */, instanceId,
1644 HeapFree(GetProcessHeap(), 0, instanceId);
1649 RegCloseKey(subKey);
1655 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
1656 LPCWSTR enumstr, DWORD flags)
1658 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
1659 DIOCR_INSTALLER, NULL, NULL);
1661 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
1662 debugstr_w(enumstr), flags);
1664 if (classesKey != INVALID_HANDLE_VALUE)
1669 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
1674 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
1675 enumKey, class, flags);
1676 RegCloseKey(enumKey);
1682 WCHAR subKeyName[MAX_PATH];
1683 LONG l = ERROR_SUCCESS;
1685 for (i = 0; !l; i++)
1687 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1688 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
1694 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
1698 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
1699 subKeyName, subKey, class, flags);
1700 RegCloseKey(subKey);
1705 RegCloseKey(classesKey);
1709 /***********************************************************************
1710 * SetupDiGetClassDevsW (SETUPAPI.@)
1712 HDEVINFO WINAPI SetupDiGetClassDevsW(
1718 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
1722 TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
1724 if (!(flags & DIGCF_ALLCLASSES) && !class)
1726 SetLastError(ERROR_INVALID_PARAMETER);
1729 if (flags & unsupportedFlags)
1730 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
1731 /* WinXP always succeeds, returns empty list for unknown classes */
1732 set = SetupDiCreateDeviceInfoList(class, parent);
1735 if (flags & DIGCF_DEVICEINTERFACE)
1736 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
1738 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
1743 /***********************************************************************
1744 * SetupDiGetClassDevsExW (SETUPAPI.@)
1746 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1759 /***********************************************************************
1760 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
1762 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
1763 HDEVINFO DeviceInfoSet,
1764 PSP_DEVINFO_DATA DeviceInfoData,
1765 const GUID *InterfaceClassGuid,
1766 PCSTR ReferenceString,
1767 DWORD CreationFlags,
1768 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1770 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
1771 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
1772 CreationFlags, DeviceInterfaceData);
1778 /***********************************************************************
1779 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
1781 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
1782 HDEVINFO DeviceInfoSet,
1783 PSP_DEVINFO_DATA DeviceInfoData,
1784 const GUID *InterfaceClassGuid,
1785 PCWSTR ReferenceString,
1786 DWORD CreationFlags,
1787 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1789 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
1790 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
1791 CreationFlags, DeviceInterfaceData);
1797 /***********************************************************************
1798 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1800 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1802 PSP_DEVINFO_DATA DeviceInfoData,
1803 CONST GUID * InterfaceClassGuid,
1805 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1809 FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
1810 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1812 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1814 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1815 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1816 SetLastError(ERROR_NO_MORE_ITEMS);
1818 SetLastError(ERROR_INVALID_HANDLE);
1821 SetLastError(ERROR_INVALID_HANDLE);
1825 /***********************************************************************
1826 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1828 * Destroy a DeviceInfoList and free all used memory of the list.
1831 * devinfo [I] DeviceInfoList pointer to list to destroy
1834 * Success: non zero value.
1835 * Failure: zero value.
1837 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1841 TRACE("%p\n", devinfo);
1842 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1844 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1846 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1850 for (i = 0; i < list->cDevices; i++)
1851 SETUPDI_FreeDeviceInfo(
1852 (struct DeviceInfo *)list->devices[i].Reserved);
1853 HeapFree(GetProcessHeap(), 0, list->devices);
1854 HeapFree(GetProcessHeap(), 0, list);
1860 SetLastError(ERROR_INVALID_HANDLE);
1865 /***********************************************************************
1866 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1868 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1869 HDEVINFO DeviceInfoSet,
1870 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1871 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1872 DWORD DeviceInterfaceDetailDataSize,
1873 PDWORD RequiredSize,
1874 PSP_DEVINFO_DATA DeviceInfoData)
1878 FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
1879 DeviceInterfaceData, DeviceInterfaceDetailData,
1880 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1882 SetLastError(ERROR_INVALID_HANDLE);
1886 /***********************************************************************
1887 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1889 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1890 HDEVINFO DeviceInfoSet,
1891 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1892 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1893 DWORD DeviceInterfaceDetailDataSize,
1894 PDWORD RequiredSize,
1895 PSP_DEVINFO_DATA DeviceInfoData)
1897 FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
1898 DeviceInterfaceData, DeviceInterfaceDetailData,
1899 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1903 struct PropertyMapEntry
1910 static struct PropertyMapEntry PropertyMap[] = {
1911 { REG_SZ, "DeviceDesc", DeviceDesc },
1912 { REG_MULTI_SZ, "HardwareId", HardwareId },
1913 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
1914 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
1915 { REG_SZ, "Service", Service },
1916 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
1917 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
1918 { REG_SZ, "Class", Class },
1919 { REG_SZ, "ClassGUID", ClassGUID },
1920 { REG_SZ, "Driver", Driver },
1921 { REG_DWORD, "ConfigFlags", ConfigFlags },
1922 { REG_SZ, "Mfg", Mfg },
1923 { REG_SZ, "FriendlyName", FriendlyName },
1924 { REG_SZ, "LocationInformation", LocationInformation },
1925 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
1926 { REG_DWORD, "Capabilities", Capabilities },
1927 { REG_DWORD, "UINumber", UINumber },
1928 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
1929 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
1932 /***********************************************************************
1933 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1935 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1936 HDEVINFO DeviceInfoSet,
1937 PSP_DEVINFO_DATA DeviceInfoData,
1939 PDWORD PropertyRegDataType,
1940 PBYTE PropertyBuffer,
1941 DWORD PropertyBufferSize,
1942 PDWORD RequiredSize)
1945 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1946 struct DeviceInfo *devInfo;
1948 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1949 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1952 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1954 SetLastError(ERROR_INVALID_HANDLE);
1957 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1959 SetLastError(ERROR_INVALID_HANDLE);
1962 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1963 || !DeviceInfoData->Reserved)
1965 SetLastError(ERROR_INVALID_PARAMETER);
1968 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1969 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1970 && PropertyMap[Property].nameA)
1972 DWORD size = PropertyBufferSize;
1973 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
1974 NULL, PropertyRegDataType, PropertyBuffer, &size);
1977 *RequiredSize = size;
1986 /***********************************************************************
1987 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1989 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
1990 HDEVINFO DeviceInfoSet,
1991 PSP_DEVINFO_DATA DeviceInfoData,
1993 PDWORD PropertyRegDataType,
1994 PBYTE PropertyBuffer,
1995 DWORD PropertyBufferSize,
1996 PDWORD RequiredSize)
1999 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2000 struct DeviceInfo *devInfo;
2002 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2003 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2006 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2008 SetLastError(ERROR_INVALID_HANDLE);
2011 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2013 SetLastError(ERROR_INVALID_HANDLE);
2016 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2017 || !DeviceInfoData->Reserved)
2019 SetLastError(ERROR_INVALID_PARAMETER);
2022 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2023 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2024 && PropertyMap[Property].nameW)
2026 DWORD size = PropertyBufferSize;
2027 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2028 NULL, PropertyRegDataType, PropertyBuffer, &size);
2031 *RequiredSize = size;
2040 /***********************************************************************
2041 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2043 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2044 HDEVINFO DeviceInfoSet,
2045 PSP_DEVINFO_DATA DeviceInfoData,
2047 const BYTE *PropertyBuffer,
2048 DWORD PropertyBufferSize)
2051 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2052 struct DeviceInfo *devInfo;
2054 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2055 PropertyBuffer, PropertyBufferSize);
2057 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2059 SetLastError(ERROR_INVALID_HANDLE);
2062 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2064 SetLastError(ERROR_INVALID_HANDLE);
2067 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2068 || !DeviceInfoData->Reserved)
2070 SetLastError(ERROR_INVALID_PARAMETER);
2073 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2074 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2075 && PropertyMap[Property].nameA)
2077 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2078 PropertyMap[Property].regType, PropertyBuffer,
2079 PropertyBufferSize);
2088 /***********************************************************************
2089 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2091 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2092 HDEVINFO DeviceInfoSet,
2093 PSP_DEVINFO_DATA DeviceInfoData,
2095 const BYTE *PropertyBuffer,
2096 DWORD PropertyBufferSize)
2099 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2100 struct DeviceInfo *devInfo;
2102 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2103 PropertyBuffer, PropertyBufferSize);
2105 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2107 SetLastError(ERROR_INVALID_HANDLE);
2110 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2112 SetLastError(ERROR_INVALID_HANDLE);
2115 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2116 || !DeviceInfoData->Reserved)
2118 SetLastError(ERROR_INVALID_PARAMETER);
2121 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2122 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2123 && PropertyMap[Property].nameW)
2125 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
2126 PropertyMap[Property].regType, PropertyBuffer,
2127 PropertyBufferSize);
2136 /***********************************************************************
2137 * SetupDiInstallClassA (SETUPAPI.@)
2139 BOOL WINAPI SetupDiInstallClassA(
2145 UNICODE_STRING FileNameW;
2148 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2150 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2154 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2156 RtlFreeUnicodeString(&FileNameW);
2161 static HKEY CreateClassKey(HINF hInf)
2163 WCHAR FullBuffer[MAX_PATH];
2164 WCHAR Buffer[MAX_PATH];
2168 if (!SetupGetLineTextW(NULL,
2176 return INVALID_HANDLE_VALUE;
2179 lstrcpyW(FullBuffer, ControlClass);
2180 lstrcatW(FullBuffer, Buffer);
2182 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2188 if (!SetupGetLineTextW(NULL,
2196 return INVALID_HANDLE_VALUE;
2199 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2203 REG_OPTION_NON_VOLATILE,
2209 return INVALID_HANDLE_VALUE;
2214 if (RegSetValueExW(hClassKey,
2219 RequiredSize * sizeof(WCHAR)))
2221 RegCloseKey(hClassKey);
2222 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
2224 return INVALID_HANDLE_VALUE;
2230 /***********************************************************************
2231 * SetupDiInstallClassW (SETUPAPI.@)
2233 BOOL WINAPI SetupDiInstallClassW(
2239 WCHAR SectionName[MAX_PATH];
2240 DWORD SectionNameLength = 0;
2242 BOOL bFileQueueCreated = FALSE;
2248 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2250 SetLastError(ERROR_INVALID_PARAMETER);
2254 /* Open the .inf file */
2255 hInf = SetupOpenInfFileW(InfFileName,
2259 if (hInf == INVALID_HANDLE_VALUE)
2265 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2266 hClassKey = CreateClassKey(hInf);
2267 if (hClassKey == INVALID_HANDLE_VALUE)
2269 SetupCloseInfFile(hInf);
2274 /* Try to append a layout file */
2276 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2279 /* Retrieve the actual section name */
2280 SetupDiGetActualSectionToInstallW(hInf,
2288 if (!(Flags & DI_NOVCP))
2290 FileQueue = SetupOpenFileQueue();
2291 if (FileQueue == INVALID_HANDLE_VALUE)
2293 SetupCloseInfFile(hInf);
2297 bFileQueueCreated = TRUE;
2302 SetupInstallFromInfSectionW(NULL,
2311 INVALID_HANDLE_VALUE,
2314 /* FIXME: More code! */
2316 if (bFileQueueCreated)
2317 SetupCloseFileQueue(FileQueue);
2319 SetupCloseInfFile(hInf);
2325 /***********************************************************************
2326 * SetupDiOpenClassRegKey (SETUPAPI.@)
2328 HKEY WINAPI SetupDiOpenClassRegKey(
2329 const GUID* ClassGuid,
2332 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2333 DIOCR_INSTALLER, NULL, NULL);
2337 /***********************************************************************
2338 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2340 HKEY WINAPI SetupDiOpenClassRegKeyExA(
2341 const GUID* ClassGuid,
2347 PWSTR MachineNameW = NULL;
2354 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2355 if (MachineNameW == NULL)
2356 return INVALID_HANDLE_VALUE;
2359 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2360 Flags, MachineNameW, Reserved);
2362 MyFree(MachineNameW);
2368 /***********************************************************************
2369 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2371 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2372 const GUID* ClassGuid,
2383 if (MachineName != NULL)
2385 FIXME("Remote access not supported yet!\n");
2386 return INVALID_HANDLE_VALUE;
2389 if (Flags == DIOCR_INSTALLER)
2391 lpKeyName = ControlClass;
2393 else if (Flags == DIOCR_INTERFACE)
2395 lpKeyName = DeviceClasses;
2399 ERR("Invalid Flags parameter!\n");
2400 SetLastError(ERROR_INVALID_PARAMETER);
2401 return INVALID_HANDLE_VALUE;
2406 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2413 hClassesKey = INVALID_HANDLE_VALUE;
2419 WCHAR bracedGuidString[39];
2421 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
2423 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2429 if ((l = RegOpenKeyExW(hClassesKey,
2436 key = INVALID_HANDLE_VALUE;
2438 RegCloseKey(hClassesKey);
2443 key = INVALID_HANDLE_VALUE;
2449 /***********************************************************************
2450 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2452 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2453 HDEVINFO DeviceInfoSet,
2456 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2458 FIXME("%p %s %08x %p\n",
2459 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2463 /***********************************************************************
2464 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2466 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
2467 HDEVINFO DeviceInfoSet,
2470 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2472 FIXME("%p %s %08x %p\n", DeviceInfoSet,
2473 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
2477 /***********************************************************************
2478 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2480 BOOL WINAPI SetupDiSetClassInstallParamsA(
2481 HDEVINFO DeviceInfoSet,
2482 PSP_DEVINFO_DATA DeviceInfoData,
2483 PSP_CLASSINSTALL_HEADER ClassInstallParams,
2484 DWORD ClassInstallParamsSize)
2486 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
2487 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
2491 /***********************************************************************
2492 * SetupDiCallClassInstaller (SETUPAPI.@)
2494 BOOL WINAPI SetupDiCallClassInstaller(
2495 DI_FUNCTION InstallFunction,
2496 HDEVINFO DeviceInfoSet,
2497 PSP_DEVINFO_DATA DeviceInfoData)
2499 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
2503 /***********************************************************************
2504 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
2506 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
2507 HDEVINFO DeviceInfoSet,
2508 PSP_DEVINFO_DATA DeviceInfoData,
2509 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
2511 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
2515 /***********************************************************************
2516 * SetupDiOpenDevRegKey (SETUPAPI.@)
2518 HKEY WINAPI SetupDiOpenDevRegKey(
2519 HDEVINFO DeviceInfoSet,
2520 PSP_DEVINFO_DATA DeviceInfoData,
2526 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
2527 Scope, HwProfile, KeyType, samDesired);
2528 return INVALID_HANDLE_VALUE;