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"
43 #include "setupapi_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
48 /* Unicode constants */
49 static const WCHAR Chicago[] = {'$','C','h','i','c','a','g','o','$',0};
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 Signature[] = {'S','i','g','n','a','t','u','r','e',0};
59 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
60 static const WCHAR WinExtension[] = {'.','W','i','n',0};
62 /* Registry key and value names */
63 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
64 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
65 'C','o','n','t','r','o','l','\\',
66 'C','l','a','s','s',0};
68 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
69 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
70 'C','o','n','t','r','o','l','\\',
71 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
72 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
73 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
75 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
76 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
77 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
78 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
79 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
80 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
81 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
82 static const WCHAR Mfg[] = {'M','f','g',0};
83 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
84 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
85 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
86 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
87 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
88 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
89 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
90 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
92 /* is used to identify if a DeviceInfoSet pointer is
94 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
98 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
105 struct DeviceInstance
108 SP_DEVINFO_DATA data;
111 /* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */
114 LPWSTR referenceString;
116 PSP_DEVINFO_DATA device;
119 /* A device may have multiple instances of the same interface, so this holds
120 * each instance belonging to a particular interface.
122 struct InterfaceInstances
126 DWORD cInstancesAllocated;
127 SP_DEVICE_INTERFACE_DATA *instances;
131 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
134 struct DeviceInfoSet *set;
139 struct list interfaces;
142 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
144 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
145 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
146 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
149 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
150 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
151 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
154 static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
158 for (i = 0; i < instances->cInstances; i++)
160 struct InterfaceInfo *ifaceInfo =
161 (struct InterfaceInfo *)instances->instances[i].Reserved;
163 if (ifaceInfo->device && ifaceInfo->device->Reserved)
165 struct DeviceInfo *devInfo =
166 (struct DeviceInfo *)ifaceInfo->device->Reserved;
168 if (devInfo->phantom)
169 SetupDiDeleteDeviceInterfaceRegKey(devInfo->set,
170 &instances->instances[i], 0);
172 HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
173 HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
174 HeapFree(GetProcessHeap(), 0, ifaceInfo);
176 HeapFree(GetProcessHeap(), 0, instances->instances);
179 /* Finds the interface with interface class InterfaceClassGuid in the device.
180 * Returns TRUE if found, and updates *interface to point to device's
181 * interfaces member where the given interface was found.
182 * Returns FALSE if not found.
184 static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
185 const GUID *InterfaceClassGuid, struct InterfaceInstances **iface_ret)
188 struct InterfaceInstances *iface;
190 TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
192 LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances,
195 if (IsEqualGUID(&iface->guid, InterfaceClassGuid))
202 TRACE("returning %d (%p)\n", found, found ? *iface_ret : NULL);
206 /* Finds the interface instance with reference string ReferenceString in the
207 * interface instance map. Returns TRUE if found, and updates instanceIndex to
208 * the index of the interface instance's instances member
209 * where the given instance was found. Returns FALSE if not found.
211 static BOOL SETUPDI_FindInterfaceInstance(
212 const struct InterfaceInstances *instances,
213 LPCWSTR ReferenceString, DWORD *instanceIndex)
218 TRACE("%s\n", debugstr_w(ReferenceString));
220 for (i = 0; !found && i < instances->cInstances; i++)
222 SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
223 struct InterfaceInfo *ifaceInfo =
224 (struct InterfaceInfo *)ifaceData->Reserved;
226 if (!ReferenceString && !ifaceInfo->referenceString)
231 else if (ReferenceString && ifaceInfo->referenceString &&
232 !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
238 TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
242 static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
243 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
245 static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
250 SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
251 /* omit length of format specifiers, but include NULL terminator: */
252 len = lstrlenW(fmt) - 4 + 1;
253 len += lstrlenW(instanceId) + lstrlenW(guidStr);
254 if (ReferenceString && *ReferenceString)
256 /* space for a hash between string and reference string: */
257 len += lstrlenW(ReferenceString) + 1;
259 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
262 int printed = sprintfW(ret, fmt, instanceId, guidStr);
265 /* replace '\\' with '#' after the "\\\\?\\" beginning */
266 for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
268 if (ReferenceString && *ReferenceString)
271 lstrcpyW(ret + printed + 1, ReferenceString);
277 /* Adds an interface with the given interface class and reference string to
278 * the device, if it doesn't already exist in the device. If iface is not
279 * NULL, returns a pointer to the newly added (or already existing) interface.
281 static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData,
282 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
283 SP_DEVICE_INTERFACE_DATA **ifaceData)
285 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
286 BOOL newInterface = FALSE, ret;
287 struct InterfaceInstances *iface = NULL;
289 TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
290 debugstr_w(ReferenceString), iface);
292 if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
294 iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
295 sizeof(struct InterfaceInstances));
298 list_add_tail(&devInfo->interfaces, &iface->entry);
304 DWORD instanceIndex = 0;
306 if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
309 SP_DEVICE_INTERFACE_DATA *instance = NULL;
311 if (!iface->cInstancesAllocated)
313 iface->instances = HeapAlloc(GetProcessHeap(), 0,
314 sizeof(SP_DEVICE_INTERFACE_DATA));
315 if (iface->instances)
316 instance = &iface->instances[iface->cInstancesAllocated++];
318 else if (iface->cInstances == iface->cInstancesAllocated)
320 iface->instances = HeapReAlloc(GetProcessHeap(), 0,
322 (iface->cInstancesAllocated + 1) *
323 sizeof(SP_DEVICE_INTERFACE_DATA));
324 if (iface->instances)
325 instance = &iface->instances[iface->cInstancesAllocated++];
328 instance = &iface->instances[iface->cInstances];
331 struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
332 0, sizeof(struct InterfaceInfo));
337 ifaceInfo->device = DeviceInfoData;
338 ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
339 devInfo->instanceId, InterfaceClassGuid,
343 ifaceInfo->referenceString =
344 HeapAlloc(GetProcessHeap(), 0,
345 (lstrlenW(ReferenceString) + 1) *
347 if (ifaceInfo->referenceString)
348 lstrcpyW(ifaceInfo->referenceString,
354 ifaceInfo->referenceString = NULL;
361 sizeof(SP_DEVICE_INTERFACE_DATA);
362 instance->InterfaceClassGuid = *InterfaceClassGuid;
363 instance->Flags = SPINT_ACTIVE; /* FIXME */
364 instance->Reserved = (ULONG_PTR)ifaceInfo;
366 iface->guid = *InterfaceClassGuid;
367 key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set,
368 instance, 0, KEY_WRITE, NULL, NULL);
369 if (key != INVALID_HANDLE_VALUE)
371 RegSetValueExW(key, SymbolicLink, 0, REG_SZ,
372 (BYTE *)ifaceInfo->symbolicLink,
373 lstrlenW(ifaceInfo->symbolicLink) *
378 *ifaceData = instance;
381 HeapFree(GetProcessHeap(), 0, ifaceInfo);
388 *ifaceData = &iface->instances[instanceIndex];
393 TRACE("returning %d\n", ret);
397 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
398 LPCWSTR symbolicLink)
400 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
405 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
406 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
407 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
408 if (info->symbolicLink)
410 lstrcpyW(info->symbolicLink, symbolicLink);
417 static HKEY SETUPDI_CreateDevKey(struct DeviceInfo *devInfo)
419 HKEY enumKey, key = INVALID_HANDLE_VALUE;
422 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
423 NULL, &enumKey, NULL);
426 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
427 KEY_READ | KEY_WRITE, NULL, &key, NULL);
428 RegCloseKey(enumKey);
433 static HKEY SETUPDI_CreateDrvKey(struct DeviceInfo *devInfo)
435 static const WCHAR slash[] = { '\\',0 };
436 WCHAR classKeyPath[MAX_PATH];
437 HKEY classKey, key = INVALID_HANDLE_VALUE;
440 lstrcpyW(classKeyPath, ControlClass);
441 lstrcatW(classKeyPath, slash);
442 SETUPDI_GuidToString(&devInfo->set->ClassGuid,
443 classKeyPath + lstrlenW(classKeyPath));
444 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
445 KEY_ALL_ACCESS, NULL, &classKey, NULL);
448 static const WCHAR fmt[] = { '%','0','4','u',0 };
451 sprintfW(devId, fmt, devInfo->devId);
452 RegCreateKeyExW(classKey, devId, 0, NULL, 0, KEY_READ | KEY_WRITE,
454 RegCloseKey(classKey);
459 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
460 DWORD devId, LPCWSTR instanceId, BOOL phantom)
462 struct DeviceInfo *devInfo = NULL;
463 HANDLE devInst = GlobalAlloc(GMEM_FIXED, sizeof(struct DeviceInfo));
465 devInfo = GlobalLock(devInst);
470 devInfo->devId = (DWORD)devInst;
472 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
473 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
474 if (devInfo->instanceId)
476 devInfo->key = INVALID_HANDLE_VALUE;
477 devInfo->phantom = phantom;
478 lstrcpyW(devInfo->instanceId, instanceId);
479 struprW(devInfo->instanceId);
480 devInfo->key = SETUPDI_CreateDevKey(devInfo);
481 if (devInfo->key != INVALID_HANDLE_VALUE)
484 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
485 (LPBYTE)&phantom, sizeof(phantom));
487 list_init(&devInfo->interfaces);
488 GlobalUnlock(devInst);
492 GlobalUnlock(devInst);
500 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
502 struct InterfaceInstances *iface, *next;
504 if (devInfo->key != INVALID_HANDLE_VALUE)
505 RegCloseKey(devInfo->key);
506 if (devInfo->phantom)
511 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
512 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
515 RegDeleteTreeW(enumKey, devInfo->instanceId);
516 RegCloseKey(enumKey);
519 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
520 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
521 struct InterfaceInstances, entry)
523 list_remove(&iface->entry);
524 SETUPDI_FreeInterfaceInstances(iface);
525 HeapFree(GetProcessHeap(), 0, iface);
527 GlobalFree((HANDLE)devInfo->devId);
530 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
531 * struct DeviceInfo, and points the returned device info's Reserved member
532 * to it. "Phantom" devices are deleted from the registry when closed.
533 * Returns a pointer to the newly allocated device info.
535 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
540 SP_DEVINFO_DATA **dev)
543 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, set->cDevices,
544 instanceId, phantom);
546 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
547 debugstr_w(instanceId), phantom);
551 struct DeviceInstance *devInst =
552 HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInstance));
556 WCHAR classGuidStr[39];
558 list_add_tail(&set->devices, &devInst->entry);
560 devInst->data.cbSize = sizeof(SP_DEVINFO_DATA);
561 devInst->data.ClassGuid = *guid;
562 devInst->data.DevInst = devInfo->devId;
563 devInst->data.Reserved = (ULONG_PTR)devInfo;
564 SETUPDI_GuidToString(guid, classGuidStr);
565 SetupDiSetDeviceRegistryPropertyW(set, &devInst->data,
566 SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
567 lstrlenW(classGuidStr) * sizeof(WCHAR));
568 if (dev) *dev = &devInst->data;
573 HeapFree(GetProcessHeap(), 0, devInfo);
574 SetLastError(ERROR_OUTOFMEMORY);
580 /***********************************************************************
581 * SetupDiBuildClassInfoList (SETUPAPI.@)
583 * Returns a list of setup class GUIDs that identify the classes
584 * that are installed on a local machine.
587 * Flags [I] control exclusion of classes from the list.
588 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
589 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
590 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
596 BOOL WINAPI SetupDiBuildClassInfoList(
598 LPGUID ClassGuidList,
599 DWORD ClassGuidListSize,
603 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
604 ClassGuidListSize, RequiredSize,
608 /***********************************************************************
609 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
611 * Returns a list of setup class GUIDs that identify the classes
612 * that are installed on a local or remote macine.
615 * Flags [I] control exclusion of classes from the list.
616 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
617 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
618 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
619 * MachineName [I] name of a remote machine.
620 * Reserved [I] must be NULL.
626 BOOL WINAPI SetupDiBuildClassInfoListExA(
628 LPGUID ClassGuidList,
629 DWORD ClassGuidListSize,
634 LPWSTR MachineNameW = NULL;
641 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
642 if (MachineNameW == NULL) return FALSE;
645 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
646 ClassGuidListSize, RequiredSize,
647 MachineNameW, Reserved);
649 MyFree(MachineNameW);
654 /***********************************************************************
655 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
657 * Returns a list of setup class GUIDs that identify the classes
658 * that are installed on a local or remote macine.
661 * Flags [I] control exclusion of classes from the list.
662 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
663 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
664 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
665 * MachineName [I] name of a remote machine.
666 * Reserved [I] must be NULL.
672 BOOL WINAPI SetupDiBuildClassInfoListExW(
674 LPGUID ClassGuidList,
675 DWORD ClassGuidListSize,
686 DWORD dwGuidListIndex = 0;
690 if (RequiredSize != NULL)
693 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
698 if (hClassesKey == INVALID_HANDLE_VALUE)
703 for (dwIndex = 0; ; dwIndex++)
706 lError = RegEnumKeyExW(hClassesKey,
714 TRACE("RegEnumKeyExW() returns %d\n", lError);
715 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
717 TRACE("Key name: %p\n", szKeyName);
719 if (RegOpenKeyExW(hClassesKey,
725 RegCloseKey(hClassesKey);
729 if (!RegQueryValueExW(hClassKey,
736 TRACE("'NoUseClass' value found!\n");
737 RegCloseKey(hClassKey);
741 if ((Flags & DIBCI_NOINSTALLCLASS) &&
742 (!RegQueryValueExW(hClassKey,
749 TRACE("'NoInstallClass' value found!\n");
750 RegCloseKey(hClassKey);
754 if ((Flags & DIBCI_NODISPLAYCLASS) &&
755 (!RegQueryValueExW(hClassKey,
762 TRACE("'NoDisplayClass' value found!\n");
763 RegCloseKey(hClassKey);
767 RegCloseKey(hClassKey);
769 TRACE("Guid: %p\n", szKeyName);
770 if (dwGuidListIndex < ClassGuidListSize)
772 if (szKeyName[0] == '{' && szKeyName[37] == '}')
776 TRACE("Guid: %p\n", &szKeyName[1]);
778 UuidFromStringW(&szKeyName[1],
779 &ClassGuidList[dwGuidListIndex]);
785 if (lError != ERROR_SUCCESS)
789 RegCloseKey(hClassesKey);
791 if (RequiredSize != NULL)
792 *RequiredSize = dwGuidListIndex;
794 if (ClassGuidListSize < dwGuidListIndex)
796 SetLastError(ERROR_INSUFFICIENT_BUFFER);
803 /***********************************************************************
804 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
806 BOOL WINAPI SetupDiClassGuidsFromNameA(
808 LPGUID ClassGuidList,
809 DWORD ClassGuidListSize,
812 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
813 ClassGuidListSize, RequiredSize,
817 /***********************************************************************
818 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
820 BOOL WINAPI SetupDiClassGuidsFromNameW(
822 LPGUID ClassGuidList,
823 DWORD ClassGuidListSize,
826 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
827 ClassGuidListSize, RequiredSize,
831 /***********************************************************************
832 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
834 BOOL WINAPI SetupDiClassGuidsFromNameExA(
836 LPGUID ClassGuidList,
837 DWORD ClassGuidListSize,
842 LPWSTR ClassNameW = NULL;
843 LPWSTR MachineNameW = NULL;
846 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
847 if (ClassNameW == NULL)
852 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
853 if (MachineNameW == NULL)
860 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
861 ClassGuidListSize, RequiredSize,
862 MachineNameW, Reserved);
864 MyFree(MachineNameW);
870 /***********************************************************************
871 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
873 BOOL WINAPI SetupDiClassGuidsFromNameExW(
875 LPGUID ClassGuidList,
876 DWORD ClassGuidListSize,
882 WCHAR szClassName[256];
888 DWORD dwGuidListIndex = 0;
890 if (RequiredSize != NULL)
893 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
898 if (hClassesKey == INVALID_HANDLE_VALUE)
903 for (dwIndex = 0; ; dwIndex++)
906 lError = RegEnumKeyExW(hClassesKey,
914 TRACE("RegEnumKeyExW() returns %d\n", lError);
915 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
917 TRACE("Key name: %p\n", szKeyName);
919 if (RegOpenKeyExW(hClassesKey,
925 RegCloseKey(hClassesKey);
929 dwLength = 256 * sizeof(WCHAR);
930 if (!RegQueryValueExW(hClassKey,
937 TRACE("Class name: %p\n", szClassName);
939 if (strcmpiW(szClassName, ClassName) == 0)
941 TRACE("Found matching class name\n");
943 TRACE("Guid: %p\n", szKeyName);
944 if (dwGuidListIndex < ClassGuidListSize)
946 if (szKeyName[0] == '{' && szKeyName[37] == '}')
950 TRACE("Guid: %p\n", &szKeyName[1]);
952 UuidFromStringW(&szKeyName[1],
953 &ClassGuidList[dwGuidListIndex]);
960 RegCloseKey(hClassKey);
963 if (lError != ERROR_SUCCESS)
967 RegCloseKey(hClassesKey);
969 if (RequiredSize != NULL)
970 *RequiredSize = dwGuidListIndex;
972 if (ClassGuidListSize < dwGuidListIndex)
974 SetLastError(ERROR_INSUFFICIENT_BUFFER);
981 /***********************************************************************
982 * SetupDiClassNameFromGuidA (SETUPAPI.@)
984 BOOL WINAPI SetupDiClassNameFromGuidA(
985 const GUID* ClassGuid,
990 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
991 ClassNameSize, RequiredSize,
995 /***********************************************************************
996 * SetupDiClassNameFromGuidW (SETUPAPI.@)
998 BOOL WINAPI SetupDiClassNameFromGuidW(
999 const GUID* ClassGuid,
1001 DWORD ClassNameSize,
1002 PDWORD RequiredSize)
1004 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1005 ClassNameSize, RequiredSize,
1009 /***********************************************************************
1010 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1012 BOOL WINAPI SetupDiClassNameFromGuidExA(
1013 const GUID* ClassGuid,
1015 DWORD ClassNameSize,
1016 PDWORD RequiredSize,
1020 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1021 LPWSTR MachineNameW = NULL;
1025 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1026 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1027 NULL, MachineNameW, Reserved);
1030 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1031 ClassNameSize, NULL, NULL);
1033 if (!ClassNameSize && RequiredSize)
1034 *RequiredSize = len;
1036 MyFree(MachineNameW);
1040 /***********************************************************************
1041 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1043 BOOL WINAPI SetupDiClassNameFromGuidExW(
1044 const GUID* ClassGuid,
1046 DWORD ClassNameSize,
1047 PDWORD RequiredSize,
1054 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1059 if (hKey == INVALID_HANDLE_VALUE)
1064 if (RequiredSize != NULL)
1067 if (RegQueryValueExW(hKey,
1078 *RequiredSize = dwLength / sizeof(WCHAR);
1081 dwLength = ClassNameSize * sizeof(WCHAR);
1082 if (RegQueryValueExW(hKey,
1098 /***********************************************************************
1099 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1102 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1105 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1108 /***********************************************************************
1109 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1112 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1117 LPWSTR MachineNameW = NULL;
1124 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1125 if (MachineNameW == NULL)
1126 return INVALID_HANDLE_VALUE;
1129 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1130 MachineNameW, Reserved);
1132 MyFree(MachineNameW);
1137 /***********************************************************************
1138 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1140 * Create an empty DeviceInfoSet list.
1143 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1145 * hwndParent [I] hwnd needed for interface related actions.
1146 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1147 * local registry will be used.
1148 * Reserved [I] must be NULL
1151 * Success: empty list.
1152 * Failure: INVALID_HANDLE_VALUE.
1155 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1160 struct DeviceInfoSet *list = NULL;
1161 DWORD size = sizeof(struct DeviceInfoSet);
1163 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1164 debugstr_w(MachineName), Reserved);
1166 if (MachineName != NULL)
1168 FIXME("remote support is not implemented\n");
1169 SetLastError(ERROR_INVALID_MACHINENAME);
1170 return INVALID_HANDLE_VALUE;
1173 if (Reserved != NULL)
1175 SetLastError(ERROR_INVALID_PARAMETER);
1176 return INVALID_HANDLE_VALUE;
1179 list = HeapAlloc(GetProcessHeap(), 0, size);
1182 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1183 return INVALID_HANDLE_VALUE;
1186 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1187 list->hwndParent = hwndParent;
1188 memcpy(&list->ClassGuid,
1189 ClassGuid ? ClassGuid : &GUID_NULL,
1190 sizeof(list->ClassGuid));
1192 list_init(&list->devices);
1197 /***********************************************************************
1198 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1200 HKEY WINAPI SetupDiCreateDevRegKeyA(
1201 HDEVINFO DeviceInfoSet,
1202 PSP_DEVINFO_DATA DeviceInfoData,
1207 PCSTR InfSectionName)
1209 PWSTR InfSectionNameW = NULL;
1212 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1213 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1217 if (!InfSectionName)
1219 SetLastError(ERROR_INVALID_PARAMETER);
1220 return INVALID_HANDLE_VALUE;
1224 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1225 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1228 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1229 HwProfile, KeyType, InfHandle, InfSectionNameW);
1230 MyFree(InfSectionNameW);
1234 /***********************************************************************
1235 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1237 HKEY WINAPI SetupDiCreateDevRegKeyW(
1238 HDEVINFO DeviceInfoSet,
1239 PSP_DEVINFO_DATA DeviceInfoData,
1244 PCWSTR InfSectionName)
1246 struct DeviceInfoSet *set = DeviceInfoSet;
1247 struct DeviceInfo *devInfo;
1248 HKEY key = INVALID_HANDLE_VALUE;
1250 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1251 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1253 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1255 SetLastError(ERROR_INVALID_HANDLE);
1256 return INVALID_HANDLE_VALUE;
1258 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1260 SetLastError(ERROR_INVALID_HANDLE);
1261 return INVALID_HANDLE_VALUE;
1263 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1264 || !DeviceInfoData->Reserved)
1266 SetLastError(ERROR_INVALID_PARAMETER);
1267 return INVALID_HANDLE_VALUE;
1269 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1270 if (devInfo->set != set)
1272 SetLastError(ERROR_INVALID_PARAMETER);
1273 return INVALID_HANDLE_VALUE;
1275 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1277 SetLastError(ERROR_INVALID_FLAGS);
1278 return INVALID_HANDLE_VALUE;
1280 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1282 SetLastError(ERROR_INVALID_FLAGS);
1283 return INVALID_HANDLE_VALUE;
1285 if (devInfo->phantom)
1287 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
1288 return INVALID_HANDLE_VALUE;
1290 if (Scope != DICS_FLAG_GLOBAL)
1291 FIXME("unimplemented for scope %d\n", Scope);
1295 key = SETUPDI_CreateDevKey(devInfo);
1298 key = SETUPDI_CreateDrvKey(devInfo);
1301 WARN("unknown KeyType %d\n", KeyType);
1304 SetupInstallFromInfSectionW(NULL, InfHandle, InfSectionName, SPINST_ALL,
1305 NULL, NULL, SP_COPY_NEWER_ONLY, NULL, NULL, DeviceInfoSet,
1310 /***********************************************************************
1311 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1313 BOOL WINAPI SetupDiCreateDeviceInfoA(
1314 HDEVINFO DeviceInfoSet,
1316 CONST GUID *ClassGuid,
1317 PCSTR DeviceDescription,
1319 DWORD CreationFlags,
1320 PSP_DEVINFO_DATA DeviceInfoData)
1323 LPWSTR DeviceNameW = NULL;
1324 LPWSTR DeviceDescriptionW = NULL;
1328 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1329 if (DeviceNameW == NULL) return FALSE;
1331 if (DeviceDescription)
1333 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1334 if (DeviceDescriptionW == NULL)
1336 MyFree(DeviceNameW);
1341 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1342 hwndParent, CreationFlags, DeviceInfoData);
1344 MyFree(DeviceNameW);
1345 MyFree(DeviceDescriptionW);
1350 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1353 int devNameLen = lstrlenW(devName);
1357 TRACE("%s\n", debugstr_w(devName));
1358 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1363 devInst |= *ptr - '0';
1369 TRACE("%d\n", valid ? devInst : 0xffffffff);
1370 return valid ? devInst : 0xffffffff;
1373 /***********************************************************************
1374 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1376 BOOL WINAPI SetupDiCreateDeviceInfoW(
1377 HDEVINFO DeviceInfoSet,
1379 CONST GUID *ClassGuid,
1380 PCWSTR DeviceDescription,
1382 DWORD CreationFlags,
1383 PSP_DEVINFO_DATA DeviceInfoData)
1385 struct DeviceInfoSet *set = DeviceInfoSet;
1386 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1387 LPCWSTR instanceId = NULL;
1389 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1390 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1391 hwndParent, CreationFlags, DeviceInfoData);
1395 SetLastError(ERROR_INVALID_DEVINST_NAME);
1398 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1400 SetLastError(ERROR_INVALID_HANDLE);
1405 SetLastError(ERROR_INVALID_PARAMETER);
1408 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1410 SetLastError(ERROR_INVALID_HANDLE);
1413 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1414 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1416 SetLastError(ERROR_CLASS_MISMATCH);
1419 if ((CreationFlags & DICD_GENERATE_ID))
1421 if (strchrW(DeviceName, '\\'))
1422 SetLastError(ERROR_INVALID_DEVINST_NAME);
1425 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1426 '\\','%','0','4','d',0};
1431 DWORD highestDevID = 0;
1432 struct DeviceInstance *devInst;
1434 LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
1436 struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
1437 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1443 devName = devInfo->instanceId;
1444 id = SETUPDI_DevNameToDevID(devName);
1445 if (id != 0xffffffff && id > highestDevID)
1448 devId = highestDevID + 1;
1452 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1453 instanceId = HeapAlloc(GetProcessHeap(), 0,
1454 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1457 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1459 allocatedInstanceId = TRUE;
1468 struct DeviceInstance *devInst;
1471 instanceId = DeviceName;
1472 LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
1474 struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
1476 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1478 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1485 SP_DEVINFO_DATA *dev = NULL;
1487 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1488 instanceId, TRUE, &dev);
1491 if (DeviceDescription)
1492 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1493 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1494 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1497 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1499 SetLastError(ERROR_INVALID_USER_BUFFER);
1503 *DeviceInfoData = *dev;
1507 if (allocatedInstanceId)
1508 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1513 /***********************************************************************
1514 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1516 BOOL WINAPI SetupDiRegisterDeviceInfo(
1517 HDEVINFO DeviceInfoSet,
1518 PSP_DEVINFO_DATA DeviceInfoData,
1520 PSP_DETSIG_CMPPROC CompareProc,
1521 PVOID CompareContext,
1522 PSP_DEVINFO_DATA DupDeviceInfoData)
1524 struct DeviceInfoSet *set = DeviceInfoSet;
1525 struct DeviceInfo *devInfo;
1527 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1528 CompareProc, CompareContext, DupDeviceInfoData);
1530 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1532 SetLastError(ERROR_INVALID_HANDLE);
1535 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1537 SetLastError(ERROR_INVALID_HANDLE);
1540 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1541 || !DeviceInfoData->Reserved)
1543 SetLastError(ERROR_INVALID_PARAMETER);
1546 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1547 if (devInfo->set != set)
1549 SetLastError(ERROR_INVALID_PARAMETER);
1552 if (devInfo->phantom)
1554 devInfo->phantom = FALSE;
1555 RegDeleteValueW(devInfo->key, Phantom);
1560 /***********************************************************************
1561 * SetupDiRemoveDevice (SETUPAPI.@)
1563 BOOL WINAPI SetupDiRemoveDevice(
1565 PSP_DEVINFO_DATA info)
1567 FIXME("(%p, %p): stub\n", devinfo, info);
1568 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1572 /***********************************************************************
1573 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1575 BOOL WINAPI SetupDiEnumDeviceInfo(
1578 PSP_DEVINFO_DATA info)
1582 TRACE("%p %d %p\n", devinfo, index, info);
1586 SetLastError(ERROR_INVALID_PARAMETER);
1589 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1591 struct DeviceInfoSet *list = devinfo;
1592 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1594 if (index < list->cDevices)
1596 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1598 struct DeviceInstance *devInst;
1601 LIST_FOR_EACH_ENTRY(devInst, &list->devices,
1602 struct DeviceInstance, entry)
1606 *info = devInst->data;
1613 SetLastError(ERROR_INVALID_USER_BUFFER);
1616 SetLastError(ERROR_NO_MORE_ITEMS);
1619 SetLastError(ERROR_INVALID_HANDLE);
1622 SetLastError(ERROR_INVALID_HANDLE);
1626 /***********************************************************************
1627 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1629 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1630 HDEVINFO DeviceInfoSet,
1631 PSP_DEVINFO_DATA DeviceInfoData,
1632 PSTR DeviceInstanceId,
1633 DWORD DeviceInstanceIdSize,
1634 PDWORD RequiredSize)
1640 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1641 DeviceInstanceIdSize, RequiredSize);
1643 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1648 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1650 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1653 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1660 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1662 DeviceInstanceIdSize, NULL, NULL);
1668 if (len > DeviceInstanceIdSize)
1670 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1674 *RequiredSize = len;
1677 HeapFree(GetProcessHeap(), 0, instanceId);
1682 /***********************************************************************
1683 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1685 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1686 HDEVINFO DeviceInfoSet,
1687 PSP_DEVINFO_DATA DeviceInfoData,
1688 PWSTR DeviceInstanceId,
1689 DWORD DeviceInstanceIdSize,
1690 PDWORD RequiredSize)
1692 struct DeviceInfoSet *set = DeviceInfoSet;
1693 struct DeviceInfo *devInfo;
1695 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1696 DeviceInstanceIdSize, RequiredSize);
1698 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1700 SetLastError(ERROR_INVALID_HANDLE);
1703 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1705 SetLastError(ERROR_INVALID_HANDLE);
1708 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1709 || !DeviceInfoData->Reserved)
1711 SetLastError(ERROR_INVALID_PARAMETER);
1714 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1715 if (devInfo->set != set)
1717 SetLastError(ERROR_INVALID_PARAMETER);
1720 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1721 if (DeviceInstanceIdSize < strlenW(devInfo->instanceId) + 1)
1723 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1725 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1728 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1730 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1734 /***********************************************************************
1735 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1737 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1739 PCSTR InfSectionName,
1740 PSTR InfSectionWithExt,
1741 DWORD InfSectionWithExtSize,
1742 PDWORD RequiredSize,
1749 /***********************************************************************
1750 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1752 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1754 PCWSTR InfSectionName,
1755 PWSTR InfSectionWithExt,
1756 DWORD InfSectionWithExtSize,
1757 PDWORD RequiredSize,
1760 WCHAR szBuffer[MAX_PATH];
1763 LONG lLineCount = -1;
1765 lstrcpyW(szBuffer, InfSectionName);
1766 dwLength = lstrlenW(szBuffer);
1768 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1770 /* Test section name with '.NTx86' extension */
1771 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1772 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1774 if (lLineCount == -1)
1776 /* Test section name with '.NT' extension */
1777 lstrcpyW(&szBuffer[dwLength], NtExtension);
1778 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1783 /* Test section name with '.Win' extension */
1784 lstrcpyW(&szBuffer[dwLength], WinExtension);
1785 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1788 if (lLineCount == -1)
1790 /* Test section name without extension */
1791 szBuffer[dwLength] = 0;
1792 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1795 if (lLineCount == -1)
1797 SetLastError(ERROR_INVALID_PARAMETER);
1801 dwFullLength = lstrlenW(szBuffer);
1803 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1805 if (InfSectionWithExtSize < (dwFullLength + 1))
1807 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1811 lstrcpyW(InfSectionWithExt, szBuffer);
1812 if (Extension != NULL)
1814 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1818 if (RequiredSize != NULL)
1820 *RequiredSize = dwFullLength + 1;
1826 /***********************************************************************
1827 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1829 BOOL WINAPI SetupDiGetClassDescriptionA(
1830 const GUID* ClassGuid,
1831 PSTR ClassDescription,
1832 DWORD ClassDescriptionSize,
1833 PDWORD RequiredSize)
1835 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1836 ClassDescriptionSize,
1837 RequiredSize, NULL, NULL);
1840 /***********************************************************************
1841 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1843 BOOL WINAPI SetupDiGetClassDescriptionW(
1844 const GUID* ClassGuid,
1845 PWSTR ClassDescription,
1846 DWORD ClassDescriptionSize,
1847 PDWORD RequiredSize)
1849 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1850 ClassDescriptionSize,
1851 RequiredSize, NULL, NULL);
1854 /***********************************************************************
1855 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1857 BOOL WINAPI SetupDiGetClassDescriptionExA(
1858 const GUID* ClassGuid,
1859 PSTR ClassDescription,
1860 DWORD ClassDescriptionSize,
1861 PDWORD RequiredSize,
1869 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1874 if (hKey == INVALID_HANDLE_VALUE)
1876 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1880 dwLength = ClassDescriptionSize;
1881 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1882 (LPBYTE)ClassDescription, &dwLength );
1883 if (RequiredSize) *RequiredSize = dwLength;
1888 /***********************************************************************
1889 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1891 BOOL WINAPI SetupDiGetClassDescriptionExW(
1892 const GUID* ClassGuid,
1893 PWSTR ClassDescription,
1894 DWORD ClassDescriptionSize,
1895 PDWORD RequiredSize,
1903 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1908 if (hKey == INVALID_HANDLE_VALUE)
1910 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1914 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1915 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1916 (LPBYTE)ClassDescription, &dwLength );
1917 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1922 /***********************************************************************
1923 * SetupDiGetClassDevsA (SETUPAPI.@)
1925 HDEVINFO WINAPI SetupDiGetClassDevsA(
1932 LPWSTR enumstrW = NULL;
1936 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1937 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1940 ret = INVALID_HANDLE_VALUE;
1943 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1945 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
1947 HeapFree(GetProcessHeap(), 0, enumstrW);
1953 /***********************************************************************
1954 * SetupDiGetClassDevsExA (SETUPAPI.@)
1956 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1966 LPWSTR enumstrW = NULL, machineW = NULL;
1970 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1971 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1974 ret = INVALID_HANDLE_VALUE;
1977 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1981 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1982 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1985 HeapFree(GetProcessHeap(), 0, enumstrW);
1986 ret = INVALID_HANDLE_VALUE;
1989 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1991 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
1992 machineW, reserved);
1993 HeapFree(GetProcessHeap(), 0, enumstrW);
1994 HeapFree(GetProcessHeap(), 0, machineW);
2000 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
2004 WCHAR subKeyName[MAX_PATH];
2005 LONG l = ERROR_SUCCESS;
2007 for (i = 0; !l; i++)
2009 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2010 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2014 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2016 if (*subKeyName == '#')
2018 /* The subkey name is the reference string, with a '#' prepended */
2019 SETUPDI_AddInterfaceInstance(dev, guid, subKeyName + 1, &iface);
2020 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2023 WCHAR symbolicLink[MAX_PATH];
2026 len = sizeof(symbolicLink);
2027 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
2028 (BYTE *)symbolicLink, &len);
2029 if (!l && dataType == REG_SZ)
2030 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
2031 RegCloseKey(subKey);
2034 /* Allow enumeration to continue */
2038 /* FIXME: find and add all the device's interfaces to the device */
2041 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
2042 HKEY key, const GUID *guid, LPCWSTR enumstr)
2044 struct DeviceInfoSet *set = DeviceInfoSet;
2046 WCHAR subKeyName[MAX_PATH];
2048 HKEY enumKey = INVALID_HANDLE_VALUE;
2050 TRACE("%s\n", debugstr_w(enumstr));
2052 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
2054 for (i = 0; !l; i++)
2056 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2057 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2062 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2065 WCHAR deviceInst[MAX_PATH * 3];
2068 len = sizeof(deviceInst);
2069 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
2070 (BYTE *)deviceInst, &len);
2071 if (!l && dataType == REG_SZ)
2073 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
2074 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
2078 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
2082 WCHAR deviceClassStr[40];
2084 len = sizeof(deviceClassStr);
2085 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
2086 &dataType, (BYTE *)deviceClassStr, &len);
2087 if (!l && dataType == REG_SZ &&
2088 deviceClassStr[0] == '{' &&
2089 deviceClassStr[37] == '}')
2092 SP_DEVINFO_DATA *dev;
2094 deviceClassStr[37] = 0;
2095 UuidFromStringW(&deviceClassStr[1],
2097 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
2098 0 /* FIXME: DevInst */, deviceInst,
2100 SETUPDI_AddDeviceInterfaces(dev, subKey, guid);
2102 RegCloseKey(deviceKey);
2106 RegCloseKey(subKey);
2108 /* Allow enumeration to continue */
2112 if (enumKey != INVALID_HANDLE_VALUE)
2113 RegCloseKey(enumKey);
2116 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
2117 const GUID *guid, LPCWSTR enumstr, DWORD flags)
2119 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(guid, KEY_READ,
2120 DIOCR_INTERFACE, NULL, NULL);
2122 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(guid),
2123 debugstr_w(enumstr), flags);
2125 if (interfacesKey != INVALID_HANDLE_VALUE)
2127 if (flags & DIGCF_ALLCLASSES)
2130 WCHAR interfaceGuidStr[40];
2131 LONG l = ERROR_SUCCESS;
2133 for (i = 0; !l; i++)
2135 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
2136 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
2137 NULL, NULL, NULL, NULL);
2140 if (interfaceGuidStr[0] == '{' &&
2141 interfaceGuidStr[37] == '}')
2146 interfaceGuidStr[37] = 0;
2147 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
2148 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
2149 KEY_READ, &interfaceKey);
2152 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2153 interfaceKey, &interfaceGuid, enumstr);
2154 RegCloseKey(interfaceKey);
2162 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
2163 * interface's key, so just pass that long
2165 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2166 interfacesKey, guid, enumstr);
2168 RegCloseKey(interfacesKey);
2172 static void SETUPDI_EnumerateMatchingDeviceInstances(struct DeviceInfoSet *set,
2173 LPCWSTR enumerator, LPCWSTR deviceName, HKEY deviceKey,
2174 const GUID *class, DWORD flags)
2177 WCHAR deviceInstance[MAX_PATH];
2178 LONG l = ERROR_SUCCESS;
2180 TRACE("%s %s\n", debugstr_w(enumerator), debugstr_w(deviceName));
2182 for (i = 0; !l; i++)
2184 len = sizeof(deviceInstance) / sizeof(deviceInstance[0]);
2185 l = RegEnumKeyExW(deviceKey, i, deviceInstance, &len, NULL, NULL, NULL,
2191 l = RegOpenKeyExW(deviceKey, deviceInstance, 0, KEY_READ, &subKey);
2194 WCHAR classGuid[40];
2197 len = sizeof(classGuid);
2198 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
2199 (BYTE *)classGuid, &len);
2200 if (!l && dataType == REG_SZ)
2202 if (classGuid[0] == '{' && classGuid[37] == '}')
2207 UuidFromStringW(&classGuid[1], &deviceClass);
2208 if ((flags & DIGCF_ALLCLASSES) ||
2209 IsEqualGUID(class, &deviceClass))
2211 static const WCHAR fmt[] =
2212 {'%','s','\\','%','s','\\','%','s',0};
2215 instanceId = HeapAlloc(GetProcessHeap(), 0,
2216 (lstrlenW(enumerator) + lstrlenW(deviceName) +
2217 lstrlenW(deviceInstance) + 3) * sizeof(WCHAR));
2220 sprintfW(instanceId, fmt, enumerator,
2221 deviceName, deviceInstance);
2222 SETUPDI_AddDeviceToSet(set, &deviceClass,
2223 0 /* FIXME: DevInst */, instanceId,
2225 HeapFree(GetProcessHeap(), 0, instanceId);
2230 RegCloseKey(subKey);
2232 /* Allow enumeration to continue */
2238 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
2239 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
2241 struct DeviceInfoSet *set = DeviceInfoSet;
2243 WCHAR subKeyName[MAX_PATH];
2244 LONG l = ERROR_SUCCESS;
2246 TRACE("%s\n", debugstr_w(parent));
2248 for (i = 0; !l; i++)
2250 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2251 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2256 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2259 TRACE("%s\n", debugstr_w(subKeyName));
2260 SETUPDI_EnumerateMatchingDeviceInstances(set, parent,
2261 subKeyName, subKey, class, flags);
2262 RegCloseKey(subKey);
2264 /* Allow enumeration to continue */
2270 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
2271 LPCWSTR enumstr, DWORD flags)
2276 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
2277 debugstr_w(enumstr), flags);
2279 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
2281 if (enumKey != INVALID_HANDLE_VALUE)
2287 l = RegOpenKeyExW(enumKey, enumstr, 0, KEY_READ,
2291 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2292 enumStrKey, class, flags);
2293 RegCloseKey(enumStrKey);
2299 WCHAR subKeyName[MAX_PATH];
2302 for (i = 0; !l; i++)
2304 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2305 l = RegEnumKeyExW(enumKey, i, subKeyName, &len, NULL,
2311 l = RegOpenKeyExW(enumKey, subKeyName, 0, KEY_READ,
2315 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2316 subKeyName, subKey, class, flags);
2317 RegCloseKey(subKey);
2319 /* Allow enumeration to continue */
2324 RegCloseKey(enumKey);
2328 /***********************************************************************
2329 * SetupDiGetClassDevsW (SETUPAPI.@)
2331 HDEVINFO WINAPI SetupDiGetClassDevsW(
2337 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2341 /***********************************************************************
2342 * SetupDiGetClassDevsExW (SETUPAPI.@)
2344 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2353 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2357 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2358 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2361 if (!(flags & DIGCF_ALLCLASSES) && !class)
2363 SetLastError(ERROR_INVALID_PARAMETER);
2366 if (flags & unsupportedFlags)
2367 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2371 set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
2375 FIXME("%s: unimplemented for remote machines\n",
2376 debugstr_w(machine));
2377 else if (flags & DIGCF_DEVICEINTERFACE)
2378 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2380 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2385 /***********************************************************************
2386 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2388 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2389 HDEVINFO DeviceInfoSet,
2390 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2392 struct DeviceInfoSet *set = DeviceInfoSet;
2394 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2396 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2398 SetLastError(ERROR_INVALID_HANDLE);
2401 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2403 SetLastError(ERROR_INVALID_HANDLE);
2407 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2409 SetLastError(ERROR_INVALID_PARAMETER);
2412 DevInfoData->ClassGuid = set->ClassGuid;
2413 DevInfoData->RemoteMachineHandle = NULL;
2414 DevInfoData->RemoteMachineName[0] = '\0';
2418 /***********************************************************************
2419 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2421 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2422 HDEVINFO DeviceInfoSet,
2423 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2425 struct DeviceInfoSet *set = DeviceInfoSet;
2427 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2429 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2431 SetLastError(ERROR_INVALID_HANDLE);
2434 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2436 SetLastError(ERROR_INVALID_HANDLE);
2440 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2442 SetLastError(ERROR_INVALID_PARAMETER);
2445 DevInfoData->ClassGuid = set->ClassGuid;
2446 DevInfoData->RemoteMachineHandle = NULL;
2447 DevInfoData->RemoteMachineName[0] = '\0';
2451 /***********************************************************************
2452 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2454 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2455 HDEVINFO DeviceInfoSet,
2456 PSP_DEVINFO_DATA DeviceInfoData,
2457 const GUID *InterfaceClassGuid,
2458 PCSTR ReferenceString,
2459 DWORD CreationFlags,
2460 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2463 LPWSTR ReferenceStringW = NULL;
2465 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2466 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2467 CreationFlags, DeviceInterfaceData);
2469 if (ReferenceString)
2471 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2472 if (ReferenceStringW == NULL) return FALSE;
2475 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2476 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2477 DeviceInterfaceData);
2479 MyFree(ReferenceStringW);
2484 /***********************************************************************
2485 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2487 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2488 HDEVINFO DeviceInfoSet,
2489 PSP_DEVINFO_DATA DeviceInfoData,
2490 const GUID *InterfaceClassGuid,
2491 PCWSTR ReferenceString,
2492 DWORD CreationFlags,
2493 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2495 struct DeviceInfoSet *set = DeviceInfoSet;
2496 struct DeviceInfo *devInfo;
2497 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2500 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2501 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2502 CreationFlags, DeviceInterfaceData);
2504 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2506 SetLastError(ERROR_INVALID_HANDLE);
2509 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2511 SetLastError(ERROR_INVALID_HANDLE);
2514 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2515 || !DeviceInfoData->Reserved)
2517 SetLastError(ERROR_INVALID_PARAMETER);
2520 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2521 if (devInfo->set != set)
2523 SetLastError(ERROR_INVALID_PARAMETER);
2526 if (!InterfaceClassGuid)
2528 SetLastError(ERROR_INVALID_USER_BUFFER);
2531 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2532 ReferenceString, &iface)))
2534 if (DeviceInterfaceData)
2536 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2538 SetLastError(ERROR_INVALID_USER_BUFFER);
2542 *DeviceInterfaceData = *iface;
2548 /***********************************************************************
2549 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2551 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2552 HDEVINFO DeviceInfoSet,
2553 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2557 PCSTR InfSectionName)
2560 PWSTR InfSectionNameW = NULL;
2562 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2563 samDesired, InfHandle, InfSectionName);
2566 if (!InfSectionName)
2568 SetLastError(ERROR_INVALID_PARAMETER);
2569 return INVALID_HANDLE_VALUE;
2571 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2572 if (!InfSectionNameW)
2573 return INVALID_HANDLE_VALUE;
2575 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2576 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2578 MyFree(InfSectionNameW);
2582 static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo)
2584 static const WCHAR hash[] = {'#',0};
2585 PWSTR instancePath = NULL;
2587 if (ifaceInfo->referenceString)
2589 instancePath = HeapAlloc(GetProcessHeap(), 0,
2590 (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR));
2593 lstrcpyW(instancePath, hash);
2594 lstrcatW(instancePath, ifaceInfo->referenceString);
2597 SetLastError(ERROR_OUTOFMEMORY);
2601 instancePath = HeapAlloc(GetProcessHeap(), 0,
2602 (lstrlenW(hash) + 1) * sizeof(WCHAR));
2604 lstrcpyW(instancePath, hash);
2606 return instancePath;
2609 /***********************************************************************
2610 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2612 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2613 HDEVINFO DeviceInfoSet,
2614 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2618 PCWSTR InfSectionName)
2620 struct DeviceInfoSet *set = DeviceInfoSet;
2621 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2624 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2625 samDesired, InfHandle, InfSectionName);
2627 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2628 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2630 SetLastError(ERROR_INVALID_HANDLE);
2631 return INVALID_HANDLE_VALUE;
2633 if (!DeviceInterfaceData ||
2634 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2635 !DeviceInterfaceData->Reserved)
2637 SetLastError(ERROR_INVALID_PARAMETER);
2638 return INVALID_HANDLE_VALUE;
2640 if (InfHandle && !InfSectionName)
2642 SetLastError(ERROR_INVALID_PARAMETER);
2643 return INVALID_HANDLE_VALUE;
2645 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2646 samDesired, NULL, &interfacesKey, NULL)))
2649 WCHAR bracedGuidString[39];
2651 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2653 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2654 samDesired, NULL, &parent, NULL)))
2656 struct InterfaceInfo *ifaceInfo =
2657 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2658 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2659 PWSTR interfKeyName = HeapAlloc(GetProcessHeap(), 0,
2660 (lstrlenW(ifaceInfo->symbolicLink) + 1) * sizeof(WCHAR));
2664 lstrcpyW(interfKeyName, ifaceInfo->symbolicLink);
2665 if (lstrlenW(ifaceInfo->symbolicLink) > 3)
2667 interfKeyName[0] = '#';
2668 interfKeyName[1] = '#';
2669 interfKeyName[3] = '#';
2671 ptr = strchrW(interfKeyName, '\\');
2674 l = RegCreateKeyExW(parent, interfKeyName, 0, NULL, 0,
2675 samDesired, NULL, &interfKey, NULL);
2678 struct DeviceInfo *devInfo =
2679 (struct DeviceInfo *)ifaceInfo->device->Reserved;
2681 l = RegSetValueExW(interfKey, DeviceInstance, 0, REG_SZ,
2682 (BYTE *)devInfo->instanceId,
2683 (lstrlenW(devInfo->instanceId) + 1) * sizeof(WCHAR));
2690 l = RegCreateKeyExW(interfKey, instancePath, 0, NULL, 0,
2691 samDesired, NULL, &key, NULL);
2695 key = INVALID_HANDLE_VALUE;
2698 FIXME("INF section installation unsupported\n");
2703 RegCloseKey(interfKey);
2707 HeapFree(GetProcessHeap(), 0, interfKeyName);
2708 HeapFree(GetProcessHeap(), 0, instancePath);
2709 RegCloseKey(parent);
2713 RegCloseKey(interfacesKey);
2720 /***********************************************************************
2721 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2723 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2724 HDEVINFO DeviceInfoSet,
2725 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2728 struct DeviceInfoSet *set = DeviceInfoSet;
2732 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2734 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2735 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2737 SetLastError(ERROR_INVALID_HANDLE);
2740 if (!DeviceInterfaceData ||
2741 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2742 !DeviceInterfaceData->Reserved)
2744 SetLastError(ERROR_INVALID_PARAMETER);
2747 parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid,
2748 KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
2749 if (parent != INVALID_HANDLE_VALUE)
2751 struct InterfaceInfo *ifaceInfo =
2752 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2753 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2757 LONG l = RegDeleteKeyW(parent, instancePath);
2763 HeapFree(GetProcessHeap(), 0, instancePath);
2765 RegCloseKey(parent);
2770 /***********************************************************************
2771 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2774 * DeviceInfoSet [I] Set of devices from which to enumerate
2776 * DeviceInfoData [I] (Optional) If specified, a specific device
2777 * instance from which to enumerate interfaces.
2778 * If it isn't specified, all interfaces for all
2779 * devices in the set are enumerated.
2780 * InterfaceClassGuid [I] The interface class to enumerate.
2781 * MemberIndex [I] An index of the interface instance to enumerate.
2782 * A caller should start with MemberIndex set to 0,
2783 * and continue until the function fails with
2784 * ERROR_NO_MORE_ITEMS.
2785 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2786 * member must be set to
2787 * sizeof(SP_DEVICE_INTERFACE_DATA).
2790 * Success: non-zero value.
2791 * Failure: FALSE. Call GetLastError() for more info.
2793 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2794 HDEVINFO DeviceInfoSet,
2795 PSP_DEVINFO_DATA DeviceInfoData,
2796 CONST GUID * InterfaceClassGuid,
2798 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2800 struct DeviceInfoSet *set = DeviceInfoSet;
2803 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2804 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2806 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2807 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2809 SetLastError(ERROR_INVALID_HANDLE);
2812 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2813 !DeviceInfoData->Reserved))
2815 SetLastError(ERROR_INVALID_PARAMETER);
2818 if (!DeviceInterfaceData ||
2819 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2821 SetLastError(ERROR_INVALID_PARAMETER);
2826 struct DeviceInfo *devInfo =
2827 (struct DeviceInfo *)DeviceInfoData->Reserved;
2828 struct InterfaceInstances *iface;
2830 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2832 if (MemberIndex < iface->cInstances)
2833 *DeviceInterfaceData = iface->instances[MemberIndex];
2836 SetLastError(ERROR_NO_MORE_ITEMS);
2841 SetLastError(ERROR_NO_MORE_ITEMS);
2845 struct DeviceInstance *devInst;
2846 DWORD cEnumerated = 0;
2849 LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
2851 struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
2852 struct InterfaceInstances *iface;
2854 if (found || cEnumerated >= MemberIndex + 1)
2856 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2858 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2859 cEnumerated += iface->cInstances;
2862 DWORD instanceIndex = MemberIndex - cEnumerated;
2864 *DeviceInterfaceData = iface->instances[instanceIndex];
2865 cEnumerated += instanceIndex + 1;
2872 SetLastError(ERROR_NO_MORE_ITEMS);
2877 /***********************************************************************
2878 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2880 * Destroy a DeviceInfoList and free all used memory of the list.
2883 * devinfo [I] DeviceInfoList pointer to list to destroy
2886 * Success: non zero value.
2887 * Failure: zero value.
2889 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2893 TRACE("%p\n", devinfo);
2894 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2896 struct DeviceInfoSet *list = devinfo;
2898 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2900 struct DeviceInstance *devInst, *devInst2;
2902 LIST_FOR_EACH_ENTRY_SAFE(devInst, devInst2, &list->devices,
2903 struct DeviceInstance, entry)
2905 SETUPDI_FreeDeviceInfo( (struct DeviceInfo *)devInst->data.Reserved );
2906 list_remove(&devInst->entry);
2907 HeapFree(GetProcessHeap(), 0, devInst);
2909 HeapFree(GetProcessHeap(), 0, list);
2915 SetLastError(ERROR_INVALID_HANDLE);
2920 /***********************************************************************
2921 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2923 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2924 HDEVINFO DeviceInfoSet,
2925 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2926 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2927 DWORD DeviceInterfaceDetailDataSize,
2928 PDWORD RequiredSize,
2929 PSP_DEVINFO_DATA DeviceInfoData)
2931 struct DeviceInfoSet *set = DeviceInfoSet;
2932 struct InterfaceInfo *info;
2933 DWORD bytesNeeded = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
2936 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2937 DeviceInterfaceData, DeviceInterfaceDetailData,
2938 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2940 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2941 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2943 SetLastError(ERROR_INVALID_HANDLE);
2946 if (!DeviceInterfaceData ||
2947 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2948 !DeviceInterfaceData->Reserved)
2950 SetLastError(ERROR_INVALID_PARAMETER);
2953 if (DeviceInterfaceDetailData &&
2954 DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2956 SetLastError(ERROR_INVALID_USER_BUFFER);
2959 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2961 SetLastError(ERROR_INVALID_USER_BUFFER);
2964 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2965 if (info->symbolicLink)
2966 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2967 NULL, 0, NULL, NULL);
2968 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2970 if (info->symbolicLink)
2971 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2972 DeviceInterfaceDetailData->DevicePath,
2973 DeviceInterfaceDetailDataSize -
2974 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2977 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2978 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2979 *DeviceInfoData = *info->device;
2985 *RequiredSize = bytesNeeded;
2986 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2991 /***********************************************************************
2992 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2994 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2995 HDEVINFO DeviceInfoSet,
2996 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2997 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2998 DWORD DeviceInterfaceDetailDataSize,
2999 PDWORD RequiredSize,
3000 PSP_DEVINFO_DATA DeviceInfoData)
3002 struct DeviceInfoSet *set = DeviceInfoSet;
3003 struct InterfaceInfo *info;
3004 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
3005 + sizeof(WCHAR); /* include NULL terminator */
3008 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3009 DeviceInterfaceData, DeviceInterfaceDetailData,
3010 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3012 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3013 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3015 SetLastError(ERROR_INVALID_HANDLE);
3018 if (!DeviceInterfaceData ||
3019 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3020 !DeviceInterfaceData->Reserved)
3022 SetLastError(ERROR_INVALID_PARAMETER);
3025 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
3026 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
3027 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
3029 SetLastError(ERROR_INVALID_USER_BUFFER);
3032 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3034 SetLastError(ERROR_INVALID_USER_BUFFER);
3037 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
3038 if (info->symbolicLink)
3039 bytesNeeded += sizeof(WCHAR)*lstrlenW(info->symbolicLink);
3040 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
3042 if (info->symbolicLink)
3043 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
3045 DeviceInterfaceDetailData->DevicePath[0] = '\0';
3046 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
3047 *DeviceInfoData = *info->device;
3053 *RequiredSize = bytesNeeded;
3054 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3059 struct PropertyMapEntry
3066 static const struct PropertyMapEntry PropertyMap[] = {
3067 { REG_SZ, "DeviceDesc", DeviceDesc },
3068 { REG_MULTI_SZ, "HardwareId", HardwareId },
3069 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
3070 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3071 { REG_SZ, "Service", Service },
3072 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3073 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3074 { REG_SZ, "Class", Class },
3075 { REG_SZ, "ClassGUID", ClassGUID },
3076 { REG_SZ, "Driver", Driver },
3077 { REG_DWORD, "ConfigFlags", ConfigFlags },
3078 { REG_SZ, "Mfg", Mfg },
3079 { REG_SZ, "FriendlyName", FriendlyName },
3080 { REG_SZ, "LocationInformation", LocationInformation },
3081 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3082 { REG_DWORD, "Capabilities", Capabilities },
3083 { REG_DWORD, "UINumber", UINumber },
3084 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
3085 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
3088 /***********************************************************************
3089 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3091 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3092 HDEVINFO DeviceInfoSet,
3093 PSP_DEVINFO_DATA DeviceInfoData,
3095 PDWORD PropertyRegDataType,
3096 PBYTE PropertyBuffer,
3097 DWORD PropertyBufferSize,
3098 PDWORD RequiredSize)
3101 struct DeviceInfoSet *set = DeviceInfoSet;
3102 struct DeviceInfo *devInfo;
3104 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
3105 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3108 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3110 SetLastError(ERROR_INVALID_HANDLE);
3113 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3115 SetLastError(ERROR_INVALID_HANDLE);
3118 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3119 || !DeviceInfoData->Reserved)
3121 SetLastError(ERROR_INVALID_PARAMETER);
3124 if (PropertyBufferSize && PropertyBuffer == NULL)
3126 SetLastError(ERROR_INVALID_DATA);
3129 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3130 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3131 && PropertyMap[Property].nameA)
3133 DWORD size = PropertyBufferSize;
3134 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
3135 NULL, PropertyRegDataType, PropertyBuffer, &size);
3137 if (l == ERROR_MORE_DATA || !PropertyBufferSize)
3138 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3144 *RequiredSize = size;
3149 /***********************************************************************
3150 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3152 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3153 HDEVINFO DeviceInfoSet,
3154 PSP_DEVINFO_DATA DeviceInfoData,
3156 PDWORD PropertyRegDataType,
3157 PBYTE PropertyBuffer,
3158 DWORD PropertyBufferSize,
3159 PDWORD RequiredSize)
3162 struct DeviceInfoSet *set = DeviceInfoSet;
3163 struct DeviceInfo *devInfo;
3165 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
3166 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3169 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3171 SetLastError(ERROR_INVALID_HANDLE);
3174 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3176 SetLastError(ERROR_INVALID_HANDLE);
3179 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3180 || !DeviceInfoData->Reserved)
3182 SetLastError(ERROR_INVALID_PARAMETER);
3185 if (PropertyBufferSize && PropertyBuffer == NULL)
3187 SetLastError(ERROR_INVALID_DATA);
3190 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3191 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3192 && PropertyMap[Property].nameW)
3194 DWORD size = PropertyBufferSize;
3195 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
3196 NULL, PropertyRegDataType, PropertyBuffer, &size);
3198 if (l == ERROR_MORE_DATA || !PropertyBufferSize)
3199 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3205 *RequiredSize = size;
3210 /***********************************************************************
3211 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3213 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3214 HDEVINFO DeviceInfoSet,
3215 PSP_DEVINFO_DATA DeviceInfoData,
3217 const BYTE *PropertyBuffer,
3218 DWORD PropertyBufferSize)
3221 struct DeviceInfoSet *set = DeviceInfoSet;
3222 struct DeviceInfo *devInfo;
3224 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3225 PropertyBuffer, PropertyBufferSize);
3227 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3229 SetLastError(ERROR_INVALID_HANDLE);
3232 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3234 SetLastError(ERROR_INVALID_HANDLE);
3237 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3238 || !DeviceInfoData->Reserved)
3240 SetLastError(ERROR_INVALID_PARAMETER);
3243 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3244 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3245 && PropertyMap[Property].nameA)
3247 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
3248 PropertyMap[Property].regType, PropertyBuffer,
3249 PropertyBufferSize);
3258 /***********************************************************************
3259 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3261 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3262 HDEVINFO DeviceInfoSet,
3263 PSP_DEVINFO_DATA DeviceInfoData,
3265 const BYTE *PropertyBuffer,
3266 DWORD PropertyBufferSize)
3269 struct DeviceInfoSet *set = DeviceInfoSet;
3270 struct DeviceInfo *devInfo;
3272 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3273 PropertyBuffer, PropertyBufferSize);
3275 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3277 SetLastError(ERROR_INVALID_HANDLE);
3280 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3282 SetLastError(ERROR_INVALID_HANDLE);
3285 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3286 || !DeviceInfoData->Reserved)
3288 SetLastError(ERROR_INVALID_PARAMETER);
3291 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3292 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3293 && PropertyMap[Property].nameW)
3295 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
3296 PropertyMap[Property].regType, PropertyBuffer,
3297 PropertyBufferSize);
3306 /***********************************************************************
3307 * SetupDiInstallClassA (SETUPAPI.@)
3309 BOOL WINAPI SetupDiInstallClassA(
3315 UNICODE_STRING FileNameW;
3320 SetLastError(ERROR_INVALID_PARAMETER);
3323 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
3325 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3329 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
3331 RtlFreeUnicodeString(&FileNameW);
3336 static HKEY CreateClassKey(HINF hInf)
3338 static const WCHAR slash[] = { '\\',0 };
3339 WCHAR FullBuffer[MAX_PATH];
3340 WCHAR Buffer[MAX_PATH];
3344 if (!SetupGetLineTextW(NULL,
3352 return INVALID_HANDLE_VALUE;
3355 lstrcpyW(FullBuffer, ControlClass);
3356 lstrcatW(FullBuffer, slash);
3357 lstrcatW(FullBuffer, Buffer);
3359 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3365 if (!SetupGetLineTextW(NULL,
3373 return INVALID_HANDLE_VALUE;
3376 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3380 REG_OPTION_NON_VOLATILE,
3386 return INVALID_HANDLE_VALUE;
3391 if (RegSetValueExW(hClassKey,
3396 RequiredSize * sizeof(WCHAR)))
3398 RegCloseKey(hClassKey);
3399 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3401 return INVALID_HANDLE_VALUE;
3407 /***********************************************************************
3408 * SetupDiInstallClassW (SETUPAPI.@)
3410 BOOL WINAPI SetupDiInstallClassW(
3416 WCHAR SectionName[MAX_PATH];
3417 DWORD SectionNameLength = 0;
3419 BOOL bFileQueueCreated = FALSE;
3427 SetLastError(ERROR_INVALID_PARAMETER);
3430 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
3432 SetLastError(ERROR_INVALID_PARAMETER);
3436 /* Open the .inf file */
3437 hInf = SetupOpenInfFileW(InfFileName,
3441 if (hInf == INVALID_HANDLE_VALUE)
3447 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3448 hClassKey = CreateClassKey(hInf);
3449 if (hClassKey == INVALID_HANDLE_VALUE)
3451 SetupCloseInfFile(hInf);
3456 /* Try to append a layout file */
3457 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3459 /* Retrieve the actual section name */
3460 SetupDiGetActualSectionToInstallW(hInf,
3468 if (!(Flags & DI_NOVCP))
3470 FileQueue = SetupOpenFileQueue();
3471 if (FileQueue == INVALID_HANDLE_VALUE)
3473 SetupCloseInfFile(hInf);
3477 bFileQueueCreated = TRUE;
3482 SetupInstallFromInfSectionW(NULL,
3485 SPINST_COPYINF | SPINST_FILES | SPINST_REGISTRY,
3491 INVALID_HANDLE_VALUE,
3494 /* FIXME: More code! */
3496 if (bFileQueueCreated)
3497 SetupCloseFileQueue(FileQueue);
3499 SetupCloseInfFile(hInf);
3505 /***********************************************************************
3506 * SetupDiOpenClassRegKey (SETUPAPI.@)
3508 HKEY WINAPI SetupDiOpenClassRegKey(
3509 const GUID* ClassGuid,
3512 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3513 DIOCR_INSTALLER, NULL, NULL);
3517 /***********************************************************************
3518 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3520 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3521 const GUID* ClassGuid,
3527 PWSTR MachineNameW = NULL;
3534 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3535 if (MachineNameW == NULL)
3536 return INVALID_HANDLE_VALUE;
3539 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3540 Flags, MachineNameW, Reserved);
3542 MyFree(MachineNameW);
3548 /***********************************************************************
3549 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3551 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3552 const GUID* ClassGuid,
3563 if (MachineName != NULL)
3565 FIXME("Remote access not supported yet!\n");
3566 return INVALID_HANDLE_VALUE;
3569 if (Flags == DIOCR_INSTALLER)
3571 lpKeyName = ControlClass;
3573 else if (Flags == DIOCR_INTERFACE)
3575 lpKeyName = DeviceClasses;
3579 ERR("Invalid Flags parameter!\n");
3580 SetLastError(ERROR_INVALID_PARAMETER);
3581 return INVALID_HANDLE_VALUE;
3586 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3593 hClassesKey = INVALID_HANDLE_VALUE;
3599 WCHAR bracedGuidString[39];
3601 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3603 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3609 if ((l = RegOpenKeyExW(hClassesKey,
3616 key = INVALID_HANDLE_VALUE;
3618 RegCloseKey(hClassesKey);
3623 key = INVALID_HANDLE_VALUE;
3629 /***********************************************************************
3630 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3632 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3633 HDEVINFO DeviceInfoSet,
3636 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3638 FIXME("%p %s %08x %p\n",
3639 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3643 /***********************************************************************
3644 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3646 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3647 HDEVINFO DeviceInfoSet,
3650 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3652 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3653 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3657 /***********************************************************************
3658 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3660 BOOL WINAPI SetupDiSetClassInstallParamsA(
3661 HDEVINFO DeviceInfoSet,
3662 PSP_DEVINFO_DATA DeviceInfoData,
3663 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3664 DWORD ClassInstallParamsSize)
3666 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3667 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3671 /***********************************************************************
3672 * SetupDiCallClassInstaller (SETUPAPI.@)
3674 BOOL WINAPI SetupDiCallClassInstaller(
3675 DI_FUNCTION InstallFunction,
3676 HDEVINFO DeviceInfoSet,
3677 PSP_DEVINFO_DATA DeviceInfoData)
3679 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3683 /***********************************************************************
3684 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3686 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3687 HDEVINFO DeviceInfoSet,
3688 PSP_DEVINFO_DATA DeviceInfoData,
3689 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3691 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3695 static HKEY SETUPDI_OpenDevKey(struct DeviceInfo *devInfo, REGSAM samDesired)
3697 HKEY enumKey, key = INVALID_HANDLE_VALUE;
3700 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
3701 NULL, &enumKey, NULL);
3704 RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
3705 RegCloseKey(enumKey);
3710 static HKEY SETUPDI_OpenDrvKey(struct DeviceInfo *devInfo, REGSAM samDesired)
3712 static const WCHAR slash[] = { '\\',0 };
3713 WCHAR classKeyPath[MAX_PATH];
3714 HKEY classKey, key = INVALID_HANDLE_VALUE;
3717 lstrcpyW(classKeyPath, ControlClass);
3718 lstrcatW(classKeyPath, slash);
3719 SETUPDI_GuidToString(&devInfo->set->ClassGuid,
3720 classKeyPath + lstrlenW(classKeyPath));
3721 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
3722 KEY_ALL_ACCESS, NULL, &classKey, NULL);
3725 static const WCHAR fmt[] = { '%','0','4','u',0 };
3728 sprintfW(devId, fmt, devInfo->devId);
3729 RegOpenKeyExW(classKey, devId, 0, samDesired, &key);
3730 RegCloseKey(classKey);
3735 /***********************************************************************
3736 * SetupDiOpenDevRegKey (SETUPAPI.@)
3738 HKEY WINAPI SetupDiOpenDevRegKey(
3739 HDEVINFO DeviceInfoSet,
3740 PSP_DEVINFO_DATA DeviceInfoData,
3746 struct DeviceInfoSet *set = DeviceInfoSet;
3747 struct DeviceInfo *devInfo;
3748 HKEY key = INVALID_HANDLE_VALUE;
3750 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3751 Scope, HwProfile, KeyType, samDesired);
3753 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3755 SetLastError(ERROR_INVALID_HANDLE);
3756 return INVALID_HANDLE_VALUE;
3758 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3760 SetLastError(ERROR_INVALID_HANDLE);
3761 return INVALID_HANDLE_VALUE;
3763 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3764 || !DeviceInfoData->Reserved)
3766 SetLastError(ERROR_INVALID_PARAMETER);
3767 return INVALID_HANDLE_VALUE;
3769 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3771 SetLastError(ERROR_INVALID_FLAGS);
3772 return INVALID_HANDLE_VALUE;
3774 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3776 SetLastError(ERROR_INVALID_FLAGS);
3777 return INVALID_HANDLE_VALUE;
3779 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3780 if (devInfo->set != set)
3782 SetLastError(ERROR_INVALID_PARAMETER);
3783 return INVALID_HANDLE_VALUE;
3785 if (devInfo->phantom)
3787 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
3788 return INVALID_HANDLE_VALUE;
3790 if (Scope != DICS_FLAG_GLOBAL)
3791 FIXME("unimplemented for scope %d\n", Scope);
3795 key = SETUPDI_OpenDevKey(devInfo, samDesired);
3798 key = SETUPDI_OpenDrvKey(devInfo, samDesired);
3801 WARN("unknown KeyType %d\n", KeyType);
3806 static BOOL SETUPDI_DeleteDevKey(struct DeviceInfo *devInfo)
3812 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
3813 NULL, &enumKey, NULL);
3816 ret = RegDeleteTreeW(enumKey, devInfo->instanceId);
3817 RegCloseKey(enumKey);
3824 static BOOL SETUPDI_DeleteDrvKey(struct DeviceInfo *devInfo)
3826 static const WCHAR slash[] = { '\\',0 };
3827 WCHAR classKeyPath[MAX_PATH];
3832 lstrcpyW(classKeyPath, ControlClass);
3833 lstrcatW(classKeyPath, slash);
3834 SETUPDI_GuidToString(&devInfo->set->ClassGuid,
3835 classKeyPath + lstrlenW(classKeyPath));
3836 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
3837 KEY_ALL_ACCESS, NULL, &classKey, NULL);
3840 static const WCHAR fmt[] = { '%','0','4','u',0 };
3843 sprintfW(devId, fmt, devInfo->devId);
3844 ret = RegDeleteTreeW(classKey, devId);
3845 RegCloseKey(classKey);
3852 /***********************************************************************
3853 * SetupDiDeleteDevRegKey (SETUPAPI.@)
3855 BOOL WINAPI SetupDiDeleteDevRegKey(
3856 HDEVINFO DeviceInfoSet,
3857 PSP_DEVINFO_DATA DeviceInfoData,
3862 struct DeviceInfoSet *set = DeviceInfoSet;
3863 struct DeviceInfo *devInfo;
3866 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
3869 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3871 SetLastError(ERROR_INVALID_HANDLE);
3874 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3876 SetLastError(ERROR_INVALID_HANDLE);
3879 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3880 || !DeviceInfoData->Reserved)
3882 SetLastError(ERROR_INVALID_PARAMETER);
3885 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3887 SetLastError(ERROR_INVALID_FLAGS);
3890 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
3892 SetLastError(ERROR_INVALID_FLAGS);
3895 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3896 if (devInfo->set != set)
3898 SetLastError(ERROR_INVALID_PARAMETER);
3901 if (devInfo->phantom)
3903 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
3906 if (Scope != DICS_FLAG_GLOBAL)
3907 FIXME("unimplemented for scope %d\n", Scope);
3911 ret = SETUPDI_DeleteDevKey(devInfo);
3914 ret = SETUPDI_DeleteDrvKey(devInfo);
3917 ret = SETUPDI_DeleteDevKey(devInfo);
3919 ret = SETUPDI_DeleteDrvKey(devInfo);
3922 WARN("unknown KeyType %d\n", KeyType);
3927 /***********************************************************************
3928 * CM_Get_Device_IDA (SETUPAPI.@)
3930 CONFIGRET WINAPI CM_Get_Device_IDA( DEVINST dnDevInst, PSTR Buffer,
3931 ULONG BufferLen, ULONG ulFlags)
3933 struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
3935 TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
3938 return CR_NO_SUCH_DEVINST;
3940 WideCharToMultiByte(CP_ACP, 0, devInfo->instanceId, -1, Buffer, BufferLen, 0, 0);
3941 TRACE("Returning %s\n", debugstr_a(Buffer));
3945 /***********************************************************************
3946 * CM_Get_Device_IDW (SETUPAPI.@)
3948 CONFIGRET WINAPI CM_Get_Device_IDW( DEVINST dnDevInst, LPWSTR Buffer,
3949 ULONG BufferLen, ULONG ulFlags)
3951 struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
3953 TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
3957 WARN("dev instance %d not found!\n", dnDevInst);
3958 return CR_NO_SUCH_DEVINST;
3961 lstrcpynW(Buffer, devInfo->instanceId, BufferLen);
3962 TRACE("Returning %s\n", debugstr_w(Buffer));
3963 GlobalUnlock((HANDLE)dnDevInst);
3969 /***********************************************************************
3970 * CM_Get_Device_ID_Size (SETUPAPI.@)
3972 CONFIGRET WINAPI CM_Get_Device_ID_Size( PULONG pulLen, DEVINST dnDevInst,
3975 struct DeviceInfo *ppdevInfo = GlobalLock((HANDLE)dnDevInst);
3977 TRACE("%x->%p, %p, %u\n", dnDevInst, ppdevInfo, pulLen, ulFlags);
3981 WARN("dev instance %d not found!\n", dnDevInst);
3982 return CR_NO_SUCH_DEVINST;
3985 *pulLen = lstrlenW(ppdevInfo->instanceId);
3986 GlobalUnlock((HANDLE)dnDevInst);
3990 /***********************************************************************
3991 * SetupDiGetINFClassA (SETUPAPI.@)
3993 BOOL WINAPI SetupDiGetINFClassA(PCSTR inf, LPGUID class_guid, PSTR class_name,
3994 DWORD size, PDWORD required_size)
3997 DWORD required_sizeA, required_sizeW;
3998 PWSTR class_nameW = NULL;
3999 UNICODE_STRING infW;
4001 if (inf) RtlCreateUnicodeStringFromAsciiz(&infW, inf);
4002 else infW.Buffer = NULL;
4003 if (class_name && size)
4004 class_nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
4006 retval = SetupDiGetINFClassW(infW.Buffer, class_guid, class_nameW, size, &required_sizeW);
4010 required_sizeA = WideCharToMultiByte( CP_ACP, 0, class_nameW, required_sizeW,
4011 class_name, size, NULL, NULL);
4013 if(required_size) *required_size = required_sizeA;
4016 if(required_size) *required_size = required_sizeW;
4021 /***********************************************************************
4022 * SetupDiGetINFClassW (SETUPAPI.@)
4024 BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name,
4025 DWORD size, PDWORD required_size)
4027 BOOL have_guid, have_name;
4029 WCHAR buffer[MAX_PATH];
4033 SetLastError(ERROR_INVALID_PARAMETER);
4037 if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(inf))
4039 FIXME("%s not found. Searching via DevicePath not implemented\n", debugstr_w(inf));
4040 SetLastError(ERROR_FILE_NOT_FOUND);
4044 if (!class_guid || !class_name || !size)
4046 SetLastError(ERROR_INVALID_PARAMETER);
4050 if (!GetPrivateProfileStringW(Version, Signature, NULL, buffer, MAX_PATH, inf))
4053 if (lstrcmpiW(buffer, Chicago))
4057 have_guid = 0 < GetPrivateProfileStringW(Version, ClassGUID, NULL, buffer, MAX_PATH, inf);
4060 buffer[lstrlenW(buffer)-1] = 0;
4061 if (RPC_S_OK != UuidFromStringW(buffer + 1, class_guid))
4063 FIXME("failed to convert \"%s\" into a guid\n", debugstr_w(buffer));
4064 SetLastError(ERROR_INVALID_PARAMETER);
4070 dret = GetPrivateProfileStringW(Version, Class, NULL, buffer, MAX_PATH, inf);
4071 have_name = 0 < dret;
4073 if (dret >= MAX_PATH -1) FIXME("buffer might be too small\n");
4074 if (have_guid && !have_name) FIXME("class name lookup via guid not implemented\n");
4078 if (dret < size) lstrcpyW(class_name, buffer);
4081 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4086 if (required_size) *required_size = dret + ((dret) ? 1 : 0);
4088 return (have_guid || have_name);