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/list.h"
37 #include "wine/unicode.h"
44 #include "setupapi_private.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
49 /* Unicode constants */
50 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
51 static const WCHAR Class[] = {'C','l','a','s','s',0};
52 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
53 static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
54 static const WCHAR NoInstallClass[] = {'N','o','I','n','s','t','a','l','l','C','l','a','s','s',0};
55 static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
56 static const WCHAR NtExtension[] = {'.','N','T',0};
57 static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
58 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
59 static const WCHAR WinExtension[] = {'.','W','i','n',0};
61 /* Registry key and value names */
62 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
63 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
64 'C','o','n','t','r','o','l','\\',
65 'C','l','a','s','s',0};
67 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
68 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
69 'C','o','n','t','r','o','l','\\',
70 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
71 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
72 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
74 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
75 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
76 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
77 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
78 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
79 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
80 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
81 static const WCHAR Mfg[] = {'M','f','g',0};
82 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
83 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
84 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
85 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
86 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
87 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
88 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
89 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
91 /* is used to identify if a DeviceInfoSet pointer is
93 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
97 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
101 SP_DEVINFO_DATA *devices;
104 /* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */
107 LPWSTR referenceString;
109 PSP_DEVINFO_DATA device;
112 /* A device may have multiple instances of the same interface, so this holds
113 * each instance belonging to a particular interface.
115 struct InterfaceInstances
119 DWORD cInstancesAllocated;
120 SP_DEVICE_INTERFACE_DATA *instances;
124 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
127 struct DeviceInfoSet *set;
131 struct list interfaces;
134 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
136 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
137 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
138 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
141 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
142 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
143 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
146 static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
150 for (i = 0; i < instances->cInstances; i++)
152 struct InterfaceInfo *ifaceInfo =
153 (struct InterfaceInfo *)instances->instances[i].Reserved;
155 HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
156 HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
158 HeapFree(GetProcessHeap(), 0, instances->instances);
161 /* Finds the interface with interface class InterfaceClassGuid in the device.
162 * Returns TRUE if found, and updates *interface to point to device's
163 * interfaces member where the given interface was found.
164 * Returns FALSE if not found.
166 static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
167 const GUID *InterfaceClassGuid, struct InterfaceInstances **interface)
170 struct InterfaceInstances *iface;
172 TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
174 LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances,
177 if (IsEqualGUID(&iface->guid, InterfaceClassGuid))
184 TRACE("returning %d (%p)\n", found, found ? *interface : NULL);
188 /* Finds the interface instance with reference string ReferenceString in the
189 * interface instance map. Returns TRUE if found, and updates instanceIndex to
190 * the index of the interface instance's instances member
191 * where the given instance was found. Returns FALSE if not found.
193 static BOOL SETUPDI_FindInterfaceInstance(
194 const struct InterfaceInstances *instances,
195 LPCWSTR ReferenceString, DWORD *instanceIndex)
200 TRACE("%s\n", debugstr_w(ReferenceString));
202 for (i = 0; !found && i < instances->cInstances; i++)
204 SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
205 struct InterfaceInfo *ifaceInfo =
206 (struct InterfaceInfo *)ifaceData->Reserved;
208 if (!ReferenceString && !ifaceInfo->referenceString)
213 else if (ReferenceString && ifaceInfo->referenceString &&
214 !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
220 TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
224 static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
225 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
227 static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
232 SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
233 /* omit length of format specifiers, but include NULL terminator: */
234 len = lstrlenW(fmt) - 4 + 1;
235 len += lstrlenW(instanceId) + lstrlenW(guidStr);
238 /* space for a hash between string and reference string: */
239 len += lstrlenW(ReferenceString) + 1;
241 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
244 int printed = sprintfW(ret, fmt, instanceId, guidStr);
247 /* replace '\\' with '#' after the "\\\\?\\" beginning */
248 for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
252 ret[printed - 1] = '\\';
253 lstrcpyW(ret + printed, ReferenceString);
259 /* Adds an interface with the given interface class and reference string to
260 * the device, if it doesn't already exist in the device. If iface is not
261 * NULL, returns a pointer to the newly added (or already existing) interface.
263 static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData,
264 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
265 SP_DEVICE_INTERFACE_DATA **ifaceData)
267 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
268 BOOL newInterface = FALSE, ret;
269 struct InterfaceInstances *iface = NULL;
271 TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
272 debugstr_w(ReferenceString), iface);
274 if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
276 iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
277 sizeof(struct InterfaceInstances));
280 list_add_tail(&devInfo->interfaces, &iface->entry);
286 DWORD instanceIndex = 0;
288 if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
291 SP_DEVICE_INTERFACE_DATA *instance = NULL;
293 if (!iface->cInstancesAllocated)
295 iface->instances = HeapAlloc(GetProcessHeap(), 0,
296 sizeof(SP_DEVICE_INTERFACE_DATA));
297 if (iface->instances)
298 instance = &iface->instances[iface->cInstancesAllocated++];
300 else if (iface->cInstances == iface->cInstancesAllocated)
302 iface->instances = HeapReAlloc(GetProcessHeap(), 0,
304 (iface->cInstancesAllocated + 1) *
305 sizeof(SP_DEVICE_INTERFACE_DATA));
306 if (iface->instances)
307 instance = &iface->instances[iface->cInstancesAllocated++];
310 instance = &iface->instances[iface->cInstances];
313 struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
314 0, sizeof(struct InterfaceInfo));
319 ifaceInfo->device = DeviceInfoData;
320 ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
321 devInfo->instanceId, InterfaceClassGuid,
325 ifaceInfo->referenceString =
326 HeapAlloc(GetProcessHeap(), 0,
327 (lstrlenW(ReferenceString) + 1) *
329 if (ifaceInfo->referenceString)
330 lstrcpyW(ifaceInfo->referenceString,
336 ifaceInfo->referenceString = NULL;
341 sizeof(SP_DEVICE_INTERFACE_DATA);
342 memcpy(&instance->InterfaceClassGuid,
343 InterfaceClassGuid, sizeof(GUID));
344 instance->Flags = SPINT_ACTIVE; /* FIXME */
345 instance->Reserved = (ULONG_PTR)ifaceInfo;
347 memcpy(&iface->guid, InterfaceClassGuid,
349 /* FIXME: now create this homeboy in the registry */
351 *ifaceData = instance;
354 HeapFree(GetProcessHeap(), 0, ifaceInfo);
361 *ifaceData = &iface->instances[instanceIndex];
366 TRACE("returning %d\n", ret);
370 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
371 LPCWSTR symbolicLink)
373 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
378 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
379 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
380 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
381 if (info->symbolicLink)
383 lstrcpyW(info->symbolicLink, symbolicLink);
390 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
391 LPCWSTR instanceId, BOOL phantom)
393 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
394 sizeof(struct DeviceInfo));
399 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
400 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
401 if (devInfo->instanceId)
406 devInfo->key = INVALID_HANDLE_VALUE;
407 devInfo->phantom = phantom;
408 lstrcpyW(devInfo->instanceId, instanceId);
409 struprW(devInfo->instanceId);
410 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
411 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
414 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
415 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
417 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
418 (LPBYTE)&phantom, sizeof(phantom));
419 RegCloseKey(enumKey);
421 list_init(&devInfo->interfaces);
425 HeapFree(GetProcessHeap(), 0, devInfo);
432 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
434 struct InterfaceInstances *iface, *next;
436 if (devInfo->key != INVALID_HANDLE_VALUE)
437 RegCloseKey(devInfo->key);
438 if (devInfo->phantom)
443 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
444 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
447 RegDeleteTreeW(enumKey, devInfo->instanceId);
448 RegCloseKey(enumKey);
451 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
452 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
453 struct InterfaceInstances, entry)
455 list_remove(&iface->entry);
456 SETUPDI_FreeInterfaceInstances(iface);
457 HeapFree(GetProcessHeap(), 0, iface);
459 HeapFree(GetProcessHeap(), 0, devInfo);
462 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
463 * struct DeviceInfo, and points the returned device info's Reserved member
464 * to it. "Phantom" devices are deleted from the registry when closed.
465 * Returns a pointer to the newly allocated device info.
467 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
472 SP_DEVINFO_DATA **dev)
475 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, instanceId,
478 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
479 debugstr_w(instanceId), phantom);
484 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
485 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
487 set->devices = HeapAlloc(GetProcessHeap(), 0,
488 sizeof(SP_DEVINFO_DATA));
491 WCHAR classGuidStr[39];
493 *dev = &set->devices[set->cDevices++];
494 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
495 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
496 (*dev)->DevInst = devInst;
497 (*dev)->Reserved = (ULONG_PTR)devInfo;
498 SETUPDI_GuidToString(guid, classGuidStr);
499 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
500 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
501 lstrlenW(classGuidStr) * sizeof(WCHAR));
506 HeapFree(GetProcessHeap(), 0, devInfo);
507 SetLastError(ERROR_OUTOFMEMORY);
513 /***********************************************************************
514 * SetupDiBuildClassInfoList (SETUPAPI.@)
516 * Returns a list of setup class GUIDs that identify the classes
517 * that are installed on a local machine.
520 * Flags [I] control exclusion of classes from the list.
521 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
522 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
523 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
529 BOOL WINAPI SetupDiBuildClassInfoList(
531 LPGUID ClassGuidList,
532 DWORD ClassGuidListSize,
536 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
537 ClassGuidListSize, RequiredSize,
541 /***********************************************************************
542 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
544 * Returns a list of setup class GUIDs that identify the classes
545 * that are installed on a local or remote macine.
548 * Flags [I] control exclusion of classes from the list.
549 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
550 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
551 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
552 * MachineName [I] name of a remote machine.
553 * Reserved [I] must be NULL.
559 BOOL WINAPI SetupDiBuildClassInfoListExA(
561 LPGUID ClassGuidList,
562 DWORD ClassGuidListSize,
567 LPWSTR MachineNameW = NULL;
574 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
575 if (MachineNameW == NULL) return FALSE;
578 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
579 ClassGuidListSize, RequiredSize,
580 MachineNameW, Reserved);
582 MyFree(MachineNameW);
587 /***********************************************************************
588 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
590 * Returns a list of setup class GUIDs that identify the classes
591 * that are installed on a local or remote macine.
594 * Flags [I] control exclusion of classes from the list.
595 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
596 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
597 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
598 * MachineName [I] name of a remote machine.
599 * Reserved [I] must be NULL.
605 BOOL WINAPI SetupDiBuildClassInfoListExW(
607 LPGUID ClassGuidList,
608 DWORD ClassGuidListSize,
619 DWORD dwGuidListIndex = 0;
623 if (RequiredSize != NULL)
626 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
631 if (hClassesKey == INVALID_HANDLE_VALUE)
636 for (dwIndex = 0; ; dwIndex++)
639 lError = RegEnumKeyExW(hClassesKey,
647 TRACE("RegEnumKeyExW() returns %d\n", lError);
648 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
650 TRACE("Key name: %p\n", szKeyName);
652 if (RegOpenKeyExW(hClassesKey,
658 RegCloseKey(hClassesKey);
662 if (!RegQueryValueExW(hClassKey,
669 TRACE("'NoUseClass' value found!\n");
670 RegCloseKey(hClassKey);
674 if ((Flags & DIBCI_NOINSTALLCLASS) &&
675 (!RegQueryValueExW(hClassKey,
682 TRACE("'NoInstallClass' value found!\n");
683 RegCloseKey(hClassKey);
687 if ((Flags & DIBCI_NODISPLAYCLASS) &&
688 (!RegQueryValueExW(hClassKey,
695 TRACE("'NoDisplayClass' value found!\n");
696 RegCloseKey(hClassKey);
700 RegCloseKey(hClassKey);
702 TRACE("Guid: %p\n", szKeyName);
703 if (dwGuidListIndex < ClassGuidListSize)
705 if (szKeyName[0] == '{' && szKeyName[37] == '}')
709 TRACE("Guid: %p\n", &szKeyName[1]);
711 UuidFromStringW(&szKeyName[1],
712 &ClassGuidList[dwGuidListIndex]);
718 if (lError != ERROR_SUCCESS)
722 RegCloseKey(hClassesKey);
724 if (RequiredSize != NULL)
725 *RequiredSize = dwGuidListIndex;
727 if (ClassGuidListSize < dwGuidListIndex)
729 SetLastError(ERROR_INSUFFICIENT_BUFFER);
736 /***********************************************************************
737 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
739 BOOL WINAPI SetupDiClassGuidsFromNameA(
741 LPGUID ClassGuidList,
742 DWORD ClassGuidListSize,
745 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
746 ClassGuidListSize, RequiredSize,
750 /***********************************************************************
751 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
753 BOOL WINAPI SetupDiClassGuidsFromNameW(
755 LPGUID ClassGuidList,
756 DWORD ClassGuidListSize,
759 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
760 ClassGuidListSize, RequiredSize,
764 /***********************************************************************
765 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
767 BOOL WINAPI SetupDiClassGuidsFromNameExA(
769 LPGUID ClassGuidList,
770 DWORD ClassGuidListSize,
775 LPWSTR ClassNameW = NULL;
776 LPWSTR MachineNameW = NULL;
781 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
782 if (ClassNameW == NULL)
787 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
788 if (MachineNameW == NULL)
795 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
796 ClassGuidListSize, RequiredSize,
797 MachineNameW, Reserved);
799 MyFree(MachineNameW);
805 /***********************************************************************
806 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
808 BOOL WINAPI SetupDiClassGuidsFromNameExW(
810 LPGUID ClassGuidList,
811 DWORD ClassGuidListSize,
817 WCHAR szClassName[256];
823 DWORD dwGuidListIndex = 0;
825 if (RequiredSize != NULL)
828 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
833 if (hClassesKey == INVALID_HANDLE_VALUE)
838 for (dwIndex = 0; ; dwIndex++)
841 lError = RegEnumKeyExW(hClassesKey,
849 TRACE("RegEnumKeyExW() returns %d\n", lError);
850 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
852 TRACE("Key name: %p\n", szKeyName);
854 if (RegOpenKeyExW(hClassesKey,
860 RegCloseKey(hClassesKey);
864 dwLength = 256 * sizeof(WCHAR);
865 if (!RegQueryValueExW(hClassKey,
872 TRACE("Class name: %p\n", szClassName);
874 if (strcmpiW(szClassName, ClassName) == 0)
876 TRACE("Found matching class name\n");
878 TRACE("Guid: %p\n", szKeyName);
879 if (dwGuidListIndex < ClassGuidListSize)
881 if (szKeyName[0] == '{' && szKeyName[37] == '}')
885 TRACE("Guid: %p\n", &szKeyName[1]);
887 UuidFromStringW(&szKeyName[1],
888 &ClassGuidList[dwGuidListIndex]);
895 RegCloseKey(hClassKey);
898 if (lError != ERROR_SUCCESS)
902 RegCloseKey(hClassesKey);
904 if (RequiredSize != NULL)
905 *RequiredSize = dwGuidListIndex;
907 if (ClassGuidListSize < dwGuidListIndex)
909 SetLastError(ERROR_INSUFFICIENT_BUFFER);
916 /***********************************************************************
917 * SetupDiClassNameFromGuidA (SETUPAPI.@)
919 BOOL WINAPI SetupDiClassNameFromGuidA(
920 const GUID* ClassGuid,
925 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
926 ClassNameSize, RequiredSize,
930 /***********************************************************************
931 * SetupDiClassNameFromGuidW (SETUPAPI.@)
933 BOOL WINAPI SetupDiClassNameFromGuidW(
934 const GUID* ClassGuid,
939 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
940 ClassNameSize, RequiredSize,
944 /***********************************************************************
945 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
947 BOOL WINAPI SetupDiClassNameFromGuidExA(
948 const GUID* ClassGuid,
955 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
956 LPWSTR MachineNameW = NULL;
960 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
961 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
962 NULL, MachineNameW, Reserved);
965 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
966 ClassNameSize, NULL, NULL);
968 if (!ClassNameSize && RequiredSize)
971 MyFree(MachineNameW);
975 /***********************************************************************
976 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
978 BOOL WINAPI SetupDiClassNameFromGuidExW(
979 const GUID* ClassGuid,
989 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
994 if (hKey == INVALID_HANDLE_VALUE)
999 if (RequiredSize != NULL)
1002 if (RegQueryValueExW(hKey,
1013 *RequiredSize = dwLength / sizeof(WCHAR);
1016 dwLength = ClassNameSize * sizeof(WCHAR);
1017 if (RegQueryValueExW(hKey,
1033 /***********************************************************************
1034 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1037 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1040 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1043 /***********************************************************************
1044 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1047 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1052 LPWSTR MachineNameW = NULL;
1059 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1060 if (MachineNameW == NULL)
1061 return (HDEVINFO)INVALID_HANDLE_VALUE;
1064 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1065 MachineNameW, Reserved);
1067 MyFree(MachineNameW);
1072 /***********************************************************************
1073 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1075 * Create an empty DeviceInfoSet list.
1078 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1080 * hwndParent [I] hwnd needed for interface related actions.
1081 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1082 * local registry will be used.
1083 * Reserved [I] must be NULL
1086 * Success: empty list.
1087 * Failure: INVALID_HANDLE_VALUE.
1090 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1095 struct DeviceInfoSet *list = NULL;
1096 DWORD size = sizeof(struct DeviceInfoSet);
1098 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1099 debugstr_w(MachineName), Reserved);
1101 if (MachineName != NULL)
1103 FIXME("remote support is not implemented\n");
1104 SetLastError(ERROR_INVALID_MACHINENAME);
1105 return (HDEVINFO)INVALID_HANDLE_VALUE;
1108 if (Reserved != NULL)
1110 SetLastError(ERROR_INVALID_PARAMETER);
1111 return (HDEVINFO)INVALID_HANDLE_VALUE;
1114 list = HeapAlloc(GetProcessHeap(), 0, size);
1117 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1118 return (HDEVINFO)INVALID_HANDLE_VALUE;
1121 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1122 list->hwndParent = hwndParent;
1123 memcpy(&list->ClassGuid,
1124 ClassGuid ? ClassGuid : &GUID_NULL,
1125 sizeof(list->ClassGuid));
1127 list->devices = NULL;
1129 return (HDEVINFO)list;
1132 /***********************************************************************
1133 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1135 BOOL WINAPI SetupDiCreateDeviceInfoA(
1136 HDEVINFO DeviceInfoSet,
1138 CONST GUID *ClassGuid,
1139 PCSTR DeviceDescription,
1141 DWORD CreationFlags,
1142 PSP_DEVINFO_DATA DeviceInfoData)
1145 LPWSTR DeviceNameW = NULL;
1146 LPWSTR DeviceDescriptionW = NULL;
1150 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1151 if (DeviceNameW == NULL) return FALSE;
1153 if (DeviceDescription)
1155 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1156 if (DeviceDescriptionW == NULL)
1158 MyFree(DeviceNameW);
1163 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1164 hwndParent, CreationFlags, DeviceInfoData);
1166 MyFree(DeviceNameW);
1167 MyFree(DeviceDescriptionW);
1172 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1175 DWORD devNameLen = lstrlenW(devName), devInst = 0;
1178 TRACE("%s\n", debugstr_w(devName));
1179 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1184 devInst |= *ptr - '0';
1190 TRACE("%d\n", valid ? devInst : 0xffffffff);
1191 return valid ? devInst : 0xffffffff;
1194 /***********************************************************************
1195 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1197 BOOL WINAPI SetupDiCreateDeviceInfoW(
1198 HDEVINFO DeviceInfoSet,
1200 CONST GUID *ClassGuid,
1201 PCWSTR DeviceDescription,
1203 DWORD CreationFlags,
1204 PSP_DEVINFO_DATA DeviceInfoData)
1206 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1207 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1208 LPCWSTR instanceId = NULL;
1210 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1211 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1212 hwndParent, CreationFlags, DeviceInfoData);
1216 SetLastError(ERROR_INVALID_DEVINST_NAME);
1219 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1221 SetLastError(ERROR_INVALID_HANDLE);
1226 SetLastError(ERROR_INVALID_PARAMETER);
1229 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1231 SetLastError(ERROR_INVALID_HANDLE);
1234 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1235 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1237 SetLastError(ERROR_CLASS_MISMATCH);
1240 if ((CreationFlags & DICD_GENERATE_ID))
1242 if (strchrW(DeviceName, '\\'))
1243 SetLastError(ERROR_INVALID_DEVINST_NAME);
1246 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1247 '\\','%','0','4','d',0};
1252 DWORD i, highestDevID = 0;
1254 for (i = 0; i < set->cDevices; i++)
1256 struct DeviceInfo *devInfo =
1257 (struct DeviceInfo *)set->devices[i].Reserved;
1258 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1264 devName = devInfo->instanceId;
1265 id = SETUPDI_DevNameToDevID(devName);
1266 if (id != 0xffffffff && id > highestDevID)
1269 devId = highestDevID + 1;
1273 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1274 instanceId = HeapAlloc(GetProcessHeap(), 0,
1275 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1278 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1280 allocatedInstanceId = TRUE;
1292 instanceId = DeviceName;
1293 for (i = 0; ret && i < set->cDevices; i++)
1295 struct DeviceInfo *devInfo =
1296 (struct DeviceInfo *)set->devices[i].Reserved;
1298 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1300 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1307 SP_DEVINFO_DATA *dev = NULL;
1309 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1310 instanceId, TRUE, &dev);
1313 if (DeviceDescription)
1314 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1315 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1316 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1319 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1321 SetLastError(ERROR_INVALID_USER_BUFFER);
1325 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1329 if (allocatedInstanceId)
1330 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1335 /***********************************************************************
1336 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1338 BOOL WINAPI SetupDiRegisterDeviceInfo(
1339 HDEVINFO DeviceInfoSet,
1340 PSP_DEVINFO_DATA DeviceInfoData,
1342 PSP_DETSIG_CMPPROC CompareProc,
1343 PVOID CompareContext,
1344 PSP_DEVINFO_DATA DupDeviceInfoData)
1346 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1347 struct DeviceInfo *devInfo;
1349 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1350 CompareProc, CompareContext, DupDeviceInfoData);
1352 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1354 SetLastError(ERROR_INVALID_HANDLE);
1357 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1359 SetLastError(ERROR_INVALID_HANDLE);
1362 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1363 || !DeviceInfoData->Reserved)
1365 SetLastError(ERROR_INVALID_PARAMETER);
1368 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1369 if (devInfo->set != set)
1371 SetLastError(ERROR_INVALID_PARAMETER);
1374 if (devInfo->phantom)
1376 devInfo->phantom = FALSE;
1377 RegDeleteValueW(devInfo->key, Phantom);
1382 /***********************************************************************
1383 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1385 BOOL WINAPI SetupDiEnumDeviceInfo(
1388 PSP_DEVINFO_DATA info)
1392 TRACE("%p %d %p\n", devinfo, index, info);
1396 SetLastError(ERROR_INVALID_PARAMETER);
1399 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1401 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1402 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1404 if (index < list->cDevices)
1406 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1408 memcpy(info, &list->devices[index], info->cbSize);
1412 SetLastError(ERROR_INVALID_USER_BUFFER);
1415 SetLastError(ERROR_NO_MORE_ITEMS);
1418 SetLastError(ERROR_INVALID_HANDLE);
1421 SetLastError(ERROR_INVALID_HANDLE);
1425 /***********************************************************************
1426 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1428 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1429 HDEVINFO DeviceInfoSet,
1430 PSP_DEVINFO_DATA DeviceInfoData,
1431 PSTR DeviceInstanceId,
1432 DWORD DeviceInstanceIdSize,
1433 PDWORD RequiredSize)
1439 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1440 DeviceInstanceIdSize, RequiredSize);
1442 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1447 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1449 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1452 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1459 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1461 DeviceInstanceIdSize, NULL, NULL);
1467 if (len > DeviceInstanceIdSize)
1469 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1473 *RequiredSize = len;
1476 HeapFree(GetProcessHeap(), 0, instanceId);
1481 /***********************************************************************
1482 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1484 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1485 HDEVINFO DeviceInfoSet,
1486 PSP_DEVINFO_DATA DeviceInfoData,
1487 PWSTR DeviceInstanceId,
1488 DWORD DeviceInstanceIdSize,
1489 PDWORD RequiredSize)
1491 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1492 struct DeviceInfo *devInfo;
1494 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1495 DeviceInstanceIdSize, RequiredSize);
1497 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1499 SetLastError(ERROR_INVALID_HANDLE);
1502 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1504 SetLastError(ERROR_INVALID_HANDLE);
1507 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1508 || !DeviceInfoData->Reserved)
1510 SetLastError(ERROR_INVALID_PARAMETER);
1513 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1514 if (devInfo->set != set)
1516 SetLastError(ERROR_INVALID_PARAMETER);
1519 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1520 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1522 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1524 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1527 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1529 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1533 /***********************************************************************
1534 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1536 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1538 PCSTR InfSectionName,
1539 PSTR InfSectionWithExt,
1540 DWORD InfSectionWithExtSize,
1541 PDWORD RequiredSize,
1548 /***********************************************************************
1549 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1551 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1553 PCWSTR InfSectionName,
1554 PWSTR InfSectionWithExt,
1555 DWORD InfSectionWithExtSize,
1556 PDWORD RequiredSize,
1559 WCHAR szBuffer[MAX_PATH];
1562 LONG lLineCount = -1;
1564 lstrcpyW(szBuffer, InfSectionName);
1565 dwLength = lstrlenW(szBuffer);
1567 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1569 /* Test section name with '.NTx86' extension */
1570 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1571 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1573 if (lLineCount == -1)
1575 /* Test section name with '.NT' extension */
1576 lstrcpyW(&szBuffer[dwLength], NtExtension);
1577 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1582 /* Test section name with '.Win' extension */
1583 lstrcpyW(&szBuffer[dwLength], WinExtension);
1584 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1587 if (lLineCount == -1)
1589 /* Test section name without extension */
1590 szBuffer[dwLength] = 0;
1591 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1594 if (lLineCount == -1)
1596 SetLastError(ERROR_INVALID_PARAMETER);
1600 dwFullLength = lstrlenW(szBuffer);
1602 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1604 if (InfSectionWithExtSize < (dwFullLength + 1))
1606 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1610 lstrcpyW(InfSectionWithExt, szBuffer);
1611 if (Extension != NULL)
1613 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1617 if (RequiredSize != NULL)
1619 *RequiredSize = dwFullLength + 1;
1625 /***********************************************************************
1626 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1628 BOOL WINAPI SetupDiGetClassDescriptionA(
1629 const GUID* ClassGuid,
1630 PSTR ClassDescription,
1631 DWORD ClassDescriptionSize,
1632 PDWORD RequiredSize)
1634 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1635 ClassDescriptionSize,
1636 RequiredSize, NULL, NULL);
1639 /***********************************************************************
1640 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1642 BOOL WINAPI SetupDiGetClassDescriptionW(
1643 const GUID* ClassGuid,
1644 PWSTR ClassDescription,
1645 DWORD ClassDescriptionSize,
1646 PDWORD RequiredSize)
1648 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1649 ClassDescriptionSize,
1650 RequiredSize, NULL, NULL);
1653 /***********************************************************************
1654 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1656 BOOL WINAPI SetupDiGetClassDescriptionExA(
1657 const GUID* ClassGuid,
1658 PSTR ClassDescription,
1659 DWORD ClassDescriptionSize,
1660 PDWORD RequiredSize,
1668 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1673 if (hKey == INVALID_HANDLE_VALUE)
1675 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1679 dwLength = ClassDescriptionSize;
1680 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1681 (LPBYTE)ClassDescription, &dwLength );
1682 if (RequiredSize) *RequiredSize = dwLength;
1687 /***********************************************************************
1688 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1690 BOOL WINAPI SetupDiGetClassDescriptionExW(
1691 const GUID* ClassGuid,
1692 PWSTR ClassDescription,
1693 DWORD ClassDescriptionSize,
1694 PDWORD RequiredSize,
1702 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1707 if (hKey == INVALID_HANDLE_VALUE)
1709 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1713 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1714 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1715 (LPBYTE)ClassDescription, &dwLength );
1716 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1721 /***********************************************************************
1722 * SetupDiGetClassDevsA (SETUPAPI.@)
1724 HDEVINFO WINAPI SetupDiGetClassDevsA(
1731 LPWSTR enumstrW = NULL;
1735 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1736 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1739 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1742 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1744 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
1745 HeapFree(GetProcessHeap(), 0, enumstrW);
1751 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
1752 const GUID *interface)
1755 WCHAR subKeyName[MAX_PATH];
1756 LONG l = ERROR_SUCCESS;
1758 for (i = 0; !l; i++)
1760 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1761 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1765 SP_DEVICE_INTERFACE_DATA *iface = NULL;
1767 /* The subkey name is the reference string, with a '#' prepended */
1768 SETUPDI_AddInterfaceInstance(dev, interface, subKeyName + 1,
1770 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1773 WCHAR symbolicLink[MAX_PATH];
1776 len = sizeof(symbolicLink);
1777 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
1778 (BYTE *)symbolicLink, &len);
1779 if (!l && dataType == REG_SZ)
1780 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
1781 RegCloseKey(subKey);
1785 /* FIXME: find and add all the device's interfaces to the device */
1788 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1789 HKEY key, const GUID *interface, LPCWSTR enumstr)
1791 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1793 WCHAR subKeyName[MAX_PATH];
1795 HKEY enumKey = INVALID_HANDLE_VALUE;
1797 TRACE("%s\n", debugstr_w(enumstr));
1799 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1801 for (i = 0; !l; i++)
1803 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1804 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1809 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1812 WCHAR deviceInst[MAX_PATH * 3];
1815 len = sizeof(deviceInst);
1816 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1817 (BYTE *)deviceInst, &len);
1818 if (!l && dataType == REG_SZ)
1820 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1821 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1825 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1829 WCHAR deviceClassStr[40];
1831 len = sizeof(deviceClassStr);
1832 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1833 &dataType, (BYTE *)deviceClassStr, &len);
1834 if (!l && dataType == REG_SZ &&
1835 deviceClassStr[0] == '{' &&
1836 deviceClassStr[37] == '}')
1839 SP_DEVINFO_DATA *dev;
1841 deviceClassStr[37] = 0;
1842 UuidFromStringW(&deviceClassStr[1],
1844 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
1845 0 /* FIXME: DevInst */, deviceInst,
1847 SETUPDI_AddDeviceInterfaces(dev, subKey,
1850 RegCloseKey(deviceKey);
1854 RegCloseKey(subKey);
1858 if (enumKey != INVALID_HANDLE_VALUE)
1859 RegCloseKey(enumKey);
1862 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1863 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1865 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1866 DIOCR_INTERFACE, NULL, NULL);
1868 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1869 debugstr_w(enumstr), flags);
1871 if (interfacesKey != INVALID_HANDLE_VALUE)
1873 if (flags & DIGCF_ALLCLASSES)
1876 WCHAR interfaceGuidStr[40];
1877 LONG l = ERROR_SUCCESS;
1879 for (i = 0; !l; i++)
1881 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
1882 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
1883 NULL, NULL, NULL, NULL);
1886 if (interfaceGuidStr[0] == '{' &&
1887 interfaceGuidStr[37] == '}')
1892 interfaceGuidStr[37] = 0;
1893 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
1894 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
1895 KEY_READ, &interfaceKey);
1898 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1899 interfaceKey, &interfaceGuid, enumstr);
1900 RegCloseKey(interfaceKey);
1908 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
1909 * interface's key, so just pass that long
1911 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1912 interfacesKey, interface, enumstr);
1914 RegCloseKey(interfacesKey);
1918 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
1919 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
1921 struct DeviceInfoSet *set = (struct DeviceInfoSet *)set;
1923 WCHAR subKeyName[MAX_PATH];
1924 LONG l = ERROR_SUCCESS;
1926 TRACE("%s\n", debugstr_w(parent));
1928 for (i = 0; !l; i++)
1930 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1931 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1936 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1939 WCHAR classGuid[40];
1942 len = sizeof(classGuid);
1943 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
1944 (BYTE *)classGuid, &len);
1945 if (!l && dataType == REG_SZ)
1947 if (classGuid[0] == '{' && classGuid[37] == '}')
1952 UuidFromStringW(&classGuid[1], &deviceClass);
1953 if ((flags & DIGCF_ALLCLASSES) ||
1954 IsEqualGUID(class, &deviceClass))
1956 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
1959 instanceId = HeapAlloc(GetProcessHeap(), 0,
1960 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
1964 SP_DEVINFO_DATA *dev;
1966 sprintfW(instanceId, fmt, parent, subKeyName);
1967 SETUPDI_AddDeviceToSet(set, &deviceClass,
1968 0 /* FIXME: DevInst */, instanceId,
1970 HeapFree(GetProcessHeap(), 0, instanceId);
1975 RegCloseKey(subKey);
1981 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
1982 LPCWSTR enumstr, DWORD flags)
1984 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
1985 DIOCR_INSTALLER, NULL, NULL);
1987 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
1988 debugstr_w(enumstr), flags);
1990 if (classesKey != INVALID_HANDLE_VALUE)
1995 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
2000 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2001 enumKey, class, flags);
2002 RegCloseKey(enumKey);
2008 WCHAR subKeyName[MAX_PATH];
2009 LONG l = ERROR_SUCCESS;
2011 for (i = 0; !l; i++)
2013 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2014 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
2020 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
2024 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2025 subKeyName, subKey, class, flags);
2026 RegCloseKey(subKey);
2031 RegCloseKey(classesKey);
2035 /***********************************************************************
2036 * SetupDiGetClassDevsW (SETUPAPI.@)
2038 HDEVINFO WINAPI SetupDiGetClassDevsW(
2044 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2048 TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
2050 if (!(flags & DIGCF_ALLCLASSES) && !class)
2052 SetLastError(ERROR_INVALID_PARAMETER);
2055 if (flags & unsupportedFlags)
2056 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2057 /* WinXP always succeeds, returns empty list for unknown classes */
2058 set = SetupDiCreateDeviceInfoList(class, parent);
2061 if (flags & DIGCF_DEVICEINTERFACE)
2062 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2064 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2069 /***********************************************************************
2070 * SetupDiGetClassDevsExW (SETUPAPI.@)
2072 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2085 /***********************************************************************
2086 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2088 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2089 HDEVINFO DeviceInfoSet,
2090 PSP_DEVINFO_DATA DeviceInfoData,
2091 const GUID *InterfaceClassGuid,
2092 PCSTR ReferenceString,
2093 DWORD CreationFlags,
2094 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2097 LPWSTR ReferenceStringW = NULL;
2099 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2100 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2101 CreationFlags, DeviceInterfaceData);
2103 if (ReferenceString)
2105 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2106 if (ReferenceStringW == NULL) return FALSE;
2109 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2110 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2111 DeviceInterfaceData);
2113 MyFree(ReferenceStringW);
2118 /***********************************************************************
2119 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2121 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2122 HDEVINFO DeviceInfoSet,
2123 PSP_DEVINFO_DATA DeviceInfoData,
2124 const GUID *InterfaceClassGuid,
2125 PCWSTR ReferenceString,
2126 DWORD CreationFlags,
2127 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2129 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2130 struct DeviceInfo *devInfo;
2131 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2134 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2135 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2136 CreationFlags, DeviceInterfaceData);
2138 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2140 SetLastError(ERROR_INVALID_HANDLE);
2143 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2145 SetLastError(ERROR_INVALID_HANDLE);
2148 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2149 || !DeviceInfoData->Reserved)
2151 SetLastError(ERROR_INVALID_PARAMETER);
2154 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2155 if (devInfo->set != set)
2157 SetLastError(ERROR_INVALID_PARAMETER);
2160 if (!InterfaceClassGuid)
2162 SetLastError(ERROR_INVALID_USER_BUFFER);
2165 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2166 ReferenceString, &iface)))
2168 if (DeviceInterfaceData)
2170 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2172 SetLastError(ERROR_INVALID_USER_BUFFER);
2176 memcpy(DeviceInterfaceData, iface, sizeof(*iface));
2182 /***********************************************************************
2183 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2185 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2186 HDEVINFO DeviceInfoSet,
2187 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2191 PCSTR InfSectionName)
2194 PWSTR InfSectionNameW = NULL;
2196 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2197 samDesired, InfHandle, InfSectionName);
2200 if (!InfSectionName)
2202 SetLastError(ERROR_INVALID_PARAMETER);
2203 return INVALID_HANDLE_VALUE;
2205 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2206 if (!InfSectionNameW)
2207 return INVALID_HANDLE_VALUE;
2209 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2210 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2212 MyFree(InfSectionNameW);
2216 /***********************************************************************
2217 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2219 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2220 HDEVINFO DeviceInfoSet,
2221 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2225 PCWSTR InfSectionName)
2227 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2228 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2231 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2232 samDesired, InfHandle, InfSectionName);
2234 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2235 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2237 SetLastError(ERROR_INVALID_HANDLE);
2238 return INVALID_HANDLE_VALUE;
2240 if (!DeviceInterfaceData ||
2241 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2242 !DeviceInterfaceData->Reserved)
2244 SetLastError(ERROR_INVALID_PARAMETER);
2245 return INVALID_HANDLE_VALUE;
2247 if (InfHandle && !InfSectionName)
2249 SetLastError(ERROR_INVALID_PARAMETER);
2250 return INVALID_HANDLE_VALUE;
2252 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2253 samDesired, NULL, &interfacesKey, NULL)))
2256 WCHAR bracedGuidString[39];
2258 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2260 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2261 samDesired, NULL, &parent, NULL)))
2263 static const WCHAR hash[] = {'#',0};
2264 struct InterfaceInfo *ifaceInfo =
2265 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2266 LPCWSTR instancePath = NULL;
2267 LPWSTR referencePath = NULL;
2269 if (ifaceInfo->referenceString)
2271 referencePath = HeapAlloc(GetProcessHeap(), 0,
2272 (lstrlenW(ifaceInfo->referenceString) + 2) *
2276 lstrcpyW(referencePath, hash);
2277 lstrcatW(referencePath, ifaceInfo->referenceString);
2278 instancePath = referencePath;
2281 SetLastError(ERROR_OUTOFMEMORY);
2284 instancePath = hash;
2289 l = RegCreateKeyExW(parent, instancePath, 0, NULL, 0,
2290 samDesired, NULL, &key, NULL);
2294 key = INVALID_HANDLE_VALUE;
2297 FIXME("INF section installation unsupported\n");
2299 HeapFree(GetProcessHeap(), 0, referencePath);
2300 RegCloseKey(parent);
2304 RegCloseKey(interfacesKey);
2311 /***********************************************************************
2312 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2315 * DeviceInfoSet [I] Set of devices from which to enumerate
2317 * DeviceInfoData [I] (Optional) If specified, a specific device
2318 * instance from which to enumerate interfaces.
2319 * If it isn't specified, all interfaces for all
2320 * devices in the set are enumerated.
2321 * InterfaceClassGuid [I] The interface class to enumerate.
2322 * MemberIndex [I] An index of the interface instance to enumerate.
2323 * A caller should start with MemberIndex set to 0,
2324 * and continue until the function fails with
2325 * ERROR_NO_MORE_ITEMS.
2326 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2327 * member must be set to
2328 * sizeof(SP_DEVICE_INTERFACE_DATA).
2331 * Success: non-zero value.
2332 * Failure: FALSE. Call GetLastError() for more info.
2334 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2335 HDEVINFO DeviceInfoSet,
2336 PSP_DEVINFO_DATA DeviceInfoData,
2337 CONST GUID * InterfaceClassGuid,
2339 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2341 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2344 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2345 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2347 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2348 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2350 SetLastError(ERROR_INVALID_HANDLE);
2353 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2354 !DeviceInfoData->Reserved))
2356 SetLastError(ERROR_INVALID_PARAMETER);
2359 if (!DeviceInterfaceData ||
2360 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2362 SetLastError(ERROR_INVALID_PARAMETER);
2367 struct DeviceInfo *devInfo =
2368 (struct DeviceInfo *)DeviceInfoData->Reserved;
2369 struct InterfaceInstances *iface;
2371 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2373 if (MemberIndex < iface->cInstances)
2374 memcpy(DeviceInterfaceData, &iface->instances[MemberIndex],
2375 sizeof(SP_DEVICE_INTERFACE_DATA));
2378 SetLastError(ERROR_NO_MORE_ITEMS);
2383 SetLastError(ERROR_NO_MORE_ITEMS);
2387 DWORD i, cEnumerated = 0;
2390 for (i = 0; !found && cEnumerated < MemberIndex + 1 &&
2391 i < set->cDevices; i++)
2393 struct DeviceInfo *devInfo =
2394 (struct DeviceInfo *)set->devices[i].Reserved;
2395 struct InterfaceInstances *iface;
2397 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2399 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2400 cEnumerated += iface->cInstances;
2403 DWORD instanceIndex = MemberIndex - cEnumerated;
2405 memcpy(DeviceInterfaceData,
2406 &iface->instances[instanceIndex],
2407 sizeof(SP_DEVICE_INTERFACE_DATA));
2408 cEnumerated += instanceIndex + 1;
2415 SetLastError(ERROR_NO_MORE_ITEMS);
2420 /***********************************************************************
2421 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2423 * Destroy a DeviceInfoList and free all used memory of the list.
2426 * devinfo [I] DeviceInfoList pointer to list to destroy
2429 * Success: non zero value.
2430 * Failure: zero value.
2432 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2436 TRACE("%p\n", devinfo);
2437 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2439 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2441 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2445 for (i = 0; i < list->cDevices; i++)
2446 SETUPDI_FreeDeviceInfo(
2447 (struct DeviceInfo *)list->devices[i].Reserved);
2448 HeapFree(GetProcessHeap(), 0, list->devices);
2449 HeapFree(GetProcessHeap(), 0, list);
2455 SetLastError(ERROR_INVALID_HANDLE);
2460 /***********************************************************************
2461 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2463 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2464 HDEVINFO DeviceInfoSet,
2465 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2466 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2467 DWORD DeviceInterfaceDetailDataSize,
2468 PDWORD RequiredSize,
2469 PSP_DEVINFO_DATA DeviceInfoData)
2471 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2472 struct InterfaceInfo *info;
2473 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)
2477 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2478 DeviceInterfaceData, DeviceInterfaceDetailData,
2479 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2481 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2482 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2484 SetLastError(ERROR_INVALID_HANDLE);
2487 if (!DeviceInterfaceData ||
2488 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2489 !DeviceInterfaceData->Reserved)
2491 SetLastError(ERROR_INVALID_PARAMETER);
2494 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2495 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) ||
2496 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2498 SetLastError(ERROR_INVALID_USER_BUFFER);
2501 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2503 SetLastError(ERROR_INVALID_USER_BUFFER);
2506 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2507 if (info->symbolicLink)
2508 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2509 NULL, 0, NULL, NULL);
2510 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2512 if (info->symbolicLink)
2513 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2514 DeviceInterfaceDetailData->DevicePath,
2515 DeviceInterfaceDetailDataSize -
2516 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2519 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2520 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2521 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2527 *RequiredSize = bytesNeeded;
2528 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2533 /***********************************************************************
2534 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2536 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2537 HDEVINFO DeviceInfoSet,
2538 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2539 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2540 DWORD DeviceInterfaceDetailDataSize,
2541 PDWORD RequiredSize,
2542 PSP_DEVINFO_DATA DeviceInfoData)
2544 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2545 struct InterfaceInfo *info;
2546 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2547 + sizeof(WCHAR); /* include NULL terminator */
2550 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2551 DeviceInterfaceData, DeviceInterfaceDetailData,
2552 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2554 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2555 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2557 SetLastError(ERROR_INVALID_HANDLE);
2560 if (!DeviceInterfaceData ||
2561 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2562 !DeviceInterfaceData->Reserved)
2564 SetLastError(ERROR_INVALID_PARAMETER);
2567 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2568 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2569 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2571 SetLastError(ERROR_INVALID_USER_BUFFER);
2574 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2576 SetLastError(ERROR_INVALID_USER_BUFFER);
2579 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2580 if (info->symbolicLink)
2581 bytesNeeded += lstrlenW(info->symbolicLink);
2582 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2584 if (info->symbolicLink)
2585 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
2587 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2588 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2589 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2595 *RequiredSize = bytesNeeded;
2596 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2601 struct PropertyMapEntry
2608 static struct PropertyMapEntry PropertyMap[] = {
2609 { REG_SZ, "DeviceDesc", DeviceDesc },
2610 { REG_MULTI_SZ, "HardwareId", HardwareId },
2611 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
2612 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
2613 { REG_SZ, "Service", Service },
2614 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
2615 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
2616 { REG_SZ, "Class", Class },
2617 { REG_SZ, "ClassGUID", ClassGUID },
2618 { REG_SZ, "Driver", Driver },
2619 { REG_DWORD, "ConfigFlags", ConfigFlags },
2620 { REG_SZ, "Mfg", Mfg },
2621 { REG_SZ, "FriendlyName", FriendlyName },
2622 { REG_SZ, "LocationInformation", LocationInformation },
2623 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
2624 { REG_DWORD, "Capabilities", Capabilities },
2625 { REG_DWORD, "UINumber", UINumber },
2626 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
2627 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
2630 /***********************************************************************
2631 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2633 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2634 HDEVINFO DeviceInfoSet,
2635 PSP_DEVINFO_DATA DeviceInfoData,
2637 PDWORD PropertyRegDataType,
2638 PBYTE PropertyBuffer,
2639 DWORD PropertyBufferSize,
2640 PDWORD RequiredSize)
2643 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2644 struct DeviceInfo *devInfo;
2646 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2647 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2650 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2652 SetLastError(ERROR_INVALID_HANDLE);
2655 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2657 SetLastError(ERROR_INVALID_HANDLE);
2660 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2661 || !DeviceInfoData->Reserved)
2663 SetLastError(ERROR_INVALID_PARAMETER);
2666 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2667 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2668 && PropertyMap[Property].nameA)
2670 DWORD size = PropertyBufferSize;
2671 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
2672 NULL, PropertyRegDataType, PropertyBuffer, &size);
2675 *RequiredSize = size;
2684 /***********************************************************************
2685 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2687 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2688 HDEVINFO DeviceInfoSet,
2689 PSP_DEVINFO_DATA DeviceInfoData,
2691 PDWORD PropertyRegDataType,
2692 PBYTE PropertyBuffer,
2693 DWORD PropertyBufferSize,
2694 PDWORD RequiredSize)
2697 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2698 struct DeviceInfo *devInfo;
2700 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2701 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2704 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2706 SetLastError(ERROR_INVALID_HANDLE);
2709 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2711 SetLastError(ERROR_INVALID_HANDLE);
2714 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2715 || !DeviceInfoData->Reserved)
2717 SetLastError(ERROR_INVALID_PARAMETER);
2720 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2721 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2722 && PropertyMap[Property].nameW)
2724 DWORD size = PropertyBufferSize;
2725 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2726 NULL, PropertyRegDataType, PropertyBuffer, &size);
2729 *RequiredSize = size;
2738 /***********************************************************************
2739 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2741 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2742 HDEVINFO DeviceInfoSet,
2743 PSP_DEVINFO_DATA DeviceInfoData,
2745 const BYTE *PropertyBuffer,
2746 DWORD PropertyBufferSize)
2749 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2750 struct DeviceInfo *devInfo;
2752 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2753 PropertyBuffer, PropertyBufferSize);
2755 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2757 SetLastError(ERROR_INVALID_HANDLE);
2760 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2762 SetLastError(ERROR_INVALID_HANDLE);
2765 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2766 || !DeviceInfoData->Reserved)
2768 SetLastError(ERROR_INVALID_PARAMETER);
2771 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2772 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2773 && PropertyMap[Property].nameA)
2775 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2776 PropertyMap[Property].regType, PropertyBuffer,
2777 PropertyBufferSize);
2786 /***********************************************************************
2787 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2789 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2790 HDEVINFO DeviceInfoSet,
2791 PSP_DEVINFO_DATA DeviceInfoData,
2793 const BYTE *PropertyBuffer,
2794 DWORD PropertyBufferSize)
2797 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2798 struct DeviceInfo *devInfo;
2800 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2801 PropertyBuffer, PropertyBufferSize);
2803 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2805 SetLastError(ERROR_INVALID_HANDLE);
2808 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2810 SetLastError(ERROR_INVALID_HANDLE);
2813 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2814 || !DeviceInfoData->Reserved)
2816 SetLastError(ERROR_INVALID_PARAMETER);
2819 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2820 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2821 && PropertyMap[Property].nameW)
2823 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
2824 PropertyMap[Property].regType, PropertyBuffer,
2825 PropertyBufferSize);
2834 /***********************************************************************
2835 * SetupDiInstallClassA (SETUPAPI.@)
2837 BOOL WINAPI SetupDiInstallClassA(
2843 UNICODE_STRING FileNameW;
2846 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2848 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2852 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2854 RtlFreeUnicodeString(&FileNameW);
2859 static HKEY CreateClassKey(HINF hInf)
2861 WCHAR FullBuffer[MAX_PATH];
2862 WCHAR Buffer[MAX_PATH];
2866 if (!SetupGetLineTextW(NULL,
2874 return INVALID_HANDLE_VALUE;
2877 lstrcpyW(FullBuffer, ControlClass);
2878 lstrcatW(FullBuffer, Buffer);
2880 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2886 if (!SetupGetLineTextW(NULL,
2894 return INVALID_HANDLE_VALUE;
2897 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2901 REG_OPTION_NON_VOLATILE,
2907 return INVALID_HANDLE_VALUE;
2912 if (RegSetValueExW(hClassKey,
2917 RequiredSize * sizeof(WCHAR)))
2919 RegCloseKey(hClassKey);
2920 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
2922 return INVALID_HANDLE_VALUE;
2928 /***********************************************************************
2929 * SetupDiInstallClassW (SETUPAPI.@)
2931 BOOL WINAPI SetupDiInstallClassW(
2937 WCHAR SectionName[MAX_PATH];
2938 DWORD SectionNameLength = 0;
2940 BOOL bFileQueueCreated = FALSE;
2946 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2948 SetLastError(ERROR_INVALID_PARAMETER);
2952 /* Open the .inf file */
2953 hInf = SetupOpenInfFileW(InfFileName,
2957 if (hInf == INVALID_HANDLE_VALUE)
2963 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2964 hClassKey = CreateClassKey(hInf);
2965 if (hClassKey == INVALID_HANDLE_VALUE)
2967 SetupCloseInfFile(hInf);
2972 /* Try to append a layout file */
2974 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2977 /* Retrieve the actual section name */
2978 SetupDiGetActualSectionToInstallW(hInf,
2986 if (!(Flags & DI_NOVCP))
2988 FileQueue = SetupOpenFileQueue();
2989 if (FileQueue == INVALID_HANDLE_VALUE)
2991 SetupCloseInfFile(hInf);
2995 bFileQueueCreated = TRUE;
3000 SetupInstallFromInfSectionW(NULL,
3009 INVALID_HANDLE_VALUE,
3012 /* FIXME: More code! */
3014 if (bFileQueueCreated)
3015 SetupCloseFileQueue(FileQueue);
3017 SetupCloseInfFile(hInf);
3023 /***********************************************************************
3024 * SetupDiOpenClassRegKey (SETUPAPI.@)
3026 HKEY WINAPI SetupDiOpenClassRegKey(
3027 const GUID* ClassGuid,
3030 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3031 DIOCR_INSTALLER, NULL, NULL);
3035 /***********************************************************************
3036 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3038 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3039 const GUID* ClassGuid,
3045 PWSTR MachineNameW = NULL;
3052 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3053 if (MachineNameW == NULL)
3054 return INVALID_HANDLE_VALUE;
3057 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3058 Flags, MachineNameW, Reserved);
3060 MyFree(MachineNameW);
3066 /***********************************************************************
3067 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3069 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3070 const GUID* ClassGuid,
3081 if (MachineName != NULL)
3083 FIXME("Remote access not supported yet!\n");
3084 return INVALID_HANDLE_VALUE;
3087 if (Flags == DIOCR_INSTALLER)
3089 lpKeyName = ControlClass;
3091 else if (Flags == DIOCR_INTERFACE)
3093 lpKeyName = DeviceClasses;
3097 ERR("Invalid Flags parameter!\n");
3098 SetLastError(ERROR_INVALID_PARAMETER);
3099 return INVALID_HANDLE_VALUE;
3104 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3111 hClassesKey = INVALID_HANDLE_VALUE;
3117 WCHAR bracedGuidString[39];
3119 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3121 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3127 if ((l = RegOpenKeyExW(hClassesKey,
3134 key = INVALID_HANDLE_VALUE;
3136 RegCloseKey(hClassesKey);
3141 key = INVALID_HANDLE_VALUE;
3147 /***********************************************************************
3148 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3150 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3151 HDEVINFO DeviceInfoSet,
3154 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3156 FIXME("%p %s %08x %p\n",
3157 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3161 /***********************************************************************
3162 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3164 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3165 HDEVINFO DeviceInfoSet,
3168 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3170 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3171 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3175 /***********************************************************************
3176 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3178 BOOL WINAPI SetupDiSetClassInstallParamsA(
3179 HDEVINFO DeviceInfoSet,
3180 PSP_DEVINFO_DATA DeviceInfoData,
3181 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3182 DWORD ClassInstallParamsSize)
3184 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3185 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3189 /***********************************************************************
3190 * SetupDiCallClassInstaller (SETUPAPI.@)
3192 BOOL WINAPI SetupDiCallClassInstaller(
3193 DI_FUNCTION InstallFunction,
3194 HDEVINFO DeviceInfoSet,
3195 PSP_DEVINFO_DATA DeviceInfoData)
3197 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3201 /***********************************************************************
3202 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3204 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3205 HDEVINFO DeviceInfoSet,
3206 PSP_DEVINFO_DATA DeviceInfoData,
3207 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3209 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3213 /***********************************************************************
3214 * SetupDiOpenDevRegKey (SETUPAPI.@)
3216 HKEY WINAPI SetupDiOpenDevRegKey(
3217 HDEVINFO DeviceInfoSet,
3218 PSP_DEVINFO_DATA DeviceInfoData,
3224 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3225 Scope, HwProfile, KeyType, samDesired);
3226 return INVALID_HANDLE_VALUE;