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;
343 sizeof(SP_DEVICE_INTERFACE_DATA);
344 memcpy(&instance->InterfaceClassGuid,
345 InterfaceClassGuid, sizeof(GUID));
346 instance->Flags = SPINT_ACTIVE; /* FIXME */
347 instance->Reserved = (ULONG_PTR)ifaceInfo;
349 memcpy(&iface->guid, InterfaceClassGuid,
351 key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set,
352 instance, 0, KEY_WRITE, NULL, NULL);
353 if (key != INVALID_HANDLE_VALUE)
355 RegSetValueExW(key, SymbolicLink, 0, REG_SZ,
356 (BYTE *)ifaceInfo->symbolicLink,
357 lstrlenW(ifaceInfo->symbolicLink) *
362 *ifaceData = instance;
365 HeapFree(GetProcessHeap(), 0, ifaceInfo);
372 *ifaceData = &iface->instances[instanceIndex];
377 TRACE("returning %d\n", ret);
381 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
382 LPCWSTR symbolicLink)
384 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
389 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
390 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
391 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
392 if (info->symbolicLink)
394 lstrcpyW(info->symbolicLink, symbolicLink);
401 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
402 LPCWSTR instanceId, BOOL phantom)
404 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
405 sizeof(struct DeviceInfo));
410 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
411 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
412 if (devInfo->instanceId)
417 devInfo->key = INVALID_HANDLE_VALUE;
418 devInfo->phantom = phantom;
419 lstrcpyW(devInfo->instanceId, instanceId);
420 struprW(devInfo->instanceId);
421 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
422 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
425 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
426 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
428 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
429 (LPBYTE)&phantom, sizeof(phantom));
430 RegCloseKey(enumKey);
432 list_init(&devInfo->interfaces);
436 HeapFree(GetProcessHeap(), 0, devInfo);
443 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
445 struct InterfaceInstances *iface, *next;
447 if (devInfo->key != INVALID_HANDLE_VALUE)
448 RegCloseKey(devInfo->key);
449 if (devInfo->phantom)
454 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
455 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
458 RegDeleteTreeW(enumKey, devInfo->instanceId);
459 RegCloseKey(enumKey);
462 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
463 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
464 struct InterfaceInstances, entry)
466 list_remove(&iface->entry);
467 SETUPDI_FreeInterfaceInstances(iface);
468 HeapFree(GetProcessHeap(), 0, iface);
470 HeapFree(GetProcessHeap(), 0, devInfo);
473 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
474 * struct DeviceInfo, and points the returned device info's Reserved member
475 * to it. "Phantom" devices are deleted from the registry when closed.
476 * Returns a pointer to the newly allocated device info.
478 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
483 SP_DEVINFO_DATA **dev)
486 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, instanceId,
489 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
490 debugstr_w(instanceId), phantom);
495 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
496 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
498 set->devices = HeapAlloc(GetProcessHeap(), 0,
499 sizeof(SP_DEVINFO_DATA));
502 WCHAR classGuidStr[39];
504 *dev = &set->devices[set->cDevices++];
505 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
506 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
507 (*dev)->DevInst = devInst;
508 (*dev)->Reserved = (ULONG_PTR)devInfo;
509 SETUPDI_GuidToString(guid, classGuidStr);
510 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
511 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
512 lstrlenW(classGuidStr) * sizeof(WCHAR));
517 HeapFree(GetProcessHeap(), 0, devInfo);
518 SetLastError(ERROR_OUTOFMEMORY);
524 /***********************************************************************
525 * SetupDiBuildClassInfoList (SETUPAPI.@)
527 * Returns a list of setup class GUIDs that identify the classes
528 * that are installed on a local machine.
531 * Flags [I] control exclusion of classes from the list.
532 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
533 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
534 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
540 BOOL WINAPI SetupDiBuildClassInfoList(
542 LPGUID ClassGuidList,
543 DWORD ClassGuidListSize,
547 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
548 ClassGuidListSize, RequiredSize,
552 /***********************************************************************
553 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
555 * Returns a list of setup class GUIDs that identify the classes
556 * that are installed on a local or remote macine.
559 * Flags [I] control exclusion of classes from the list.
560 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
561 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
562 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
563 * MachineName [I] name of a remote machine.
564 * Reserved [I] must be NULL.
570 BOOL WINAPI SetupDiBuildClassInfoListExA(
572 LPGUID ClassGuidList,
573 DWORD ClassGuidListSize,
578 LPWSTR MachineNameW = NULL;
585 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
586 if (MachineNameW == NULL) return FALSE;
589 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
590 ClassGuidListSize, RequiredSize,
591 MachineNameW, Reserved);
593 MyFree(MachineNameW);
598 /***********************************************************************
599 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
601 * Returns a list of setup class GUIDs that identify the classes
602 * that are installed on a local or remote macine.
605 * Flags [I] control exclusion of classes from the list.
606 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
607 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
608 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
609 * MachineName [I] name of a remote machine.
610 * Reserved [I] must be NULL.
616 BOOL WINAPI SetupDiBuildClassInfoListExW(
618 LPGUID ClassGuidList,
619 DWORD ClassGuidListSize,
630 DWORD dwGuidListIndex = 0;
634 if (RequiredSize != NULL)
637 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
642 if (hClassesKey == INVALID_HANDLE_VALUE)
647 for (dwIndex = 0; ; dwIndex++)
650 lError = RegEnumKeyExW(hClassesKey,
658 TRACE("RegEnumKeyExW() returns %d\n", lError);
659 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
661 TRACE("Key name: %p\n", szKeyName);
663 if (RegOpenKeyExW(hClassesKey,
669 RegCloseKey(hClassesKey);
673 if (!RegQueryValueExW(hClassKey,
680 TRACE("'NoUseClass' value found!\n");
681 RegCloseKey(hClassKey);
685 if ((Flags & DIBCI_NOINSTALLCLASS) &&
686 (!RegQueryValueExW(hClassKey,
693 TRACE("'NoInstallClass' value found!\n");
694 RegCloseKey(hClassKey);
698 if ((Flags & DIBCI_NODISPLAYCLASS) &&
699 (!RegQueryValueExW(hClassKey,
706 TRACE("'NoDisplayClass' value found!\n");
707 RegCloseKey(hClassKey);
711 RegCloseKey(hClassKey);
713 TRACE("Guid: %p\n", szKeyName);
714 if (dwGuidListIndex < ClassGuidListSize)
716 if (szKeyName[0] == '{' && szKeyName[37] == '}')
720 TRACE("Guid: %p\n", &szKeyName[1]);
722 UuidFromStringW(&szKeyName[1],
723 &ClassGuidList[dwGuidListIndex]);
729 if (lError != ERROR_SUCCESS)
733 RegCloseKey(hClassesKey);
735 if (RequiredSize != NULL)
736 *RequiredSize = dwGuidListIndex;
738 if (ClassGuidListSize < dwGuidListIndex)
740 SetLastError(ERROR_INSUFFICIENT_BUFFER);
747 /***********************************************************************
748 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
750 BOOL WINAPI SetupDiClassGuidsFromNameA(
752 LPGUID ClassGuidList,
753 DWORD ClassGuidListSize,
756 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
757 ClassGuidListSize, RequiredSize,
761 /***********************************************************************
762 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
764 BOOL WINAPI SetupDiClassGuidsFromNameW(
766 LPGUID ClassGuidList,
767 DWORD ClassGuidListSize,
770 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
771 ClassGuidListSize, RequiredSize,
775 /***********************************************************************
776 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
778 BOOL WINAPI SetupDiClassGuidsFromNameExA(
780 LPGUID ClassGuidList,
781 DWORD ClassGuidListSize,
786 LPWSTR ClassNameW = NULL;
787 LPWSTR MachineNameW = NULL;
792 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
793 if (ClassNameW == NULL)
798 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
799 if (MachineNameW == NULL)
806 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
807 ClassGuidListSize, RequiredSize,
808 MachineNameW, Reserved);
810 MyFree(MachineNameW);
816 /***********************************************************************
817 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
819 BOOL WINAPI SetupDiClassGuidsFromNameExW(
821 LPGUID ClassGuidList,
822 DWORD ClassGuidListSize,
828 WCHAR szClassName[256];
834 DWORD dwGuidListIndex = 0;
836 if (RequiredSize != NULL)
839 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
844 if (hClassesKey == INVALID_HANDLE_VALUE)
849 for (dwIndex = 0; ; dwIndex++)
852 lError = RegEnumKeyExW(hClassesKey,
860 TRACE("RegEnumKeyExW() returns %d\n", lError);
861 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
863 TRACE("Key name: %p\n", szKeyName);
865 if (RegOpenKeyExW(hClassesKey,
871 RegCloseKey(hClassesKey);
875 dwLength = 256 * sizeof(WCHAR);
876 if (!RegQueryValueExW(hClassKey,
883 TRACE("Class name: %p\n", szClassName);
885 if (strcmpiW(szClassName, ClassName) == 0)
887 TRACE("Found matching class name\n");
889 TRACE("Guid: %p\n", szKeyName);
890 if (dwGuidListIndex < ClassGuidListSize)
892 if (szKeyName[0] == '{' && szKeyName[37] == '}')
896 TRACE("Guid: %p\n", &szKeyName[1]);
898 UuidFromStringW(&szKeyName[1],
899 &ClassGuidList[dwGuidListIndex]);
906 RegCloseKey(hClassKey);
909 if (lError != ERROR_SUCCESS)
913 RegCloseKey(hClassesKey);
915 if (RequiredSize != NULL)
916 *RequiredSize = dwGuidListIndex;
918 if (ClassGuidListSize < dwGuidListIndex)
920 SetLastError(ERROR_INSUFFICIENT_BUFFER);
927 /***********************************************************************
928 * SetupDiClassNameFromGuidA (SETUPAPI.@)
930 BOOL WINAPI SetupDiClassNameFromGuidA(
931 const GUID* ClassGuid,
936 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
937 ClassNameSize, RequiredSize,
941 /***********************************************************************
942 * SetupDiClassNameFromGuidW (SETUPAPI.@)
944 BOOL WINAPI SetupDiClassNameFromGuidW(
945 const GUID* ClassGuid,
950 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
951 ClassNameSize, RequiredSize,
955 /***********************************************************************
956 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
958 BOOL WINAPI SetupDiClassNameFromGuidExA(
959 const GUID* ClassGuid,
966 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
967 LPWSTR MachineNameW = NULL;
971 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
972 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
973 NULL, MachineNameW, Reserved);
976 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
977 ClassNameSize, NULL, NULL);
979 if (!ClassNameSize && RequiredSize)
982 MyFree(MachineNameW);
986 /***********************************************************************
987 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
989 BOOL WINAPI SetupDiClassNameFromGuidExW(
990 const GUID* ClassGuid,
1000 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1005 if (hKey == INVALID_HANDLE_VALUE)
1010 if (RequiredSize != NULL)
1013 if (RegQueryValueExW(hKey,
1024 *RequiredSize = dwLength / sizeof(WCHAR);
1027 dwLength = ClassNameSize * sizeof(WCHAR);
1028 if (RegQueryValueExW(hKey,
1044 /***********************************************************************
1045 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1048 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1051 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1054 /***********************************************************************
1055 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1058 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1063 LPWSTR MachineNameW = NULL;
1070 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1071 if (MachineNameW == NULL)
1072 return (HDEVINFO)INVALID_HANDLE_VALUE;
1075 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1076 MachineNameW, Reserved);
1078 MyFree(MachineNameW);
1083 /***********************************************************************
1084 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1086 * Create an empty DeviceInfoSet list.
1089 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1091 * hwndParent [I] hwnd needed for interface related actions.
1092 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1093 * local registry will be used.
1094 * Reserved [I] must be NULL
1097 * Success: empty list.
1098 * Failure: INVALID_HANDLE_VALUE.
1101 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1106 struct DeviceInfoSet *list = NULL;
1107 DWORD size = sizeof(struct DeviceInfoSet);
1109 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1110 debugstr_w(MachineName), Reserved);
1112 if (MachineName != NULL)
1114 FIXME("remote support is not implemented\n");
1115 SetLastError(ERROR_INVALID_MACHINENAME);
1116 return (HDEVINFO)INVALID_HANDLE_VALUE;
1119 if (Reserved != NULL)
1121 SetLastError(ERROR_INVALID_PARAMETER);
1122 return (HDEVINFO)INVALID_HANDLE_VALUE;
1125 list = HeapAlloc(GetProcessHeap(), 0, size);
1128 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1129 return (HDEVINFO)INVALID_HANDLE_VALUE;
1132 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1133 list->hwndParent = hwndParent;
1134 memcpy(&list->ClassGuid,
1135 ClassGuid ? ClassGuid : &GUID_NULL,
1136 sizeof(list->ClassGuid));
1138 list->devices = NULL;
1140 return (HDEVINFO)list;
1143 /***********************************************************************
1144 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1146 BOOL WINAPI SetupDiCreateDeviceInfoA(
1147 HDEVINFO DeviceInfoSet,
1149 CONST GUID *ClassGuid,
1150 PCSTR DeviceDescription,
1152 DWORD CreationFlags,
1153 PSP_DEVINFO_DATA DeviceInfoData)
1156 LPWSTR DeviceNameW = NULL;
1157 LPWSTR DeviceDescriptionW = NULL;
1161 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1162 if (DeviceNameW == NULL) return FALSE;
1164 if (DeviceDescription)
1166 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1167 if (DeviceDescriptionW == NULL)
1169 MyFree(DeviceNameW);
1174 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1175 hwndParent, CreationFlags, DeviceInfoData);
1177 MyFree(DeviceNameW);
1178 MyFree(DeviceDescriptionW);
1183 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1186 DWORD devNameLen = lstrlenW(devName), devInst = 0;
1189 TRACE("%s\n", debugstr_w(devName));
1190 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1195 devInst |= *ptr - '0';
1201 TRACE("%d\n", valid ? devInst : 0xffffffff);
1202 return valid ? devInst : 0xffffffff;
1205 /***********************************************************************
1206 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1208 BOOL WINAPI SetupDiCreateDeviceInfoW(
1209 HDEVINFO DeviceInfoSet,
1211 CONST GUID *ClassGuid,
1212 PCWSTR DeviceDescription,
1214 DWORD CreationFlags,
1215 PSP_DEVINFO_DATA DeviceInfoData)
1217 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1218 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1219 LPCWSTR instanceId = NULL;
1221 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1222 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1223 hwndParent, CreationFlags, DeviceInfoData);
1227 SetLastError(ERROR_INVALID_DEVINST_NAME);
1230 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1232 SetLastError(ERROR_INVALID_HANDLE);
1237 SetLastError(ERROR_INVALID_PARAMETER);
1240 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1242 SetLastError(ERROR_INVALID_HANDLE);
1245 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1246 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1248 SetLastError(ERROR_CLASS_MISMATCH);
1251 if ((CreationFlags & DICD_GENERATE_ID))
1253 if (strchrW(DeviceName, '\\'))
1254 SetLastError(ERROR_INVALID_DEVINST_NAME);
1257 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1258 '\\','%','0','4','d',0};
1263 DWORD i, highestDevID = 0;
1265 for (i = 0; i < set->cDevices; i++)
1267 struct DeviceInfo *devInfo =
1268 (struct DeviceInfo *)set->devices[i].Reserved;
1269 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1275 devName = devInfo->instanceId;
1276 id = SETUPDI_DevNameToDevID(devName);
1277 if (id != 0xffffffff && id > highestDevID)
1280 devId = highestDevID + 1;
1284 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1285 instanceId = HeapAlloc(GetProcessHeap(), 0,
1286 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1289 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1291 allocatedInstanceId = TRUE;
1303 instanceId = DeviceName;
1304 for (i = 0; ret && i < set->cDevices; i++)
1306 struct DeviceInfo *devInfo =
1307 (struct DeviceInfo *)set->devices[i].Reserved;
1309 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1311 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1318 SP_DEVINFO_DATA *dev = NULL;
1320 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1321 instanceId, TRUE, &dev);
1324 if (DeviceDescription)
1325 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1326 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1327 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1330 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1332 SetLastError(ERROR_INVALID_USER_BUFFER);
1336 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1340 if (allocatedInstanceId)
1341 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1346 /***********************************************************************
1347 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1349 BOOL WINAPI SetupDiRegisterDeviceInfo(
1350 HDEVINFO DeviceInfoSet,
1351 PSP_DEVINFO_DATA DeviceInfoData,
1353 PSP_DETSIG_CMPPROC CompareProc,
1354 PVOID CompareContext,
1355 PSP_DEVINFO_DATA DupDeviceInfoData)
1357 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1358 struct DeviceInfo *devInfo;
1360 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1361 CompareProc, CompareContext, DupDeviceInfoData);
1363 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1365 SetLastError(ERROR_INVALID_HANDLE);
1368 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1370 SetLastError(ERROR_INVALID_HANDLE);
1373 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1374 || !DeviceInfoData->Reserved)
1376 SetLastError(ERROR_INVALID_PARAMETER);
1379 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1380 if (devInfo->set != set)
1382 SetLastError(ERROR_INVALID_PARAMETER);
1385 if (devInfo->phantom)
1387 devInfo->phantom = FALSE;
1388 RegDeleteValueW(devInfo->key, Phantom);
1393 /***********************************************************************
1394 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1396 BOOL WINAPI SetupDiEnumDeviceInfo(
1399 PSP_DEVINFO_DATA info)
1403 TRACE("%p %d %p\n", devinfo, index, info);
1407 SetLastError(ERROR_INVALID_PARAMETER);
1410 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1412 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1413 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1415 if (index < list->cDevices)
1417 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1419 memcpy(info, &list->devices[index], info->cbSize);
1423 SetLastError(ERROR_INVALID_USER_BUFFER);
1426 SetLastError(ERROR_NO_MORE_ITEMS);
1429 SetLastError(ERROR_INVALID_HANDLE);
1432 SetLastError(ERROR_INVALID_HANDLE);
1436 /***********************************************************************
1437 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1439 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1440 HDEVINFO DeviceInfoSet,
1441 PSP_DEVINFO_DATA DeviceInfoData,
1442 PSTR DeviceInstanceId,
1443 DWORD DeviceInstanceIdSize,
1444 PDWORD RequiredSize)
1450 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1451 DeviceInstanceIdSize, RequiredSize);
1453 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1458 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1460 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1463 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1470 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1472 DeviceInstanceIdSize, NULL, NULL);
1478 if (len > DeviceInstanceIdSize)
1480 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1484 *RequiredSize = len;
1487 HeapFree(GetProcessHeap(), 0, instanceId);
1492 /***********************************************************************
1493 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1495 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1496 HDEVINFO DeviceInfoSet,
1497 PSP_DEVINFO_DATA DeviceInfoData,
1498 PWSTR DeviceInstanceId,
1499 DWORD DeviceInstanceIdSize,
1500 PDWORD RequiredSize)
1502 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1503 struct DeviceInfo *devInfo;
1505 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1506 DeviceInstanceIdSize, RequiredSize);
1508 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1510 SetLastError(ERROR_INVALID_HANDLE);
1513 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1515 SetLastError(ERROR_INVALID_HANDLE);
1518 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1519 || !DeviceInfoData->Reserved)
1521 SetLastError(ERROR_INVALID_PARAMETER);
1524 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1525 if (devInfo->set != set)
1527 SetLastError(ERROR_INVALID_PARAMETER);
1530 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1531 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1533 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1535 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1538 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1540 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1544 /***********************************************************************
1545 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1547 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1549 PCSTR InfSectionName,
1550 PSTR InfSectionWithExt,
1551 DWORD InfSectionWithExtSize,
1552 PDWORD RequiredSize,
1559 /***********************************************************************
1560 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1562 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1564 PCWSTR InfSectionName,
1565 PWSTR InfSectionWithExt,
1566 DWORD InfSectionWithExtSize,
1567 PDWORD RequiredSize,
1570 WCHAR szBuffer[MAX_PATH];
1573 LONG lLineCount = -1;
1575 lstrcpyW(szBuffer, InfSectionName);
1576 dwLength = lstrlenW(szBuffer);
1578 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1580 /* Test section name with '.NTx86' extension */
1581 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1582 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1584 if (lLineCount == -1)
1586 /* Test section name with '.NT' extension */
1587 lstrcpyW(&szBuffer[dwLength], NtExtension);
1588 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1593 /* Test section name with '.Win' extension */
1594 lstrcpyW(&szBuffer[dwLength], WinExtension);
1595 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1598 if (lLineCount == -1)
1600 /* Test section name without extension */
1601 szBuffer[dwLength] = 0;
1602 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1605 if (lLineCount == -1)
1607 SetLastError(ERROR_INVALID_PARAMETER);
1611 dwFullLength = lstrlenW(szBuffer);
1613 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1615 if (InfSectionWithExtSize < (dwFullLength + 1))
1617 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1621 lstrcpyW(InfSectionWithExt, szBuffer);
1622 if (Extension != NULL)
1624 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1628 if (RequiredSize != NULL)
1630 *RequiredSize = dwFullLength + 1;
1636 /***********************************************************************
1637 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1639 BOOL WINAPI SetupDiGetClassDescriptionA(
1640 const GUID* ClassGuid,
1641 PSTR ClassDescription,
1642 DWORD ClassDescriptionSize,
1643 PDWORD RequiredSize)
1645 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1646 ClassDescriptionSize,
1647 RequiredSize, NULL, NULL);
1650 /***********************************************************************
1651 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1653 BOOL WINAPI SetupDiGetClassDescriptionW(
1654 const GUID* ClassGuid,
1655 PWSTR ClassDescription,
1656 DWORD ClassDescriptionSize,
1657 PDWORD RequiredSize)
1659 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1660 ClassDescriptionSize,
1661 RequiredSize, NULL, NULL);
1664 /***********************************************************************
1665 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1667 BOOL WINAPI SetupDiGetClassDescriptionExA(
1668 const GUID* ClassGuid,
1669 PSTR ClassDescription,
1670 DWORD ClassDescriptionSize,
1671 PDWORD RequiredSize,
1679 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1684 if (hKey == INVALID_HANDLE_VALUE)
1686 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1690 dwLength = ClassDescriptionSize;
1691 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1692 (LPBYTE)ClassDescription, &dwLength );
1693 if (RequiredSize) *RequiredSize = dwLength;
1698 /***********************************************************************
1699 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1701 BOOL WINAPI SetupDiGetClassDescriptionExW(
1702 const GUID* ClassGuid,
1703 PWSTR ClassDescription,
1704 DWORD ClassDescriptionSize,
1705 PDWORD RequiredSize,
1713 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1718 if (hKey == INVALID_HANDLE_VALUE)
1720 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1724 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1725 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1726 (LPBYTE)ClassDescription, &dwLength );
1727 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1732 /***********************************************************************
1733 * SetupDiGetClassDevsA (SETUPAPI.@)
1735 HDEVINFO WINAPI SetupDiGetClassDevsA(
1742 LPWSTR enumstrW = NULL;
1746 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1747 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1750 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1753 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1755 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
1756 HeapFree(GetProcessHeap(), 0, enumstrW);
1762 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
1763 const GUID *interface)
1766 WCHAR subKeyName[MAX_PATH];
1767 LONG l = ERROR_SUCCESS;
1769 for (i = 0; !l; i++)
1771 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1772 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1776 SP_DEVICE_INTERFACE_DATA *iface = NULL;
1778 /* The subkey name is the reference string, with a '#' prepended */
1779 SETUPDI_AddInterfaceInstance(dev, interface, subKeyName + 1,
1781 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1784 WCHAR symbolicLink[MAX_PATH];
1787 len = sizeof(symbolicLink);
1788 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
1789 (BYTE *)symbolicLink, &len);
1790 if (!l && dataType == REG_SZ)
1791 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
1792 RegCloseKey(subKey);
1796 /* FIXME: find and add all the device's interfaces to the device */
1799 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1800 HKEY key, const GUID *interface, LPCWSTR enumstr)
1802 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1804 WCHAR subKeyName[MAX_PATH];
1806 HKEY enumKey = INVALID_HANDLE_VALUE;
1808 TRACE("%s\n", debugstr_w(enumstr));
1810 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1812 for (i = 0; !l; i++)
1814 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1815 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1820 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1823 WCHAR deviceInst[MAX_PATH * 3];
1826 len = sizeof(deviceInst);
1827 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1828 (BYTE *)deviceInst, &len);
1829 if (!l && dataType == REG_SZ)
1831 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1832 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1836 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1840 WCHAR deviceClassStr[40];
1842 len = sizeof(deviceClassStr);
1843 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1844 &dataType, (BYTE *)deviceClassStr, &len);
1845 if (!l && dataType == REG_SZ &&
1846 deviceClassStr[0] == '{' &&
1847 deviceClassStr[37] == '}')
1850 SP_DEVINFO_DATA *dev;
1852 deviceClassStr[37] = 0;
1853 UuidFromStringW(&deviceClassStr[1],
1855 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
1856 0 /* FIXME: DevInst */, deviceInst,
1858 SETUPDI_AddDeviceInterfaces(dev, subKey,
1861 RegCloseKey(deviceKey);
1865 RegCloseKey(subKey);
1869 if (enumKey != INVALID_HANDLE_VALUE)
1870 RegCloseKey(enumKey);
1873 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1874 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1876 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1877 DIOCR_INTERFACE, NULL, NULL);
1879 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1880 debugstr_w(enumstr), flags);
1882 if (interfacesKey != INVALID_HANDLE_VALUE)
1884 if (flags & DIGCF_ALLCLASSES)
1887 WCHAR interfaceGuidStr[40];
1888 LONG l = ERROR_SUCCESS;
1890 for (i = 0; !l; i++)
1892 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
1893 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
1894 NULL, NULL, NULL, NULL);
1897 if (interfaceGuidStr[0] == '{' &&
1898 interfaceGuidStr[37] == '}')
1903 interfaceGuidStr[37] = 0;
1904 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
1905 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
1906 KEY_READ, &interfaceKey);
1909 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1910 interfaceKey, &interfaceGuid, enumstr);
1911 RegCloseKey(interfaceKey);
1919 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
1920 * interface's key, so just pass that long
1922 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1923 interfacesKey, interface, enumstr);
1925 RegCloseKey(interfacesKey);
1929 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
1930 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
1932 struct DeviceInfoSet *set = (struct DeviceInfoSet *)set;
1934 WCHAR subKeyName[MAX_PATH];
1935 LONG l = ERROR_SUCCESS;
1937 TRACE("%s\n", debugstr_w(parent));
1939 for (i = 0; !l; i++)
1941 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1942 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1947 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1950 WCHAR classGuid[40];
1953 len = sizeof(classGuid);
1954 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
1955 (BYTE *)classGuid, &len);
1956 if (!l && dataType == REG_SZ)
1958 if (classGuid[0] == '{' && classGuid[37] == '}')
1963 UuidFromStringW(&classGuid[1], &deviceClass);
1964 if ((flags & DIGCF_ALLCLASSES) ||
1965 IsEqualGUID(class, &deviceClass))
1967 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
1970 instanceId = HeapAlloc(GetProcessHeap(), 0,
1971 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
1975 SP_DEVINFO_DATA *dev;
1977 sprintfW(instanceId, fmt, parent, subKeyName);
1978 SETUPDI_AddDeviceToSet(set, &deviceClass,
1979 0 /* FIXME: DevInst */, instanceId,
1981 HeapFree(GetProcessHeap(), 0, instanceId);
1986 RegCloseKey(subKey);
1992 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
1993 LPCWSTR enumstr, DWORD flags)
1995 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
1996 DIOCR_INSTALLER, NULL, NULL);
1998 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
1999 debugstr_w(enumstr), flags);
2001 if (classesKey != INVALID_HANDLE_VALUE)
2006 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
2011 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2012 enumKey, class, flags);
2013 RegCloseKey(enumKey);
2019 WCHAR subKeyName[MAX_PATH];
2020 LONG l = ERROR_SUCCESS;
2022 for (i = 0; !l; i++)
2024 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2025 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
2031 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
2035 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2036 subKeyName, subKey, class, flags);
2037 RegCloseKey(subKey);
2042 RegCloseKey(classesKey);
2046 /***********************************************************************
2047 * SetupDiGetClassDevsW (SETUPAPI.@)
2049 HDEVINFO WINAPI SetupDiGetClassDevsW(
2055 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2059 TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
2061 if (!(flags & DIGCF_ALLCLASSES) && !class)
2063 SetLastError(ERROR_INVALID_PARAMETER);
2066 if (flags & unsupportedFlags)
2067 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2068 /* WinXP always succeeds, returns empty list for unknown classes */
2069 set = SetupDiCreateDeviceInfoList(class, parent);
2072 if (flags & DIGCF_DEVICEINTERFACE)
2073 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2075 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2080 /***********************************************************************
2081 * SetupDiGetClassDevsExW (SETUPAPI.@)
2083 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2096 /***********************************************************************
2097 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2099 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2100 HDEVINFO DeviceInfoSet,
2101 PSP_DEVINFO_DATA DeviceInfoData,
2102 const GUID *InterfaceClassGuid,
2103 PCSTR ReferenceString,
2104 DWORD CreationFlags,
2105 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2108 LPWSTR ReferenceStringW = NULL;
2110 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2111 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2112 CreationFlags, DeviceInterfaceData);
2114 if (ReferenceString)
2116 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2117 if (ReferenceStringW == NULL) return FALSE;
2120 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2121 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2122 DeviceInterfaceData);
2124 MyFree(ReferenceStringW);
2129 /***********************************************************************
2130 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2132 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2133 HDEVINFO DeviceInfoSet,
2134 PSP_DEVINFO_DATA DeviceInfoData,
2135 const GUID *InterfaceClassGuid,
2136 PCWSTR ReferenceString,
2137 DWORD CreationFlags,
2138 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2140 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2141 struct DeviceInfo *devInfo;
2142 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2145 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2146 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2147 CreationFlags, DeviceInterfaceData);
2149 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2151 SetLastError(ERROR_INVALID_HANDLE);
2154 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2156 SetLastError(ERROR_INVALID_HANDLE);
2159 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2160 || !DeviceInfoData->Reserved)
2162 SetLastError(ERROR_INVALID_PARAMETER);
2165 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2166 if (devInfo->set != set)
2168 SetLastError(ERROR_INVALID_PARAMETER);
2171 if (!InterfaceClassGuid)
2173 SetLastError(ERROR_INVALID_USER_BUFFER);
2176 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2177 ReferenceString, &iface)))
2179 if (DeviceInterfaceData)
2181 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2183 SetLastError(ERROR_INVALID_USER_BUFFER);
2187 memcpy(DeviceInterfaceData, iface, sizeof(*iface));
2193 /***********************************************************************
2194 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2196 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2197 HDEVINFO DeviceInfoSet,
2198 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2202 PCSTR InfSectionName)
2205 PWSTR InfSectionNameW = NULL;
2207 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2208 samDesired, InfHandle, InfSectionName);
2211 if (!InfSectionName)
2213 SetLastError(ERROR_INVALID_PARAMETER);
2214 return INVALID_HANDLE_VALUE;
2216 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2217 if (!InfSectionNameW)
2218 return INVALID_HANDLE_VALUE;
2220 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2221 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2223 MyFree(InfSectionNameW);
2227 /***********************************************************************
2228 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2230 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2231 HDEVINFO DeviceInfoSet,
2232 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2236 PCWSTR InfSectionName)
2238 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2239 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2242 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2243 samDesired, InfHandle, InfSectionName);
2245 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2246 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2248 SetLastError(ERROR_INVALID_HANDLE);
2249 return INVALID_HANDLE_VALUE;
2251 if (!DeviceInterfaceData ||
2252 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2253 !DeviceInterfaceData->Reserved)
2255 SetLastError(ERROR_INVALID_PARAMETER);
2256 return INVALID_HANDLE_VALUE;
2258 if (InfHandle && !InfSectionName)
2260 SetLastError(ERROR_INVALID_PARAMETER);
2261 return INVALID_HANDLE_VALUE;
2263 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2264 samDesired, NULL, &interfacesKey, NULL)))
2267 WCHAR bracedGuidString[39];
2269 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2271 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2272 samDesired, NULL, &parent, NULL)))
2274 static const WCHAR hash[] = {'#',0};
2275 struct InterfaceInfo *ifaceInfo =
2276 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2277 LPCWSTR instancePath = NULL;
2278 LPWSTR referencePath = NULL;
2280 if (ifaceInfo->referenceString)
2282 referencePath = HeapAlloc(GetProcessHeap(), 0,
2283 (lstrlenW(ifaceInfo->referenceString) + 2) *
2287 lstrcpyW(referencePath, hash);
2288 lstrcatW(referencePath, ifaceInfo->referenceString);
2289 instancePath = referencePath;
2292 SetLastError(ERROR_OUTOFMEMORY);
2295 instancePath = hash;
2300 l = RegCreateKeyExW(parent, instancePath, 0, NULL, 0,
2301 samDesired, NULL, &key, NULL);
2305 key = INVALID_HANDLE_VALUE;
2308 FIXME("INF section installation unsupported\n");
2310 HeapFree(GetProcessHeap(), 0, referencePath);
2311 RegCloseKey(parent);
2315 RegCloseKey(interfacesKey);
2322 /***********************************************************************
2323 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2326 * DeviceInfoSet [I] Set of devices from which to enumerate
2328 * DeviceInfoData [I] (Optional) If specified, a specific device
2329 * instance from which to enumerate interfaces.
2330 * If it isn't specified, all interfaces for all
2331 * devices in the set are enumerated.
2332 * InterfaceClassGuid [I] The interface class to enumerate.
2333 * MemberIndex [I] An index of the interface instance to enumerate.
2334 * A caller should start with MemberIndex set to 0,
2335 * and continue until the function fails with
2336 * ERROR_NO_MORE_ITEMS.
2337 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2338 * member must be set to
2339 * sizeof(SP_DEVICE_INTERFACE_DATA).
2342 * Success: non-zero value.
2343 * Failure: FALSE. Call GetLastError() for more info.
2345 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2346 HDEVINFO DeviceInfoSet,
2347 PSP_DEVINFO_DATA DeviceInfoData,
2348 CONST GUID * InterfaceClassGuid,
2350 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2352 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2355 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2356 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2358 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2359 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2361 SetLastError(ERROR_INVALID_HANDLE);
2364 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2365 !DeviceInfoData->Reserved))
2367 SetLastError(ERROR_INVALID_PARAMETER);
2370 if (!DeviceInterfaceData ||
2371 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2373 SetLastError(ERROR_INVALID_PARAMETER);
2378 struct DeviceInfo *devInfo =
2379 (struct DeviceInfo *)DeviceInfoData->Reserved;
2380 struct InterfaceInstances *iface;
2382 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2384 if (MemberIndex < iface->cInstances)
2385 memcpy(DeviceInterfaceData, &iface->instances[MemberIndex],
2386 sizeof(SP_DEVICE_INTERFACE_DATA));
2389 SetLastError(ERROR_NO_MORE_ITEMS);
2394 SetLastError(ERROR_NO_MORE_ITEMS);
2398 DWORD i, cEnumerated = 0;
2401 for (i = 0; !found && cEnumerated < MemberIndex + 1 &&
2402 i < set->cDevices; i++)
2404 struct DeviceInfo *devInfo =
2405 (struct DeviceInfo *)set->devices[i].Reserved;
2406 struct InterfaceInstances *iface;
2408 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2410 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2411 cEnumerated += iface->cInstances;
2414 DWORD instanceIndex = MemberIndex - cEnumerated;
2416 memcpy(DeviceInterfaceData,
2417 &iface->instances[instanceIndex],
2418 sizeof(SP_DEVICE_INTERFACE_DATA));
2419 cEnumerated += instanceIndex + 1;
2426 SetLastError(ERROR_NO_MORE_ITEMS);
2431 /***********************************************************************
2432 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2434 * Destroy a DeviceInfoList and free all used memory of the list.
2437 * devinfo [I] DeviceInfoList pointer to list to destroy
2440 * Success: non zero value.
2441 * Failure: zero value.
2443 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2447 TRACE("%p\n", devinfo);
2448 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2450 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2452 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2456 for (i = 0; i < list->cDevices; i++)
2457 SETUPDI_FreeDeviceInfo(
2458 (struct DeviceInfo *)list->devices[i].Reserved);
2459 HeapFree(GetProcessHeap(), 0, list->devices);
2460 HeapFree(GetProcessHeap(), 0, list);
2466 SetLastError(ERROR_INVALID_HANDLE);
2471 /***********************************************************************
2472 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2474 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2475 HDEVINFO DeviceInfoSet,
2476 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2477 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2478 DWORD DeviceInterfaceDetailDataSize,
2479 PDWORD RequiredSize,
2480 PSP_DEVINFO_DATA DeviceInfoData)
2482 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2483 struct InterfaceInfo *info;
2484 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)
2488 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2489 DeviceInterfaceData, DeviceInterfaceDetailData,
2490 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2492 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2493 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2495 SetLastError(ERROR_INVALID_HANDLE);
2498 if (!DeviceInterfaceData ||
2499 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2500 !DeviceInterfaceData->Reserved)
2502 SetLastError(ERROR_INVALID_PARAMETER);
2505 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2506 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) ||
2507 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2509 SetLastError(ERROR_INVALID_USER_BUFFER);
2512 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2514 SetLastError(ERROR_INVALID_USER_BUFFER);
2517 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2518 if (info->symbolicLink)
2519 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2520 NULL, 0, NULL, NULL);
2521 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2523 if (info->symbolicLink)
2524 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2525 DeviceInterfaceDetailData->DevicePath,
2526 DeviceInterfaceDetailDataSize -
2527 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2530 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2531 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2532 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2538 *RequiredSize = bytesNeeded;
2539 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2544 /***********************************************************************
2545 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2547 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2548 HDEVINFO DeviceInfoSet,
2549 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2550 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2551 DWORD DeviceInterfaceDetailDataSize,
2552 PDWORD RequiredSize,
2553 PSP_DEVINFO_DATA DeviceInfoData)
2555 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2556 struct InterfaceInfo *info;
2557 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2558 + sizeof(WCHAR); /* include NULL terminator */
2561 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2562 DeviceInterfaceData, DeviceInterfaceDetailData,
2563 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2565 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2566 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2568 SetLastError(ERROR_INVALID_HANDLE);
2571 if (!DeviceInterfaceData ||
2572 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2573 !DeviceInterfaceData->Reserved)
2575 SetLastError(ERROR_INVALID_PARAMETER);
2578 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2579 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2580 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2582 SetLastError(ERROR_INVALID_USER_BUFFER);
2585 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2587 SetLastError(ERROR_INVALID_USER_BUFFER);
2590 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2591 if (info->symbolicLink)
2592 bytesNeeded += lstrlenW(info->symbolicLink);
2593 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2595 if (info->symbolicLink)
2596 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
2598 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2599 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2600 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2606 *RequiredSize = bytesNeeded;
2607 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2612 struct PropertyMapEntry
2619 static struct PropertyMapEntry PropertyMap[] = {
2620 { REG_SZ, "DeviceDesc", DeviceDesc },
2621 { REG_MULTI_SZ, "HardwareId", HardwareId },
2622 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
2623 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
2624 { REG_SZ, "Service", Service },
2625 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
2626 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
2627 { REG_SZ, "Class", Class },
2628 { REG_SZ, "ClassGUID", ClassGUID },
2629 { REG_SZ, "Driver", Driver },
2630 { REG_DWORD, "ConfigFlags", ConfigFlags },
2631 { REG_SZ, "Mfg", Mfg },
2632 { REG_SZ, "FriendlyName", FriendlyName },
2633 { REG_SZ, "LocationInformation", LocationInformation },
2634 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
2635 { REG_DWORD, "Capabilities", Capabilities },
2636 { REG_DWORD, "UINumber", UINumber },
2637 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
2638 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
2641 /***********************************************************************
2642 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2644 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2645 HDEVINFO DeviceInfoSet,
2646 PSP_DEVINFO_DATA DeviceInfoData,
2648 PDWORD PropertyRegDataType,
2649 PBYTE PropertyBuffer,
2650 DWORD PropertyBufferSize,
2651 PDWORD RequiredSize)
2654 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2655 struct DeviceInfo *devInfo;
2657 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2658 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2661 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2663 SetLastError(ERROR_INVALID_HANDLE);
2666 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2668 SetLastError(ERROR_INVALID_HANDLE);
2671 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2672 || !DeviceInfoData->Reserved)
2674 SetLastError(ERROR_INVALID_PARAMETER);
2677 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2678 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2679 && PropertyMap[Property].nameA)
2681 DWORD size = PropertyBufferSize;
2682 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
2683 NULL, PropertyRegDataType, PropertyBuffer, &size);
2686 *RequiredSize = size;
2695 /***********************************************************************
2696 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2698 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2699 HDEVINFO DeviceInfoSet,
2700 PSP_DEVINFO_DATA DeviceInfoData,
2702 PDWORD PropertyRegDataType,
2703 PBYTE PropertyBuffer,
2704 DWORD PropertyBufferSize,
2705 PDWORD RequiredSize)
2708 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2709 struct DeviceInfo *devInfo;
2711 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2712 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2715 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2717 SetLastError(ERROR_INVALID_HANDLE);
2720 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2722 SetLastError(ERROR_INVALID_HANDLE);
2725 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2726 || !DeviceInfoData->Reserved)
2728 SetLastError(ERROR_INVALID_PARAMETER);
2731 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2732 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2733 && PropertyMap[Property].nameW)
2735 DWORD size = PropertyBufferSize;
2736 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2737 NULL, PropertyRegDataType, PropertyBuffer, &size);
2740 *RequiredSize = size;
2749 /***********************************************************************
2750 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2752 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2753 HDEVINFO DeviceInfoSet,
2754 PSP_DEVINFO_DATA DeviceInfoData,
2756 const BYTE *PropertyBuffer,
2757 DWORD PropertyBufferSize)
2760 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2761 struct DeviceInfo *devInfo;
2763 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2764 PropertyBuffer, PropertyBufferSize);
2766 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2768 SetLastError(ERROR_INVALID_HANDLE);
2771 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2773 SetLastError(ERROR_INVALID_HANDLE);
2776 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2777 || !DeviceInfoData->Reserved)
2779 SetLastError(ERROR_INVALID_PARAMETER);
2782 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2783 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2784 && PropertyMap[Property].nameA)
2786 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2787 PropertyMap[Property].regType, PropertyBuffer,
2788 PropertyBufferSize);
2797 /***********************************************************************
2798 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2800 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2801 HDEVINFO DeviceInfoSet,
2802 PSP_DEVINFO_DATA DeviceInfoData,
2804 const BYTE *PropertyBuffer,
2805 DWORD PropertyBufferSize)
2808 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2809 struct DeviceInfo *devInfo;
2811 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2812 PropertyBuffer, PropertyBufferSize);
2814 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2816 SetLastError(ERROR_INVALID_HANDLE);
2819 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2821 SetLastError(ERROR_INVALID_HANDLE);
2824 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2825 || !DeviceInfoData->Reserved)
2827 SetLastError(ERROR_INVALID_PARAMETER);
2830 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2831 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2832 && PropertyMap[Property].nameW)
2834 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
2835 PropertyMap[Property].regType, PropertyBuffer,
2836 PropertyBufferSize);
2845 /***********************************************************************
2846 * SetupDiInstallClassA (SETUPAPI.@)
2848 BOOL WINAPI SetupDiInstallClassA(
2854 UNICODE_STRING FileNameW;
2857 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2859 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2863 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2865 RtlFreeUnicodeString(&FileNameW);
2870 static HKEY CreateClassKey(HINF hInf)
2872 WCHAR FullBuffer[MAX_PATH];
2873 WCHAR Buffer[MAX_PATH];
2877 if (!SetupGetLineTextW(NULL,
2885 return INVALID_HANDLE_VALUE;
2888 lstrcpyW(FullBuffer, ControlClass);
2889 lstrcatW(FullBuffer, Buffer);
2891 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2897 if (!SetupGetLineTextW(NULL,
2905 return INVALID_HANDLE_VALUE;
2908 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2912 REG_OPTION_NON_VOLATILE,
2918 return INVALID_HANDLE_VALUE;
2923 if (RegSetValueExW(hClassKey,
2928 RequiredSize * sizeof(WCHAR)))
2930 RegCloseKey(hClassKey);
2931 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
2933 return INVALID_HANDLE_VALUE;
2939 /***********************************************************************
2940 * SetupDiInstallClassW (SETUPAPI.@)
2942 BOOL WINAPI SetupDiInstallClassW(
2948 WCHAR SectionName[MAX_PATH];
2949 DWORD SectionNameLength = 0;
2951 BOOL bFileQueueCreated = FALSE;
2957 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2959 SetLastError(ERROR_INVALID_PARAMETER);
2963 /* Open the .inf file */
2964 hInf = SetupOpenInfFileW(InfFileName,
2968 if (hInf == INVALID_HANDLE_VALUE)
2974 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2975 hClassKey = CreateClassKey(hInf);
2976 if (hClassKey == INVALID_HANDLE_VALUE)
2978 SetupCloseInfFile(hInf);
2983 /* Try to append a layout file */
2985 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2988 /* Retrieve the actual section name */
2989 SetupDiGetActualSectionToInstallW(hInf,
2997 if (!(Flags & DI_NOVCP))
2999 FileQueue = SetupOpenFileQueue();
3000 if (FileQueue == INVALID_HANDLE_VALUE)
3002 SetupCloseInfFile(hInf);
3006 bFileQueueCreated = TRUE;
3011 SetupInstallFromInfSectionW(NULL,
3020 INVALID_HANDLE_VALUE,
3023 /* FIXME: More code! */
3025 if (bFileQueueCreated)
3026 SetupCloseFileQueue(FileQueue);
3028 SetupCloseInfFile(hInf);
3034 /***********************************************************************
3035 * SetupDiOpenClassRegKey (SETUPAPI.@)
3037 HKEY WINAPI SetupDiOpenClassRegKey(
3038 const GUID* ClassGuid,
3041 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3042 DIOCR_INSTALLER, NULL, NULL);
3046 /***********************************************************************
3047 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3049 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3050 const GUID* ClassGuid,
3056 PWSTR MachineNameW = NULL;
3063 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3064 if (MachineNameW == NULL)
3065 return INVALID_HANDLE_VALUE;
3068 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3069 Flags, MachineNameW, Reserved);
3071 MyFree(MachineNameW);
3077 /***********************************************************************
3078 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3080 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3081 const GUID* ClassGuid,
3092 if (MachineName != NULL)
3094 FIXME("Remote access not supported yet!\n");
3095 return INVALID_HANDLE_VALUE;
3098 if (Flags == DIOCR_INSTALLER)
3100 lpKeyName = ControlClass;
3102 else if (Flags == DIOCR_INTERFACE)
3104 lpKeyName = DeviceClasses;
3108 ERR("Invalid Flags parameter!\n");
3109 SetLastError(ERROR_INVALID_PARAMETER);
3110 return INVALID_HANDLE_VALUE;
3115 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3122 hClassesKey = INVALID_HANDLE_VALUE;
3128 WCHAR bracedGuidString[39];
3130 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3132 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3138 if ((l = RegOpenKeyExW(hClassesKey,
3145 key = INVALID_HANDLE_VALUE;
3147 RegCloseKey(hClassesKey);
3152 key = INVALID_HANDLE_VALUE;
3158 /***********************************************************************
3159 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3161 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3162 HDEVINFO DeviceInfoSet,
3165 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3167 FIXME("%p %s %08x %p\n",
3168 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3172 /***********************************************************************
3173 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3175 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3176 HDEVINFO DeviceInfoSet,
3179 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3181 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3182 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3186 /***********************************************************************
3187 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3189 BOOL WINAPI SetupDiSetClassInstallParamsA(
3190 HDEVINFO DeviceInfoSet,
3191 PSP_DEVINFO_DATA DeviceInfoData,
3192 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3193 DWORD ClassInstallParamsSize)
3195 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3196 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3200 /***********************************************************************
3201 * SetupDiCallClassInstaller (SETUPAPI.@)
3203 BOOL WINAPI SetupDiCallClassInstaller(
3204 DI_FUNCTION InstallFunction,
3205 HDEVINFO DeviceInfoSet,
3206 PSP_DEVINFO_DATA DeviceInfoData)
3208 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3212 /***********************************************************************
3213 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3215 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3216 HDEVINFO DeviceInfoSet,
3217 PSP_DEVINFO_DATA DeviceInfoData,
3218 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3220 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3224 /***********************************************************************
3225 * SetupDiOpenDevRegKey (SETUPAPI.@)
3227 HKEY WINAPI SetupDiOpenDevRegKey(
3228 HDEVINFO DeviceInfoSet,
3229 PSP_DEVINFO_DATA DeviceInfoData,
3235 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3236 Scope, HwProfile, KeyType, samDesired);
3237 return INVALID_HANDLE_VALUE;