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};
88 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
90 /* is used to identify if a DeviceInfoSet pointer is
92 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
96 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
100 SP_DEVINFO_DATA *devices;
103 /* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */
106 LPWSTR referenceString;
110 /* A device may have multiple instances of the same interface, so this holds
111 * each instance belonging to a particular interface.
113 struct InterfaceInstances
117 DWORD cInstancesAllocated;
118 SP_DEVICE_INTERFACE_DATA *instances;
121 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
128 DWORD cInterfacesAllocated;
129 struct InterfaceInstances *interfaces;
132 static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
136 for (i = 0; i < instances->cInstances; i++)
138 struct InterfaceInfo *ifaceInfo =
139 (struct InterfaceInfo *)instances->instances[i].Reserved;
141 HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
142 HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
144 HeapFree(GetProcessHeap(), 0, instances->instances);
147 /* Finds the interface with interface class InterfaceClassGuid in the device.
148 * Returns TRUE if found, and updates interfaceIndex to the index of the
149 * device's interfaces member where the given interface was found.
150 * Returns FALSE if not found.
152 static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
153 const GUID *InterfaceClassGuid, DWORD *interfaceIndex)
158 TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
160 for (i = 0; !found && i < devInfo->cInterfaces; i++)
162 if (IsEqualGUID(&devInfo->interfaces[i].guid, InterfaceClassGuid))
168 TRACE("returning %d (%d)\n", found, found ? *interfaceIndex : 0);
172 /* Finds the interface instance with reference string ReferenceString in the
173 * interface instance map. Returns TRUE if found, and updates instanceIndex to
174 * the index of the interface instance's instances member
175 * where the given instance was found. Returns FALSE if not found.
177 static BOOL SETUPDI_FindInterfaceInstance(
178 const struct InterfaceInstances *instances,
179 LPCWSTR ReferenceString, DWORD *instanceIndex)
184 TRACE("%s\n", debugstr_w(ReferenceString));
186 for (i = 0; !found && i < instances->cInstances; i++)
188 SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
189 struct InterfaceInfo *ifaceInfo =
190 (struct InterfaceInfo *)ifaceData->Reserved;
192 if (!ReferenceString && !ifaceInfo->referenceString)
197 else if (ReferenceString && ifaceInfo->referenceString &&
198 !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
204 TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
208 /* Adds an interface with the given interface class and reference string to
209 * the device, if it doesn't already exist in the device. If iface is not
210 * NULL, returns a pointer to the newly added (or already existing) interface.
212 static BOOL SETUPDI_AddInterfaceInstance(struct DeviceInfo *devInfo,
213 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
214 SP_DEVICE_INTERFACE_DATA **ifaceData)
216 BOOL newInterface = FALSE, ret;
217 DWORD interfaceIndex = 0;
218 struct InterfaceInstances *iface = NULL;
220 TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
221 debugstr_w(ReferenceString), iface);
223 if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid,
226 if (!devInfo->cInterfacesAllocated)
228 devInfo->interfaces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
229 sizeof(struct InterfaceInstances));
230 if (devInfo->interfaces)
232 iface = &devInfo->interfaces[devInfo->cInterfacesAllocated++];
236 else if (devInfo->cInterfaces == devInfo->cInterfacesAllocated)
238 devInfo->interfaces = HeapReAlloc(GetProcessHeap(),
239 HEAP_ZERO_MEMORY, devInfo->interfaces,
240 (devInfo->cInterfacesAllocated + 1) *
241 sizeof(struct InterfaceInstances));
242 if (devInfo->interfaces)
244 iface = &devInfo->interfaces[devInfo->cInterfacesAllocated++];
249 iface = &devInfo->interfaces[devInfo->cInterfaces];
252 iface = &devInfo->interfaces[interfaceIndex];
255 DWORD instanceIndex = 0;
257 if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
260 SP_DEVICE_INTERFACE_DATA *instance = NULL;
262 if (!iface->cInstancesAllocated)
264 iface->instances = HeapAlloc(GetProcessHeap(), 0,
265 sizeof(SP_DEVICE_INTERFACE_DATA));
266 if (iface->instances)
267 instance = &iface->instances[iface->cInstancesAllocated++];
269 else if (iface->cInstances == iface->cInstancesAllocated)
271 iface->instances = HeapReAlloc(GetProcessHeap(), 0,
273 (iface->cInstancesAllocated + 1) *
274 sizeof(SP_DEVICE_INTERFACE_DATA));
275 if (iface->instances)
276 instance = &iface->instances[iface->cInstancesAllocated++];
279 instance = &iface->instances[iface->cInstances];
282 struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
283 0, sizeof(struct InterfaceInfo));
288 ifaceInfo->symbolicLink = NULL;
291 ifaceInfo->referenceString =
292 HeapAlloc(GetProcessHeap(), 0,
293 (lstrlenW(ReferenceString) + 1) *
295 if (ifaceInfo->referenceString)
296 lstrcpyW(ifaceInfo->referenceString,
302 ifaceInfo->referenceString = NULL;
307 sizeof(SP_DEVICE_INTERFACE_DATA);
308 memcpy(&instance->InterfaceClassGuid,
309 InterfaceClassGuid, sizeof(GUID));
310 instance->Flags = SPINT_ACTIVE; /* FIXME */
311 instance->Reserved = (ULONG_PTR)ifaceInfo;
314 memcpy(&iface->guid, InterfaceClassGuid,
316 devInfo->cInterfaces++;
318 /* FIXME: now create this homeboy in the registry */
320 *ifaceData = instance;
323 HeapFree(GetProcessHeap(), 0, ifaceInfo);
331 &devInfo->interfaces[interfaceIndex].instances[instanceIndex];
336 TRACE("returning %d\n", ret);
340 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
341 LPCWSTR symbolicLink)
343 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
348 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
349 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
350 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
351 if (info->symbolicLink)
353 lstrcpyW(info->symbolicLink, symbolicLink);
360 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId,
363 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
364 sizeof(struct DeviceInfo));
368 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
369 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
370 if (devInfo->instanceId)
375 devInfo->key = INVALID_HANDLE_VALUE;
376 devInfo->phantom = phantom;
377 lstrcpyW(devInfo->instanceId, instanceId);
378 struprW(devInfo->instanceId);
379 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
380 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
383 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
384 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
386 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
387 (LPBYTE)&phantom, sizeof(phantom));
388 RegCloseKey(enumKey);
390 devInfo->cInterfaces = devInfo->cInterfacesAllocated = 0;
391 devInfo->interfaces = NULL;
395 HeapFree(GetProcessHeap(), 0, devInfo);
402 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
406 if (devInfo->key != INVALID_HANDLE_VALUE)
407 RegCloseKey(devInfo->key);
408 if (devInfo->phantom)
413 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
414 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
417 RegDeleteTreeW(enumKey, devInfo->instanceId);
418 RegCloseKey(enumKey);
421 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
422 for (i = 0; i < devInfo->cInterfaces; i++)
423 SETUPDI_FreeInterfaceInstances(&devInfo->interfaces[i]);
424 HeapFree(GetProcessHeap(), 0, devInfo->interfaces);
425 HeapFree(GetProcessHeap(), 0, devInfo);
428 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
430 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
431 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
432 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
435 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
436 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
437 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
440 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
441 * struct DeviceInfo, and points the returned device info's Reserved member
442 * to it. "Phantom" devices are deleted from the registry when closed.
443 * Returns a pointer to the newly allocated device info.
445 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
450 SP_DEVINFO_DATA **dev)
453 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(instanceId,
456 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
457 debugstr_w(instanceId), phantom);
462 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
463 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
465 set->devices = HeapAlloc(GetProcessHeap(), 0,
466 sizeof(SP_DEVINFO_DATA));
469 WCHAR classGuidStr[39];
471 *dev = &set->devices[set->cDevices++];
472 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
473 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
474 (*dev)->DevInst = devInst;
475 (*dev)->Reserved = (ULONG_PTR)devInfo;
476 SETUPDI_GuidToString(guid, classGuidStr);
477 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
478 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
479 lstrlenW(classGuidStr) * sizeof(WCHAR));
484 HeapFree(GetProcessHeap(), 0, devInfo);
485 SetLastError(ERROR_OUTOFMEMORY);
491 /***********************************************************************
492 * SetupDiBuildClassInfoList (SETUPAPI.@)
494 * Returns a list of setup class GUIDs that identify the classes
495 * that are installed on a local machine.
498 * Flags [I] control exclusion of classes from the list.
499 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
500 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
501 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
507 BOOL WINAPI SetupDiBuildClassInfoList(
509 LPGUID ClassGuidList,
510 DWORD ClassGuidListSize,
514 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
515 ClassGuidListSize, RequiredSize,
519 /***********************************************************************
520 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
522 * Returns a list of setup class GUIDs that identify the classes
523 * that are installed on a local or remote macine.
526 * Flags [I] control exclusion of classes from the list.
527 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
528 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
529 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
530 * MachineName [I] name of a remote machine.
531 * Reserved [I] must be NULL.
537 BOOL WINAPI SetupDiBuildClassInfoListExA(
539 LPGUID ClassGuidList,
540 DWORD ClassGuidListSize,
545 LPWSTR MachineNameW = NULL;
552 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
553 if (MachineNameW == NULL) return FALSE;
556 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
557 ClassGuidListSize, RequiredSize,
558 MachineNameW, Reserved);
560 MyFree(MachineNameW);
565 /***********************************************************************
566 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
568 * Returns a list of setup class GUIDs that identify the classes
569 * that are installed on a local or remote macine.
572 * Flags [I] control exclusion of classes from the list.
573 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
574 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
575 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
576 * MachineName [I] name of a remote machine.
577 * Reserved [I] must be NULL.
583 BOOL WINAPI SetupDiBuildClassInfoListExW(
585 LPGUID ClassGuidList,
586 DWORD ClassGuidListSize,
597 DWORD dwGuidListIndex = 0;
601 if (RequiredSize != NULL)
604 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
609 if (hClassesKey == INVALID_HANDLE_VALUE)
614 for (dwIndex = 0; ; dwIndex++)
617 lError = RegEnumKeyExW(hClassesKey,
625 TRACE("RegEnumKeyExW() returns %d\n", lError);
626 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
628 TRACE("Key name: %p\n", szKeyName);
630 if (RegOpenKeyExW(hClassesKey,
636 RegCloseKey(hClassesKey);
640 if (!RegQueryValueExW(hClassKey,
647 TRACE("'NoUseClass' value found!\n");
648 RegCloseKey(hClassKey);
652 if ((Flags & DIBCI_NOINSTALLCLASS) &&
653 (!RegQueryValueExW(hClassKey,
660 TRACE("'NoInstallClass' value found!\n");
661 RegCloseKey(hClassKey);
665 if ((Flags & DIBCI_NODISPLAYCLASS) &&
666 (!RegQueryValueExW(hClassKey,
673 TRACE("'NoDisplayClass' value found!\n");
674 RegCloseKey(hClassKey);
678 RegCloseKey(hClassKey);
680 TRACE("Guid: %p\n", szKeyName);
681 if (dwGuidListIndex < ClassGuidListSize)
683 if (szKeyName[0] == '{' && szKeyName[37] == '}')
687 TRACE("Guid: %p\n", &szKeyName[1]);
689 UuidFromStringW(&szKeyName[1],
690 &ClassGuidList[dwGuidListIndex]);
696 if (lError != ERROR_SUCCESS)
700 RegCloseKey(hClassesKey);
702 if (RequiredSize != NULL)
703 *RequiredSize = dwGuidListIndex;
705 if (ClassGuidListSize < dwGuidListIndex)
707 SetLastError(ERROR_INSUFFICIENT_BUFFER);
714 /***********************************************************************
715 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
717 BOOL WINAPI SetupDiClassGuidsFromNameA(
719 LPGUID ClassGuidList,
720 DWORD ClassGuidListSize,
723 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
724 ClassGuidListSize, RequiredSize,
728 /***********************************************************************
729 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
731 BOOL WINAPI SetupDiClassGuidsFromNameW(
733 LPGUID ClassGuidList,
734 DWORD ClassGuidListSize,
737 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
738 ClassGuidListSize, RequiredSize,
742 /***********************************************************************
743 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
745 BOOL WINAPI SetupDiClassGuidsFromNameExA(
747 LPGUID ClassGuidList,
748 DWORD ClassGuidListSize,
753 LPWSTR ClassNameW = NULL;
754 LPWSTR MachineNameW = NULL;
759 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
760 if (ClassNameW == NULL)
765 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
766 if (MachineNameW == NULL)
773 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
774 ClassGuidListSize, RequiredSize,
775 MachineNameW, Reserved);
777 MyFree(MachineNameW);
783 /***********************************************************************
784 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
786 BOOL WINAPI SetupDiClassGuidsFromNameExW(
788 LPGUID ClassGuidList,
789 DWORD ClassGuidListSize,
795 WCHAR szClassName[256];
801 DWORD dwGuidListIndex = 0;
803 if (RequiredSize != NULL)
806 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
811 if (hClassesKey == INVALID_HANDLE_VALUE)
816 for (dwIndex = 0; ; dwIndex++)
819 lError = RegEnumKeyExW(hClassesKey,
827 TRACE("RegEnumKeyExW() returns %d\n", lError);
828 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
830 TRACE("Key name: %p\n", szKeyName);
832 if (RegOpenKeyExW(hClassesKey,
838 RegCloseKey(hClassesKey);
842 dwLength = 256 * sizeof(WCHAR);
843 if (!RegQueryValueExW(hClassKey,
850 TRACE("Class name: %p\n", szClassName);
852 if (strcmpiW(szClassName, ClassName) == 0)
854 TRACE("Found matching class name\n");
856 TRACE("Guid: %p\n", szKeyName);
857 if (dwGuidListIndex < ClassGuidListSize)
859 if (szKeyName[0] == '{' && szKeyName[37] == '}')
863 TRACE("Guid: %p\n", &szKeyName[1]);
865 UuidFromStringW(&szKeyName[1],
866 &ClassGuidList[dwGuidListIndex]);
873 RegCloseKey(hClassKey);
876 if (lError != ERROR_SUCCESS)
880 RegCloseKey(hClassesKey);
882 if (RequiredSize != NULL)
883 *RequiredSize = dwGuidListIndex;
885 if (ClassGuidListSize < dwGuidListIndex)
887 SetLastError(ERROR_INSUFFICIENT_BUFFER);
894 /***********************************************************************
895 * SetupDiClassNameFromGuidA (SETUPAPI.@)
897 BOOL WINAPI SetupDiClassNameFromGuidA(
898 const GUID* ClassGuid,
903 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
904 ClassNameSize, RequiredSize,
908 /***********************************************************************
909 * SetupDiClassNameFromGuidW (SETUPAPI.@)
911 BOOL WINAPI SetupDiClassNameFromGuidW(
912 const GUID* ClassGuid,
917 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
918 ClassNameSize, RequiredSize,
922 /***********************************************************************
923 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
925 BOOL WINAPI SetupDiClassNameFromGuidExA(
926 const GUID* ClassGuid,
933 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
934 LPWSTR MachineNameW = NULL;
938 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
939 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
940 NULL, MachineNameW, Reserved);
943 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
944 ClassNameSize, NULL, NULL);
946 if (!ClassNameSize && RequiredSize)
949 MyFree(MachineNameW);
953 /***********************************************************************
954 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
956 BOOL WINAPI SetupDiClassNameFromGuidExW(
957 const GUID* ClassGuid,
967 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
972 if (hKey == INVALID_HANDLE_VALUE)
977 if (RequiredSize != NULL)
980 if (RegQueryValueExW(hKey,
991 *RequiredSize = dwLength / sizeof(WCHAR);
994 dwLength = ClassNameSize * sizeof(WCHAR);
995 if (RegQueryValueExW(hKey,
1011 /***********************************************************************
1012 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1015 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1018 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1021 /***********************************************************************
1022 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1025 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1030 LPWSTR MachineNameW = NULL;
1037 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1038 if (MachineNameW == NULL)
1039 return (HDEVINFO)INVALID_HANDLE_VALUE;
1042 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1043 MachineNameW, Reserved);
1045 MyFree(MachineNameW);
1050 /***********************************************************************
1051 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1053 * Create an empty DeviceInfoSet list.
1056 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1058 * hwndParent [I] hwnd needed for interface related actions.
1059 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1060 * local registry will be used.
1061 * Reserved [I] must be NULL
1064 * Success: empty list.
1065 * Failure: INVALID_HANDLE_VALUE.
1068 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1073 struct DeviceInfoSet *list = NULL;
1074 DWORD size = sizeof(struct DeviceInfoSet);
1076 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1077 debugstr_w(MachineName), Reserved);
1079 if (MachineName != NULL)
1081 FIXME("remote support is not implemented\n");
1082 SetLastError(ERROR_INVALID_MACHINENAME);
1083 return (HDEVINFO)INVALID_HANDLE_VALUE;
1086 if (Reserved != NULL)
1088 SetLastError(ERROR_INVALID_PARAMETER);
1089 return (HDEVINFO)INVALID_HANDLE_VALUE;
1092 list = HeapAlloc(GetProcessHeap(), 0, size);
1095 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1096 return (HDEVINFO)INVALID_HANDLE_VALUE;
1099 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1100 list->hwndParent = hwndParent;
1101 memcpy(&list->ClassGuid,
1102 ClassGuid ? ClassGuid : &GUID_NULL,
1103 sizeof(list->ClassGuid));
1105 list->devices = NULL;
1107 return (HDEVINFO)list;
1110 /***********************************************************************
1111 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1113 BOOL WINAPI SetupDiCreateDeviceInfoA(
1114 HDEVINFO DeviceInfoSet,
1116 CONST GUID *ClassGuid,
1117 PCSTR DeviceDescription,
1119 DWORD CreationFlags,
1120 PSP_DEVINFO_DATA DeviceInfoData)
1123 LPWSTR DeviceNameW = NULL;
1124 LPWSTR DeviceDescriptionW = NULL;
1128 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1129 if (DeviceNameW == NULL) return FALSE;
1131 if (DeviceDescription)
1133 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1134 if (DeviceDescriptionW == NULL)
1136 MyFree(DeviceNameW);
1141 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1142 hwndParent, CreationFlags, DeviceInfoData);
1144 MyFree(DeviceNameW);
1145 MyFree(DeviceDescriptionW);
1150 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1153 DWORD devNameLen = lstrlenW(devName), devInst = 0;
1156 TRACE("%s\n", debugstr_w(devName));
1157 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1162 devInst |= *ptr - '0';
1168 TRACE("%d\n", valid ? devInst : 0xffffffff);
1169 return valid ? devInst : 0xffffffff;
1172 /***********************************************************************
1173 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1175 BOOL WINAPI SetupDiCreateDeviceInfoW(
1176 HDEVINFO DeviceInfoSet,
1178 CONST GUID *ClassGuid,
1179 PCWSTR DeviceDescription,
1181 DWORD CreationFlags,
1182 PSP_DEVINFO_DATA DeviceInfoData)
1184 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1185 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1186 LPCWSTR instanceId = NULL;
1188 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1189 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1190 hwndParent, CreationFlags, DeviceInfoData);
1194 SetLastError(ERROR_INVALID_DEVINST_NAME);
1197 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1199 SetLastError(ERROR_INVALID_HANDLE);
1204 SetLastError(ERROR_INVALID_PARAMETER);
1207 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1209 SetLastError(ERROR_INVALID_HANDLE);
1212 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1213 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1215 SetLastError(ERROR_CLASS_MISMATCH);
1218 if ((CreationFlags & DICD_GENERATE_ID))
1220 if (strchrW(DeviceName, '\\'))
1221 SetLastError(ERROR_INVALID_DEVINST_NAME);
1224 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1225 '\\','%','0','4','d',0};
1230 DWORD i, highestDevID = 0;
1232 for (i = 0; i < set->cDevices; i++)
1234 struct DeviceInfo *devInfo =
1235 (struct DeviceInfo *)set->devices[i].Reserved;
1236 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1242 devName = devInfo->instanceId;
1243 id = SETUPDI_DevNameToDevID(devName);
1244 if (id != 0xffffffff && id > highestDevID)
1247 devId = highestDevID + 1;
1251 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1252 instanceId = HeapAlloc(GetProcessHeap(), 0,
1253 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1256 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1258 allocatedInstanceId = TRUE;
1270 instanceId = DeviceName;
1271 for (i = 0; ret && i < set->cDevices; i++)
1273 struct DeviceInfo *devInfo =
1274 (struct DeviceInfo *)set->devices[i].Reserved;
1276 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1278 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1285 SP_DEVINFO_DATA *dev = NULL;
1287 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1288 instanceId, TRUE, &dev);
1291 if (DeviceDescription)
1292 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1293 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1294 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1297 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1299 SetLastError(ERROR_INVALID_USER_BUFFER);
1303 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1307 if (allocatedInstanceId)
1308 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1313 /***********************************************************************
1314 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1316 BOOL WINAPI SetupDiRegisterDeviceInfo(
1317 HDEVINFO DeviceInfoSet,
1318 PSP_DEVINFO_DATA DeviceInfoData,
1320 PSP_DETSIG_CMPPROC CompareProc,
1321 PVOID CompareContext,
1322 PSP_DEVINFO_DATA DupDeviceInfoData)
1324 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1325 struct DeviceInfo *devInfo;
1327 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1328 CompareProc, CompareContext, DupDeviceInfoData);
1330 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1332 SetLastError(ERROR_INVALID_HANDLE);
1335 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1337 SetLastError(ERROR_INVALID_HANDLE);
1340 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1341 || !DeviceInfoData->Reserved)
1343 SetLastError(ERROR_INVALID_PARAMETER);
1346 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1347 if (devInfo->phantom)
1349 devInfo->phantom = FALSE;
1350 RegDeleteValueW(devInfo->key, Phantom);
1355 /***********************************************************************
1356 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1358 BOOL WINAPI SetupDiEnumDeviceInfo(
1361 PSP_DEVINFO_DATA info)
1365 TRACE("%p %d %p\n", devinfo, index, info);
1369 SetLastError(ERROR_INVALID_PARAMETER);
1372 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1374 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1375 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1377 if (index < list->cDevices)
1379 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1381 memcpy(info, &list->devices[index], info->cbSize);
1385 SetLastError(ERROR_INVALID_USER_BUFFER);
1388 SetLastError(ERROR_NO_MORE_ITEMS);
1391 SetLastError(ERROR_INVALID_HANDLE);
1394 SetLastError(ERROR_INVALID_HANDLE);
1398 /***********************************************************************
1399 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1401 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1402 HDEVINFO DeviceInfoSet,
1403 PSP_DEVINFO_DATA DeviceInfoData,
1404 PSTR DeviceInstanceId,
1405 DWORD DeviceInstanceIdSize,
1406 PDWORD RequiredSize)
1412 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1413 DeviceInstanceIdSize, RequiredSize);
1415 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1420 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1422 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1425 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1432 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1434 DeviceInstanceIdSize, NULL, NULL);
1440 if (len > DeviceInstanceIdSize)
1442 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1446 *RequiredSize = len;
1449 HeapFree(GetProcessHeap(), 0, instanceId);
1454 /***********************************************************************
1455 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1457 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1458 HDEVINFO DeviceInfoSet,
1459 PSP_DEVINFO_DATA DeviceInfoData,
1460 PWSTR DeviceInstanceId,
1461 DWORD DeviceInstanceIdSize,
1462 PDWORD RequiredSize)
1464 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1465 struct DeviceInfo *devInfo;
1467 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1468 DeviceInstanceIdSize, RequiredSize);
1470 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1472 SetLastError(ERROR_INVALID_HANDLE);
1475 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1477 SetLastError(ERROR_INVALID_HANDLE);
1480 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1481 || !DeviceInfoData->Reserved)
1483 SetLastError(ERROR_INVALID_PARAMETER);
1486 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1487 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1488 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1490 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1492 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1495 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1497 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1501 /***********************************************************************
1502 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1504 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1506 PCSTR InfSectionName,
1507 PSTR InfSectionWithExt,
1508 DWORD InfSectionWithExtSize,
1509 PDWORD RequiredSize,
1516 /***********************************************************************
1517 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1519 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1521 PCWSTR InfSectionName,
1522 PWSTR InfSectionWithExt,
1523 DWORD InfSectionWithExtSize,
1524 PDWORD RequiredSize,
1527 WCHAR szBuffer[MAX_PATH];
1530 LONG lLineCount = -1;
1532 lstrcpyW(szBuffer, InfSectionName);
1533 dwLength = lstrlenW(szBuffer);
1535 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1537 /* Test section name with '.NTx86' extension */
1538 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1539 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1541 if (lLineCount == -1)
1543 /* Test section name with '.NT' extension */
1544 lstrcpyW(&szBuffer[dwLength], NtExtension);
1545 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1550 /* Test section name with '.Win' extension */
1551 lstrcpyW(&szBuffer[dwLength], WinExtension);
1552 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1555 if (lLineCount == -1)
1557 /* Test section name without extension */
1558 szBuffer[dwLength] = 0;
1559 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1562 if (lLineCount == -1)
1564 SetLastError(ERROR_INVALID_PARAMETER);
1568 dwFullLength = lstrlenW(szBuffer);
1570 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1572 if (InfSectionWithExtSize < (dwFullLength + 1))
1574 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1578 lstrcpyW(InfSectionWithExt, szBuffer);
1579 if (Extension != NULL)
1581 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1585 if (RequiredSize != NULL)
1587 *RequiredSize = dwFullLength + 1;
1593 /***********************************************************************
1594 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1596 BOOL WINAPI SetupDiGetClassDescriptionA(
1597 const GUID* ClassGuid,
1598 PSTR ClassDescription,
1599 DWORD ClassDescriptionSize,
1600 PDWORD RequiredSize)
1602 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1603 ClassDescriptionSize,
1604 RequiredSize, NULL, NULL);
1607 /***********************************************************************
1608 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1610 BOOL WINAPI SetupDiGetClassDescriptionW(
1611 const GUID* ClassGuid,
1612 PWSTR ClassDescription,
1613 DWORD ClassDescriptionSize,
1614 PDWORD RequiredSize)
1616 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1617 ClassDescriptionSize,
1618 RequiredSize, NULL, NULL);
1621 /***********************************************************************
1622 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1624 BOOL WINAPI SetupDiGetClassDescriptionExA(
1625 const GUID* ClassGuid,
1626 PSTR ClassDescription,
1627 DWORD ClassDescriptionSize,
1628 PDWORD RequiredSize,
1636 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1641 if (hKey == INVALID_HANDLE_VALUE)
1643 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1647 dwLength = ClassDescriptionSize;
1648 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1649 (LPBYTE)ClassDescription, &dwLength );
1650 if (RequiredSize) *RequiredSize = dwLength;
1655 /***********************************************************************
1656 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1658 BOOL WINAPI SetupDiGetClassDescriptionExW(
1659 const GUID* ClassGuid,
1660 PWSTR ClassDescription,
1661 DWORD ClassDescriptionSize,
1662 PDWORD RequiredSize,
1670 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1675 if (hKey == INVALID_HANDLE_VALUE)
1677 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1681 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1682 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1683 (LPBYTE)ClassDescription, &dwLength );
1684 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1689 /***********************************************************************
1690 * SetupDiGetClassDevsA (SETUPAPI.@)
1692 HDEVINFO WINAPI SetupDiGetClassDevsA(
1699 LPWSTR enumstrW = NULL;
1703 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1704 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1707 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1710 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1712 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
1713 HeapFree(GetProcessHeap(), 0, enumstrW);
1719 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
1720 const GUID *interface)
1722 struct DeviceInfo *devInfo = (struct DeviceInfo *)dev->Reserved;
1724 WCHAR subKeyName[MAX_PATH];
1725 LONG l = ERROR_SUCCESS;
1727 for (i = 0; !l; i++)
1729 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1730 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1734 SP_DEVICE_INTERFACE_DATA *iface = NULL;
1736 /* The subkey name is the reference string, with a '#' prepended */
1737 SETUPDI_AddInterfaceInstance(devInfo, interface, subKeyName + 1,
1739 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1742 WCHAR symbolicLink[MAX_PATH];
1745 len = sizeof(symbolicLink);
1746 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
1747 (BYTE *)symbolicLink, &len);
1748 if (!l && dataType == REG_SZ)
1749 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
1750 RegCloseKey(subKey);
1754 /* FIXME: find and add all the device's interfaces to the device */
1757 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1758 HKEY key, const GUID *interface, LPCWSTR enumstr)
1760 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1762 WCHAR subKeyName[MAX_PATH];
1764 HKEY enumKey = INVALID_HANDLE_VALUE;
1766 TRACE("%s\n", debugstr_w(enumstr));
1768 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1770 for (i = 0; !l; i++)
1772 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1773 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1778 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1781 WCHAR deviceInst[MAX_PATH * 3];
1784 len = sizeof(deviceInst);
1785 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1786 (BYTE *)deviceInst, &len);
1787 if (!l && dataType == REG_SZ)
1789 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1790 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1794 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1798 WCHAR deviceClassStr[40];
1800 len = sizeof(deviceClassStr);
1801 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1802 &dataType, (BYTE *)deviceClassStr, &len);
1803 if (!l && dataType == REG_SZ &&
1804 deviceClassStr[0] == '{' &&
1805 deviceClassStr[37] == '}')
1808 SP_DEVINFO_DATA *dev;
1810 deviceClassStr[37] = 0;
1811 UuidFromStringW(&deviceClassStr[1],
1813 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
1814 0 /* FIXME: DevInst */, deviceInst,
1816 SETUPDI_AddDeviceInterfaces(dev, subKey,
1819 RegCloseKey(deviceKey);
1823 RegCloseKey(subKey);
1827 if (enumKey != INVALID_HANDLE_VALUE)
1828 RegCloseKey(enumKey);
1831 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1832 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1834 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1835 DIOCR_INTERFACE, NULL, NULL);
1837 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1838 debugstr_w(enumstr), flags);
1840 if (interfacesKey != INVALID_HANDLE_VALUE)
1842 if (flags & DIGCF_ALLCLASSES)
1845 WCHAR interfaceGuidStr[40];
1846 LONG l = ERROR_SUCCESS;
1848 for (i = 0; !l; i++)
1850 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
1851 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
1852 NULL, NULL, NULL, NULL);
1855 if (interfaceGuidStr[0] == '{' &&
1856 interfaceGuidStr[37] == '}')
1861 interfaceGuidStr[37] = 0;
1862 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
1863 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
1864 KEY_READ, &interfaceKey);
1867 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1868 interfaceKey, &interfaceGuid, enumstr);
1869 RegCloseKey(interfaceKey);
1877 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
1878 * interface's key, so just pass that long
1880 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1881 interfacesKey, interface, enumstr);
1883 RegCloseKey(interfacesKey);
1887 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
1888 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
1890 struct DeviceInfoSet *set = (struct DeviceInfoSet *)set;
1892 WCHAR subKeyName[MAX_PATH];
1893 LONG l = ERROR_SUCCESS;
1895 TRACE("%s\n", debugstr_w(parent));
1897 for (i = 0; !l; i++)
1899 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1900 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1905 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1908 WCHAR classGuid[40];
1911 len = sizeof(classGuid);
1912 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
1913 (BYTE *)classGuid, &len);
1914 if (!l && dataType == REG_SZ)
1916 if (classGuid[0] == '{' && classGuid[37] == '}')
1921 UuidFromStringW(&classGuid[1], &deviceClass);
1922 if ((flags & DIGCF_ALLCLASSES) ||
1923 IsEqualGUID(class, &deviceClass))
1925 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
1928 instanceId = HeapAlloc(GetProcessHeap(), 0,
1929 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
1933 SP_DEVINFO_DATA *dev;
1935 sprintfW(instanceId, fmt, parent, subKeyName);
1936 SETUPDI_AddDeviceToSet(set, &deviceClass,
1937 0 /* FIXME: DevInst */, instanceId,
1939 HeapFree(GetProcessHeap(), 0, instanceId);
1944 RegCloseKey(subKey);
1950 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
1951 LPCWSTR enumstr, DWORD flags)
1953 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
1954 DIOCR_INSTALLER, NULL, NULL);
1956 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
1957 debugstr_w(enumstr), flags);
1959 if (classesKey != INVALID_HANDLE_VALUE)
1964 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
1969 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
1970 enumKey, class, flags);
1971 RegCloseKey(enumKey);
1977 WCHAR subKeyName[MAX_PATH];
1978 LONG l = ERROR_SUCCESS;
1980 for (i = 0; !l; i++)
1982 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1983 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
1989 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
1993 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
1994 subKeyName, subKey, class, flags);
1995 RegCloseKey(subKey);
2000 RegCloseKey(classesKey);
2004 /***********************************************************************
2005 * SetupDiGetClassDevsW (SETUPAPI.@)
2007 HDEVINFO WINAPI SetupDiGetClassDevsW(
2013 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2017 TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
2019 if (!(flags & DIGCF_ALLCLASSES) && !class)
2021 SetLastError(ERROR_INVALID_PARAMETER);
2024 if (flags & unsupportedFlags)
2025 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2026 /* WinXP always succeeds, returns empty list for unknown classes */
2027 set = SetupDiCreateDeviceInfoList(class, parent);
2030 if (flags & DIGCF_DEVICEINTERFACE)
2031 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2033 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2038 /***********************************************************************
2039 * SetupDiGetClassDevsExW (SETUPAPI.@)
2041 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2054 /***********************************************************************
2055 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2057 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2058 HDEVINFO DeviceInfoSet,
2059 PSP_DEVINFO_DATA DeviceInfoData,
2060 const GUID *InterfaceClassGuid,
2061 PCSTR ReferenceString,
2062 DWORD CreationFlags,
2063 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2066 LPWSTR ReferenceStringW = NULL;
2068 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2069 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2070 CreationFlags, DeviceInterfaceData);
2072 if (ReferenceString)
2074 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2075 if (ReferenceStringW == NULL) return FALSE;
2078 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2079 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2080 DeviceInterfaceData);
2082 MyFree(ReferenceStringW);
2087 /***********************************************************************
2088 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2090 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2091 HDEVINFO DeviceInfoSet,
2092 PSP_DEVINFO_DATA DeviceInfoData,
2093 const GUID *InterfaceClassGuid,
2094 PCWSTR ReferenceString,
2095 DWORD CreationFlags,
2096 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2098 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2099 struct DeviceInfo *devInfo;
2100 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2103 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2104 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2105 CreationFlags, DeviceInterfaceData);
2107 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2109 SetLastError(ERROR_INVALID_HANDLE);
2112 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2114 SetLastError(ERROR_INVALID_HANDLE);
2117 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2118 || !DeviceInfoData->Reserved)
2120 SetLastError(ERROR_INVALID_PARAMETER);
2123 if (!InterfaceClassGuid)
2125 SetLastError(ERROR_INVALID_USER_BUFFER);
2128 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2129 if ((ret = SETUPDI_AddInterfaceInstance(devInfo, InterfaceClassGuid,
2130 ReferenceString, &iface)))
2132 if (DeviceInterfaceData)
2134 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2136 SetLastError(ERROR_INVALID_USER_BUFFER);
2140 memcpy(DeviceInterfaceData, iface, sizeof(*iface));
2146 /***********************************************************************
2147 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2150 * DeviceInfoSet [I] Set of devices from which to enumerate
2152 * DeviceInfoData [I] (Optional) If specified, a specific device
2153 * instance from which to enumerate interfaces.
2154 * If it isn't specified, all interfaces for all
2155 * devices in the set are enumerated.
2156 * InterfaceClassGuid [I] The interface class to enumerate.
2157 * MemberIndex [I] An index of the interface instance to enumerate.
2158 * A caller should start with MemberIndex set to 0,
2159 * and continue until the function fails with
2160 * ERROR_NO_MORE_ITEMS.
2161 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2162 * member must be set to
2163 * sizeof(SP_DEVICE_INTERFACE_DATA).
2166 * Success: non-zero value.
2167 * Failure: FALSE. Call GetLastError() for more info.
2169 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2170 HDEVINFO DeviceInfoSet,
2171 PSP_DEVINFO_DATA DeviceInfoData,
2172 CONST GUID * InterfaceClassGuid,
2174 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2176 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2179 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2180 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2182 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2183 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2185 SetLastError(ERROR_INVALID_HANDLE);
2188 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2189 !DeviceInfoData->Reserved))
2191 SetLastError(ERROR_INVALID_PARAMETER);
2194 if (!DeviceInterfaceData ||
2195 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2197 SetLastError(ERROR_INVALID_PARAMETER);
2202 struct DeviceInfo *devInfo =
2203 (struct DeviceInfo *)DeviceInfoData->Reserved;
2206 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &i)))
2208 if (MemberIndex < devInfo->interfaces[i].cInstances)
2209 memcpy(DeviceInterfaceData,
2210 &devInfo->interfaces[i].instances[MemberIndex],
2211 sizeof(SP_DEVICE_INTERFACE_DATA));
2214 SetLastError(ERROR_NO_MORE_ITEMS);
2219 SetLastError(ERROR_NO_MORE_ITEMS);
2223 DWORD i, cEnumerated = 0;
2226 for (i = 0; !found && cEnumerated < MemberIndex + 1 &&
2227 i < set->cDevices; i++)
2229 struct DeviceInfo *devInfo =
2230 (struct DeviceInfo *)set->devices[i].Reserved;
2231 DWORD interfaceIndex;
2233 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid,
2236 struct InterfaceInstances *interface =
2237 &devInfo->interfaces[interfaceIndex];
2239 if (cEnumerated + interface->cInstances < MemberIndex + 1)
2240 cEnumerated += interface->cInstances;
2243 DWORD instanceIndex = MemberIndex - cEnumerated;
2245 memcpy(DeviceInterfaceData,
2246 &interface->instances[instanceIndex],
2247 sizeof(SP_DEVICE_INTERFACE_DATA));
2248 cEnumerated += instanceIndex + 1;
2255 SetLastError(ERROR_NO_MORE_ITEMS);
2260 /***********************************************************************
2261 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2263 * Destroy a DeviceInfoList and free all used memory of the list.
2266 * devinfo [I] DeviceInfoList pointer to list to destroy
2269 * Success: non zero value.
2270 * Failure: zero value.
2272 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2276 TRACE("%p\n", devinfo);
2277 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2279 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2281 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2285 for (i = 0; i < list->cDevices; i++)
2286 SETUPDI_FreeDeviceInfo(
2287 (struct DeviceInfo *)list->devices[i].Reserved);
2288 HeapFree(GetProcessHeap(), 0, list->devices);
2289 HeapFree(GetProcessHeap(), 0, list);
2295 SetLastError(ERROR_INVALID_HANDLE);
2300 /***********************************************************************
2301 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2303 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2304 HDEVINFO DeviceInfoSet,
2305 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2306 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2307 DWORD DeviceInterfaceDetailDataSize,
2308 PDWORD RequiredSize,
2309 PSP_DEVINFO_DATA DeviceInfoData)
2311 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2312 struct InterfaceInfo *info;
2313 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)
2317 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2318 DeviceInterfaceData, DeviceInterfaceDetailData,
2319 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2321 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2322 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2324 SetLastError(ERROR_INVALID_HANDLE);
2327 if (!DeviceInterfaceData ||
2328 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2329 !DeviceInterfaceData->Reserved)
2331 SetLastError(ERROR_INVALID_PARAMETER);
2334 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2335 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) ||
2336 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2338 SetLastError(ERROR_INVALID_USER_BUFFER);
2341 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2343 SetLastError(ERROR_INVALID_USER_BUFFER);
2346 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2347 if (info->symbolicLink)
2348 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2349 NULL, 0, NULL, NULL);
2350 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2352 if (info->symbolicLink)
2353 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2354 DeviceInterfaceDetailData->DevicePath,
2355 DeviceInterfaceDetailDataSize -
2356 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2359 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2365 *RequiredSize = bytesNeeded;
2366 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2371 /***********************************************************************
2372 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2374 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2375 HDEVINFO DeviceInfoSet,
2376 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2377 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2378 DWORD DeviceInterfaceDetailDataSize,
2379 PDWORD RequiredSize,
2380 PSP_DEVINFO_DATA DeviceInfoData)
2382 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2383 struct InterfaceInfo *info;
2384 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2385 + sizeof(WCHAR); /* include NULL terminator */
2388 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2389 DeviceInterfaceData, DeviceInterfaceDetailData,
2390 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2392 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2393 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2395 SetLastError(ERROR_INVALID_HANDLE);
2398 if (!DeviceInterfaceData ||
2399 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2400 !DeviceInterfaceData->Reserved)
2402 SetLastError(ERROR_INVALID_PARAMETER);
2405 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2406 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2407 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2409 SetLastError(ERROR_INVALID_USER_BUFFER);
2412 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2414 SetLastError(ERROR_INVALID_USER_BUFFER);
2417 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2418 if (info->symbolicLink)
2419 bytesNeeded += lstrlenW(info->symbolicLink);
2420 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2422 if (info->symbolicLink)
2423 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
2425 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2431 *RequiredSize = bytesNeeded;
2432 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2437 struct PropertyMapEntry
2444 static struct PropertyMapEntry PropertyMap[] = {
2445 { REG_SZ, "DeviceDesc", DeviceDesc },
2446 { REG_MULTI_SZ, "HardwareId", HardwareId },
2447 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
2448 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
2449 { REG_SZ, "Service", Service },
2450 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
2451 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
2452 { REG_SZ, "Class", Class },
2453 { REG_SZ, "ClassGUID", ClassGUID },
2454 { REG_SZ, "Driver", Driver },
2455 { REG_DWORD, "ConfigFlags", ConfigFlags },
2456 { REG_SZ, "Mfg", Mfg },
2457 { REG_SZ, "FriendlyName", FriendlyName },
2458 { REG_SZ, "LocationInformation", LocationInformation },
2459 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
2460 { REG_DWORD, "Capabilities", Capabilities },
2461 { REG_DWORD, "UINumber", UINumber },
2462 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
2463 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
2466 /***********************************************************************
2467 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2469 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2470 HDEVINFO DeviceInfoSet,
2471 PSP_DEVINFO_DATA DeviceInfoData,
2473 PDWORD PropertyRegDataType,
2474 PBYTE PropertyBuffer,
2475 DWORD PropertyBufferSize,
2476 PDWORD RequiredSize)
2479 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2480 struct DeviceInfo *devInfo;
2482 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2483 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2486 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2488 SetLastError(ERROR_INVALID_HANDLE);
2491 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2493 SetLastError(ERROR_INVALID_HANDLE);
2496 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2497 || !DeviceInfoData->Reserved)
2499 SetLastError(ERROR_INVALID_PARAMETER);
2502 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2503 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2504 && PropertyMap[Property].nameA)
2506 DWORD size = PropertyBufferSize;
2507 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
2508 NULL, PropertyRegDataType, PropertyBuffer, &size);
2511 *RequiredSize = size;
2520 /***********************************************************************
2521 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2523 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2524 HDEVINFO DeviceInfoSet,
2525 PSP_DEVINFO_DATA DeviceInfoData,
2527 PDWORD PropertyRegDataType,
2528 PBYTE PropertyBuffer,
2529 DWORD PropertyBufferSize,
2530 PDWORD RequiredSize)
2533 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2534 struct DeviceInfo *devInfo;
2536 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2537 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2540 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2542 SetLastError(ERROR_INVALID_HANDLE);
2545 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2547 SetLastError(ERROR_INVALID_HANDLE);
2550 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2551 || !DeviceInfoData->Reserved)
2553 SetLastError(ERROR_INVALID_PARAMETER);
2556 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2557 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2558 && PropertyMap[Property].nameW)
2560 DWORD size = PropertyBufferSize;
2561 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2562 NULL, PropertyRegDataType, PropertyBuffer, &size);
2565 *RequiredSize = size;
2574 /***********************************************************************
2575 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2577 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2578 HDEVINFO DeviceInfoSet,
2579 PSP_DEVINFO_DATA DeviceInfoData,
2581 const BYTE *PropertyBuffer,
2582 DWORD PropertyBufferSize)
2585 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2586 struct DeviceInfo *devInfo;
2588 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2589 PropertyBuffer, PropertyBufferSize);
2591 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2593 SetLastError(ERROR_INVALID_HANDLE);
2596 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2598 SetLastError(ERROR_INVALID_HANDLE);
2601 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2602 || !DeviceInfoData->Reserved)
2604 SetLastError(ERROR_INVALID_PARAMETER);
2607 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2608 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2609 && PropertyMap[Property].nameA)
2611 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2612 PropertyMap[Property].regType, PropertyBuffer,
2613 PropertyBufferSize);
2622 /***********************************************************************
2623 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2625 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2626 HDEVINFO DeviceInfoSet,
2627 PSP_DEVINFO_DATA DeviceInfoData,
2629 const BYTE *PropertyBuffer,
2630 DWORD PropertyBufferSize)
2633 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2634 struct DeviceInfo *devInfo;
2636 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2637 PropertyBuffer, PropertyBufferSize);
2639 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2641 SetLastError(ERROR_INVALID_HANDLE);
2644 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2646 SetLastError(ERROR_INVALID_HANDLE);
2649 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2650 || !DeviceInfoData->Reserved)
2652 SetLastError(ERROR_INVALID_PARAMETER);
2655 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2656 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2657 && PropertyMap[Property].nameW)
2659 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
2660 PropertyMap[Property].regType, PropertyBuffer,
2661 PropertyBufferSize);
2670 /***********************************************************************
2671 * SetupDiInstallClassA (SETUPAPI.@)
2673 BOOL WINAPI SetupDiInstallClassA(
2679 UNICODE_STRING FileNameW;
2682 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2684 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2688 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2690 RtlFreeUnicodeString(&FileNameW);
2695 static HKEY CreateClassKey(HINF hInf)
2697 WCHAR FullBuffer[MAX_PATH];
2698 WCHAR Buffer[MAX_PATH];
2702 if (!SetupGetLineTextW(NULL,
2710 return INVALID_HANDLE_VALUE;
2713 lstrcpyW(FullBuffer, ControlClass);
2714 lstrcatW(FullBuffer, Buffer);
2716 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2722 if (!SetupGetLineTextW(NULL,
2730 return INVALID_HANDLE_VALUE;
2733 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2737 REG_OPTION_NON_VOLATILE,
2743 return INVALID_HANDLE_VALUE;
2748 if (RegSetValueExW(hClassKey,
2753 RequiredSize * sizeof(WCHAR)))
2755 RegCloseKey(hClassKey);
2756 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
2758 return INVALID_HANDLE_VALUE;
2764 /***********************************************************************
2765 * SetupDiInstallClassW (SETUPAPI.@)
2767 BOOL WINAPI SetupDiInstallClassW(
2773 WCHAR SectionName[MAX_PATH];
2774 DWORD SectionNameLength = 0;
2776 BOOL bFileQueueCreated = FALSE;
2782 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2784 SetLastError(ERROR_INVALID_PARAMETER);
2788 /* Open the .inf file */
2789 hInf = SetupOpenInfFileW(InfFileName,
2793 if (hInf == INVALID_HANDLE_VALUE)
2799 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2800 hClassKey = CreateClassKey(hInf);
2801 if (hClassKey == INVALID_HANDLE_VALUE)
2803 SetupCloseInfFile(hInf);
2808 /* Try to append a layout file */
2810 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2813 /* Retrieve the actual section name */
2814 SetupDiGetActualSectionToInstallW(hInf,
2822 if (!(Flags & DI_NOVCP))
2824 FileQueue = SetupOpenFileQueue();
2825 if (FileQueue == INVALID_HANDLE_VALUE)
2827 SetupCloseInfFile(hInf);
2831 bFileQueueCreated = TRUE;
2836 SetupInstallFromInfSectionW(NULL,
2845 INVALID_HANDLE_VALUE,
2848 /* FIXME: More code! */
2850 if (bFileQueueCreated)
2851 SetupCloseFileQueue(FileQueue);
2853 SetupCloseInfFile(hInf);
2859 /***********************************************************************
2860 * SetupDiOpenClassRegKey (SETUPAPI.@)
2862 HKEY WINAPI SetupDiOpenClassRegKey(
2863 const GUID* ClassGuid,
2866 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2867 DIOCR_INSTALLER, NULL, NULL);
2871 /***********************************************************************
2872 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2874 HKEY WINAPI SetupDiOpenClassRegKeyExA(
2875 const GUID* ClassGuid,
2881 PWSTR MachineNameW = NULL;
2888 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2889 if (MachineNameW == NULL)
2890 return INVALID_HANDLE_VALUE;
2893 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2894 Flags, MachineNameW, Reserved);
2896 MyFree(MachineNameW);
2902 /***********************************************************************
2903 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2905 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2906 const GUID* ClassGuid,
2917 if (MachineName != NULL)
2919 FIXME("Remote access not supported yet!\n");
2920 return INVALID_HANDLE_VALUE;
2923 if (Flags == DIOCR_INSTALLER)
2925 lpKeyName = ControlClass;
2927 else if (Flags == DIOCR_INTERFACE)
2929 lpKeyName = DeviceClasses;
2933 ERR("Invalid Flags parameter!\n");
2934 SetLastError(ERROR_INVALID_PARAMETER);
2935 return INVALID_HANDLE_VALUE;
2940 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2947 hClassesKey = INVALID_HANDLE_VALUE;
2953 WCHAR bracedGuidString[39];
2955 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
2957 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2963 if ((l = RegOpenKeyExW(hClassesKey,
2970 key = INVALID_HANDLE_VALUE;
2972 RegCloseKey(hClassesKey);
2977 key = INVALID_HANDLE_VALUE;
2983 /***********************************************************************
2984 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2986 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2987 HDEVINFO DeviceInfoSet,
2990 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2992 FIXME("%p %s %08x %p\n",
2993 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2997 /***********************************************************************
2998 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3000 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3001 HDEVINFO DeviceInfoSet,
3004 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3006 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3007 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3011 /***********************************************************************
3012 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3014 BOOL WINAPI SetupDiSetClassInstallParamsA(
3015 HDEVINFO DeviceInfoSet,
3016 PSP_DEVINFO_DATA DeviceInfoData,
3017 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3018 DWORD ClassInstallParamsSize)
3020 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3021 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3025 /***********************************************************************
3026 * SetupDiCallClassInstaller (SETUPAPI.@)
3028 BOOL WINAPI SetupDiCallClassInstaller(
3029 DI_FUNCTION InstallFunction,
3030 HDEVINFO DeviceInfoSet,
3031 PSP_DEVINFO_DATA DeviceInfoData)
3033 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3037 /***********************************************************************
3038 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3040 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3041 HDEVINFO DeviceInfoSet,
3042 PSP_DEVINFO_DATA DeviceInfoData,
3043 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3045 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3049 /***********************************************************************
3050 * SetupDiOpenDevRegKey (SETUPAPI.@)
3052 HKEY WINAPI SetupDiOpenDevRegKey(
3053 HDEVINFO DeviceInfoSet,
3054 PSP_DEVINFO_DATA DeviceInfoData,
3060 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3061 Scope, HwProfile, KeyType, samDesired);
3062 return INVALID_HANDLE_VALUE;