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 struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
411 LPCWSTR instanceId, BOOL phantom)
413 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
414 sizeof(struct DeviceInfo));
419 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
420 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
421 if (devInfo->instanceId)
426 devInfo->key = INVALID_HANDLE_VALUE;
427 devInfo->phantom = phantom;
428 lstrcpyW(devInfo->instanceId, instanceId);
429 struprW(devInfo->instanceId);
430 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
431 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
434 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
435 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
437 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
438 (LPBYTE)&phantom, sizeof(phantom));
439 RegCloseKey(enumKey);
441 list_init(&devInfo->interfaces);
445 HeapFree(GetProcessHeap(), 0, devInfo);
452 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
454 struct InterfaceInstances *iface, *next;
456 if (devInfo->key != INVALID_HANDLE_VALUE)
457 RegCloseKey(devInfo->key);
458 if (devInfo->phantom)
463 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
464 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
467 RegDeleteTreeW(enumKey, devInfo->instanceId);
468 RegCloseKey(enumKey);
471 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
472 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
473 struct InterfaceInstances, entry)
475 list_remove(&iface->entry);
476 SETUPDI_FreeInterfaceInstances(iface);
477 HeapFree(GetProcessHeap(), 0, iface);
479 HeapFree(GetProcessHeap(), 0, devInfo);
482 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
483 * struct DeviceInfo, and points the returned device info's Reserved member
484 * to it. "Phantom" devices are deleted from the registry when closed.
485 * Returns a pointer to the newly allocated device info.
487 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
492 SP_DEVINFO_DATA **dev)
495 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, instanceId,
498 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
499 debugstr_w(instanceId), phantom);
504 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
505 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
507 set->devices = HeapAlloc(GetProcessHeap(), 0,
508 sizeof(SP_DEVINFO_DATA));
511 WCHAR classGuidStr[39];
513 *dev = &set->devices[set->cDevices++];
514 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
515 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
516 (*dev)->DevInst = devInst;
517 (*dev)->Reserved = (ULONG_PTR)devInfo;
518 SETUPDI_GuidToString(guid, classGuidStr);
519 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
520 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
521 lstrlenW(classGuidStr) * sizeof(WCHAR));
526 HeapFree(GetProcessHeap(), 0, devInfo);
527 SetLastError(ERROR_OUTOFMEMORY);
533 /***********************************************************************
534 * SetupDiBuildClassInfoList (SETUPAPI.@)
536 * Returns a list of setup class GUIDs that identify the classes
537 * that are installed on a local machine.
540 * Flags [I] control exclusion of classes from the list.
541 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
542 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
543 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
549 BOOL WINAPI SetupDiBuildClassInfoList(
551 LPGUID ClassGuidList,
552 DWORD ClassGuidListSize,
556 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
557 ClassGuidListSize, RequiredSize,
561 /***********************************************************************
562 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
564 * Returns a list of setup class GUIDs that identify the classes
565 * that are installed on a local or remote macine.
568 * Flags [I] control exclusion of classes from the list.
569 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
570 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
571 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
572 * MachineName [I] name of a remote machine.
573 * Reserved [I] must be NULL.
579 BOOL WINAPI SetupDiBuildClassInfoListExA(
581 LPGUID ClassGuidList,
582 DWORD ClassGuidListSize,
587 LPWSTR MachineNameW = NULL;
594 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
595 if (MachineNameW == NULL) return FALSE;
598 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
599 ClassGuidListSize, RequiredSize,
600 MachineNameW, Reserved);
602 MyFree(MachineNameW);
607 /***********************************************************************
608 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
610 * Returns a list of setup class GUIDs that identify the classes
611 * that are installed on a local or remote macine.
614 * Flags [I] control exclusion of classes from the list.
615 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
616 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
617 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
618 * MachineName [I] name of a remote machine.
619 * Reserved [I] must be NULL.
625 BOOL WINAPI SetupDiBuildClassInfoListExW(
627 LPGUID ClassGuidList,
628 DWORD ClassGuidListSize,
639 DWORD dwGuidListIndex = 0;
643 if (RequiredSize != NULL)
646 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
651 if (hClassesKey == INVALID_HANDLE_VALUE)
656 for (dwIndex = 0; ; dwIndex++)
659 lError = RegEnumKeyExW(hClassesKey,
667 TRACE("RegEnumKeyExW() returns %d\n", lError);
668 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
670 TRACE("Key name: %p\n", szKeyName);
672 if (RegOpenKeyExW(hClassesKey,
678 RegCloseKey(hClassesKey);
682 if (!RegQueryValueExW(hClassKey,
689 TRACE("'NoUseClass' value found!\n");
690 RegCloseKey(hClassKey);
694 if ((Flags & DIBCI_NOINSTALLCLASS) &&
695 (!RegQueryValueExW(hClassKey,
702 TRACE("'NoInstallClass' value found!\n");
703 RegCloseKey(hClassKey);
707 if ((Flags & DIBCI_NODISPLAYCLASS) &&
708 (!RegQueryValueExW(hClassKey,
715 TRACE("'NoDisplayClass' value found!\n");
716 RegCloseKey(hClassKey);
720 RegCloseKey(hClassKey);
722 TRACE("Guid: %p\n", szKeyName);
723 if (dwGuidListIndex < ClassGuidListSize)
725 if (szKeyName[0] == '{' && szKeyName[37] == '}')
729 TRACE("Guid: %p\n", &szKeyName[1]);
731 UuidFromStringW(&szKeyName[1],
732 &ClassGuidList[dwGuidListIndex]);
738 if (lError != ERROR_SUCCESS)
742 RegCloseKey(hClassesKey);
744 if (RequiredSize != NULL)
745 *RequiredSize = dwGuidListIndex;
747 if (ClassGuidListSize < dwGuidListIndex)
749 SetLastError(ERROR_INSUFFICIENT_BUFFER);
756 /***********************************************************************
757 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
759 BOOL WINAPI SetupDiClassGuidsFromNameA(
761 LPGUID ClassGuidList,
762 DWORD ClassGuidListSize,
765 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
766 ClassGuidListSize, RequiredSize,
770 /***********************************************************************
771 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
773 BOOL WINAPI SetupDiClassGuidsFromNameW(
775 LPGUID ClassGuidList,
776 DWORD ClassGuidListSize,
779 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
780 ClassGuidListSize, RequiredSize,
784 /***********************************************************************
785 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
787 BOOL WINAPI SetupDiClassGuidsFromNameExA(
789 LPGUID ClassGuidList,
790 DWORD ClassGuidListSize,
795 LPWSTR ClassNameW = NULL;
796 LPWSTR MachineNameW = NULL;
799 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
800 if (ClassNameW == NULL)
805 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
806 if (MachineNameW == NULL)
813 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
814 ClassGuidListSize, RequiredSize,
815 MachineNameW, Reserved);
817 MyFree(MachineNameW);
823 /***********************************************************************
824 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
826 BOOL WINAPI SetupDiClassGuidsFromNameExW(
828 LPGUID ClassGuidList,
829 DWORD ClassGuidListSize,
835 WCHAR szClassName[256];
841 DWORD dwGuidListIndex = 0;
843 if (RequiredSize != NULL)
846 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
851 if (hClassesKey == INVALID_HANDLE_VALUE)
856 for (dwIndex = 0; ; dwIndex++)
859 lError = RegEnumKeyExW(hClassesKey,
867 TRACE("RegEnumKeyExW() returns %d\n", lError);
868 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
870 TRACE("Key name: %p\n", szKeyName);
872 if (RegOpenKeyExW(hClassesKey,
878 RegCloseKey(hClassesKey);
882 dwLength = 256 * sizeof(WCHAR);
883 if (!RegQueryValueExW(hClassKey,
890 TRACE("Class name: %p\n", szClassName);
892 if (strcmpiW(szClassName, ClassName) == 0)
894 TRACE("Found matching class name\n");
896 TRACE("Guid: %p\n", szKeyName);
897 if (dwGuidListIndex < ClassGuidListSize)
899 if (szKeyName[0] == '{' && szKeyName[37] == '}')
903 TRACE("Guid: %p\n", &szKeyName[1]);
905 UuidFromStringW(&szKeyName[1],
906 &ClassGuidList[dwGuidListIndex]);
913 RegCloseKey(hClassKey);
916 if (lError != ERROR_SUCCESS)
920 RegCloseKey(hClassesKey);
922 if (RequiredSize != NULL)
923 *RequiredSize = dwGuidListIndex;
925 if (ClassGuidListSize < dwGuidListIndex)
927 SetLastError(ERROR_INSUFFICIENT_BUFFER);
934 /***********************************************************************
935 * SetupDiClassNameFromGuidA (SETUPAPI.@)
937 BOOL WINAPI SetupDiClassNameFromGuidA(
938 const GUID* ClassGuid,
943 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
944 ClassNameSize, RequiredSize,
948 /***********************************************************************
949 * SetupDiClassNameFromGuidW (SETUPAPI.@)
951 BOOL WINAPI SetupDiClassNameFromGuidW(
952 const GUID* ClassGuid,
957 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
958 ClassNameSize, RequiredSize,
962 /***********************************************************************
963 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
965 BOOL WINAPI SetupDiClassNameFromGuidExA(
966 const GUID* ClassGuid,
973 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
974 LPWSTR MachineNameW = NULL;
978 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
979 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
980 NULL, MachineNameW, Reserved);
983 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
984 ClassNameSize, NULL, NULL);
986 if (!ClassNameSize && RequiredSize)
989 MyFree(MachineNameW);
993 /***********************************************************************
994 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
996 BOOL WINAPI SetupDiClassNameFromGuidExW(
997 const GUID* ClassGuid,
1000 PDWORD RequiredSize,
1007 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1012 if (hKey == INVALID_HANDLE_VALUE)
1017 if (RequiredSize != NULL)
1020 if (RegQueryValueExW(hKey,
1031 *RequiredSize = dwLength / sizeof(WCHAR);
1034 dwLength = ClassNameSize * sizeof(WCHAR);
1035 if (RegQueryValueExW(hKey,
1051 /***********************************************************************
1052 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1055 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1058 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1061 /***********************************************************************
1062 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1065 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1070 LPWSTR MachineNameW = NULL;
1077 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1078 if (MachineNameW == NULL)
1079 return (HDEVINFO)INVALID_HANDLE_VALUE;
1082 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1083 MachineNameW, Reserved);
1085 MyFree(MachineNameW);
1090 /***********************************************************************
1091 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1093 * Create an empty DeviceInfoSet list.
1096 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1098 * hwndParent [I] hwnd needed for interface related actions.
1099 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1100 * local registry will be used.
1101 * Reserved [I] must be NULL
1104 * Success: empty list.
1105 * Failure: INVALID_HANDLE_VALUE.
1108 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1113 struct DeviceInfoSet *list = NULL;
1114 DWORD size = sizeof(struct DeviceInfoSet);
1116 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1117 debugstr_w(MachineName), Reserved);
1119 if (MachineName != NULL)
1121 FIXME("remote support is not implemented\n");
1122 SetLastError(ERROR_INVALID_MACHINENAME);
1123 return (HDEVINFO)INVALID_HANDLE_VALUE;
1126 if (Reserved != NULL)
1128 SetLastError(ERROR_INVALID_PARAMETER);
1129 return (HDEVINFO)INVALID_HANDLE_VALUE;
1132 list = HeapAlloc(GetProcessHeap(), 0, size);
1135 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1136 return (HDEVINFO)INVALID_HANDLE_VALUE;
1139 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1140 list->hwndParent = hwndParent;
1141 memcpy(&list->ClassGuid,
1142 ClassGuid ? ClassGuid : &GUID_NULL,
1143 sizeof(list->ClassGuid));
1145 list->devices = NULL;
1147 return (HDEVINFO)list;
1150 /***********************************************************************
1151 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1153 BOOL WINAPI SetupDiCreateDeviceInfoA(
1154 HDEVINFO DeviceInfoSet,
1156 CONST GUID *ClassGuid,
1157 PCSTR DeviceDescription,
1159 DWORD CreationFlags,
1160 PSP_DEVINFO_DATA DeviceInfoData)
1163 LPWSTR DeviceNameW = NULL;
1164 LPWSTR DeviceDescriptionW = NULL;
1168 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1169 if (DeviceNameW == NULL) return FALSE;
1171 if (DeviceDescription)
1173 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1174 if (DeviceDescriptionW == NULL)
1176 MyFree(DeviceNameW);
1181 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1182 hwndParent, CreationFlags, DeviceInfoData);
1184 MyFree(DeviceNameW);
1185 MyFree(DeviceDescriptionW);
1190 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1193 DWORD devNameLen = lstrlenW(devName), devInst = 0;
1196 TRACE("%s\n", debugstr_w(devName));
1197 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1202 devInst |= *ptr - '0';
1208 TRACE("%d\n", valid ? devInst : 0xffffffff);
1209 return valid ? devInst : 0xffffffff;
1212 /***********************************************************************
1213 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1215 BOOL WINAPI SetupDiCreateDeviceInfoW(
1216 HDEVINFO DeviceInfoSet,
1218 CONST GUID *ClassGuid,
1219 PCWSTR DeviceDescription,
1221 DWORD CreationFlags,
1222 PSP_DEVINFO_DATA DeviceInfoData)
1224 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1225 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1226 LPCWSTR instanceId = NULL;
1228 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1229 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1230 hwndParent, CreationFlags, DeviceInfoData);
1234 SetLastError(ERROR_INVALID_DEVINST_NAME);
1237 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1239 SetLastError(ERROR_INVALID_HANDLE);
1244 SetLastError(ERROR_INVALID_PARAMETER);
1247 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1249 SetLastError(ERROR_INVALID_HANDLE);
1252 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1253 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1255 SetLastError(ERROR_CLASS_MISMATCH);
1258 if ((CreationFlags & DICD_GENERATE_ID))
1260 if (strchrW(DeviceName, '\\'))
1261 SetLastError(ERROR_INVALID_DEVINST_NAME);
1264 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1265 '\\','%','0','4','d',0};
1270 DWORD i, highestDevID = 0;
1272 for (i = 0; i < set->cDevices; i++)
1274 struct DeviceInfo *devInfo =
1275 (struct DeviceInfo *)set->devices[i].Reserved;
1276 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1282 devName = devInfo->instanceId;
1283 id = SETUPDI_DevNameToDevID(devName);
1284 if (id != 0xffffffff && id > highestDevID)
1287 devId = highestDevID + 1;
1291 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1292 instanceId = HeapAlloc(GetProcessHeap(), 0,
1293 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1296 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1298 allocatedInstanceId = TRUE;
1310 instanceId = DeviceName;
1311 for (i = 0; ret && i < set->cDevices; i++)
1313 struct DeviceInfo *devInfo =
1314 (struct DeviceInfo *)set->devices[i].Reserved;
1316 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1318 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1325 SP_DEVINFO_DATA *dev = NULL;
1327 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1328 instanceId, TRUE, &dev);
1331 if (DeviceDescription)
1332 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1333 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1334 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1337 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1339 SetLastError(ERROR_INVALID_USER_BUFFER);
1343 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1347 if (allocatedInstanceId)
1348 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1353 /***********************************************************************
1354 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1356 BOOL WINAPI SetupDiRegisterDeviceInfo(
1357 HDEVINFO DeviceInfoSet,
1358 PSP_DEVINFO_DATA DeviceInfoData,
1360 PSP_DETSIG_CMPPROC CompareProc,
1361 PVOID CompareContext,
1362 PSP_DEVINFO_DATA DupDeviceInfoData)
1364 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1365 struct DeviceInfo *devInfo;
1367 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1368 CompareProc, CompareContext, DupDeviceInfoData);
1370 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1372 SetLastError(ERROR_INVALID_HANDLE);
1375 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1377 SetLastError(ERROR_INVALID_HANDLE);
1380 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1381 || !DeviceInfoData->Reserved)
1383 SetLastError(ERROR_INVALID_PARAMETER);
1386 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1387 if (devInfo->set != set)
1389 SetLastError(ERROR_INVALID_PARAMETER);
1392 if (devInfo->phantom)
1394 devInfo->phantom = FALSE;
1395 RegDeleteValueW(devInfo->key, Phantom);
1400 /***********************************************************************
1401 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1403 BOOL WINAPI SetupDiEnumDeviceInfo(
1406 PSP_DEVINFO_DATA info)
1410 TRACE("%p %d %p\n", devinfo, index, info);
1414 SetLastError(ERROR_INVALID_PARAMETER);
1417 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1419 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1420 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1422 if (index < list->cDevices)
1424 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1426 memcpy(info, &list->devices[index], info->cbSize);
1430 SetLastError(ERROR_INVALID_USER_BUFFER);
1433 SetLastError(ERROR_NO_MORE_ITEMS);
1436 SetLastError(ERROR_INVALID_HANDLE);
1439 SetLastError(ERROR_INVALID_HANDLE);
1443 /***********************************************************************
1444 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1446 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1447 HDEVINFO DeviceInfoSet,
1448 PSP_DEVINFO_DATA DeviceInfoData,
1449 PSTR DeviceInstanceId,
1450 DWORD DeviceInstanceIdSize,
1451 PDWORD RequiredSize)
1457 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1458 DeviceInstanceIdSize, RequiredSize);
1460 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1465 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1467 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1470 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1477 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1479 DeviceInstanceIdSize, NULL, NULL);
1485 if (len > DeviceInstanceIdSize)
1487 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1491 *RequiredSize = len;
1494 HeapFree(GetProcessHeap(), 0, instanceId);
1499 /***********************************************************************
1500 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1502 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1503 HDEVINFO DeviceInfoSet,
1504 PSP_DEVINFO_DATA DeviceInfoData,
1505 PWSTR DeviceInstanceId,
1506 DWORD DeviceInstanceIdSize,
1507 PDWORD RequiredSize)
1509 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1510 struct DeviceInfo *devInfo;
1512 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1513 DeviceInstanceIdSize, RequiredSize);
1515 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1517 SetLastError(ERROR_INVALID_HANDLE);
1520 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1522 SetLastError(ERROR_INVALID_HANDLE);
1525 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1526 || !DeviceInfoData->Reserved)
1528 SetLastError(ERROR_INVALID_PARAMETER);
1531 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1532 if (devInfo->set != set)
1534 SetLastError(ERROR_INVALID_PARAMETER);
1537 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1538 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1540 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1542 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1545 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1547 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1551 /***********************************************************************
1552 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1554 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1556 PCSTR InfSectionName,
1557 PSTR InfSectionWithExt,
1558 DWORD InfSectionWithExtSize,
1559 PDWORD RequiredSize,
1566 /***********************************************************************
1567 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1569 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1571 PCWSTR InfSectionName,
1572 PWSTR InfSectionWithExt,
1573 DWORD InfSectionWithExtSize,
1574 PDWORD RequiredSize,
1577 WCHAR szBuffer[MAX_PATH];
1580 LONG lLineCount = -1;
1582 lstrcpyW(szBuffer, InfSectionName);
1583 dwLength = lstrlenW(szBuffer);
1585 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1587 /* Test section name with '.NTx86' extension */
1588 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1589 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1591 if (lLineCount == -1)
1593 /* Test section name with '.NT' extension */
1594 lstrcpyW(&szBuffer[dwLength], NtExtension);
1595 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1600 /* Test section name with '.Win' extension */
1601 lstrcpyW(&szBuffer[dwLength], WinExtension);
1602 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1605 if (lLineCount == -1)
1607 /* Test section name without extension */
1608 szBuffer[dwLength] = 0;
1609 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1612 if (lLineCount == -1)
1614 SetLastError(ERROR_INVALID_PARAMETER);
1618 dwFullLength = lstrlenW(szBuffer);
1620 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1622 if (InfSectionWithExtSize < (dwFullLength + 1))
1624 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1628 lstrcpyW(InfSectionWithExt, szBuffer);
1629 if (Extension != NULL)
1631 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1635 if (RequiredSize != NULL)
1637 *RequiredSize = dwFullLength + 1;
1643 /***********************************************************************
1644 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1646 BOOL WINAPI SetupDiGetClassDescriptionA(
1647 const GUID* ClassGuid,
1648 PSTR ClassDescription,
1649 DWORD ClassDescriptionSize,
1650 PDWORD RequiredSize)
1652 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1653 ClassDescriptionSize,
1654 RequiredSize, NULL, NULL);
1657 /***********************************************************************
1658 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1660 BOOL WINAPI SetupDiGetClassDescriptionW(
1661 const GUID* ClassGuid,
1662 PWSTR ClassDescription,
1663 DWORD ClassDescriptionSize,
1664 PDWORD RequiredSize)
1666 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1667 ClassDescriptionSize,
1668 RequiredSize, NULL, NULL);
1671 /***********************************************************************
1672 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1674 BOOL WINAPI SetupDiGetClassDescriptionExA(
1675 const GUID* ClassGuid,
1676 PSTR ClassDescription,
1677 DWORD ClassDescriptionSize,
1678 PDWORD RequiredSize,
1686 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1691 if (hKey == INVALID_HANDLE_VALUE)
1693 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1697 dwLength = ClassDescriptionSize;
1698 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1699 (LPBYTE)ClassDescription, &dwLength );
1700 if (RequiredSize) *RequiredSize = dwLength;
1705 /***********************************************************************
1706 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1708 BOOL WINAPI SetupDiGetClassDescriptionExW(
1709 const GUID* ClassGuid,
1710 PWSTR ClassDescription,
1711 DWORD ClassDescriptionSize,
1712 PDWORD RequiredSize,
1720 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1725 if (hKey == INVALID_HANDLE_VALUE)
1727 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1731 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1732 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1733 (LPBYTE)ClassDescription, &dwLength );
1734 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1739 /***********************************************************************
1740 * SetupDiGetClassDevsA (SETUPAPI.@)
1742 HDEVINFO WINAPI SetupDiGetClassDevsA(
1749 LPWSTR enumstrW = NULL;
1753 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1754 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1757 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1760 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1762 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
1764 HeapFree(GetProcessHeap(), 0, enumstrW);
1770 /***********************************************************************
1771 * SetupDiGetClassDevsExA (SETUPAPI.@)
1773 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1783 LPWSTR enumstrW = NULL, machineW = NULL;
1787 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1788 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1791 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1794 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1798 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1799 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1802 HeapFree(GetProcessHeap(), 0, enumstrW);
1803 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1806 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1808 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
1809 machineW, reserved);
1810 HeapFree(GetProcessHeap(), 0, enumstrW);
1811 HeapFree(GetProcessHeap(), 0, machineW);
1817 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
1818 const GUID *interface)
1821 WCHAR subKeyName[MAX_PATH];
1822 LONG l = ERROR_SUCCESS;
1824 for (i = 0; !l; i++)
1826 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1827 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1831 SP_DEVICE_INTERFACE_DATA *iface = NULL;
1833 /* The subkey name is the reference string, with a '#' prepended */
1834 SETUPDI_AddInterfaceInstance(dev, interface, subKeyName + 1,
1836 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1839 WCHAR symbolicLink[MAX_PATH];
1842 len = sizeof(symbolicLink);
1843 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
1844 (BYTE *)symbolicLink, &len);
1845 if (!l && dataType == REG_SZ)
1846 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
1847 RegCloseKey(subKey);
1851 /* FIXME: find and add all the device's interfaces to the device */
1854 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1855 HKEY key, const GUID *interface, LPCWSTR enumstr)
1857 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1859 WCHAR subKeyName[MAX_PATH];
1861 HKEY enumKey = INVALID_HANDLE_VALUE;
1863 TRACE("%s\n", debugstr_w(enumstr));
1865 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1867 for (i = 0; !l; i++)
1869 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1870 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1875 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1878 WCHAR deviceInst[MAX_PATH * 3];
1881 len = sizeof(deviceInst);
1882 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1883 (BYTE *)deviceInst, &len);
1884 if (!l && dataType == REG_SZ)
1886 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1887 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1891 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1895 WCHAR deviceClassStr[40];
1897 len = sizeof(deviceClassStr);
1898 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1899 &dataType, (BYTE *)deviceClassStr, &len);
1900 if (!l && dataType == REG_SZ &&
1901 deviceClassStr[0] == '{' &&
1902 deviceClassStr[37] == '}')
1905 SP_DEVINFO_DATA *dev;
1907 deviceClassStr[37] = 0;
1908 UuidFromStringW(&deviceClassStr[1],
1910 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
1911 0 /* FIXME: DevInst */, deviceInst,
1913 SETUPDI_AddDeviceInterfaces(dev, subKey,
1916 RegCloseKey(deviceKey);
1920 RegCloseKey(subKey);
1924 if (enumKey != INVALID_HANDLE_VALUE)
1925 RegCloseKey(enumKey);
1928 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1929 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1931 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1932 DIOCR_INTERFACE, NULL, NULL);
1934 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1935 debugstr_w(enumstr), flags);
1937 if (interfacesKey != INVALID_HANDLE_VALUE)
1939 if (flags & DIGCF_ALLCLASSES)
1942 WCHAR interfaceGuidStr[40];
1943 LONG l = ERROR_SUCCESS;
1945 for (i = 0; !l; i++)
1947 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
1948 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
1949 NULL, NULL, NULL, NULL);
1952 if (interfaceGuidStr[0] == '{' &&
1953 interfaceGuidStr[37] == '}')
1958 interfaceGuidStr[37] = 0;
1959 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
1960 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
1961 KEY_READ, &interfaceKey);
1964 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1965 interfaceKey, &interfaceGuid, enumstr);
1966 RegCloseKey(interfaceKey);
1974 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
1975 * interface's key, so just pass that long
1977 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1978 interfacesKey, interface, enumstr);
1980 RegCloseKey(interfacesKey);
1984 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
1985 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
1987 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1989 WCHAR subKeyName[MAX_PATH];
1990 LONG l = ERROR_SUCCESS;
1992 TRACE("%s\n", debugstr_w(parent));
1994 for (i = 0; !l; i++)
1996 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1997 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2002 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2005 WCHAR classGuid[40];
2008 len = sizeof(classGuid);
2009 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
2010 (BYTE *)classGuid, &len);
2011 if (!l && dataType == REG_SZ)
2013 if (classGuid[0] == '{' && classGuid[37] == '}')
2018 UuidFromStringW(&classGuid[1], &deviceClass);
2019 if ((flags & DIGCF_ALLCLASSES) ||
2020 IsEqualGUID(class, &deviceClass))
2022 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
2025 instanceId = HeapAlloc(GetProcessHeap(), 0,
2026 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
2030 SP_DEVINFO_DATA *dev;
2032 sprintfW(instanceId, fmt, parent, subKeyName);
2033 SETUPDI_AddDeviceToSet(set, &deviceClass,
2034 0 /* FIXME: DevInst */, instanceId,
2036 HeapFree(GetProcessHeap(), 0, instanceId);
2041 RegCloseKey(subKey);
2047 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
2048 LPCWSTR enumstr, DWORD flags)
2050 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
2051 DIOCR_INSTALLER, NULL, NULL);
2053 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
2054 debugstr_w(enumstr), flags);
2056 if (classesKey != INVALID_HANDLE_VALUE)
2061 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
2066 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2067 enumKey, class, flags);
2068 RegCloseKey(enumKey);
2074 WCHAR subKeyName[MAX_PATH];
2075 LONG l = ERROR_SUCCESS;
2077 for (i = 0; !l; i++)
2079 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2080 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
2086 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
2090 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2091 subKeyName, subKey, class, flags);
2092 RegCloseKey(subKey);
2097 RegCloseKey(classesKey);
2101 /***********************************************************************
2102 * SetupDiGetClassDevsW (SETUPAPI.@)
2104 HDEVINFO WINAPI SetupDiGetClassDevsW(
2110 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2114 /***********************************************************************
2115 * SetupDiGetClassDevsExW (SETUPAPI.@)
2117 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2126 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2130 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2131 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2134 if (!(flags & DIGCF_ALLCLASSES) && !class)
2136 SetLastError(ERROR_INVALID_PARAMETER);
2139 if (flags & unsupportedFlags)
2140 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2144 set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
2148 FIXME("%s: unimplemented for remote machines\n",
2149 debugstr_w(machine));
2150 else if (flags & DIGCF_DEVICEINTERFACE)
2151 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2153 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2158 /***********************************************************************
2159 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2161 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2162 HDEVINFO DeviceInfoSet,
2163 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2165 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2167 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2169 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2171 SetLastError(ERROR_INVALID_HANDLE);
2174 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2176 SetLastError(ERROR_INVALID_HANDLE);
2180 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2182 SetLastError(ERROR_INVALID_PARAMETER);
2185 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2186 DevInfoData->RemoteMachineHandle = NULL;
2187 DevInfoData->RemoteMachineName[0] = '\0';
2191 /***********************************************************************
2192 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2194 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2195 HDEVINFO DeviceInfoSet,
2196 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2198 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2200 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2202 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2204 SetLastError(ERROR_INVALID_HANDLE);
2207 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2209 SetLastError(ERROR_INVALID_HANDLE);
2213 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2215 SetLastError(ERROR_INVALID_PARAMETER);
2218 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2219 DevInfoData->RemoteMachineHandle = NULL;
2220 DevInfoData->RemoteMachineName[0] = '\0';
2224 /***********************************************************************
2225 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2227 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2228 HDEVINFO DeviceInfoSet,
2229 PSP_DEVINFO_DATA DeviceInfoData,
2230 const GUID *InterfaceClassGuid,
2231 PCSTR ReferenceString,
2232 DWORD CreationFlags,
2233 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2236 LPWSTR ReferenceStringW = NULL;
2238 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2239 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2240 CreationFlags, DeviceInterfaceData);
2242 if (ReferenceString)
2244 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2245 if (ReferenceStringW == NULL) return FALSE;
2248 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2249 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2250 DeviceInterfaceData);
2252 MyFree(ReferenceStringW);
2257 /***********************************************************************
2258 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2260 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2261 HDEVINFO DeviceInfoSet,
2262 PSP_DEVINFO_DATA DeviceInfoData,
2263 const GUID *InterfaceClassGuid,
2264 PCWSTR ReferenceString,
2265 DWORD CreationFlags,
2266 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2268 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2269 struct DeviceInfo *devInfo;
2270 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2273 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2274 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2275 CreationFlags, DeviceInterfaceData);
2277 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2279 SetLastError(ERROR_INVALID_HANDLE);
2282 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2284 SetLastError(ERROR_INVALID_HANDLE);
2287 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2288 || !DeviceInfoData->Reserved)
2290 SetLastError(ERROR_INVALID_PARAMETER);
2293 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2294 if (devInfo->set != set)
2296 SetLastError(ERROR_INVALID_PARAMETER);
2299 if (!InterfaceClassGuid)
2301 SetLastError(ERROR_INVALID_USER_BUFFER);
2304 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2305 ReferenceString, &iface)))
2307 if (DeviceInterfaceData)
2309 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2311 SetLastError(ERROR_INVALID_USER_BUFFER);
2315 memcpy(DeviceInterfaceData, iface, sizeof(*iface));
2321 /***********************************************************************
2322 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2324 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2325 HDEVINFO DeviceInfoSet,
2326 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2330 PCSTR InfSectionName)
2333 PWSTR InfSectionNameW = NULL;
2335 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2336 samDesired, InfHandle, InfSectionName);
2339 if (!InfSectionName)
2341 SetLastError(ERROR_INVALID_PARAMETER);
2342 return INVALID_HANDLE_VALUE;
2344 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2345 if (!InfSectionNameW)
2346 return INVALID_HANDLE_VALUE;
2348 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2349 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2351 MyFree(InfSectionNameW);
2355 static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo)
2357 static const WCHAR hash[] = {'#',0};
2358 PWSTR instancePath = NULL;
2360 if (ifaceInfo->referenceString)
2362 instancePath = HeapAlloc(GetProcessHeap(), 0,
2363 (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR));
2366 lstrcpyW(instancePath, hash);
2367 lstrcatW(instancePath, ifaceInfo->referenceString);
2370 SetLastError(ERROR_OUTOFMEMORY);
2374 instancePath = HeapAlloc(GetProcessHeap(), 0,
2375 (lstrlenW(hash) + 1) * sizeof(WCHAR));
2377 lstrcpyW(instancePath, hash);
2379 return instancePath;
2382 /***********************************************************************
2383 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2385 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2386 HDEVINFO DeviceInfoSet,
2387 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2391 PCWSTR InfSectionName)
2393 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2394 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2397 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2398 samDesired, InfHandle, InfSectionName);
2400 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2401 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2403 SetLastError(ERROR_INVALID_HANDLE);
2404 return INVALID_HANDLE_VALUE;
2406 if (!DeviceInterfaceData ||
2407 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2408 !DeviceInterfaceData->Reserved)
2410 SetLastError(ERROR_INVALID_PARAMETER);
2411 return INVALID_HANDLE_VALUE;
2413 if (InfHandle && !InfSectionName)
2415 SetLastError(ERROR_INVALID_PARAMETER);
2416 return INVALID_HANDLE_VALUE;
2418 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2419 samDesired, NULL, &interfacesKey, NULL)))
2422 WCHAR bracedGuidString[39];
2424 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2426 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2427 samDesired, NULL, &parent, NULL)))
2429 struct InterfaceInfo *ifaceInfo =
2430 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2431 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2437 l = RegCreateKeyExW(parent, instancePath, 0, NULL, 0,
2438 samDesired, NULL, &key, NULL);
2442 key = INVALID_HANDLE_VALUE;
2445 FIXME("INF section installation unsupported\n");
2447 HeapFree(GetProcessHeap(), 0, instancePath);
2448 RegCloseKey(parent);
2452 RegCloseKey(interfacesKey);
2459 /***********************************************************************
2460 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2462 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2463 HDEVINFO DeviceInfoSet,
2464 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2467 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2471 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2473 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2474 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2476 SetLastError(ERROR_INVALID_HANDLE);
2479 if (!DeviceInterfaceData ||
2480 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2481 !DeviceInterfaceData->Reserved)
2483 SetLastError(ERROR_INVALID_PARAMETER);
2486 parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid,
2487 KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
2488 if (parent != INVALID_HANDLE_VALUE)
2490 struct InterfaceInfo *ifaceInfo =
2491 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2492 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2496 LONG l = RegDeleteKeyW(parent, instancePath);
2502 HeapFree(GetProcessHeap(), 0, instancePath);
2504 RegCloseKey(parent);
2509 /***********************************************************************
2510 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2513 * DeviceInfoSet [I] Set of devices from which to enumerate
2515 * DeviceInfoData [I] (Optional) If specified, a specific device
2516 * instance from which to enumerate interfaces.
2517 * If it isn't specified, all interfaces for all
2518 * devices in the set are enumerated.
2519 * InterfaceClassGuid [I] The interface class to enumerate.
2520 * MemberIndex [I] An index of the interface instance to enumerate.
2521 * A caller should start with MemberIndex set to 0,
2522 * and continue until the function fails with
2523 * ERROR_NO_MORE_ITEMS.
2524 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2525 * member must be set to
2526 * sizeof(SP_DEVICE_INTERFACE_DATA).
2529 * Success: non-zero value.
2530 * Failure: FALSE. Call GetLastError() for more info.
2532 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2533 HDEVINFO DeviceInfoSet,
2534 PSP_DEVINFO_DATA DeviceInfoData,
2535 CONST GUID * InterfaceClassGuid,
2537 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2539 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2542 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2543 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2545 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2546 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2548 SetLastError(ERROR_INVALID_HANDLE);
2551 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2552 !DeviceInfoData->Reserved))
2554 SetLastError(ERROR_INVALID_PARAMETER);
2557 if (!DeviceInterfaceData ||
2558 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2560 SetLastError(ERROR_INVALID_PARAMETER);
2565 struct DeviceInfo *devInfo =
2566 (struct DeviceInfo *)DeviceInfoData->Reserved;
2567 struct InterfaceInstances *iface;
2569 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2571 if (MemberIndex < iface->cInstances)
2572 memcpy(DeviceInterfaceData, &iface->instances[MemberIndex],
2573 sizeof(SP_DEVICE_INTERFACE_DATA));
2576 SetLastError(ERROR_NO_MORE_ITEMS);
2581 SetLastError(ERROR_NO_MORE_ITEMS);
2585 DWORD i, cEnumerated = 0;
2588 for (i = 0; !found && cEnumerated < MemberIndex + 1 &&
2589 i < set->cDevices; i++)
2591 struct DeviceInfo *devInfo =
2592 (struct DeviceInfo *)set->devices[i].Reserved;
2593 struct InterfaceInstances *iface;
2595 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2597 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2598 cEnumerated += iface->cInstances;
2601 DWORD instanceIndex = MemberIndex - cEnumerated;
2603 memcpy(DeviceInterfaceData,
2604 &iface->instances[instanceIndex],
2605 sizeof(SP_DEVICE_INTERFACE_DATA));
2606 cEnumerated += instanceIndex + 1;
2613 SetLastError(ERROR_NO_MORE_ITEMS);
2618 /***********************************************************************
2619 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2621 * Destroy a DeviceInfoList and free all used memory of the list.
2624 * devinfo [I] DeviceInfoList pointer to list to destroy
2627 * Success: non zero value.
2628 * Failure: zero value.
2630 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2634 TRACE("%p\n", devinfo);
2635 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2637 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2639 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2643 for (i = 0; i < list->cDevices; i++)
2644 SETUPDI_FreeDeviceInfo(
2645 (struct DeviceInfo *)list->devices[i].Reserved);
2646 HeapFree(GetProcessHeap(), 0, list->devices);
2647 HeapFree(GetProcessHeap(), 0, list);
2653 SetLastError(ERROR_INVALID_HANDLE);
2658 /***********************************************************************
2659 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2661 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2662 HDEVINFO DeviceInfoSet,
2663 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2664 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2665 DWORD DeviceInterfaceDetailDataSize,
2666 PDWORD RequiredSize,
2667 PSP_DEVINFO_DATA DeviceInfoData)
2669 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2670 struct InterfaceInfo *info;
2671 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)
2675 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2676 DeviceInterfaceData, DeviceInterfaceDetailData,
2677 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2679 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2680 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2682 SetLastError(ERROR_INVALID_HANDLE);
2685 if (!DeviceInterfaceData ||
2686 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2687 !DeviceInterfaceData->Reserved)
2689 SetLastError(ERROR_INVALID_PARAMETER);
2692 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2693 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) ||
2694 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2696 SetLastError(ERROR_INVALID_USER_BUFFER);
2699 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2701 SetLastError(ERROR_INVALID_USER_BUFFER);
2704 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2705 if (info->symbolicLink)
2706 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2707 NULL, 0, NULL, NULL);
2708 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2710 if (info->symbolicLink)
2711 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2712 DeviceInterfaceDetailData->DevicePath,
2713 DeviceInterfaceDetailDataSize -
2714 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2717 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2718 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2719 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2725 *RequiredSize = bytesNeeded;
2726 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2731 /***********************************************************************
2732 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2734 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2735 HDEVINFO DeviceInfoSet,
2736 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2737 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2738 DWORD DeviceInterfaceDetailDataSize,
2739 PDWORD RequiredSize,
2740 PSP_DEVINFO_DATA DeviceInfoData)
2742 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2743 struct InterfaceInfo *info;
2744 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2745 + sizeof(WCHAR); /* include NULL terminator */
2748 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2749 DeviceInterfaceData, DeviceInterfaceDetailData,
2750 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2752 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2753 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2755 SetLastError(ERROR_INVALID_HANDLE);
2758 if (!DeviceInterfaceData ||
2759 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2760 !DeviceInterfaceData->Reserved)
2762 SetLastError(ERROR_INVALID_PARAMETER);
2765 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2766 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2767 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2769 SetLastError(ERROR_INVALID_USER_BUFFER);
2772 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2774 SetLastError(ERROR_INVALID_USER_BUFFER);
2777 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2778 if (info->symbolicLink)
2779 bytesNeeded += lstrlenW(info->symbolicLink);
2780 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2782 if (info->symbolicLink)
2783 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
2785 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2786 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2787 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2793 *RequiredSize = bytesNeeded;
2794 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2799 struct PropertyMapEntry
2806 static struct PropertyMapEntry PropertyMap[] = {
2807 { REG_SZ, "DeviceDesc", DeviceDesc },
2808 { REG_MULTI_SZ, "HardwareId", HardwareId },
2809 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
2810 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
2811 { REG_SZ, "Service", Service },
2812 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
2813 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
2814 { REG_SZ, "Class", Class },
2815 { REG_SZ, "ClassGUID", ClassGUID },
2816 { REG_SZ, "Driver", Driver },
2817 { REG_DWORD, "ConfigFlags", ConfigFlags },
2818 { REG_SZ, "Mfg", Mfg },
2819 { REG_SZ, "FriendlyName", FriendlyName },
2820 { REG_SZ, "LocationInformation", LocationInformation },
2821 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
2822 { REG_DWORD, "Capabilities", Capabilities },
2823 { REG_DWORD, "UINumber", UINumber },
2824 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
2825 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
2828 /***********************************************************************
2829 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2831 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2832 HDEVINFO DeviceInfoSet,
2833 PSP_DEVINFO_DATA DeviceInfoData,
2835 PDWORD PropertyRegDataType,
2836 PBYTE PropertyBuffer,
2837 DWORD PropertyBufferSize,
2838 PDWORD RequiredSize)
2841 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2842 struct DeviceInfo *devInfo;
2844 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2845 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2848 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2850 SetLastError(ERROR_INVALID_HANDLE);
2853 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2855 SetLastError(ERROR_INVALID_HANDLE);
2858 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2859 || !DeviceInfoData->Reserved)
2861 SetLastError(ERROR_INVALID_PARAMETER);
2864 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2865 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2866 && PropertyMap[Property].nameA)
2868 DWORD size = PropertyBufferSize;
2869 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
2870 NULL, PropertyRegDataType, PropertyBuffer, &size);
2873 *RequiredSize = size;
2882 /***********************************************************************
2883 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2885 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2886 HDEVINFO DeviceInfoSet,
2887 PSP_DEVINFO_DATA DeviceInfoData,
2889 PDWORD PropertyRegDataType,
2890 PBYTE PropertyBuffer,
2891 DWORD PropertyBufferSize,
2892 PDWORD RequiredSize)
2895 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2896 struct DeviceInfo *devInfo;
2898 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2899 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2902 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2904 SetLastError(ERROR_INVALID_HANDLE);
2907 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2909 SetLastError(ERROR_INVALID_HANDLE);
2912 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2913 || !DeviceInfoData->Reserved)
2915 SetLastError(ERROR_INVALID_PARAMETER);
2918 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2919 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2920 && PropertyMap[Property].nameW)
2922 DWORD size = PropertyBufferSize;
2923 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2924 NULL, PropertyRegDataType, PropertyBuffer, &size);
2927 *RequiredSize = size;
2936 /***********************************************************************
2937 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2939 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2940 HDEVINFO DeviceInfoSet,
2941 PSP_DEVINFO_DATA DeviceInfoData,
2943 const BYTE *PropertyBuffer,
2944 DWORD PropertyBufferSize)
2947 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2948 struct DeviceInfo *devInfo;
2950 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2951 PropertyBuffer, PropertyBufferSize);
2953 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2955 SetLastError(ERROR_INVALID_HANDLE);
2958 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2960 SetLastError(ERROR_INVALID_HANDLE);
2963 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2964 || !DeviceInfoData->Reserved)
2966 SetLastError(ERROR_INVALID_PARAMETER);
2969 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2970 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2971 && PropertyMap[Property].nameA)
2973 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2974 PropertyMap[Property].regType, PropertyBuffer,
2975 PropertyBufferSize);
2984 /***********************************************************************
2985 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2987 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2988 HDEVINFO DeviceInfoSet,
2989 PSP_DEVINFO_DATA DeviceInfoData,
2991 const BYTE *PropertyBuffer,
2992 DWORD PropertyBufferSize)
2995 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2996 struct DeviceInfo *devInfo;
2998 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2999 PropertyBuffer, PropertyBufferSize);
3001 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3003 SetLastError(ERROR_INVALID_HANDLE);
3006 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3008 SetLastError(ERROR_INVALID_HANDLE);
3011 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3012 || !DeviceInfoData->Reserved)
3014 SetLastError(ERROR_INVALID_PARAMETER);
3017 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3018 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3019 && PropertyMap[Property].nameW)
3021 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
3022 PropertyMap[Property].regType, PropertyBuffer,
3023 PropertyBufferSize);
3032 /***********************************************************************
3033 * SetupDiInstallClassA (SETUPAPI.@)
3035 BOOL WINAPI SetupDiInstallClassA(
3041 UNICODE_STRING FileNameW;
3044 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
3046 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3050 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
3052 RtlFreeUnicodeString(&FileNameW);
3057 static HKEY CreateClassKey(HINF hInf)
3059 WCHAR FullBuffer[MAX_PATH];
3060 WCHAR Buffer[MAX_PATH];
3064 if (!SetupGetLineTextW(NULL,
3072 return INVALID_HANDLE_VALUE;
3075 lstrcpyW(FullBuffer, ControlClass);
3076 lstrcatW(FullBuffer, Buffer);
3078 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3084 if (!SetupGetLineTextW(NULL,
3092 return INVALID_HANDLE_VALUE;
3095 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3099 REG_OPTION_NON_VOLATILE,
3105 return INVALID_HANDLE_VALUE;
3110 if (RegSetValueExW(hClassKey,
3115 RequiredSize * sizeof(WCHAR)))
3117 RegCloseKey(hClassKey);
3118 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3120 return INVALID_HANDLE_VALUE;
3126 /***********************************************************************
3127 * SetupDiInstallClassW (SETUPAPI.@)
3129 BOOL WINAPI SetupDiInstallClassW(
3135 WCHAR SectionName[MAX_PATH];
3136 DWORD SectionNameLength = 0;
3138 BOOL bFileQueueCreated = FALSE;
3144 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
3146 SetLastError(ERROR_INVALID_PARAMETER);
3150 /* Open the .inf file */
3151 hInf = SetupOpenInfFileW(InfFileName,
3155 if (hInf == INVALID_HANDLE_VALUE)
3161 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3162 hClassKey = CreateClassKey(hInf);
3163 if (hClassKey == INVALID_HANDLE_VALUE)
3165 SetupCloseInfFile(hInf);
3170 /* Try to append a layout file */
3172 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3175 /* Retrieve the actual section name */
3176 SetupDiGetActualSectionToInstallW(hInf,
3184 if (!(Flags & DI_NOVCP))
3186 FileQueue = SetupOpenFileQueue();
3187 if (FileQueue == INVALID_HANDLE_VALUE)
3189 SetupCloseInfFile(hInf);
3193 bFileQueueCreated = TRUE;
3198 SetupInstallFromInfSectionW(NULL,
3207 INVALID_HANDLE_VALUE,
3210 /* FIXME: More code! */
3212 if (bFileQueueCreated)
3213 SetupCloseFileQueue(FileQueue);
3215 SetupCloseInfFile(hInf);
3221 /***********************************************************************
3222 * SetupDiOpenClassRegKey (SETUPAPI.@)
3224 HKEY WINAPI SetupDiOpenClassRegKey(
3225 const GUID* ClassGuid,
3228 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3229 DIOCR_INSTALLER, NULL, NULL);
3233 /***********************************************************************
3234 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3236 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3237 const GUID* ClassGuid,
3243 PWSTR MachineNameW = NULL;
3250 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3251 if (MachineNameW == NULL)
3252 return INVALID_HANDLE_VALUE;
3255 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3256 Flags, MachineNameW, Reserved);
3258 MyFree(MachineNameW);
3264 /***********************************************************************
3265 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3267 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3268 const GUID* ClassGuid,
3279 if (MachineName != NULL)
3281 FIXME("Remote access not supported yet!\n");
3282 return INVALID_HANDLE_VALUE;
3285 if (Flags == DIOCR_INSTALLER)
3287 lpKeyName = ControlClass;
3289 else if (Flags == DIOCR_INTERFACE)
3291 lpKeyName = DeviceClasses;
3295 ERR("Invalid Flags parameter!\n");
3296 SetLastError(ERROR_INVALID_PARAMETER);
3297 return INVALID_HANDLE_VALUE;
3302 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3309 hClassesKey = INVALID_HANDLE_VALUE;
3315 WCHAR bracedGuidString[39];
3317 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3319 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3325 if ((l = RegOpenKeyExW(hClassesKey,
3332 key = INVALID_HANDLE_VALUE;
3334 RegCloseKey(hClassesKey);
3339 key = INVALID_HANDLE_VALUE;
3345 /***********************************************************************
3346 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3348 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3349 HDEVINFO DeviceInfoSet,
3352 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3354 FIXME("%p %s %08x %p\n",
3355 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3359 /***********************************************************************
3360 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3362 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3363 HDEVINFO DeviceInfoSet,
3366 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3368 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3369 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3373 /***********************************************************************
3374 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3376 BOOL WINAPI SetupDiSetClassInstallParamsA(
3377 HDEVINFO DeviceInfoSet,
3378 PSP_DEVINFO_DATA DeviceInfoData,
3379 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3380 DWORD ClassInstallParamsSize)
3382 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3383 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3387 /***********************************************************************
3388 * SetupDiCallClassInstaller (SETUPAPI.@)
3390 BOOL WINAPI SetupDiCallClassInstaller(
3391 DI_FUNCTION InstallFunction,
3392 HDEVINFO DeviceInfoSet,
3393 PSP_DEVINFO_DATA DeviceInfoData)
3395 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3399 /***********************************************************************
3400 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3402 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3403 HDEVINFO DeviceInfoSet,
3404 PSP_DEVINFO_DATA DeviceInfoData,
3405 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3407 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3411 /***********************************************************************
3412 * SetupDiOpenDevRegKey (SETUPAPI.@)
3414 HKEY WINAPI SetupDiOpenDevRegKey(
3415 HDEVINFO DeviceInfoSet,
3416 PSP_DEVINFO_DATA DeviceInfoData,
3422 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3423 Scope, HwProfile, KeyType, samDesired);
3424 return INVALID_HANDLE_VALUE;