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 if (ifaceInfo->device && ifaceInfo->device->Reserved)
157 struct DeviceInfo *devInfo =
158 (struct DeviceInfo *)ifaceInfo->device->Reserved;
160 if (devInfo->phantom)
161 SetupDiDeleteDeviceInterfaceRegKey(devInfo->set,
162 &instances->instances[i], 0);
164 HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
165 HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
167 HeapFree(GetProcessHeap(), 0, instances->instances);
170 /* Finds the interface with interface class InterfaceClassGuid in the device.
171 * Returns TRUE if found, and updates *interface to point to device's
172 * interfaces member where the given interface was found.
173 * Returns FALSE if not found.
175 static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
176 const GUID *InterfaceClassGuid, struct InterfaceInstances **interface)
179 struct InterfaceInstances *iface;
181 TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
183 LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances,
186 if (IsEqualGUID(&iface->guid, InterfaceClassGuid))
193 TRACE("returning %d (%p)\n", found, found ? *interface : NULL);
197 /* Finds the interface instance with reference string ReferenceString in the
198 * interface instance map. Returns TRUE if found, and updates instanceIndex to
199 * the index of the interface instance's instances member
200 * where the given instance was found. Returns FALSE if not found.
202 static BOOL SETUPDI_FindInterfaceInstance(
203 const struct InterfaceInstances *instances,
204 LPCWSTR ReferenceString, DWORD *instanceIndex)
209 TRACE("%s\n", debugstr_w(ReferenceString));
211 for (i = 0; !found && i < instances->cInstances; i++)
213 SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
214 struct InterfaceInfo *ifaceInfo =
215 (struct InterfaceInfo *)ifaceData->Reserved;
217 if (!ReferenceString && !ifaceInfo->referenceString)
222 else if (ReferenceString && ifaceInfo->referenceString &&
223 !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
229 TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
233 static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
234 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
236 static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
241 SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
242 /* omit length of format specifiers, but include NULL terminator: */
243 len = lstrlenW(fmt) - 4 + 1;
244 len += lstrlenW(instanceId) + lstrlenW(guidStr);
247 /* space for a hash between string and reference string: */
248 len += lstrlenW(ReferenceString) + 1;
250 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
253 int printed = sprintfW(ret, fmt, instanceId, guidStr);
256 /* replace '\\' with '#' after the "\\\\?\\" beginning */
257 for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
261 ret[printed - 1] = '\\';
262 lstrcpyW(ret + printed, ReferenceString);
268 /* Adds an interface with the given interface class and reference string to
269 * the device, if it doesn't already exist in the device. If iface is not
270 * NULL, returns a pointer to the newly added (or already existing) interface.
272 static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData,
273 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
274 SP_DEVICE_INTERFACE_DATA **ifaceData)
276 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
277 BOOL newInterface = FALSE, ret;
278 struct InterfaceInstances *iface = NULL;
280 TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
281 debugstr_w(ReferenceString), iface);
283 if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
285 iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
286 sizeof(struct InterfaceInstances));
289 list_add_tail(&devInfo->interfaces, &iface->entry);
295 DWORD instanceIndex = 0;
297 if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
300 SP_DEVICE_INTERFACE_DATA *instance = NULL;
302 if (!iface->cInstancesAllocated)
304 iface->instances = HeapAlloc(GetProcessHeap(), 0,
305 sizeof(SP_DEVICE_INTERFACE_DATA));
306 if (iface->instances)
307 instance = &iface->instances[iface->cInstancesAllocated++];
309 else if (iface->cInstances == iface->cInstancesAllocated)
311 iface->instances = HeapReAlloc(GetProcessHeap(), 0,
313 (iface->cInstancesAllocated + 1) *
314 sizeof(SP_DEVICE_INTERFACE_DATA));
315 if (iface->instances)
316 instance = &iface->instances[iface->cInstancesAllocated++];
319 instance = &iface->instances[iface->cInstances];
322 struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
323 0, sizeof(struct InterfaceInfo));
328 ifaceInfo->device = DeviceInfoData;
329 ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
330 devInfo->instanceId, InterfaceClassGuid,
334 ifaceInfo->referenceString =
335 HeapAlloc(GetProcessHeap(), 0,
336 (lstrlenW(ReferenceString) + 1) *
338 if (ifaceInfo->referenceString)
339 lstrcpyW(ifaceInfo->referenceString,
345 ifaceInfo->referenceString = NULL;
352 sizeof(SP_DEVICE_INTERFACE_DATA);
353 memcpy(&instance->InterfaceClassGuid,
354 InterfaceClassGuid, sizeof(GUID));
355 instance->Flags = SPINT_ACTIVE; /* FIXME */
356 instance->Reserved = (ULONG_PTR)ifaceInfo;
358 memcpy(&iface->guid, InterfaceClassGuid,
360 key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set,
361 instance, 0, KEY_WRITE, NULL, NULL);
362 if (key != INVALID_HANDLE_VALUE)
364 RegSetValueExW(key, SymbolicLink, 0, REG_SZ,
365 (BYTE *)ifaceInfo->symbolicLink,
366 lstrlenW(ifaceInfo->symbolicLink) *
371 *ifaceData = instance;
374 HeapFree(GetProcessHeap(), 0, ifaceInfo);
381 *ifaceData = &iface->instances[instanceIndex];
386 TRACE("returning %d\n", ret);
390 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
391 LPCWSTR symbolicLink)
393 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
398 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
399 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
400 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
401 if (info->symbolicLink)
403 lstrcpyW(info->symbolicLink, symbolicLink);
410 static HKEY SETUPDI_CreateDevKey(struct DeviceInfo *devInfo)
412 HKEY enumKey, key = INVALID_HANDLE_VALUE;
415 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
416 NULL, &enumKey, NULL);
419 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
420 KEY_READ | KEY_WRITE, NULL, &key, NULL);
421 RegCloseKey(enumKey);
426 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
427 LPCWSTR instanceId, BOOL phantom)
429 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
430 sizeof(struct DeviceInfo));
435 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
436 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
437 if (devInfo->instanceId)
439 devInfo->key = INVALID_HANDLE_VALUE;
440 devInfo->phantom = phantom;
441 lstrcpyW(devInfo->instanceId, instanceId);
442 struprW(devInfo->instanceId);
443 devInfo->key = SETUPDI_CreateDevKey(devInfo);
444 if (devInfo->key != INVALID_HANDLE_VALUE)
447 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
448 (LPBYTE)&phantom, sizeof(phantom));
450 list_init(&devInfo->interfaces);
454 HeapFree(GetProcessHeap(), 0, devInfo);
461 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
463 struct InterfaceInstances *iface, *next;
465 if (devInfo->key != INVALID_HANDLE_VALUE)
466 RegCloseKey(devInfo->key);
467 if (devInfo->phantom)
472 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
473 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
476 RegDeleteTreeW(enumKey, devInfo->instanceId);
477 RegCloseKey(enumKey);
480 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
481 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
482 struct InterfaceInstances, entry)
484 list_remove(&iface->entry);
485 SETUPDI_FreeInterfaceInstances(iface);
486 HeapFree(GetProcessHeap(), 0, iface);
488 HeapFree(GetProcessHeap(), 0, devInfo);
491 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
492 * struct DeviceInfo, and points the returned device info's Reserved member
493 * to it. "Phantom" devices are deleted from the registry when closed.
494 * Returns a pointer to the newly allocated device info.
496 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
501 SP_DEVINFO_DATA **dev)
504 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, instanceId,
507 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
508 debugstr_w(instanceId), phantom);
513 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
514 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
516 set->devices = HeapAlloc(GetProcessHeap(), 0,
517 sizeof(SP_DEVINFO_DATA));
520 WCHAR classGuidStr[39];
522 *dev = &set->devices[set->cDevices++];
523 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
524 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
525 (*dev)->DevInst = devInst;
526 (*dev)->Reserved = (ULONG_PTR)devInfo;
527 SETUPDI_GuidToString(guid, classGuidStr);
528 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
529 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
530 lstrlenW(classGuidStr) * sizeof(WCHAR));
535 HeapFree(GetProcessHeap(), 0, devInfo);
536 SetLastError(ERROR_OUTOFMEMORY);
542 /***********************************************************************
543 * SetupDiBuildClassInfoList (SETUPAPI.@)
545 * Returns a list of setup class GUIDs that identify the classes
546 * that are installed on a local machine.
549 * Flags [I] control exclusion of classes from the list.
550 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
551 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
552 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
558 BOOL WINAPI SetupDiBuildClassInfoList(
560 LPGUID ClassGuidList,
561 DWORD ClassGuidListSize,
565 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
566 ClassGuidListSize, RequiredSize,
570 /***********************************************************************
571 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
573 * Returns a list of setup class GUIDs that identify the classes
574 * that are installed on a local or remote macine.
577 * Flags [I] control exclusion of classes from the list.
578 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
579 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
580 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
581 * MachineName [I] name of a remote machine.
582 * Reserved [I] must be NULL.
588 BOOL WINAPI SetupDiBuildClassInfoListExA(
590 LPGUID ClassGuidList,
591 DWORD ClassGuidListSize,
596 LPWSTR MachineNameW = NULL;
603 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
604 if (MachineNameW == NULL) return FALSE;
607 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
608 ClassGuidListSize, RequiredSize,
609 MachineNameW, Reserved);
611 MyFree(MachineNameW);
616 /***********************************************************************
617 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
619 * Returns a list of setup class GUIDs that identify the classes
620 * that are installed on a local or remote macine.
623 * Flags [I] control exclusion of classes from the list.
624 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
625 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
626 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
627 * MachineName [I] name of a remote machine.
628 * Reserved [I] must be NULL.
634 BOOL WINAPI SetupDiBuildClassInfoListExW(
636 LPGUID ClassGuidList,
637 DWORD ClassGuidListSize,
648 DWORD dwGuidListIndex = 0;
652 if (RequiredSize != NULL)
655 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
660 if (hClassesKey == INVALID_HANDLE_VALUE)
665 for (dwIndex = 0; ; dwIndex++)
668 lError = RegEnumKeyExW(hClassesKey,
676 TRACE("RegEnumKeyExW() returns %d\n", lError);
677 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
679 TRACE("Key name: %p\n", szKeyName);
681 if (RegOpenKeyExW(hClassesKey,
687 RegCloseKey(hClassesKey);
691 if (!RegQueryValueExW(hClassKey,
698 TRACE("'NoUseClass' value found!\n");
699 RegCloseKey(hClassKey);
703 if ((Flags & DIBCI_NOINSTALLCLASS) &&
704 (!RegQueryValueExW(hClassKey,
711 TRACE("'NoInstallClass' value found!\n");
712 RegCloseKey(hClassKey);
716 if ((Flags & DIBCI_NODISPLAYCLASS) &&
717 (!RegQueryValueExW(hClassKey,
724 TRACE("'NoDisplayClass' value found!\n");
725 RegCloseKey(hClassKey);
729 RegCloseKey(hClassKey);
731 TRACE("Guid: %p\n", szKeyName);
732 if (dwGuidListIndex < ClassGuidListSize)
734 if (szKeyName[0] == '{' && szKeyName[37] == '}')
738 TRACE("Guid: %p\n", &szKeyName[1]);
740 UuidFromStringW(&szKeyName[1],
741 &ClassGuidList[dwGuidListIndex]);
747 if (lError != ERROR_SUCCESS)
751 RegCloseKey(hClassesKey);
753 if (RequiredSize != NULL)
754 *RequiredSize = dwGuidListIndex;
756 if (ClassGuidListSize < dwGuidListIndex)
758 SetLastError(ERROR_INSUFFICIENT_BUFFER);
765 /***********************************************************************
766 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
768 BOOL WINAPI SetupDiClassGuidsFromNameA(
770 LPGUID ClassGuidList,
771 DWORD ClassGuidListSize,
774 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
775 ClassGuidListSize, RequiredSize,
779 /***********************************************************************
780 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
782 BOOL WINAPI SetupDiClassGuidsFromNameW(
784 LPGUID ClassGuidList,
785 DWORD ClassGuidListSize,
788 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
789 ClassGuidListSize, RequiredSize,
793 /***********************************************************************
794 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
796 BOOL WINAPI SetupDiClassGuidsFromNameExA(
798 LPGUID ClassGuidList,
799 DWORD ClassGuidListSize,
804 LPWSTR ClassNameW = NULL;
805 LPWSTR MachineNameW = NULL;
808 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
809 if (ClassNameW == NULL)
814 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
815 if (MachineNameW == NULL)
822 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
823 ClassGuidListSize, RequiredSize,
824 MachineNameW, Reserved);
826 MyFree(MachineNameW);
832 /***********************************************************************
833 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
835 BOOL WINAPI SetupDiClassGuidsFromNameExW(
837 LPGUID ClassGuidList,
838 DWORD ClassGuidListSize,
844 WCHAR szClassName[256];
850 DWORD dwGuidListIndex = 0;
852 if (RequiredSize != NULL)
855 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
860 if (hClassesKey == INVALID_HANDLE_VALUE)
865 for (dwIndex = 0; ; dwIndex++)
868 lError = RegEnumKeyExW(hClassesKey,
876 TRACE("RegEnumKeyExW() returns %d\n", lError);
877 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
879 TRACE("Key name: %p\n", szKeyName);
881 if (RegOpenKeyExW(hClassesKey,
887 RegCloseKey(hClassesKey);
891 dwLength = 256 * sizeof(WCHAR);
892 if (!RegQueryValueExW(hClassKey,
899 TRACE("Class name: %p\n", szClassName);
901 if (strcmpiW(szClassName, ClassName) == 0)
903 TRACE("Found matching class name\n");
905 TRACE("Guid: %p\n", szKeyName);
906 if (dwGuidListIndex < ClassGuidListSize)
908 if (szKeyName[0] == '{' && szKeyName[37] == '}')
912 TRACE("Guid: %p\n", &szKeyName[1]);
914 UuidFromStringW(&szKeyName[1],
915 &ClassGuidList[dwGuidListIndex]);
922 RegCloseKey(hClassKey);
925 if (lError != ERROR_SUCCESS)
929 RegCloseKey(hClassesKey);
931 if (RequiredSize != NULL)
932 *RequiredSize = dwGuidListIndex;
934 if (ClassGuidListSize < dwGuidListIndex)
936 SetLastError(ERROR_INSUFFICIENT_BUFFER);
943 /***********************************************************************
944 * SetupDiClassNameFromGuidA (SETUPAPI.@)
946 BOOL WINAPI SetupDiClassNameFromGuidA(
947 const GUID* ClassGuid,
952 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
953 ClassNameSize, RequiredSize,
957 /***********************************************************************
958 * SetupDiClassNameFromGuidW (SETUPAPI.@)
960 BOOL WINAPI SetupDiClassNameFromGuidW(
961 const GUID* ClassGuid,
966 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
967 ClassNameSize, RequiredSize,
971 /***********************************************************************
972 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
974 BOOL WINAPI SetupDiClassNameFromGuidExA(
975 const GUID* ClassGuid,
982 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
983 LPWSTR MachineNameW = NULL;
987 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
988 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
989 NULL, MachineNameW, Reserved);
992 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
993 ClassNameSize, NULL, NULL);
995 if (!ClassNameSize && RequiredSize)
998 MyFree(MachineNameW);
1002 /***********************************************************************
1003 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1005 BOOL WINAPI SetupDiClassNameFromGuidExW(
1006 const GUID* ClassGuid,
1008 DWORD ClassNameSize,
1009 PDWORD RequiredSize,
1016 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1021 if (hKey == INVALID_HANDLE_VALUE)
1026 if (RequiredSize != NULL)
1029 if (RegQueryValueExW(hKey,
1040 *RequiredSize = dwLength / sizeof(WCHAR);
1043 dwLength = ClassNameSize * sizeof(WCHAR);
1044 if (RegQueryValueExW(hKey,
1060 /***********************************************************************
1061 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1064 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1067 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1070 /***********************************************************************
1071 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1074 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1079 LPWSTR MachineNameW = NULL;
1086 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1087 if (MachineNameW == NULL)
1088 return (HDEVINFO)INVALID_HANDLE_VALUE;
1091 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1092 MachineNameW, Reserved);
1094 MyFree(MachineNameW);
1099 /***********************************************************************
1100 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1102 * Create an empty DeviceInfoSet list.
1105 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1107 * hwndParent [I] hwnd needed for interface related actions.
1108 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1109 * local registry will be used.
1110 * Reserved [I] must be NULL
1113 * Success: empty list.
1114 * Failure: INVALID_HANDLE_VALUE.
1117 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1122 struct DeviceInfoSet *list = NULL;
1123 DWORD size = sizeof(struct DeviceInfoSet);
1125 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1126 debugstr_w(MachineName), Reserved);
1128 if (MachineName != NULL)
1130 FIXME("remote support is not implemented\n");
1131 SetLastError(ERROR_INVALID_MACHINENAME);
1132 return (HDEVINFO)INVALID_HANDLE_VALUE;
1135 if (Reserved != NULL)
1137 SetLastError(ERROR_INVALID_PARAMETER);
1138 return (HDEVINFO)INVALID_HANDLE_VALUE;
1141 list = HeapAlloc(GetProcessHeap(), 0, size);
1144 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1145 return (HDEVINFO)INVALID_HANDLE_VALUE;
1148 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1149 list->hwndParent = hwndParent;
1150 memcpy(&list->ClassGuid,
1151 ClassGuid ? ClassGuid : &GUID_NULL,
1152 sizeof(list->ClassGuid));
1154 list->devices = NULL;
1156 return (HDEVINFO)list;
1159 /***********************************************************************
1160 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1162 HKEY WINAPI SetupDiCreateDevRegKeyA(
1163 HDEVINFO DeviceInfoSet,
1164 PSP_DEVINFO_DATA DeviceInfoData,
1169 PCSTR InfSectionName)
1171 PWSTR InfSectionNameW = NULL;
1174 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1175 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1179 if (!InfSectionName)
1181 SetLastError(ERROR_INVALID_PARAMETER);
1182 return INVALID_HANDLE_VALUE;
1186 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1187 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1190 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1191 HwProfile, KeyType, InfHandle, InfSectionNameW);
1192 MyFree(InfSectionNameW);
1196 /***********************************************************************
1197 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1199 HKEY WINAPI SetupDiCreateDevRegKeyW(
1200 HDEVINFO DeviceInfoSet,
1201 PSP_DEVINFO_DATA DeviceInfoData,
1206 PCWSTR InfSectionName)
1208 FIXME("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1209 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1210 return INVALID_HANDLE_VALUE;
1213 /***********************************************************************
1214 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1216 BOOL WINAPI SetupDiCreateDeviceInfoA(
1217 HDEVINFO DeviceInfoSet,
1219 CONST GUID *ClassGuid,
1220 PCSTR DeviceDescription,
1222 DWORD CreationFlags,
1223 PSP_DEVINFO_DATA DeviceInfoData)
1226 LPWSTR DeviceNameW = NULL;
1227 LPWSTR DeviceDescriptionW = NULL;
1231 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1232 if (DeviceNameW == NULL) return FALSE;
1234 if (DeviceDescription)
1236 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1237 if (DeviceDescriptionW == NULL)
1239 MyFree(DeviceNameW);
1244 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1245 hwndParent, CreationFlags, DeviceInfoData);
1247 MyFree(DeviceNameW);
1248 MyFree(DeviceDescriptionW);
1253 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1256 DWORD devNameLen = lstrlenW(devName), devInst = 0;
1259 TRACE("%s\n", debugstr_w(devName));
1260 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1265 devInst |= *ptr - '0';
1271 TRACE("%d\n", valid ? devInst : 0xffffffff);
1272 return valid ? devInst : 0xffffffff;
1275 /***********************************************************************
1276 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1278 BOOL WINAPI SetupDiCreateDeviceInfoW(
1279 HDEVINFO DeviceInfoSet,
1281 CONST GUID *ClassGuid,
1282 PCWSTR DeviceDescription,
1284 DWORD CreationFlags,
1285 PSP_DEVINFO_DATA DeviceInfoData)
1287 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1288 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1289 LPCWSTR instanceId = NULL;
1291 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1292 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1293 hwndParent, CreationFlags, DeviceInfoData);
1297 SetLastError(ERROR_INVALID_DEVINST_NAME);
1300 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1302 SetLastError(ERROR_INVALID_HANDLE);
1307 SetLastError(ERROR_INVALID_PARAMETER);
1310 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1312 SetLastError(ERROR_INVALID_HANDLE);
1315 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1316 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1318 SetLastError(ERROR_CLASS_MISMATCH);
1321 if ((CreationFlags & DICD_GENERATE_ID))
1323 if (strchrW(DeviceName, '\\'))
1324 SetLastError(ERROR_INVALID_DEVINST_NAME);
1327 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1328 '\\','%','0','4','d',0};
1333 DWORD i, highestDevID = 0;
1335 for (i = 0; i < set->cDevices; i++)
1337 struct DeviceInfo *devInfo =
1338 (struct DeviceInfo *)set->devices[i].Reserved;
1339 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1345 devName = devInfo->instanceId;
1346 id = SETUPDI_DevNameToDevID(devName);
1347 if (id != 0xffffffff && id > highestDevID)
1350 devId = highestDevID + 1;
1354 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1355 instanceId = HeapAlloc(GetProcessHeap(), 0,
1356 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1359 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1361 allocatedInstanceId = TRUE;
1373 instanceId = DeviceName;
1374 for (i = 0; ret && i < set->cDevices; i++)
1376 struct DeviceInfo *devInfo =
1377 (struct DeviceInfo *)set->devices[i].Reserved;
1379 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1381 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1388 SP_DEVINFO_DATA *dev = NULL;
1390 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1391 instanceId, TRUE, &dev);
1394 if (DeviceDescription)
1395 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1396 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1397 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1400 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1402 SetLastError(ERROR_INVALID_USER_BUFFER);
1406 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1410 if (allocatedInstanceId)
1411 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1416 /***********************************************************************
1417 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1419 BOOL WINAPI SetupDiRegisterDeviceInfo(
1420 HDEVINFO DeviceInfoSet,
1421 PSP_DEVINFO_DATA DeviceInfoData,
1423 PSP_DETSIG_CMPPROC CompareProc,
1424 PVOID CompareContext,
1425 PSP_DEVINFO_DATA DupDeviceInfoData)
1427 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1428 struct DeviceInfo *devInfo;
1430 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1431 CompareProc, CompareContext, DupDeviceInfoData);
1433 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1435 SetLastError(ERROR_INVALID_HANDLE);
1438 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1440 SetLastError(ERROR_INVALID_HANDLE);
1443 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1444 || !DeviceInfoData->Reserved)
1446 SetLastError(ERROR_INVALID_PARAMETER);
1449 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1450 if (devInfo->set != set)
1452 SetLastError(ERROR_INVALID_PARAMETER);
1455 if (devInfo->phantom)
1457 devInfo->phantom = FALSE;
1458 RegDeleteValueW(devInfo->key, Phantom);
1463 /***********************************************************************
1464 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1466 BOOL WINAPI SetupDiEnumDeviceInfo(
1469 PSP_DEVINFO_DATA info)
1473 TRACE("%p %d %p\n", devinfo, index, info);
1477 SetLastError(ERROR_INVALID_PARAMETER);
1480 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1482 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1483 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1485 if (index < list->cDevices)
1487 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1489 memcpy(info, &list->devices[index], info->cbSize);
1493 SetLastError(ERROR_INVALID_USER_BUFFER);
1496 SetLastError(ERROR_NO_MORE_ITEMS);
1499 SetLastError(ERROR_INVALID_HANDLE);
1502 SetLastError(ERROR_INVALID_HANDLE);
1506 /***********************************************************************
1507 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1509 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1510 HDEVINFO DeviceInfoSet,
1511 PSP_DEVINFO_DATA DeviceInfoData,
1512 PSTR DeviceInstanceId,
1513 DWORD DeviceInstanceIdSize,
1514 PDWORD RequiredSize)
1520 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1521 DeviceInstanceIdSize, RequiredSize);
1523 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1528 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1530 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1533 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1540 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1542 DeviceInstanceIdSize, NULL, NULL);
1548 if (len > DeviceInstanceIdSize)
1550 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1554 *RequiredSize = len;
1557 HeapFree(GetProcessHeap(), 0, instanceId);
1562 /***********************************************************************
1563 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1565 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1566 HDEVINFO DeviceInfoSet,
1567 PSP_DEVINFO_DATA DeviceInfoData,
1568 PWSTR DeviceInstanceId,
1569 DWORD DeviceInstanceIdSize,
1570 PDWORD RequiredSize)
1572 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1573 struct DeviceInfo *devInfo;
1575 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1576 DeviceInstanceIdSize, RequiredSize);
1578 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1580 SetLastError(ERROR_INVALID_HANDLE);
1583 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1585 SetLastError(ERROR_INVALID_HANDLE);
1588 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1589 || !DeviceInfoData->Reserved)
1591 SetLastError(ERROR_INVALID_PARAMETER);
1594 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1595 if (devInfo->set != set)
1597 SetLastError(ERROR_INVALID_PARAMETER);
1600 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1601 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1603 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1605 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1608 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1610 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1614 /***********************************************************************
1615 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1617 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1619 PCSTR InfSectionName,
1620 PSTR InfSectionWithExt,
1621 DWORD InfSectionWithExtSize,
1622 PDWORD RequiredSize,
1629 /***********************************************************************
1630 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1632 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1634 PCWSTR InfSectionName,
1635 PWSTR InfSectionWithExt,
1636 DWORD InfSectionWithExtSize,
1637 PDWORD RequiredSize,
1640 WCHAR szBuffer[MAX_PATH];
1643 LONG lLineCount = -1;
1645 lstrcpyW(szBuffer, InfSectionName);
1646 dwLength = lstrlenW(szBuffer);
1648 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1650 /* Test section name with '.NTx86' extension */
1651 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1652 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1654 if (lLineCount == -1)
1656 /* Test section name with '.NT' extension */
1657 lstrcpyW(&szBuffer[dwLength], NtExtension);
1658 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1663 /* Test section name with '.Win' extension */
1664 lstrcpyW(&szBuffer[dwLength], WinExtension);
1665 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1668 if (lLineCount == -1)
1670 /* Test section name without extension */
1671 szBuffer[dwLength] = 0;
1672 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1675 if (lLineCount == -1)
1677 SetLastError(ERROR_INVALID_PARAMETER);
1681 dwFullLength = lstrlenW(szBuffer);
1683 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1685 if (InfSectionWithExtSize < (dwFullLength + 1))
1687 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1691 lstrcpyW(InfSectionWithExt, szBuffer);
1692 if (Extension != NULL)
1694 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1698 if (RequiredSize != NULL)
1700 *RequiredSize = dwFullLength + 1;
1706 /***********************************************************************
1707 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1709 BOOL WINAPI SetupDiGetClassDescriptionA(
1710 const GUID* ClassGuid,
1711 PSTR ClassDescription,
1712 DWORD ClassDescriptionSize,
1713 PDWORD RequiredSize)
1715 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1716 ClassDescriptionSize,
1717 RequiredSize, NULL, NULL);
1720 /***********************************************************************
1721 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1723 BOOL WINAPI SetupDiGetClassDescriptionW(
1724 const GUID* ClassGuid,
1725 PWSTR ClassDescription,
1726 DWORD ClassDescriptionSize,
1727 PDWORD RequiredSize)
1729 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1730 ClassDescriptionSize,
1731 RequiredSize, NULL, NULL);
1734 /***********************************************************************
1735 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1737 BOOL WINAPI SetupDiGetClassDescriptionExA(
1738 const GUID* ClassGuid,
1739 PSTR ClassDescription,
1740 DWORD ClassDescriptionSize,
1741 PDWORD RequiredSize,
1749 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1754 if (hKey == INVALID_HANDLE_VALUE)
1756 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1760 dwLength = ClassDescriptionSize;
1761 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1762 (LPBYTE)ClassDescription, &dwLength );
1763 if (RequiredSize) *RequiredSize = dwLength;
1768 /***********************************************************************
1769 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1771 BOOL WINAPI SetupDiGetClassDescriptionExW(
1772 const GUID* ClassGuid,
1773 PWSTR ClassDescription,
1774 DWORD ClassDescriptionSize,
1775 PDWORD RequiredSize,
1783 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1788 if (hKey == INVALID_HANDLE_VALUE)
1790 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1794 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1795 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1796 (LPBYTE)ClassDescription, &dwLength );
1797 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1802 /***********************************************************************
1803 * SetupDiGetClassDevsA (SETUPAPI.@)
1805 HDEVINFO WINAPI SetupDiGetClassDevsA(
1812 LPWSTR enumstrW = NULL;
1816 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1817 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1820 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1823 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1825 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
1827 HeapFree(GetProcessHeap(), 0, enumstrW);
1833 /***********************************************************************
1834 * SetupDiGetClassDevsExA (SETUPAPI.@)
1836 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1846 LPWSTR enumstrW = NULL, machineW = NULL;
1850 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1851 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1854 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1857 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1861 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1862 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1865 HeapFree(GetProcessHeap(), 0, enumstrW);
1866 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1869 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1871 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
1872 machineW, reserved);
1873 HeapFree(GetProcessHeap(), 0, enumstrW);
1874 HeapFree(GetProcessHeap(), 0, machineW);
1880 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
1881 const GUID *interface)
1884 WCHAR subKeyName[MAX_PATH];
1885 LONG l = ERROR_SUCCESS;
1887 for (i = 0; !l; i++)
1889 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1890 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1894 SP_DEVICE_INTERFACE_DATA *iface = NULL;
1896 /* The subkey name is the reference string, with a '#' prepended */
1897 SETUPDI_AddInterfaceInstance(dev, interface, subKeyName + 1,
1899 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1902 WCHAR symbolicLink[MAX_PATH];
1905 len = sizeof(symbolicLink);
1906 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
1907 (BYTE *)symbolicLink, &len);
1908 if (!l && dataType == REG_SZ)
1909 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
1910 RegCloseKey(subKey);
1914 /* FIXME: find and add all the device's interfaces to the device */
1917 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1918 HKEY key, const GUID *interface, LPCWSTR enumstr)
1920 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1922 WCHAR subKeyName[MAX_PATH];
1924 HKEY enumKey = INVALID_HANDLE_VALUE;
1926 TRACE("%s\n", debugstr_w(enumstr));
1928 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1930 for (i = 0; !l; i++)
1932 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1933 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1938 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1941 WCHAR deviceInst[MAX_PATH * 3];
1944 len = sizeof(deviceInst);
1945 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1946 (BYTE *)deviceInst, &len);
1947 if (!l && dataType == REG_SZ)
1949 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1950 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1954 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1958 WCHAR deviceClassStr[40];
1960 len = sizeof(deviceClassStr);
1961 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1962 &dataType, (BYTE *)deviceClassStr, &len);
1963 if (!l && dataType == REG_SZ &&
1964 deviceClassStr[0] == '{' &&
1965 deviceClassStr[37] == '}')
1968 SP_DEVINFO_DATA *dev;
1970 deviceClassStr[37] = 0;
1971 UuidFromStringW(&deviceClassStr[1],
1973 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
1974 0 /* FIXME: DevInst */, deviceInst,
1976 SETUPDI_AddDeviceInterfaces(dev, subKey,
1979 RegCloseKey(deviceKey);
1983 RegCloseKey(subKey);
1987 if (enumKey != INVALID_HANDLE_VALUE)
1988 RegCloseKey(enumKey);
1991 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1992 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1994 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1995 DIOCR_INTERFACE, NULL, NULL);
1997 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1998 debugstr_w(enumstr), flags);
2000 if (interfacesKey != INVALID_HANDLE_VALUE)
2002 if (flags & DIGCF_ALLCLASSES)
2005 WCHAR interfaceGuidStr[40];
2006 LONG l = ERROR_SUCCESS;
2008 for (i = 0; !l; i++)
2010 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
2011 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
2012 NULL, NULL, NULL, NULL);
2015 if (interfaceGuidStr[0] == '{' &&
2016 interfaceGuidStr[37] == '}')
2021 interfaceGuidStr[37] = 0;
2022 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
2023 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
2024 KEY_READ, &interfaceKey);
2027 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2028 interfaceKey, &interfaceGuid, enumstr);
2029 RegCloseKey(interfaceKey);
2037 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
2038 * interface's key, so just pass that long
2040 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2041 interfacesKey, interface, enumstr);
2043 RegCloseKey(interfacesKey);
2047 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
2048 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
2050 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2052 WCHAR subKeyName[MAX_PATH];
2053 LONG l = ERROR_SUCCESS;
2055 TRACE("%s\n", debugstr_w(parent));
2057 for (i = 0; !l; i++)
2059 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2060 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2065 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2068 WCHAR classGuid[40];
2071 len = sizeof(classGuid);
2072 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
2073 (BYTE *)classGuid, &len);
2074 if (!l && dataType == REG_SZ)
2076 if (classGuid[0] == '{' && classGuid[37] == '}')
2081 UuidFromStringW(&classGuid[1], &deviceClass);
2082 if ((flags & DIGCF_ALLCLASSES) ||
2083 IsEqualGUID(class, &deviceClass))
2085 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
2088 instanceId = HeapAlloc(GetProcessHeap(), 0,
2089 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
2093 SP_DEVINFO_DATA *dev;
2095 sprintfW(instanceId, fmt, parent, subKeyName);
2096 SETUPDI_AddDeviceToSet(set, &deviceClass,
2097 0 /* FIXME: DevInst */, instanceId,
2099 HeapFree(GetProcessHeap(), 0, instanceId);
2104 RegCloseKey(subKey);
2110 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
2111 LPCWSTR enumstr, DWORD flags)
2113 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
2114 DIOCR_INSTALLER, NULL, NULL);
2116 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
2117 debugstr_w(enumstr), flags);
2119 if (classesKey != INVALID_HANDLE_VALUE)
2124 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
2129 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2130 enumKey, class, flags);
2131 RegCloseKey(enumKey);
2137 WCHAR subKeyName[MAX_PATH];
2138 LONG l = ERROR_SUCCESS;
2140 for (i = 0; !l; i++)
2142 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2143 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
2149 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
2153 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2154 subKeyName, subKey, class, flags);
2155 RegCloseKey(subKey);
2160 RegCloseKey(classesKey);
2164 /***********************************************************************
2165 * SetupDiGetClassDevsW (SETUPAPI.@)
2167 HDEVINFO WINAPI SetupDiGetClassDevsW(
2173 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2177 /***********************************************************************
2178 * SetupDiGetClassDevsExW (SETUPAPI.@)
2180 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2189 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2193 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2194 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2197 if (!(flags & DIGCF_ALLCLASSES) && !class)
2199 SetLastError(ERROR_INVALID_PARAMETER);
2202 if (flags & unsupportedFlags)
2203 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2207 set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
2211 FIXME("%s: unimplemented for remote machines\n",
2212 debugstr_w(machine));
2213 else if (flags & DIGCF_DEVICEINTERFACE)
2214 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2216 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2221 /***********************************************************************
2222 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2224 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2225 HDEVINFO DeviceInfoSet,
2226 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2228 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2230 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2232 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2234 SetLastError(ERROR_INVALID_HANDLE);
2237 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2239 SetLastError(ERROR_INVALID_HANDLE);
2243 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2245 SetLastError(ERROR_INVALID_PARAMETER);
2248 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2249 DevInfoData->RemoteMachineHandle = NULL;
2250 DevInfoData->RemoteMachineName[0] = '\0';
2254 /***********************************************************************
2255 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2257 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2258 HDEVINFO DeviceInfoSet,
2259 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2261 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2263 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2265 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2267 SetLastError(ERROR_INVALID_HANDLE);
2270 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2272 SetLastError(ERROR_INVALID_HANDLE);
2276 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2278 SetLastError(ERROR_INVALID_PARAMETER);
2281 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2282 DevInfoData->RemoteMachineHandle = NULL;
2283 DevInfoData->RemoteMachineName[0] = '\0';
2287 /***********************************************************************
2288 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2290 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2291 HDEVINFO DeviceInfoSet,
2292 PSP_DEVINFO_DATA DeviceInfoData,
2293 const GUID *InterfaceClassGuid,
2294 PCSTR ReferenceString,
2295 DWORD CreationFlags,
2296 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2299 LPWSTR ReferenceStringW = NULL;
2301 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2302 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2303 CreationFlags, DeviceInterfaceData);
2305 if (ReferenceString)
2307 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2308 if (ReferenceStringW == NULL) return FALSE;
2311 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2312 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2313 DeviceInterfaceData);
2315 MyFree(ReferenceStringW);
2320 /***********************************************************************
2321 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2323 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2324 HDEVINFO DeviceInfoSet,
2325 PSP_DEVINFO_DATA DeviceInfoData,
2326 const GUID *InterfaceClassGuid,
2327 PCWSTR ReferenceString,
2328 DWORD CreationFlags,
2329 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2331 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2332 struct DeviceInfo *devInfo;
2333 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2336 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2337 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2338 CreationFlags, DeviceInterfaceData);
2340 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2342 SetLastError(ERROR_INVALID_HANDLE);
2345 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2347 SetLastError(ERROR_INVALID_HANDLE);
2350 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2351 || !DeviceInfoData->Reserved)
2353 SetLastError(ERROR_INVALID_PARAMETER);
2356 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2357 if (devInfo->set != set)
2359 SetLastError(ERROR_INVALID_PARAMETER);
2362 if (!InterfaceClassGuid)
2364 SetLastError(ERROR_INVALID_USER_BUFFER);
2367 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2368 ReferenceString, &iface)))
2370 if (DeviceInterfaceData)
2372 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2374 SetLastError(ERROR_INVALID_USER_BUFFER);
2378 memcpy(DeviceInterfaceData, iface, sizeof(*iface));
2384 /***********************************************************************
2385 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2387 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2388 HDEVINFO DeviceInfoSet,
2389 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2393 PCSTR InfSectionName)
2396 PWSTR InfSectionNameW = NULL;
2398 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2399 samDesired, InfHandle, InfSectionName);
2402 if (!InfSectionName)
2404 SetLastError(ERROR_INVALID_PARAMETER);
2405 return INVALID_HANDLE_VALUE;
2407 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2408 if (!InfSectionNameW)
2409 return INVALID_HANDLE_VALUE;
2411 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2412 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2414 MyFree(InfSectionNameW);
2418 static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo)
2420 static const WCHAR hash[] = {'#',0};
2421 PWSTR instancePath = NULL;
2423 if (ifaceInfo->referenceString)
2425 instancePath = HeapAlloc(GetProcessHeap(), 0,
2426 (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR));
2429 lstrcpyW(instancePath, hash);
2430 lstrcatW(instancePath, ifaceInfo->referenceString);
2433 SetLastError(ERROR_OUTOFMEMORY);
2437 instancePath = HeapAlloc(GetProcessHeap(), 0,
2438 (lstrlenW(hash) + 1) * sizeof(WCHAR));
2440 lstrcpyW(instancePath, hash);
2442 return instancePath;
2445 /***********************************************************************
2446 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2448 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2449 HDEVINFO DeviceInfoSet,
2450 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2454 PCWSTR InfSectionName)
2456 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2457 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2460 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2461 samDesired, InfHandle, InfSectionName);
2463 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2464 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2466 SetLastError(ERROR_INVALID_HANDLE);
2467 return INVALID_HANDLE_VALUE;
2469 if (!DeviceInterfaceData ||
2470 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2471 !DeviceInterfaceData->Reserved)
2473 SetLastError(ERROR_INVALID_PARAMETER);
2474 return INVALID_HANDLE_VALUE;
2476 if (InfHandle && !InfSectionName)
2478 SetLastError(ERROR_INVALID_PARAMETER);
2479 return INVALID_HANDLE_VALUE;
2481 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2482 samDesired, NULL, &interfacesKey, NULL)))
2485 WCHAR bracedGuidString[39];
2487 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2489 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2490 samDesired, NULL, &parent, NULL)))
2492 struct InterfaceInfo *ifaceInfo =
2493 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2494 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2500 l = RegCreateKeyExW(parent, instancePath, 0, NULL, 0,
2501 samDesired, NULL, &key, NULL);
2505 key = INVALID_HANDLE_VALUE;
2508 FIXME("INF section installation unsupported\n");
2510 HeapFree(GetProcessHeap(), 0, instancePath);
2511 RegCloseKey(parent);
2515 RegCloseKey(interfacesKey);
2522 /***********************************************************************
2523 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2525 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2526 HDEVINFO DeviceInfoSet,
2527 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2530 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2534 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2536 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2537 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2539 SetLastError(ERROR_INVALID_HANDLE);
2542 if (!DeviceInterfaceData ||
2543 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2544 !DeviceInterfaceData->Reserved)
2546 SetLastError(ERROR_INVALID_PARAMETER);
2549 parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid,
2550 KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
2551 if (parent != INVALID_HANDLE_VALUE)
2553 struct InterfaceInfo *ifaceInfo =
2554 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2555 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2559 LONG l = RegDeleteKeyW(parent, instancePath);
2565 HeapFree(GetProcessHeap(), 0, instancePath);
2567 RegCloseKey(parent);
2572 /***********************************************************************
2573 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2576 * DeviceInfoSet [I] Set of devices from which to enumerate
2578 * DeviceInfoData [I] (Optional) If specified, a specific device
2579 * instance from which to enumerate interfaces.
2580 * If it isn't specified, all interfaces for all
2581 * devices in the set are enumerated.
2582 * InterfaceClassGuid [I] The interface class to enumerate.
2583 * MemberIndex [I] An index of the interface instance to enumerate.
2584 * A caller should start with MemberIndex set to 0,
2585 * and continue until the function fails with
2586 * ERROR_NO_MORE_ITEMS.
2587 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2588 * member must be set to
2589 * sizeof(SP_DEVICE_INTERFACE_DATA).
2592 * Success: non-zero value.
2593 * Failure: FALSE. Call GetLastError() for more info.
2595 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2596 HDEVINFO DeviceInfoSet,
2597 PSP_DEVINFO_DATA DeviceInfoData,
2598 CONST GUID * InterfaceClassGuid,
2600 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2602 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2605 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2606 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2608 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2609 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2611 SetLastError(ERROR_INVALID_HANDLE);
2614 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2615 !DeviceInfoData->Reserved))
2617 SetLastError(ERROR_INVALID_PARAMETER);
2620 if (!DeviceInterfaceData ||
2621 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2623 SetLastError(ERROR_INVALID_PARAMETER);
2628 struct DeviceInfo *devInfo =
2629 (struct DeviceInfo *)DeviceInfoData->Reserved;
2630 struct InterfaceInstances *iface;
2632 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2634 if (MemberIndex < iface->cInstances)
2635 memcpy(DeviceInterfaceData, &iface->instances[MemberIndex],
2636 sizeof(SP_DEVICE_INTERFACE_DATA));
2639 SetLastError(ERROR_NO_MORE_ITEMS);
2644 SetLastError(ERROR_NO_MORE_ITEMS);
2648 DWORD i, cEnumerated = 0;
2651 for (i = 0; !found && cEnumerated < MemberIndex + 1 &&
2652 i < set->cDevices; i++)
2654 struct DeviceInfo *devInfo =
2655 (struct DeviceInfo *)set->devices[i].Reserved;
2656 struct InterfaceInstances *iface;
2658 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2660 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2661 cEnumerated += iface->cInstances;
2664 DWORD instanceIndex = MemberIndex - cEnumerated;
2666 memcpy(DeviceInterfaceData,
2667 &iface->instances[instanceIndex],
2668 sizeof(SP_DEVICE_INTERFACE_DATA));
2669 cEnumerated += instanceIndex + 1;
2676 SetLastError(ERROR_NO_MORE_ITEMS);
2681 /***********************************************************************
2682 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2684 * Destroy a DeviceInfoList and free all used memory of the list.
2687 * devinfo [I] DeviceInfoList pointer to list to destroy
2690 * Success: non zero value.
2691 * Failure: zero value.
2693 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2697 TRACE("%p\n", devinfo);
2698 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2700 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2702 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2706 for (i = 0; i < list->cDevices; i++)
2707 SETUPDI_FreeDeviceInfo(
2708 (struct DeviceInfo *)list->devices[i].Reserved);
2709 HeapFree(GetProcessHeap(), 0, list->devices);
2710 HeapFree(GetProcessHeap(), 0, list);
2716 SetLastError(ERROR_INVALID_HANDLE);
2721 /***********************************************************************
2722 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2724 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2725 HDEVINFO DeviceInfoSet,
2726 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2727 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2728 DWORD DeviceInterfaceDetailDataSize,
2729 PDWORD RequiredSize,
2730 PSP_DEVINFO_DATA DeviceInfoData)
2732 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2733 struct InterfaceInfo *info;
2734 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)
2738 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2739 DeviceInterfaceData, DeviceInterfaceDetailData,
2740 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2742 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2743 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2745 SetLastError(ERROR_INVALID_HANDLE);
2748 if (!DeviceInterfaceData ||
2749 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2750 !DeviceInterfaceData->Reserved)
2752 SetLastError(ERROR_INVALID_PARAMETER);
2755 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2756 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) ||
2757 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2759 SetLastError(ERROR_INVALID_USER_BUFFER);
2762 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2764 SetLastError(ERROR_INVALID_USER_BUFFER);
2767 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2768 if (info->symbolicLink)
2769 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2770 NULL, 0, NULL, NULL);
2771 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2773 if (info->symbolicLink)
2774 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2775 DeviceInterfaceDetailData->DevicePath,
2776 DeviceInterfaceDetailDataSize -
2777 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2780 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2781 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2782 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2788 *RequiredSize = bytesNeeded;
2789 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2794 /***********************************************************************
2795 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2797 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2798 HDEVINFO DeviceInfoSet,
2799 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2800 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2801 DWORD DeviceInterfaceDetailDataSize,
2802 PDWORD RequiredSize,
2803 PSP_DEVINFO_DATA DeviceInfoData)
2805 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2806 struct InterfaceInfo *info;
2807 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2808 + sizeof(WCHAR); /* include NULL terminator */
2811 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2812 DeviceInterfaceData, DeviceInterfaceDetailData,
2813 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2815 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2816 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2818 SetLastError(ERROR_INVALID_HANDLE);
2821 if (!DeviceInterfaceData ||
2822 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2823 !DeviceInterfaceData->Reserved)
2825 SetLastError(ERROR_INVALID_PARAMETER);
2828 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2829 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2830 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2832 SetLastError(ERROR_INVALID_USER_BUFFER);
2835 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2837 SetLastError(ERROR_INVALID_USER_BUFFER);
2840 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2841 if (info->symbolicLink)
2842 bytesNeeded += lstrlenW(info->symbolicLink);
2843 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2845 if (info->symbolicLink)
2846 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
2848 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2849 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2850 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2856 *RequiredSize = bytesNeeded;
2857 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2862 struct PropertyMapEntry
2869 static struct PropertyMapEntry PropertyMap[] = {
2870 { REG_SZ, "DeviceDesc", DeviceDesc },
2871 { REG_MULTI_SZ, "HardwareId", HardwareId },
2872 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
2873 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
2874 { REG_SZ, "Service", Service },
2875 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
2876 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
2877 { REG_SZ, "Class", Class },
2878 { REG_SZ, "ClassGUID", ClassGUID },
2879 { REG_SZ, "Driver", Driver },
2880 { REG_DWORD, "ConfigFlags", ConfigFlags },
2881 { REG_SZ, "Mfg", Mfg },
2882 { REG_SZ, "FriendlyName", FriendlyName },
2883 { REG_SZ, "LocationInformation", LocationInformation },
2884 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
2885 { REG_DWORD, "Capabilities", Capabilities },
2886 { REG_DWORD, "UINumber", UINumber },
2887 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
2888 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
2891 /***********************************************************************
2892 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2894 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2895 HDEVINFO DeviceInfoSet,
2896 PSP_DEVINFO_DATA DeviceInfoData,
2898 PDWORD PropertyRegDataType,
2899 PBYTE PropertyBuffer,
2900 DWORD PropertyBufferSize,
2901 PDWORD RequiredSize)
2904 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2905 struct DeviceInfo *devInfo;
2907 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2908 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2911 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2913 SetLastError(ERROR_INVALID_HANDLE);
2916 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2918 SetLastError(ERROR_INVALID_HANDLE);
2921 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2922 || !DeviceInfoData->Reserved)
2924 SetLastError(ERROR_INVALID_PARAMETER);
2927 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2928 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2929 && PropertyMap[Property].nameA)
2931 DWORD size = PropertyBufferSize;
2932 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
2933 NULL, PropertyRegDataType, PropertyBuffer, &size);
2936 *RequiredSize = size;
2945 /***********************************************************************
2946 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2948 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2949 HDEVINFO DeviceInfoSet,
2950 PSP_DEVINFO_DATA DeviceInfoData,
2952 PDWORD PropertyRegDataType,
2953 PBYTE PropertyBuffer,
2954 DWORD PropertyBufferSize,
2955 PDWORD RequiredSize)
2958 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2959 struct DeviceInfo *devInfo;
2961 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2962 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2965 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2967 SetLastError(ERROR_INVALID_HANDLE);
2970 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2972 SetLastError(ERROR_INVALID_HANDLE);
2975 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2976 || !DeviceInfoData->Reserved)
2978 SetLastError(ERROR_INVALID_PARAMETER);
2981 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2982 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2983 && PropertyMap[Property].nameW)
2985 DWORD size = PropertyBufferSize;
2986 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2987 NULL, PropertyRegDataType, PropertyBuffer, &size);
2990 *RequiredSize = size;
2999 /***********************************************************************
3000 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3002 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3003 HDEVINFO DeviceInfoSet,
3004 PSP_DEVINFO_DATA DeviceInfoData,
3006 const BYTE *PropertyBuffer,
3007 DWORD PropertyBufferSize)
3010 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3011 struct DeviceInfo *devInfo;
3013 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3014 PropertyBuffer, PropertyBufferSize);
3016 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3018 SetLastError(ERROR_INVALID_HANDLE);
3021 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3023 SetLastError(ERROR_INVALID_HANDLE);
3026 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3027 || !DeviceInfoData->Reserved)
3029 SetLastError(ERROR_INVALID_PARAMETER);
3032 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3033 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3034 && PropertyMap[Property].nameA)
3036 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
3037 PropertyMap[Property].regType, PropertyBuffer,
3038 PropertyBufferSize);
3047 /***********************************************************************
3048 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3050 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3051 HDEVINFO DeviceInfoSet,
3052 PSP_DEVINFO_DATA DeviceInfoData,
3054 const BYTE *PropertyBuffer,
3055 DWORD PropertyBufferSize)
3058 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3059 struct DeviceInfo *devInfo;
3061 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3062 PropertyBuffer, PropertyBufferSize);
3064 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3066 SetLastError(ERROR_INVALID_HANDLE);
3069 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3071 SetLastError(ERROR_INVALID_HANDLE);
3074 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3075 || !DeviceInfoData->Reserved)
3077 SetLastError(ERROR_INVALID_PARAMETER);
3080 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3081 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3082 && PropertyMap[Property].nameW)
3084 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
3085 PropertyMap[Property].regType, PropertyBuffer,
3086 PropertyBufferSize);
3095 /***********************************************************************
3096 * SetupDiInstallClassA (SETUPAPI.@)
3098 BOOL WINAPI SetupDiInstallClassA(
3104 UNICODE_STRING FileNameW;
3107 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
3109 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3113 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
3115 RtlFreeUnicodeString(&FileNameW);
3120 static HKEY CreateClassKey(HINF hInf)
3122 static const WCHAR slash[] = { '\\',0 };
3123 WCHAR FullBuffer[MAX_PATH];
3124 WCHAR Buffer[MAX_PATH];
3128 if (!SetupGetLineTextW(NULL,
3136 return INVALID_HANDLE_VALUE;
3139 lstrcpyW(FullBuffer, ControlClass);
3140 lstrcatW(FullBuffer, slash);
3141 lstrcatW(FullBuffer, Buffer);
3143 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3149 if (!SetupGetLineTextW(NULL,
3157 return INVALID_HANDLE_VALUE;
3160 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3164 REG_OPTION_NON_VOLATILE,
3170 return INVALID_HANDLE_VALUE;
3175 if (RegSetValueExW(hClassKey,
3180 RequiredSize * sizeof(WCHAR)))
3182 RegCloseKey(hClassKey);
3183 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3185 return INVALID_HANDLE_VALUE;
3191 /***********************************************************************
3192 * SetupDiInstallClassW (SETUPAPI.@)
3194 BOOL WINAPI SetupDiInstallClassW(
3200 WCHAR SectionName[MAX_PATH];
3201 DWORD SectionNameLength = 0;
3203 BOOL bFileQueueCreated = FALSE;
3209 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
3211 SetLastError(ERROR_INVALID_PARAMETER);
3215 /* Open the .inf file */
3216 hInf = SetupOpenInfFileW(InfFileName,
3220 if (hInf == INVALID_HANDLE_VALUE)
3226 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3227 hClassKey = CreateClassKey(hInf);
3228 if (hClassKey == INVALID_HANDLE_VALUE)
3230 SetupCloseInfFile(hInf);
3235 /* Try to append a layout file */
3236 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3238 /* Retrieve the actual section name */
3239 SetupDiGetActualSectionToInstallW(hInf,
3247 if (!(Flags & DI_NOVCP))
3249 FileQueue = SetupOpenFileQueue();
3250 if (FileQueue == INVALID_HANDLE_VALUE)
3252 SetupCloseInfFile(hInf);
3256 bFileQueueCreated = TRUE;
3261 SetupInstallFromInfSectionW(NULL,
3264 SPINST_COPYINF | SPINST_FILES | SPINST_REGISTRY,
3270 INVALID_HANDLE_VALUE,
3273 /* FIXME: More code! */
3275 if (bFileQueueCreated)
3276 SetupCloseFileQueue(FileQueue);
3278 SetupCloseInfFile(hInf);
3284 /***********************************************************************
3285 * SetupDiOpenClassRegKey (SETUPAPI.@)
3287 HKEY WINAPI SetupDiOpenClassRegKey(
3288 const GUID* ClassGuid,
3291 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3292 DIOCR_INSTALLER, NULL, NULL);
3296 /***********************************************************************
3297 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3299 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3300 const GUID* ClassGuid,
3306 PWSTR MachineNameW = NULL;
3313 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3314 if (MachineNameW == NULL)
3315 return INVALID_HANDLE_VALUE;
3318 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3319 Flags, MachineNameW, Reserved);
3321 MyFree(MachineNameW);
3327 /***********************************************************************
3328 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3330 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3331 const GUID* ClassGuid,
3342 if (MachineName != NULL)
3344 FIXME("Remote access not supported yet!\n");
3345 return INVALID_HANDLE_VALUE;
3348 if (Flags == DIOCR_INSTALLER)
3350 lpKeyName = ControlClass;
3352 else if (Flags == DIOCR_INTERFACE)
3354 lpKeyName = DeviceClasses;
3358 ERR("Invalid Flags parameter!\n");
3359 SetLastError(ERROR_INVALID_PARAMETER);
3360 return INVALID_HANDLE_VALUE;
3365 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3372 hClassesKey = INVALID_HANDLE_VALUE;
3378 WCHAR bracedGuidString[39];
3380 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3382 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3388 if ((l = RegOpenKeyExW(hClassesKey,
3395 key = INVALID_HANDLE_VALUE;
3397 RegCloseKey(hClassesKey);
3402 key = INVALID_HANDLE_VALUE;
3408 /***********************************************************************
3409 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3411 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3412 HDEVINFO DeviceInfoSet,
3415 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3417 FIXME("%p %s %08x %p\n",
3418 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3422 /***********************************************************************
3423 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3425 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3426 HDEVINFO DeviceInfoSet,
3429 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3431 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3432 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3436 /***********************************************************************
3437 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3439 BOOL WINAPI SetupDiSetClassInstallParamsA(
3440 HDEVINFO DeviceInfoSet,
3441 PSP_DEVINFO_DATA DeviceInfoData,
3442 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3443 DWORD ClassInstallParamsSize)
3445 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3446 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3450 /***********************************************************************
3451 * SetupDiCallClassInstaller (SETUPAPI.@)
3453 BOOL WINAPI SetupDiCallClassInstaller(
3454 DI_FUNCTION InstallFunction,
3455 HDEVINFO DeviceInfoSet,
3456 PSP_DEVINFO_DATA DeviceInfoData)
3458 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3462 /***********************************************************************
3463 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3465 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3466 HDEVINFO DeviceInfoSet,
3467 PSP_DEVINFO_DATA DeviceInfoData,
3468 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3470 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3474 /***********************************************************************
3475 * SetupDiOpenDevRegKey (SETUPAPI.@)
3477 HKEY WINAPI SetupDiOpenDevRegKey(
3478 HDEVINFO DeviceInfoSet,
3479 PSP_DEVINFO_DATA DeviceInfoData,
3485 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3486 Scope, HwProfile, KeyType, samDesired);
3487 return INVALID_HANDLE_VALUE;