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 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1762 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1764 PSP_DEVINFO_DATA DeviceInfoData,
1765 CONST GUID * InterfaceClassGuid,
1767 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1771 FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
1772 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1774 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1776 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1777 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1778 SetLastError(ERROR_NO_MORE_ITEMS);
1780 SetLastError(ERROR_INVALID_HANDLE);
1783 SetLastError(ERROR_INVALID_HANDLE);
1787 /***********************************************************************
1788 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1790 * Destroy a DeviceInfoList and free all used memory of the list.
1793 * devinfo [I] DeviceInfoList pointer to list to destroy
1796 * Success: non zero value.
1797 * Failure: zero value.
1799 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1803 TRACE("%p\n", devinfo);
1804 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1806 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1808 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1812 for (i = 0; i < list->cDevices; i++)
1813 SETUPDI_FreeDeviceInfo(
1814 (struct DeviceInfo *)list->devices[i].Reserved);
1815 HeapFree(GetProcessHeap(), 0, list->devices);
1816 HeapFree(GetProcessHeap(), 0, list);
1822 SetLastError(ERROR_INVALID_HANDLE);
1827 /***********************************************************************
1828 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1830 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1831 HDEVINFO DeviceInfoSet,
1832 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1833 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1834 DWORD DeviceInterfaceDetailDataSize,
1835 PDWORD RequiredSize,
1836 PSP_DEVINFO_DATA DeviceInfoData)
1840 FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
1841 DeviceInterfaceData, DeviceInterfaceDetailData,
1842 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1844 SetLastError(ERROR_INVALID_HANDLE);
1848 /***********************************************************************
1849 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1851 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1852 HDEVINFO DeviceInfoSet,
1853 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1854 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1855 DWORD DeviceInterfaceDetailDataSize,
1856 PDWORD RequiredSize,
1857 PSP_DEVINFO_DATA DeviceInfoData)
1859 FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
1860 DeviceInterfaceData, DeviceInterfaceDetailData,
1861 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1865 struct PropertyMapEntry
1872 static struct PropertyMapEntry PropertyMap[] = {
1873 { REG_SZ, "DeviceDesc", DeviceDesc },
1874 { REG_MULTI_SZ, "HardwareId", HardwareId },
1875 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
1876 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
1877 { REG_SZ, "Service", Service },
1878 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
1879 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
1880 { REG_SZ, "Class", Class },
1881 { REG_SZ, "ClassGUID", ClassGUID },
1882 { REG_SZ, "Driver", Driver },
1883 { REG_DWORD, "ConfigFlags", ConfigFlags },
1884 { REG_SZ, "Mfg", Mfg },
1885 { REG_SZ, "FriendlyName", FriendlyName },
1886 { REG_SZ, "LocationInformation", LocationInformation },
1887 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
1888 { REG_DWORD, "Capabilities", Capabilities },
1889 { REG_DWORD, "UINumber", UINumber },
1890 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
1891 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
1894 /***********************************************************************
1895 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1897 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1898 HDEVINFO DeviceInfoSet,
1899 PSP_DEVINFO_DATA DeviceInfoData,
1901 PDWORD PropertyRegDataType,
1902 PBYTE PropertyBuffer,
1903 DWORD PropertyBufferSize,
1904 PDWORD RequiredSize)
1907 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1908 struct DeviceInfo *devInfo;
1910 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1911 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1914 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1916 SetLastError(ERROR_INVALID_HANDLE);
1919 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1921 SetLastError(ERROR_INVALID_HANDLE);
1924 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1925 || !DeviceInfoData->Reserved)
1927 SetLastError(ERROR_INVALID_PARAMETER);
1930 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1931 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1932 && PropertyMap[Property].nameA)
1934 DWORD size = PropertyBufferSize;
1935 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
1936 NULL, PropertyRegDataType, PropertyBuffer, &size);
1939 *RequiredSize = size;
1948 /***********************************************************************
1949 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1951 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
1952 HDEVINFO DeviceInfoSet,
1953 PSP_DEVINFO_DATA DeviceInfoData,
1955 PDWORD PropertyRegDataType,
1956 PBYTE PropertyBuffer,
1957 DWORD PropertyBufferSize,
1958 PDWORD RequiredSize)
1961 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1962 struct DeviceInfo *devInfo;
1964 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1965 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1968 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1970 SetLastError(ERROR_INVALID_HANDLE);
1973 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1975 SetLastError(ERROR_INVALID_HANDLE);
1978 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1979 || !DeviceInfoData->Reserved)
1981 SetLastError(ERROR_INVALID_PARAMETER);
1984 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1985 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1986 && PropertyMap[Property].nameW)
1988 DWORD size = PropertyBufferSize;
1989 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
1990 NULL, PropertyRegDataType, PropertyBuffer, &size);
1993 *RequiredSize = size;
2002 /***********************************************************************
2003 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2005 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2006 HDEVINFO DeviceInfoSet,
2007 PSP_DEVINFO_DATA DeviceInfoData,
2009 const BYTE *PropertyBuffer,
2010 DWORD PropertyBufferSize)
2013 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2014 struct DeviceInfo *devInfo;
2016 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2017 PropertyBuffer, PropertyBufferSize);
2019 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2021 SetLastError(ERROR_INVALID_HANDLE);
2024 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2026 SetLastError(ERROR_INVALID_HANDLE);
2029 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2030 || !DeviceInfoData->Reserved)
2032 SetLastError(ERROR_INVALID_PARAMETER);
2035 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2036 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2037 && PropertyMap[Property].nameA)
2039 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2040 PropertyMap[Property].regType, PropertyBuffer,
2041 PropertyBufferSize);
2050 /***********************************************************************
2051 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2053 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2054 HDEVINFO DeviceInfoSet,
2055 PSP_DEVINFO_DATA DeviceInfoData,
2057 const BYTE *PropertyBuffer,
2058 DWORD PropertyBufferSize)
2061 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2062 struct DeviceInfo *devInfo;
2064 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2065 PropertyBuffer, PropertyBufferSize);
2067 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2069 SetLastError(ERROR_INVALID_HANDLE);
2072 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2074 SetLastError(ERROR_INVALID_HANDLE);
2077 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2078 || !DeviceInfoData->Reserved)
2080 SetLastError(ERROR_INVALID_PARAMETER);
2083 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2084 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2085 && PropertyMap[Property].nameW)
2087 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
2088 PropertyMap[Property].regType, PropertyBuffer,
2089 PropertyBufferSize);
2098 /***********************************************************************
2099 * SetupDiInstallClassA (SETUPAPI.@)
2101 BOOL WINAPI SetupDiInstallClassA(
2107 UNICODE_STRING FileNameW;
2110 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2112 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2116 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2118 RtlFreeUnicodeString(&FileNameW);
2123 static HKEY CreateClassKey(HINF hInf)
2125 WCHAR FullBuffer[MAX_PATH];
2126 WCHAR Buffer[MAX_PATH];
2130 if (!SetupGetLineTextW(NULL,
2138 return INVALID_HANDLE_VALUE;
2141 lstrcpyW(FullBuffer, ControlClass);
2142 lstrcatW(FullBuffer, Buffer);
2144 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2150 if (!SetupGetLineTextW(NULL,
2158 return INVALID_HANDLE_VALUE;
2161 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2165 REG_OPTION_NON_VOLATILE,
2171 return INVALID_HANDLE_VALUE;
2176 if (RegSetValueExW(hClassKey,
2181 RequiredSize * sizeof(WCHAR)))
2183 RegCloseKey(hClassKey);
2184 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
2186 return INVALID_HANDLE_VALUE;
2192 /***********************************************************************
2193 * SetupDiInstallClassW (SETUPAPI.@)
2195 BOOL WINAPI SetupDiInstallClassW(
2201 WCHAR SectionName[MAX_PATH];
2202 DWORD SectionNameLength = 0;
2204 BOOL bFileQueueCreated = FALSE;
2210 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2212 SetLastError(ERROR_INVALID_PARAMETER);
2216 /* Open the .inf file */
2217 hInf = SetupOpenInfFileW(InfFileName,
2221 if (hInf == INVALID_HANDLE_VALUE)
2227 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2228 hClassKey = CreateClassKey(hInf);
2229 if (hClassKey == INVALID_HANDLE_VALUE)
2231 SetupCloseInfFile(hInf);
2236 /* Try to append a layout file */
2238 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2241 /* Retrieve the actual section name */
2242 SetupDiGetActualSectionToInstallW(hInf,
2250 if (!(Flags & DI_NOVCP))
2252 FileQueue = SetupOpenFileQueue();
2253 if (FileQueue == INVALID_HANDLE_VALUE)
2255 SetupCloseInfFile(hInf);
2259 bFileQueueCreated = TRUE;
2264 SetupInstallFromInfSectionW(NULL,
2273 INVALID_HANDLE_VALUE,
2276 /* FIXME: More code! */
2278 if (bFileQueueCreated)
2279 SetupCloseFileQueue(FileQueue);
2281 SetupCloseInfFile(hInf);
2287 /***********************************************************************
2288 * SetupDiOpenClassRegKey (SETUPAPI.@)
2290 HKEY WINAPI SetupDiOpenClassRegKey(
2291 const GUID* ClassGuid,
2294 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2295 DIOCR_INSTALLER, NULL, NULL);
2299 /***********************************************************************
2300 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2302 HKEY WINAPI SetupDiOpenClassRegKeyExA(
2303 const GUID* ClassGuid,
2309 PWSTR MachineNameW = NULL;
2316 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2317 if (MachineNameW == NULL)
2318 return INVALID_HANDLE_VALUE;
2321 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2322 Flags, MachineNameW, Reserved);
2324 MyFree(MachineNameW);
2330 /***********************************************************************
2331 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2333 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2334 const GUID* ClassGuid,
2340 WCHAR bracedGuidString[39];
2345 if (MachineName != NULL)
2347 FIXME("Remote access not supported yet!\n");
2348 return INVALID_HANDLE_VALUE;
2351 if (Flags == DIOCR_INSTALLER)
2353 lpKeyName = ControlClass;
2355 else if (Flags == DIOCR_INTERFACE)
2357 lpKeyName = DeviceClasses;
2361 ERR("Invalid Flags parameter!\n");
2362 SetLastError(ERROR_INVALID_PARAMETER);
2363 return INVALID_HANDLE_VALUE;
2366 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2372 return INVALID_HANDLE_VALUE;
2375 if (ClassGuid == NULL)
2378 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
2380 if (RegOpenKeyExW(hClassesKey,
2386 RegCloseKey(hClassesKey);
2387 return INVALID_HANDLE_VALUE;
2390 RegCloseKey(hClassesKey);
2395 /***********************************************************************
2396 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2398 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2399 HDEVINFO DeviceInfoSet,
2402 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2404 FIXME("%p %s %08x %p\n",
2405 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2409 /***********************************************************************
2410 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2412 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
2413 HDEVINFO DeviceInfoSet,
2416 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2418 FIXME("%p %s %08x %p\n", DeviceInfoSet,
2419 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
2423 /***********************************************************************
2424 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2426 BOOL WINAPI SetupDiSetClassInstallParamsA(
2427 HDEVINFO DeviceInfoSet,
2428 PSP_DEVINFO_DATA DeviceInfoData,
2429 PSP_CLASSINSTALL_HEADER ClassInstallParams,
2430 DWORD ClassInstallParamsSize)
2432 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
2433 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
2437 /***********************************************************************
2438 * SetupDiCallClassInstaller (SETUPAPI.@)
2440 BOOL WINAPI SetupDiCallClassInstaller(
2441 DI_FUNCTION InstallFunction,
2442 HDEVINFO DeviceInfoSet,
2443 PSP_DEVINFO_DATA DeviceInfoData)
2445 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
2449 /***********************************************************************
2450 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
2452 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
2453 HDEVINFO DeviceInfoSet,
2454 PSP_DEVINFO_DATA DeviceInfoData,
2455 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
2457 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
2461 /***********************************************************************
2462 * SetupDiOpenDevRegKey (SETUPAPI.@)
2464 HKEY WINAPI SetupDiOpenDevRegKey(
2465 HDEVINFO DeviceInfoSet,
2466 PSP_DEVINFO_DATA DeviceInfoData,
2472 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
2473 Scope, HwProfile, KeyType, samDesired);
2474 return INVALID_HANDLE_VALUE;