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
;
132 struct list interfaces
;
135 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
137 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
138 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
139 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
142 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
143 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
144 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
147 static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances
*instances
)
151 for (i
= 0; i
< instances
->cInstances
; i
++)
153 struct InterfaceInfo
*ifaceInfo
=
154 (struct InterfaceInfo
*)instances
->instances
[i
].Reserved
;
156 if (ifaceInfo
->device
&& ifaceInfo
->device
->Reserved
)
158 struct DeviceInfo
*devInfo
=
159 (struct DeviceInfo
*)ifaceInfo
->device
->Reserved
;
161 if (devInfo
->phantom
)
162 SetupDiDeleteDeviceInterfaceRegKey(devInfo
->set
,
163 &instances
->instances
[i
], 0);
165 HeapFree(GetProcessHeap(), 0, ifaceInfo
->referenceString
);
166 HeapFree(GetProcessHeap(), 0, ifaceInfo
->symbolicLink
);
167 HeapFree(GetProcessHeap(), 0, ifaceInfo
);
169 HeapFree(GetProcessHeap(), 0, instances
->instances
);
172 /* Finds the interface with interface class InterfaceClassGuid in the device.
173 * Returns TRUE if found, and updates *interface to point to device's
174 * interfaces member where the given interface was found.
175 * Returns FALSE if not found.
177 static BOOL
SETUPDI_FindInterface(const struct DeviceInfo
*devInfo
,
178 const GUID
*InterfaceClassGuid
, struct InterfaceInstances
**interface
)
181 struct InterfaceInstances
*iface
;
183 TRACE("%s\n", debugstr_guid(InterfaceClassGuid
));
185 LIST_FOR_EACH_ENTRY(iface
, &devInfo
->interfaces
, struct InterfaceInstances
,
188 if (IsEqualGUID(&iface
->guid
, InterfaceClassGuid
))
195 TRACE("returning %d (%p)\n", found
, found
? *interface
: NULL
);
199 /* Finds the interface instance with reference string ReferenceString in the
200 * interface instance map. Returns TRUE if found, and updates instanceIndex to
201 * the index of the interface instance's instances member
202 * where the given instance was found. Returns FALSE if not found.
204 static BOOL
SETUPDI_FindInterfaceInstance(
205 const struct InterfaceInstances
*instances
,
206 LPCWSTR ReferenceString
, DWORD
*instanceIndex
)
211 TRACE("%s\n", debugstr_w(ReferenceString
));
213 for (i
= 0; !found
&& i
< instances
->cInstances
; i
++)
215 SP_DEVICE_INTERFACE_DATA
*ifaceData
= &instances
->instances
[i
];
216 struct InterfaceInfo
*ifaceInfo
=
217 (struct InterfaceInfo
*)ifaceData
->Reserved
;
219 if (!ReferenceString
&& !ifaceInfo
->referenceString
)
224 else if (ReferenceString
&& ifaceInfo
->referenceString
&&
225 !lstrcmpiW(ifaceInfo
->referenceString
, ReferenceString
))
231 TRACE("returning %d (%d)\n", found
, found
? *instanceIndex
: 0);
235 static LPWSTR
SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId
,
236 const GUID
*InterfaceClassGuid
, LPCWSTR ReferenceString
)
238 static const WCHAR fmt
[] = {'\\','\\','?','\\','%','s','#','%','s',0};
243 SETUPDI_GuidToString(InterfaceClassGuid
, guidStr
);
244 /* omit length of format specifiers, but include NULL terminator: */
245 len
= lstrlenW(fmt
) - 4 + 1;
246 len
+= lstrlenW(instanceId
) + lstrlenW(guidStr
);
249 /* space for a hash between string and reference string: */
250 len
+= lstrlenW(ReferenceString
) + 1;
252 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
255 int printed
= sprintfW(ret
, fmt
, instanceId
, guidStr
);
258 /* replace '\\' with '#' after the "\\\\?\\" beginning */
259 for (ptr
= strchrW(ret
+ 4, '\\'); ptr
; ptr
= strchrW(ptr
+ 1, '\\'))
263 ret
[printed
- 1] = '\\';
264 lstrcpyW(ret
+ printed
, ReferenceString
);
270 /* Adds an interface with the given interface class and reference string to
271 * the device, if it doesn't already exist in the device. If iface is not
272 * NULL, returns a pointer to the newly added (or already existing) interface.
274 static BOOL
SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData
,
275 const GUID
*InterfaceClassGuid
, LPCWSTR ReferenceString
,
276 SP_DEVICE_INTERFACE_DATA
**ifaceData
)
278 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
279 BOOL newInterface
= FALSE
, ret
;
280 struct InterfaceInstances
*iface
= NULL
;
282 TRACE("%p %s %s %p\n", devInfo
, debugstr_guid(InterfaceClassGuid
),
283 debugstr_w(ReferenceString
), iface
);
285 if (!(ret
= SETUPDI_FindInterface(devInfo
, InterfaceClassGuid
, &iface
)))
287 iface
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
288 sizeof(struct InterfaceInstances
));
291 list_add_tail(&devInfo
->interfaces
, &iface
->entry
);
297 DWORD instanceIndex
= 0;
299 if (!(ret
= SETUPDI_FindInterfaceInstance(iface
, ReferenceString
,
302 SP_DEVICE_INTERFACE_DATA
*instance
= NULL
;
304 if (!iface
->cInstancesAllocated
)
306 iface
->instances
= HeapAlloc(GetProcessHeap(), 0,
307 sizeof(SP_DEVICE_INTERFACE_DATA
));
308 if (iface
->instances
)
309 instance
= &iface
->instances
[iface
->cInstancesAllocated
++];
311 else if (iface
->cInstances
== iface
->cInstancesAllocated
)
313 iface
->instances
= HeapReAlloc(GetProcessHeap(), 0,
315 (iface
->cInstancesAllocated
+ 1) *
316 sizeof(SP_DEVICE_INTERFACE_DATA
));
317 if (iface
->instances
)
318 instance
= &iface
->instances
[iface
->cInstancesAllocated
++];
321 instance
= &iface
->instances
[iface
->cInstances
];
324 struct InterfaceInfo
*ifaceInfo
= HeapAlloc(GetProcessHeap(),
325 0, sizeof(struct InterfaceInfo
));
330 ifaceInfo
->device
= DeviceInfoData
;
331 ifaceInfo
->symbolicLink
= SETUPDI_CreateSymbolicLinkPath(
332 devInfo
->instanceId
, InterfaceClassGuid
,
336 ifaceInfo
->referenceString
=
337 HeapAlloc(GetProcessHeap(), 0,
338 (lstrlenW(ReferenceString
) + 1) *
340 if (ifaceInfo
->referenceString
)
341 lstrcpyW(ifaceInfo
->referenceString
,
347 ifaceInfo
->referenceString
= NULL
;
354 sizeof(SP_DEVICE_INTERFACE_DATA
);
355 memcpy(&instance
->InterfaceClassGuid
,
356 InterfaceClassGuid
, sizeof(GUID
));
357 instance
->Flags
= SPINT_ACTIVE
; /* FIXME */
358 instance
->Reserved
= (ULONG_PTR
)ifaceInfo
;
360 memcpy(&iface
->guid
, InterfaceClassGuid
,
362 key
= SetupDiCreateDeviceInterfaceRegKeyW(devInfo
->set
,
363 instance
, 0, KEY_WRITE
, NULL
, NULL
);
364 if (key
!= INVALID_HANDLE_VALUE
)
366 RegSetValueExW(key
, SymbolicLink
, 0, REG_SZ
,
367 (BYTE
*)ifaceInfo
->symbolicLink
,
368 lstrlenW(ifaceInfo
->symbolicLink
) *
373 *ifaceData
= instance
;
376 HeapFree(GetProcessHeap(), 0, ifaceInfo
);
383 *ifaceData
= &iface
->instances
[instanceIndex
];
388 TRACE("returning %d\n", ret
);
392 static BOOL
SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA
*iface
,
393 LPCWSTR symbolicLink
)
395 struct InterfaceInfo
*info
= (struct InterfaceInfo
*)iface
->Reserved
;
400 HeapFree(GetProcessHeap(), 0, info
->symbolicLink
);
401 info
->symbolicLink
= HeapAlloc(GetProcessHeap(), 0,
402 (lstrlenW(symbolicLink
) + 1) * sizeof(WCHAR
));
403 if (info
->symbolicLink
)
405 lstrcpyW(info
->symbolicLink
, symbolicLink
);
412 static HKEY
SETUPDI_CreateDevKey(struct DeviceInfo
*devInfo
)
414 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
417 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_ALL_ACCESS
,
418 NULL
, &enumKey
, NULL
);
421 RegCreateKeyExW(enumKey
, devInfo
->instanceId
, 0, NULL
, 0,
422 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
423 RegCloseKey(enumKey
);
428 static HKEY
SETUPDI_CreateDrvKey(struct DeviceInfo
*devInfo
)
430 static const WCHAR slash
[] = { '\\',0 };
431 WCHAR classKeyPath
[MAX_PATH
];
432 HKEY classKey
, key
= INVALID_HANDLE_VALUE
;
435 lstrcpyW(classKeyPath
, ControlClass
);
436 lstrcatW(classKeyPath
, slash
);
437 SETUPDI_GuidToString(&devInfo
->set
->ClassGuid
,
438 classKeyPath
+ lstrlenW(classKeyPath
));
439 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, classKeyPath
, 0, NULL
, 0,
440 KEY_ALL_ACCESS
, NULL
, &classKey
, NULL
);
443 static const WCHAR fmt
[] = { '%','0','4','u',0 };
446 sprintfW(devId
, fmt
, devInfo
->devId
);
447 RegCreateKeyExW(classKey
, devId
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
449 RegCloseKey(classKey
);
454 static struct DeviceInfo
*SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet
*set
,
455 DWORD devId
, LPCWSTR instanceId
, BOOL phantom
)
457 struct DeviceInfo
*devInfo
= HeapAlloc(GetProcessHeap(), 0,
458 sizeof(struct DeviceInfo
));
463 devInfo
->devId
= devId
;
464 devInfo
->instanceId
= HeapAlloc(GetProcessHeap(), 0,
465 (lstrlenW(instanceId
) + 1) * sizeof(WCHAR
));
466 if (devInfo
->instanceId
)
468 devInfo
->key
= INVALID_HANDLE_VALUE
;
469 devInfo
->phantom
= phantom
;
470 lstrcpyW(devInfo
->instanceId
, instanceId
);
471 struprW(devInfo
->instanceId
);
472 devInfo
->key
= SETUPDI_CreateDevKey(devInfo
);
473 if (devInfo
->key
!= INVALID_HANDLE_VALUE
)
476 RegSetValueExW(devInfo
->key
, Phantom
, 0, REG_DWORD
,
477 (LPBYTE
)&phantom
, sizeof(phantom
));
479 list_init(&devInfo
->interfaces
);
483 HeapFree(GetProcessHeap(), 0, devInfo
);
490 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo
*devInfo
)
492 struct InterfaceInstances
*iface
, *next
;
494 if (devInfo
->key
!= INVALID_HANDLE_VALUE
)
495 RegCloseKey(devInfo
->key
);
496 if (devInfo
->phantom
)
501 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0,
502 KEY_ALL_ACCESS
, NULL
, &enumKey
, NULL
);
505 RegDeleteTreeW(enumKey
, devInfo
->instanceId
);
506 RegCloseKey(enumKey
);
509 HeapFree(GetProcessHeap(), 0, devInfo
->instanceId
);
510 LIST_FOR_EACH_ENTRY_SAFE(iface
, next
, &devInfo
->interfaces
,
511 struct InterfaceInstances
, entry
)
513 list_remove(&iface
->entry
);
514 SETUPDI_FreeInterfaceInstances(iface
);
515 HeapFree(GetProcessHeap(), 0, iface
);
517 HeapFree(GetProcessHeap(), 0, devInfo
);
520 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
521 * struct DeviceInfo, and points the returned device info's Reserved member
522 * to it. "Phantom" devices are deleted from the registry when closed.
523 * Returns a pointer to the newly allocated device info.
525 static BOOL
SETUPDI_AddDeviceToSet(struct DeviceInfoSet
*set
,
530 SP_DEVINFO_DATA
**dev
)
533 struct DeviceInfo
*devInfo
= SETUPDI_AllocateDeviceInfo(set
, set
->cDevices
,
534 instanceId
, phantom
);
536 TRACE("%p, %s, %d, %s, %d\n", set
, debugstr_guid(guid
), devInst
,
537 debugstr_w(instanceId
), phantom
);
542 set
->devices
= HeapReAlloc(GetProcessHeap(), 0, set
->devices
,
543 (set
->cDevices
+ 1) * sizeof(SP_DEVINFO_DATA
));
545 set
->devices
= HeapAlloc(GetProcessHeap(), 0,
546 sizeof(SP_DEVINFO_DATA
));
549 WCHAR classGuidStr
[39];
550 SP_DEVINFO_DATA
*DeviceInfoData
= &set
->devices
[set
->cDevices
++];
552 DeviceInfoData
->cbSize
= sizeof(SP_DEVINFO_DATA
);
553 memcpy(&DeviceInfoData
->ClassGuid
, guid
, sizeof(GUID
));
554 DeviceInfoData
->DevInst
= devInst
;
555 DeviceInfoData
->Reserved
= (ULONG_PTR
)devInfo
;
556 SETUPDI_GuidToString(guid
, classGuidStr
);
557 SetupDiSetDeviceRegistryPropertyW((HDEVINFO
)set
,
558 DeviceInfoData
, SPDRP_CLASSGUID
, (const BYTE
*)classGuidStr
,
559 lstrlenW(classGuidStr
) * sizeof(WCHAR
));
561 *dev
= DeviceInfoData
;
566 HeapFree(GetProcessHeap(), 0, devInfo
);
567 SetLastError(ERROR_OUTOFMEMORY
);
573 /***********************************************************************
574 * SetupDiBuildClassInfoList (SETUPAPI.@)
576 * Returns a list of setup class GUIDs that identify the classes
577 * that are installed on a local machine.
580 * Flags [I] control exclusion of classes from the list.
581 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
582 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
583 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
589 BOOL WINAPI
SetupDiBuildClassInfoList(
591 LPGUID ClassGuidList
,
592 DWORD ClassGuidListSize
,
596 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
597 ClassGuidListSize
, RequiredSize
,
601 /***********************************************************************
602 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
604 * Returns a list of setup class GUIDs that identify the classes
605 * that are installed on a local or remote macine.
608 * Flags [I] control exclusion of classes from the list.
609 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
610 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
611 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
612 * MachineName [I] name of a remote machine.
613 * Reserved [I] must be NULL.
619 BOOL WINAPI
SetupDiBuildClassInfoListExA(
621 LPGUID ClassGuidList
,
622 DWORD ClassGuidListSize
,
627 LPWSTR MachineNameW
= NULL
;
634 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
635 if (MachineNameW
== NULL
) return FALSE
;
638 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
639 ClassGuidListSize
, RequiredSize
,
640 MachineNameW
, Reserved
);
642 MyFree(MachineNameW
);
647 /***********************************************************************
648 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
650 * Returns a list of setup class GUIDs that identify the classes
651 * that are installed on a local or remote macine.
654 * Flags [I] control exclusion of classes from the list.
655 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
656 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
657 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
658 * MachineName [I] name of a remote machine.
659 * Reserved [I] must be NULL.
665 BOOL WINAPI
SetupDiBuildClassInfoListExW(
667 LPGUID ClassGuidList
,
668 DWORD ClassGuidListSize
,
679 DWORD dwGuidListIndex
= 0;
683 if (RequiredSize
!= NULL
)
686 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
691 if (hClassesKey
== INVALID_HANDLE_VALUE
)
696 for (dwIndex
= 0; ; dwIndex
++)
699 lError
= RegEnumKeyExW(hClassesKey
,
707 TRACE("RegEnumKeyExW() returns %d\n", lError
);
708 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
710 TRACE("Key name: %p\n", szKeyName
);
712 if (RegOpenKeyExW(hClassesKey
,
718 RegCloseKey(hClassesKey
);
722 if (!RegQueryValueExW(hClassKey
,
729 TRACE("'NoUseClass' value found!\n");
730 RegCloseKey(hClassKey
);
734 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
735 (!RegQueryValueExW(hClassKey
,
742 TRACE("'NoInstallClass' value found!\n");
743 RegCloseKey(hClassKey
);
747 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
748 (!RegQueryValueExW(hClassKey
,
755 TRACE("'NoDisplayClass' value found!\n");
756 RegCloseKey(hClassKey
);
760 RegCloseKey(hClassKey
);
762 TRACE("Guid: %p\n", szKeyName
);
763 if (dwGuidListIndex
< ClassGuidListSize
)
765 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
769 TRACE("Guid: %p\n", &szKeyName
[1]);
771 UuidFromStringW(&szKeyName
[1],
772 &ClassGuidList
[dwGuidListIndex
]);
778 if (lError
!= ERROR_SUCCESS
)
782 RegCloseKey(hClassesKey
);
784 if (RequiredSize
!= NULL
)
785 *RequiredSize
= dwGuidListIndex
;
787 if (ClassGuidListSize
< dwGuidListIndex
)
789 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
796 /***********************************************************************
797 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
799 BOOL WINAPI
SetupDiClassGuidsFromNameA(
801 LPGUID ClassGuidList
,
802 DWORD ClassGuidListSize
,
805 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
806 ClassGuidListSize
, RequiredSize
,
810 /***********************************************************************
811 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
813 BOOL WINAPI
SetupDiClassGuidsFromNameW(
815 LPGUID ClassGuidList
,
816 DWORD ClassGuidListSize
,
819 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
820 ClassGuidListSize
, RequiredSize
,
824 /***********************************************************************
825 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
827 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
829 LPGUID ClassGuidList
,
830 DWORD ClassGuidListSize
,
835 LPWSTR ClassNameW
= NULL
;
836 LPWSTR MachineNameW
= NULL
;
839 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
840 if (ClassNameW
== NULL
)
845 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
846 if (MachineNameW
== NULL
)
853 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
854 ClassGuidListSize
, RequiredSize
,
855 MachineNameW
, Reserved
);
857 MyFree(MachineNameW
);
863 /***********************************************************************
864 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
866 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
868 LPGUID ClassGuidList
,
869 DWORD ClassGuidListSize
,
875 WCHAR szClassName
[256];
881 DWORD dwGuidListIndex
= 0;
883 if (RequiredSize
!= NULL
)
886 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
891 if (hClassesKey
== INVALID_HANDLE_VALUE
)
896 for (dwIndex
= 0; ; dwIndex
++)
899 lError
= RegEnumKeyExW(hClassesKey
,
907 TRACE("RegEnumKeyExW() returns %d\n", lError
);
908 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
910 TRACE("Key name: %p\n", szKeyName
);
912 if (RegOpenKeyExW(hClassesKey
,
918 RegCloseKey(hClassesKey
);
922 dwLength
= 256 * sizeof(WCHAR
);
923 if (!RegQueryValueExW(hClassKey
,
930 TRACE("Class name: %p\n", szClassName
);
932 if (strcmpiW(szClassName
, ClassName
) == 0)
934 TRACE("Found matching class name\n");
936 TRACE("Guid: %p\n", szKeyName
);
937 if (dwGuidListIndex
< ClassGuidListSize
)
939 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
943 TRACE("Guid: %p\n", &szKeyName
[1]);
945 UuidFromStringW(&szKeyName
[1],
946 &ClassGuidList
[dwGuidListIndex
]);
953 RegCloseKey(hClassKey
);
956 if (lError
!= ERROR_SUCCESS
)
960 RegCloseKey(hClassesKey
);
962 if (RequiredSize
!= NULL
)
963 *RequiredSize
= dwGuidListIndex
;
965 if (ClassGuidListSize
< dwGuidListIndex
)
967 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
974 /***********************************************************************
975 * SetupDiClassNameFromGuidA (SETUPAPI.@)
977 BOOL WINAPI
SetupDiClassNameFromGuidA(
978 const GUID
* ClassGuid
,
983 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
984 ClassNameSize
, RequiredSize
,
988 /***********************************************************************
989 * SetupDiClassNameFromGuidW (SETUPAPI.@)
991 BOOL WINAPI
SetupDiClassNameFromGuidW(
992 const GUID
* ClassGuid
,
997 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
998 ClassNameSize
, RequiredSize
,
1002 /***********************************************************************
1003 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1005 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1006 const GUID
* ClassGuid
,
1008 DWORD ClassNameSize
,
1009 PDWORD RequiredSize
,
1013 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1014 LPWSTR MachineNameW
= NULL
;
1018 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1019 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1020 NULL
, MachineNameW
, Reserved
);
1023 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1024 ClassNameSize
, NULL
, NULL
);
1026 if (!ClassNameSize
&& RequiredSize
)
1027 *RequiredSize
= len
;
1029 MyFree(MachineNameW
);
1033 /***********************************************************************
1034 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1036 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1037 const GUID
* ClassGuid
,
1039 DWORD ClassNameSize
,
1040 PDWORD RequiredSize
,
1047 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1052 if (hKey
== INVALID_HANDLE_VALUE
)
1057 if (RequiredSize
!= NULL
)
1060 if (RegQueryValueExW(hKey
,
1071 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1074 dwLength
= ClassNameSize
* sizeof(WCHAR
);
1075 if (RegQueryValueExW(hKey
,
1091 /***********************************************************************
1092 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1095 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1098 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1101 /***********************************************************************
1102 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1105 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1110 LPWSTR MachineNameW
= NULL
;
1117 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1118 if (MachineNameW
== NULL
)
1119 return INVALID_HANDLE_VALUE
;
1122 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1123 MachineNameW
, Reserved
);
1125 MyFree(MachineNameW
);
1130 /***********************************************************************
1131 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1133 * Create an empty DeviceInfoSet list.
1136 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1138 * hwndParent [I] hwnd needed for interface related actions.
1139 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1140 * local registry will be used.
1141 * Reserved [I] must be NULL
1144 * Success: empty list.
1145 * Failure: INVALID_HANDLE_VALUE.
1148 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1153 struct DeviceInfoSet
*list
= NULL
;
1154 DWORD size
= sizeof(struct DeviceInfoSet
);
1156 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1157 debugstr_w(MachineName
), Reserved
);
1159 if (MachineName
!= NULL
)
1161 FIXME("remote support is not implemented\n");
1162 SetLastError(ERROR_INVALID_MACHINENAME
);
1163 return INVALID_HANDLE_VALUE
;
1166 if (Reserved
!= NULL
)
1168 SetLastError(ERROR_INVALID_PARAMETER
);
1169 return INVALID_HANDLE_VALUE
;
1172 list
= HeapAlloc(GetProcessHeap(), 0, size
);
1175 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1176 return INVALID_HANDLE_VALUE
;
1179 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1180 list
->hwndParent
= hwndParent
;
1181 memcpy(&list
->ClassGuid
,
1182 ClassGuid
? ClassGuid
: &GUID_NULL
,
1183 sizeof(list
->ClassGuid
));
1185 list
->devices
= NULL
;
1187 return (HDEVINFO
)list
;
1190 /***********************************************************************
1191 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1193 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1194 HDEVINFO DeviceInfoSet
,
1195 PSP_DEVINFO_DATA DeviceInfoData
,
1200 PCSTR InfSectionName
)
1202 PWSTR InfSectionNameW
= NULL
;
1205 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1206 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1210 if (!InfSectionName
)
1212 SetLastError(ERROR_INVALID_PARAMETER
);
1213 return INVALID_HANDLE_VALUE
;
1217 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
1218 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1221 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1222 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1223 MyFree(InfSectionNameW
);
1227 /***********************************************************************
1228 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1230 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1231 HDEVINFO DeviceInfoSet
,
1232 PSP_DEVINFO_DATA DeviceInfoData
,
1237 PCWSTR InfSectionName
)
1239 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1240 struct DeviceInfo
*devInfo
;
1241 HKEY key
= INVALID_HANDLE_VALUE
;
1243 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1244 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1246 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1248 SetLastError(ERROR_INVALID_HANDLE
);
1249 return INVALID_HANDLE_VALUE
;
1251 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1253 SetLastError(ERROR_INVALID_HANDLE
);
1254 return INVALID_HANDLE_VALUE
;
1256 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1257 || !DeviceInfoData
->Reserved
)
1259 SetLastError(ERROR_INVALID_PARAMETER
);
1260 return INVALID_HANDLE_VALUE
;
1262 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1263 if (devInfo
->set
!= set
)
1265 SetLastError(ERROR_INVALID_PARAMETER
);
1266 return INVALID_HANDLE_VALUE
;
1268 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1270 SetLastError(ERROR_INVALID_FLAGS
);
1271 return INVALID_HANDLE_VALUE
;
1273 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1275 SetLastError(ERROR_INVALID_FLAGS
);
1276 return INVALID_HANDLE_VALUE
;
1278 if (devInfo
->phantom
)
1280 SetLastError(ERROR_DEVINFO_NOT_REGISTERED
);
1281 return INVALID_HANDLE_VALUE
;
1283 if (Scope
!= DICS_FLAG_GLOBAL
)
1284 FIXME("unimplemented for scope %d\n", Scope
);
1288 key
= SETUPDI_CreateDevKey(devInfo
);
1291 key
= SETUPDI_CreateDrvKey(devInfo
);
1294 WARN("unknown KeyType %d\n", KeyType
);
1297 SetupInstallFromInfSectionW(NULL
, InfHandle
, InfSectionName
, SPINST_ALL
,
1298 NULL
, NULL
, SP_COPY_NEWER_ONLY
, NULL
, NULL
, DeviceInfoSet
,
1303 /***********************************************************************
1304 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1306 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1307 HDEVINFO DeviceInfoSet
,
1309 CONST GUID
*ClassGuid
,
1310 PCSTR DeviceDescription
,
1312 DWORD CreationFlags
,
1313 PSP_DEVINFO_DATA DeviceInfoData
)
1316 LPWSTR DeviceNameW
= NULL
;
1317 LPWSTR DeviceDescriptionW
= NULL
;
1321 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
1322 if (DeviceNameW
== NULL
) return FALSE
;
1324 if (DeviceDescription
)
1326 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
1327 if (DeviceDescriptionW
== NULL
)
1329 MyFree(DeviceNameW
);
1334 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1335 hwndParent
, CreationFlags
, DeviceInfoData
);
1337 MyFree(DeviceNameW
);
1338 MyFree(DeviceDescriptionW
);
1343 static DWORD
SETUPDI_DevNameToDevID(LPCWSTR devName
)
1346 DWORD devNameLen
= lstrlenW(devName
), devInst
= 0;
1349 TRACE("%s\n", debugstr_w(devName
));
1350 for (ptr
= devName
; valid
&& *ptr
&& ptr
- devName
< devNameLen
; )
1355 devInst
|= *ptr
- '0';
1361 TRACE("%d\n", valid
? devInst
: 0xffffffff);
1362 return valid
? devInst
: 0xffffffff;
1365 /***********************************************************************
1366 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1368 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1369 HDEVINFO DeviceInfoSet
,
1371 CONST GUID
*ClassGuid
,
1372 PCWSTR DeviceDescription
,
1374 DWORD CreationFlags
,
1375 PSP_DEVINFO_DATA DeviceInfoData
)
1377 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1378 BOOL ret
= FALSE
, allocatedInstanceId
= FALSE
;
1379 LPCWSTR instanceId
= NULL
;
1381 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1382 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1383 hwndParent
, CreationFlags
, DeviceInfoData
);
1387 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1390 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1392 SetLastError(ERROR_INVALID_HANDLE
);
1397 SetLastError(ERROR_INVALID_PARAMETER
);
1400 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1402 SetLastError(ERROR_INVALID_HANDLE
);
1405 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1406 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1408 SetLastError(ERROR_CLASS_MISMATCH
);
1411 if ((CreationFlags
& DICD_GENERATE_ID
))
1413 if (strchrW(DeviceName
, '\\'))
1414 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1417 static const WCHAR newDeviceFmt
[] = {'R','O','O','T','\\','%','s',
1418 '\\','%','0','4','d',0};
1423 DWORD i
, highestDevID
= 0;
1425 for (i
= 0; i
< set
->cDevices
; i
++)
1427 struct DeviceInfo
*devInfo
=
1428 (struct DeviceInfo
*)set
->devices
[i
].Reserved
;
1429 LPCWSTR devName
= strrchrW(devInfo
->instanceId
, '\\');
1435 devName
= devInfo
->instanceId
;
1436 id
= SETUPDI_DevNameToDevID(devName
);
1437 if (id
!= 0xffffffff && id
> highestDevID
)
1440 devId
= highestDevID
+ 1;
1444 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1445 instanceId
= HeapAlloc(GetProcessHeap(), 0,
1446 (17 + lstrlenW(DeviceName
)) * sizeof(WCHAR
));
1449 sprintfW((LPWSTR
)instanceId
, newDeviceFmt
, DeviceName
,
1451 allocatedInstanceId
= TRUE
;
1463 instanceId
= DeviceName
;
1464 for (i
= 0; ret
&& i
< set
->cDevices
; i
++)
1466 struct DeviceInfo
*devInfo
=
1467 (struct DeviceInfo
*)set
->devices
[i
].Reserved
;
1469 if (!lstrcmpiW(DeviceName
, devInfo
->instanceId
))
1471 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
1478 SP_DEVINFO_DATA
*dev
= NULL
;
1480 ret
= SETUPDI_AddDeviceToSet(set
, ClassGuid
, 0 /* FIXME: DevInst */,
1481 instanceId
, TRUE
, &dev
);
1484 if (DeviceDescription
)
1485 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
1486 dev
, SPDRP_DEVICEDESC
, (const BYTE
*)DeviceDescription
,
1487 lstrlenW(DeviceDescription
) * sizeof(WCHAR
));
1490 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1492 SetLastError(ERROR_INVALID_USER_BUFFER
);
1496 memcpy(DeviceInfoData
, dev
, sizeof(SP_DEVINFO_DATA
));
1500 if (allocatedInstanceId
)
1501 HeapFree(GetProcessHeap(), 0, (LPWSTR
)instanceId
);
1506 /***********************************************************************
1507 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1509 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1510 HDEVINFO DeviceInfoSet
,
1511 PSP_DEVINFO_DATA DeviceInfoData
,
1513 PSP_DETSIG_CMPPROC CompareProc
,
1514 PVOID CompareContext
,
1515 PSP_DEVINFO_DATA DupDeviceInfoData
)
1517 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1518 struct DeviceInfo
*devInfo
;
1520 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1521 CompareProc
, CompareContext
, DupDeviceInfoData
);
1523 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1525 SetLastError(ERROR_INVALID_HANDLE
);
1528 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1530 SetLastError(ERROR_INVALID_HANDLE
);
1533 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1534 || !DeviceInfoData
->Reserved
)
1536 SetLastError(ERROR_INVALID_PARAMETER
);
1539 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1540 if (devInfo
->set
!= set
)
1542 SetLastError(ERROR_INVALID_PARAMETER
);
1545 if (devInfo
->phantom
)
1547 devInfo
->phantom
= FALSE
;
1548 RegDeleteValueW(devInfo
->key
, Phantom
);
1553 /***********************************************************************
1554 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1556 BOOL WINAPI
SetupDiEnumDeviceInfo(
1559 PSP_DEVINFO_DATA info
)
1563 TRACE("%p %d %p\n", devinfo
, index
, info
);
1567 SetLastError(ERROR_INVALID_PARAMETER
);
1570 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1572 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1573 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1575 if (index
< list
->cDevices
)
1577 if (info
->cbSize
== sizeof(SP_DEVINFO_DATA
))
1579 memcpy(info
, &list
->devices
[index
], info
->cbSize
);
1583 SetLastError(ERROR_INVALID_USER_BUFFER
);
1586 SetLastError(ERROR_NO_MORE_ITEMS
);
1589 SetLastError(ERROR_INVALID_HANDLE
);
1592 SetLastError(ERROR_INVALID_HANDLE
);
1596 /***********************************************************************
1597 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1599 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1600 HDEVINFO DeviceInfoSet
,
1601 PSP_DEVINFO_DATA DeviceInfoData
,
1602 PSTR DeviceInstanceId
,
1603 DWORD DeviceInstanceIdSize
,
1604 PDWORD RequiredSize
)
1610 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1611 DeviceInstanceIdSize
, RequiredSize
);
1613 SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1618 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1620 instanceId
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1623 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1630 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1632 DeviceInstanceIdSize
, NULL
, NULL
);
1638 if (len
> DeviceInstanceIdSize
)
1640 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1644 *RequiredSize
= len
;
1647 HeapFree(GetProcessHeap(), 0, instanceId
);
1652 /***********************************************************************
1653 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1655 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1656 HDEVINFO DeviceInfoSet
,
1657 PSP_DEVINFO_DATA DeviceInfoData
,
1658 PWSTR DeviceInstanceId
,
1659 DWORD DeviceInstanceIdSize
,
1660 PDWORD RequiredSize
)
1662 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1663 struct DeviceInfo
*devInfo
;
1665 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1666 DeviceInstanceIdSize
, RequiredSize
);
1668 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1670 SetLastError(ERROR_INVALID_HANDLE
);
1673 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1675 SetLastError(ERROR_INVALID_HANDLE
);
1678 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1679 || !DeviceInfoData
->Reserved
)
1681 SetLastError(ERROR_INVALID_PARAMETER
);
1684 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1685 if (devInfo
->set
!= set
)
1687 SetLastError(ERROR_INVALID_PARAMETER
);
1690 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
1691 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
1693 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1695 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1698 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
1700 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1704 /***********************************************************************
1705 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1707 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
1709 PCSTR InfSectionName
,
1710 PSTR InfSectionWithExt
,
1711 DWORD InfSectionWithExtSize
,
1712 PDWORD RequiredSize
,
1719 /***********************************************************************
1720 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1722 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
1724 PCWSTR InfSectionName
,
1725 PWSTR InfSectionWithExt
,
1726 DWORD InfSectionWithExtSize
,
1727 PDWORD RequiredSize
,
1730 WCHAR szBuffer
[MAX_PATH
];
1733 LONG lLineCount
= -1;
1735 lstrcpyW(szBuffer
, InfSectionName
);
1736 dwLength
= lstrlenW(szBuffer
);
1738 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
1740 /* Test section name with '.NTx86' extension */
1741 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
1742 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
1744 if (lLineCount
== -1)
1746 /* Test section name with '.NT' extension */
1747 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
1748 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
1753 /* Test section name with '.Win' extension */
1754 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
1755 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
1758 if (lLineCount
== -1)
1760 /* Test section name without extension */
1761 szBuffer
[dwLength
] = 0;
1762 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
1765 if (lLineCount
== -1)
1767 SetLastError(ERROR_INVALID_PARAMETER
);
1771 dwFullLength
= lstrlenW(szBuffer
);
1773 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1775 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1777 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1781 lstrcpyW(InfSectionWithExt
, szBuffer
);
1782 if (Extension
!= NULL
)
1784 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1788 if (RequiredSize
!= NULL
)
1790 *RequiredSize
= dwFullLength
+ 1;
1796 /***********************************************************************
1797 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1799 BOOL WINAPI
SetupDiGetClassDescriptionA(
1800 const GUID
* ClassGuid
,
1801 PSTR ClassDescription
,
1802 DWORD ClassDescriptionSize
,
1803 PDWORD RequiredSize
)
1805 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1806 ClassDescriptionSize
,
1807 RequiredSize
, NULL
, NULL
);
1810 /***********************************************************************
1811 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1813 BOOL WINAPI
SetupDiGetClassDescriptionW(
1814 const GUID
* ClassGuid
,
1815 PWSTR ClassDescription
,
1816 DWORD ClassDescriptionSize
,
1817 PDWORD RequiredSize
)
1819 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1820 ClassDescriptionSize
,
1821 RequiredSize
, NULL
, NULL
);
1824 /***********************************************************************
1825 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1827 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1828 const GUID
* ClassGuid
,
1829 PSTR ClassDescription
,
1830 DWORD ClassDescriptionSize
,
1831 PDWORD RequiredSize
,
1839 hKey
= SetupDiOpenClassRegKeyExA(ClassGuid
,
1844 if (hKey
== INVALID_HANDLE_VALUE
)
1846 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1850 dwLength
= ClassDescriptionSize
;
1851 ret
= !RegQueryValueExA( hKey
, NULL
, NULL
, NULL
,
1852 (LPBYTE
)ClassDescription
, &dwLength
);
1853 if (RequiredSize
) *RequiredSize
= dwLength
;
1858 /***********************************************************************
1859 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1861 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1862 const GUID
* ClassGuid
,
1863 PWSTR ClassDescription
,
1864 DWORD ClassDescriptionSize
,
1865 PDWORD RequiredSize
,
1873 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1878 if (hKey
== INVALID_HANDLE_VALUE
)
1880 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1884 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1885 ret
= !RegQueryValueExW( hKey
, NULL
, NULL
, NULL
,
1886 (LPBYTE
)ClassDescription
, &dwLength
);
1887 if (RequiredSize
) *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1892 /***********************************************************************
1893 * SetupDiGetClassDevsA (SETUPAPI.@)
1895 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1902 LPWSTR enumstrW
= NULL
;
1906 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1907 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1910 ret
= INVALID_HANDLE_VALUE
;
1913 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1915 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, NULL
, NULL
,
1917 HeapFree(GetProcessHeap(), 0, enumstrW
);
1923 /***********************************************************************
1924 * SetupDiGetClassDevsExA (SETUPAPI.@)
1926 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1936 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
1940 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1941 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1944 ret
= INVALID_HANDLE_VALUE
;
1947 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1951 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1952 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1955 HeapFree(GetProcessHeap(), 0, enumstrW
);
1956 ret
= INVALID_HANDLE_VALUE
;
1959 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1961 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
1962 machineW
, reserved
);
1963 HeapFree(GetProcessHeap(), 0, enumstrW
);
1964 HeapFree(GetProcessHeap(), 0, machineW
);
1970 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA
*dev
, HKEY key
,
1971 const GUID
*interface
)
1974 WCHAR subKeyName
[MAX_PATH
];
1975 LONG l
= ERROR_SUCCESS
;
1977 for (i
= 0; !l
; i
++)
1979 len
= sizeof(subKeyName
) / sizeof(subKeyName
[0]);
1980 l
= RegEnumKeyExW(key
, i
, subKeyName
, &len
, NULL
, NULL
, NULL
, NULL
);
1984 SP_DEVICE_INTERFACE_DATA
*iface
= NULL
;
1986 /* The subkey name is the reference string, with a '#' prepended */
1987 SETUPDI_AddInterfaceInstance(dev
, interface
, subKeyName
+ 1,
1989 l
= RegOpenKeyExW(key
, subKeyName
, 0, KEY_READ
, &subKey
);
1992 WCHAR symbolicLink
[MAX_PATH
];
1995 len
= sizeof(symbolicLink
);
1996 l
= RegQueryValueExW(subKey
, SymbolicLink
, NULL
, &dataType
,
1997 (BYTE
*)symbolicLink
, &len
);
1998 if (!l
&& dataType
== REG_SZ
)
1999 SETUPDI_SetInterfaceSymbolicLink(iface
, symbolicLink
);
2000 RegCloseKey(subKey
);
2002 /* Allow enumeration to continue */
2006 /* FIXME: find and add all the device's interfaces to the device */
2009 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet
,
2010 HKEY key
, const GUID
*interface
, LPCWSTR enumstr
)
2012 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2014 WCHAR subKeyName
[MAX_PATH
];
2016 HKEY enumKey
= INVALID_HANDLE_VALUE
;
2018 TRACE("%s\n", debugstr_w(enumstr
));
2020 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_READ
, NULL
,
2022 for (i
= 0; !l
; i
++)
2024 len
= sizeof(subKeyName
) / sizeof(subKeyName
[0]);
2025 l
= RegEnumKeyExW(key
, i
, subKeyName
, &len
, NULL
, NULL
, NULL
, NULL
);
2030 l
= RegOpenKeyExW(key
, subKeyName
, 0, KEY_READ
, &subKey
);
2033 WCHAR deviceInst
[MAX_PATH
* 3];
2036 len
= sizeof(deviceInst
);
2037 l
= RegQueryValueExW(subKey
, DeviceInstance
, NULL
, &dataType
,
2038 (BYTE
*)deviceInst
, &len
);
2039 if (!l
&& dataType
== REG_SZ
)
2041 TRACE("found instance ID %s\n", debugstr_w(deviceInst
));
2042 if (!enumstr
|| !lstrcmpiW(enumstr
, deviceInst
))
2046 l
= RegOpenKeyExW(enumKey
, deviceInst
, 0, KEY_READ
,
2050 WCHAR deviceClassStr
[40];
2052 len
= sizeof(deviceClassStr
);
2053 l
= RegQueryValueExW(deviceKey
, ClassGUID
, NULL
,
2054 &dataType
, (BYTE
*)deviceClassStr
, &len
);
2055 if (!l
&& dataType
== REG_SZ
&&
2056 deviceClassStr
[0] == '{' &&
2057 deviceClassStr
[37] == '}')
2060 SP_DEVINFO_DATA
*dev
;
2062 deviceClassStr
[37] = 0;
2063 UuidFromStringW(&deviceClassStr
[1],
2065 if (SETUPDI_AddDeviceToSet(set
, &deviceClass
,
2066 0 /* FIXME: DevInst */, deviceInst
,
2068 SETUPDI_AddDeviceInterfaces(dev
, subKey
,
2071 RegCloseKey(deviceKey
);
2075 RegCloseKey(subKey
);
2077 /* Allow enumeration to continue */
2081 if (enumKey
!= INVALID_HANDLE_VALUE
)
2082 RegCloseKey(enumKey
);
2085 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet
,
2086 const GUID
*interface
, LPCWSTR enumstr
, DWORD flags
)
2088 HKEY interfacesKey
= SetupDiOpenClassRegKeyExW(interface
, KEY_READ
,
2089 DIOCR_INTERFACE
, NULL
, NULL
);
2091 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet
, debugstr_guid(interface
),
2092 debugstr_w(enumstr
), flags
);
2094 if (interfacesKey
!= INVALID_HANDLE_VALUE
)
2096 if (flags
& DIGCF_ALLCLASSES
)
2099 WCHAR interfaceGuidStr
[40];
2100 LONG l
= ERROR_SUCCESS
;
2102 for (i
= 0; !l
; i
++)
2104 len
= sizeof(interfaceGuidStr
) / sizeof(interfaceGuidStr
[0]);
2105 l
= RegEnumKeyExW(interfacesKey
, i
, interfaceGuidStr
, &len
,
2106 NULL
, NULL
, NULL
, NULL
);
2109 if (interfaceGuidStr
[0] == '{' &&
2110 interfaceGuidStr
[37] == '}')
2115 interfaceGuidStr
[37] = 0;
2116 UuidFromStringW(&interfaceGuidStr
[1], &interfaceGuid
);
2117 l
= RegOpenKeyExW(interfacesKey
, interfaceGuidStr
, 0,
2118 KEY_READ
, &interfaceKey
);
2121 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet
,
2122 interfaceKey
, &interfaceGuid
, enumstr
);
2123 RegCloseKey(interfaceKey
);
2131 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
2132 * interface's key, so just pass that long
2134 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet
,
2135 interfacesKey
, interface
, enumstr
);
2137 RegCloseKey(interfacesKey
);
2141 static void SETUPDI_EnumerateMatchingDeviceInstances(struct DeviceInfoSet
*set
,
2142 LPCWSTR enumerator
, LPCWSTR deviceName
, HKEY deviceKey
,
2143 const GUID
*class, DWORD flags
)
2146 WCHAR deviceInstance
[MAX_PATH
];
2147 LONG l
= ERROR_SUCCESS
;
2149 TRACE("%s %s\n", debugstr_w(enumerator
), debugstr_w(deviceName
));
2151 for (i
= 0; !l
; i
++)
2153 len
= sizeof(deviceInstance
) / sizeof(deviceInstance
[0]);
2154 l
= RegEnumKeyExW(deviceKey
, i
, deviceInstance
, &len
, NULL
, NULL
, NULL
,
2160 l
= RegOpenKeyExW(deviceKey
, deviceInstance
, 0, KEY_READ
, &subKey
);
2163 WCHAR classGuid
[40];
2166 len
= sizeof(classGuid
);
2167 l
= RegQueryValueExW(subKey
, ClassGUID
, NULL
, &dataType
,
2168 (BYTE
*)classGuid
, &len
);
2169 if (!l
&& dataType
== REG_SZ
)
2171 if (classGuid
[0] == '{' && classGuid
[37] == '}')
2176 UuidFromStringW(&classGuid
[1], &deviceClass
);
2177 if ((flags
& DIGCF_ALLCLASSES
) ||
2178 IsEqualGUID(class, &deviceClass
))
2180 static const WCHAR fmt
[] =
2181 {'%','s','\\','%','s','\\','%','s',0};
2184 instanceId
= HeapAlloc(GetProcessHeap(), 0,
2185 (lstrlenW(enumerator
) + lstrlenW(deviceName
) +
2186 lstrlenW(deviceInstance
) + 3) * sizeof(WCHAR
));
2189 sprintfW(instanceId
, fmt
, enumerator
,
2190 deviceName
, deviceInstance
);
2191 SETUPDI_AddDeviceToSet(set
, &deviceClass
,
2192 0 /* FIXME: DevInst */, instanceId
,
2194 HeapFree(GetProcessHeap(), 0, instanceId
);
2199 RegCloseKey(subKey
);
2201 /* Allow enumeration to continue */
2207 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet
,
2208 LPCWSTR parent
, HKEY key
, const GUID
*class, DWORD flags
)
2210 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2212 WCHAR subKeyName
[MAX_PATH
];
2213 LONG l
= ERROR_SUCCESS
;
2215 TRACE("%s\n", debugstr_w(parent
));
2217 for (i
= 0; !l
; i
++)
2219 len
= sizeof(subKeyName
) / sizeof(subKeyName
[0]);
2220 l
= RegEnumKeyExW(key
, i
, subKeyName
, &len
, NULL
, NULL
, NULL
, NULL
);
2225 l
= RegOpenKeyExW(key
, subKeyName
, 0, KEY_READ
, &subKey
);
2228 TRACE("%s\n", debugstr_w(subKeyName
));
2229 SETUPDI_EnumerateMatchingDeviceInstances(set
, parent
,
2230 subKeyName
, subKey
, class, flags
);
2231 RegCloseKey(subKey
);
2233 /* Allow enumeration to continue */
2239 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet
, const GUID
*class,
2240 LPCWSTR enumstr
, DWORD flags
)
2245 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet
, debugstr_guid(class),
2246 debugstr_w(enumstr
), flags
);
2248 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_READ
, NULL
,
2250 if (enumKey
!= INVALID_HANDLE_VALUE
)
2256 l
= RegOpenKeyExW(enumKey
, enumstr
, 0, KEY_READ
,
2260 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet
, enumstr
,
2261 enumStrKey
, class, flags
);
2262 RegCloseKey(enumStrKey
);
2268 WCHAR subKeyName
[MAX_PATH
];
2271 for (i
= 0; !l
; i
++)
2273 len
= sizeof(subKeyName
) / sizeof(subKeyName
[0]);
2274 l
= RegEnumKeyExW(enumKey
, i
, subKeyName
, &len
, NULL
,
2280 l
= RegOpenKeyExW(enumKey
, subKeyName
, 0, KEY_READ
,
2284 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet
,
2285 subKeyName
, subKey
, class, flags
);
2286 RegCloseKey(subKey
);
2288 /* Allow enumeration to continue */
2293 RegCloseKey(enumKey
);
2297 /***********************************************************************
2298 * SetupDiGetClassDevsW (SETUPAPI.@)
2300 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2306 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2310 /***********************************************************************
2311 * SetupDiGetClassDevsExW (SETUPAPI.@)
2313 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2322 static const DWORD unsupportedFlags
= DIGCF_DEFAULT
| DIGCF_PRESENT
|
2326 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2327 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2330 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2332 SetLastError(ERROR_INVALID_PARAMETER
);
2335 if (flags
& unsupportedFlags
)
2336 WARN("unsupported flags %08x\n", flags
& unsupportedFlags
);
2340 set
= SetupDiCreateDeviceInfoListExW(class, parent
, machine
, reserved
);
2344 FIXME("%s: unimplemented for remote machines\n",
2345 debugstr_w(machine
));
2346 else if (flags
& DIGCF_DEVICEINTERFACE
)
2347 SETUPDI_EnumerateInterfaces(set
, class, enumstr
, flags
);
2349 SETUPDI_EnumerateDevices(set
, class, enumstr
, flags
);
2354 /***********************************************************************
2355 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2357 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2358 HDEVINFO DeviceInfoSet
,
2359 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2361 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2363 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2365 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2367 SetLastError(ERROR_INVALID_HANDLE
);
2370 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2372 SetLastError(ERROR_INVALID_HANDLE
);
2376 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2378 SetLastError(ERROR_INVALID_PARAMETER
);
2381 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2382 DevInfoData
->RemoteMachineHandle
= NULL
;
2383 DevInfoData
->RemoteMachineName
[0] = '\0';
2387 /***********************************************************************
2388 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2390 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2391 HDEVINFO DeviceInfoSet
,
2392 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2394 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2396 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2398 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2400 SetLastError(ERROR_INVALID_HANDLE
);
2403 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2405 SetLastError(ERROR_INVALID_HANDLE
);
2409 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2411 SetLastError(ERROR_INVALID_PARAMETER
);
2414 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2415 DevInfoData
->RemoteMachineHandle
= NULL
;
2416 DevInfoData
->RemoteMachineName
[0] = '\0';
2420 /***********************************************************************
2421 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2423 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2424 HDEVINFO DeviceInfoSet
,
2425 PSP_DEVINFO_DATA DeviceInfoData
,
2426 const GUID
*InterfaceClassGuid
,
2427 PCSTR ReferenceString
,
2428 DWORD CreationFlags
,
2429 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2432 LPWSTR ReferenceStringW
= NULL
;
2434 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2435 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2436 CreationFlags
, DeviceInterfaceData
);
2438 if (ReferenceString
)
2440 ReferenceStringW
= MultiByteToUnicode(ReferenceString
, CP_ACP
);
2441 if (ReferenceStringW
== NULL
) return FALSE
;
2444 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2445 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2446 DeviceInterfaceData
);
2448 MyFree(ReferenceStringW
);
2453 /***********************************************************************
2454 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2456 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2457 HDEVINFO DeviceInfoSet
,
2458 PSP_DEVINFO_DATA DeviceInfoData
,
2459 const GUID
*InterfaceClassGuid
,
2460 PCWSTR ReferenceString
,
2461 DWORD CreationFlags
,
2462 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2464 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2465 struct DeviceInfo
*devInfo
;
2466 SP_DEVICE_INTERFACE_DATA
*iface
= NULL
;
2469 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2470 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2471 CreationFlags
, DeviceInterfaceData
);
2473 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2475 SetLastError(ERROR_INVALID_HANDLE
);
2478 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2480 SetLastError(ERROR_INVALID_HANDLE
);
2483 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2484 || !DeviceInfoData
->Reserved
)
2486 SetLastError(ERROR_INVALID_PARAMETER
);
2489 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2490 if (devInfo
->set
!= set
)
2492 SetLastError(ERROR_INVALID_PARAMETER
);
2495 if (!InterfaceClassGuid
)
2497 SetLastError(ERROR_INVALID_USER_BUFFER
);
2500 if ((ret
= SETUPDI_AddInterfaceInstance(DeviceInfoData
, InterfaceClassGuid
,
2501 ReferenceString
, &iface
)))
2503 if (DeviceInterfaceData
)
2505 if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2507 SetLastError(ERROR_INVALID_USER_BUFFER
);
2511 memcpy(DeviceInterfaceData
, iface
, sizeof(*iface
));
2517 /***********************************************************************
2518 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2520 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2521 HDEVINFO DeviceInfoSet
,
2522 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2526 PCSTR InfSectionName
)
2529 PWSTR InfSectionNameW
= NULL
;
2531 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2532 samDesired
, InfHandle
, InfSectionName
);
2535 if (!InfSectionName
)
2537 SetLastError(ERROR_INVALID_PARAMETER
);
2538 return INVALID_HANDLE_VALUE
;
2540 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
2541 if (!InfSectionNameW
)
2542 return INVALID_HANDLE_VALUE
;
2544 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2545 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2547 MyFree(InfSectionNameW
);
2551 static PWSTR
SETUPDI_GetInstancePath(struct InterfaceInfo
*ifaceInfo
)
2553 static const WCHAR hash
[] = {'#',0};
2554 PWSTR instancePath
= NULL
;
2556 if (ifaceInfo
->referenceString
)
2558 instancePath
= HeapAlloc(GetProcessHeap(), 0,
2559 (lstrlenW(ifaceInfo
->referenceString
) + 2) * sizeof(WCHAR
));
2562 lstrcpyW(instancePath
, hash
);
2563 lstrcatW(instancePath
, ifaceInfo
->referenceString
);
2566 SetLastError(ERROR_OUTOFMEMORY
);
2570 instancePath
= HeapAlloc(GetProcessHeap(), 0,
2571 (lstrlenW(hash
) + 1) * sizeof(WCHAR
));
2573 lstrcpyW(instancePath
, hash
);
2575 return instancePath
;
2578 /***********************************************************************
2579 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2581 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2582 HDEVINFO DeviceInfoSet
,
2583 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2587 PCWSTR InfSectionName
)
2589 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2590 HKEY key
= INVALID_HANDLE_VALUE
, interfacesKey
;
2593 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2594 samDesired
, InfHandle
, InfSectionName
);
2596 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2597 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2599 SetLastError(ERROR_INVALID_HANDLE
);
2600 return INVALID_HANDLE_VALUE
;
2602 if (!DeviceInterfaceData
||
2603 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2604 !DeviceInterfaceData
->Reserved
)
2606 SetLastError(ERROR_INVALID_PARAMETER
);
2607 return INVALID_HANDLE_VALUE
;
2609 if (InfHandle
&& !InfSectionName
)
2611 SetLastError(ERROR_INVALID_PARAMETER
);
2612 return INVALID_HANDLE_VALUE
;
2614 if (!(l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, DeviceClasses
, 0, NULL
, 0,
2615 samDesired
, NULL
, &interfacesKey
, NULL
)))
2618 WCHAR bracedGuidString
[39];
2620 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
,
2622 if (!(l
= RegCreateKeyExW(interfacesKey
, bracedGuidString
, 0, NULL
, 0,
2623 samDesired
, NULL
, &parent
, NULL
)))
2625 struct InterfaceInfo
*ifaceInfo
=
2626 (struct InterfaceInfo
*)DeviceInterfaceData
->Reserved
;
2627 PWSTR instancePath
= SETUPDI_GetInstancePath(ifaceInfo
);
2633 l
= RegCreateKeyExW(parent
, instancePath
, 0, NULL
, 0,
2634 samDesired
, NULL
, &key
, NULL
);
2638 key
= INVALID_HANDLE_VALUE
;
2641 FIXME("INF section installation unsupported\n");
2643 HeapFree(GetProcessHeap(), 0, instancePath
);
2644 RegCloseKey(parent
);
2648 RegCloseKey(interfacesKey
);
2655 /***********************************************************************
2656 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2658 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2659 HDEVINFO DeviceInfoSet
,
2660 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2663 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2667 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2669 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2670 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2672 SetLastError(ERROR_INVALID_HANDLE
);
2675 if (!DeviceInterfaceData
||
2676 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2677 !DeviceInterfaceData
->Reserved
)
2679 SetLastError(ERROR_INVALID_PARAMETER
);
2682 parent
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
,
2683 KEY_ALL_ACCESS
, DIOCR_INTERFACE
, NULL
, NULL
);
2684 if (parent
!= INVALID_HANDLE_VALUE
)
2686 struct InterfaceInfo
*ifaceInfo
=
2687 (struct InterfaceInfo
*)DeviceInterfaceData
->Reserved
;
2688 PWSTR instancePath
= SETUPDI_GetInstancePath(ifaceInfo
);
2692 LONG l
= RegDeleteKeyW(parent
, instancePath
);
2698 HeapFree(GetProcessHeap(), 0, instancePath
);
2700 RegCloseKey(parent
);
2705 /***********************************************************************
2706 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2709 * DeviceInfoSet [I] Set of devices from which to enumerate
2711 * DeviceInfoData [I] (Optional) If specified, a specific device
2712 * instance from which to enumerate interfaces.
2713 * If it isn't specified, all interfaces for all
2714 * devices in the set are enumerated.
2715 * InterfaceClassGuid [I] The interface class to enumerate.
2716 * MemberIndex [I] An index of the interface instance to enumerate.
2717 * A caller should start with MemberIndex set to 0,
2718 * and continue until the function fails with
2719 * ERROR_NO_MORE_ITEMS.
2720 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2721 * member must be set to
2722 * sizeof(SP_DEVICE_INTERFACE_DATA).
2725 * Success: non-zero value.
2726 * Failure: FALSE. Call GetLastError() for more info.
2728 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2729 HDEVINFO DeviceInfoSet
,
2730 PSP_DEVINFO_DATA DeviceInfoData
,
2731 CONST GUID
* InterfaceClassGuid
,
2733 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2735 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2738 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2739 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2741 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2742 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2744 SetLastError(ERROR_INVALID_HANDLE
);
2747 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2748 !DeviceInfoData
->Reserved
))
2750 SetLastError(ERROR_INVALID_PARAMETER
);
2753 if (!DeviceInterfaceData
||
2754 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2756 SetLastError(ERROR_INVALID_PARAMETER
);
2761 struct DeviceInfo
*devInfo
=
2762 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2763 struct InterfaceInstances
*iface
;
2765 if ((ret
= SETUPDI_FindInterface(devInfo
, InterfaceClassGuid
, &iface
)))
2767 if (MemberIndex
< iface
->cInstances
)
2768 memcpy(DeviceInterfaceData
, &iface
->instances
[MemberIndex
],
2769 sizeof(SP_DEVICE_INTERFACE_DATA
));
2772 SetLastError(ERROR_NO_MORE_ITEMS
);
2777 SetLastError(ERROR_NO_MORE_ITEMS
);
2781 DWORD i
, cEnumerated
= 0;
2784 for (i
= 0; !found
&& cEnumerated
< MemberIndex
+ 1 &&
2785 i
< set
->cDevices
; i
++)
2787 struct DeviceInfo
*devInfo
=
2788 (struct DeviceInfo
*)set
->devices
[i
].Reserved
;
2789 struct InterfaceInstances
*iface
;
2791 if (SETUPDI_FindInterface(devInfo
, InterfaceClassGuid
, &iface
))
2793 if (cEnumerated
+ iface
->cInstances
< MemberIndex
+ 1)
2794 cEnumerated
+= iface
->cInstances
;
2797 DWORD instanceIndex
= MemberIndex
- cEnumerated
;
2799 memcpy(DeviceInterfaceData
,
2800 &iface
->instances
[instanceIndex
],
2801 sizeof(SP_DEVICE_INTERFACE_DATA
));
2802 cEnumerated
+= instanceIndex
+ 1;
2809 SetLastError(ERROR_NO_MORE_ITEMS
);
2814 /***********************************************************************
2815 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2817 * Destroy a DeviceInfoList and free all used memory of the list.
2820 * devinfo [I] DeviceInfoList pointer to list to destroy
2823 * Success: non zero value.
2824 * Failure: zero value.
2826 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2830 TRACE("%p\n", devinfo
);
2831 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2833 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2835 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2839 for (i
= 0; i
< list
->cDevices
; i
++)
2840 SETUPDI_FreeDeviceInfo(
2841 (struct DeviceInfo
*)list
->devices
[i
].Reserved
);
2842 HeapFree(GetProcessHeap(), 0, list
->devices
);
2843 HeapFree(GetProcessHeap(), 0, list
);
2849 SetLastError(ERROR_INVALID_HANDLE
);
2854 /***********************************************************************
2855 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2857 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2858 HDEVINFO DeviceInfoSet
,
2859 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2860 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2861 DWORD DeviceInterfaceDetailDataSize
,
2862 PDWORD RequiredSize
,
2863 PSP_DEVINFO_DATA DeviceInfoData
)
2865 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2866 struct InterfaceInfo
*info
;
2867 DWORD bytesNeeded
= offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)
2871 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2872 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2873 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2875 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2876 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2878 SetLastError(ERROR_INVALID_HANDLE
);
2881 if (!DeviceInterfaceData
||
2882 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2883 !DeviceInterfaceData
->Reserved
)
2885 SetLastError(ERROR_INVALID_PARAMETER
);
2888 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!=
2889 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(char)))
2891 SetLastError(ERROR_INVALID_USER_BUFFER
);
2894 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2896 SetLastError(ERROR_INVALID_USER_BUFFER
);
2899 info
= (struct InterfaceInfo
*)DeviceInterfaceData
->Reserved
;
2900 if (info
->symbolicLink
)
2901 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
->symbolicLink
, -1,
2902 NULL
, 0, NULL
, NULL
);
2903 if (DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2905 if (info
->symbolicLink
)
2906 WideCharToMultiByte(CP_ACP
, 0, info
->symbolicLink
, -1,
2907 DeviceInterfaceDetailData
->DevicePath
,
2908 DeviceInterfaceDetailDataSize
-
2909 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2912 DeviceInterfaceDetailData
->DevicePath
[0] = '\0';
2913 if (DeviceInfoData
&& DeviceInfoData
->cbSize
== sizeof(SP_DEVINFO_DATA
))
2914 memcpy(DeviceInfoData
, info
->device
, sizeof(SP_DEVINFO_DATA
));
2920 *RequiredSize
= bytesNeeded
;
2921 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2926 /***********************************************************************
2927 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2929 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2930 HDEVINFO DeviceInfoSet
,
2931 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2932 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2933 DWORD DeviceInterfaceDetailDataSize
,
2934 PDWORD RequiredSize
,
2935 PSP_DEVINFO_DATA DeviceInfoData
)
2937 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2938 struct InterfaceInfo
*info
;
2939 DWORD bytesNeeded
= offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2940 + sizeof(WCHAR
); /* include NULL terminator */
2943 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2944 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2945 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2947 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2948 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2950 SetLastError(ERROR_INVALID_HANDLE
);
2953 if (!DeviceInterfaceData
||
2954 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2955 !DeviceInterfaceData
->Reserved
)
2957 SetLastError(ERROR_INVALID_PARAMETER
);
2960 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
<
2961 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
) ||
2962 DeviceInterfaceDetailData
->cbSize
> sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
)))
2964 SetLastError(ERROR_INVALID_USER_BUFFER
);
2967 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2969 SetLastError(ERROR_INVALID_USER_BUFFER
);
2972 info
= (struct InterfaceInfo
*)DeviceInterfaceData
->Reserved
;
2973 if (info
->symbolicLink
)
2974 bytesNeeded
+= lstrlenW(info
->symbolicLink
);
2975 if (DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2977 if (info
->symbolicLink
)
2978 lstrcpyW(DeviceInterfaceDetailData
->DevicePath
, info
->symbolicLink
);
2980 DeviceInterfaceDetailData
->DevicePath
[0] = '\0';
2981 if (DeviceInfoData
&& DeviceInfoData
->cbSize
== sizeof(SP_DEVINFO_DATA
))
2982 memcpy(DeviceInfoData
, info
->device
, sizeof(SP_DEVINFO_DATA
));
2988 *RequiredSize
= bytesNeeded
;
2989 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2994 struct PropertyMapEntry
3001 static struct PropertyMapEntry PropertyMap
[] = {
3002 { REG_SZ
, "DeviceDesc", DeviceDesc
},
3003 { REG_MULTI_SZ
, "HardwareId", HardwareId
},
3004 { REG_MULTI_SZ
, "CompatibleIDs", CompatibleIDs
},
3005 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3006 { REG_SZ
, "Service", Service
},
3007 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3008 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3009 { REG_SZ
, "Class", Class
},
3010 { REG_SZ
, "ClassGUID", ClassGUID
},
3011 { REG_SZ
, "Driver", Driver
},
3012 { REG_DWORD
, "ConfigFlags", ConfigFlags
},
3013 { REG_SZ
, "Mfg", Mfg
},
3014 { REG_SZ
, "FriendlyName", FriendlyName
},
3015 { REG_SZ
, "LocationInformation", LocationInformation
},
3016 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3017 { REG_DWORD
, "Capabilities", Capabilities
},
3018 { REG_DWORD
, "UINumber", UINumber
},
3019 { REG_MULTI_SZ
, "UpperFilters", UpperFilters
},
3020 { REG_MULTI_SZ
, "LowerFilters", LowerFilters
},
3023 /***********************************************************************
3024 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3026 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3027 HDEVINFO DeviceInfoSet
,
3028 PSP_DEVINFO_DATA DeviceInfoData
,
3030 PDWORD PropertyRegDataType
,
3031 PBYTE PropertyBuffer
,
3032 DWORD PropertyBufferSize
,
3033 PDWORD RequiredSize
)
3036 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3037 struct DeviceInfo
*devInfo
;
3039 TRACE("%04x %p %d %p %p %d %p\n", (DWORD
)DeviceInfoSet
, DeviceInfoData
,
3040 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3043 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3045 SetLastError(ERROR_INVALID_HANDLE
);
3048 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3050 SetLastError(ERROR_INVALID_HANDLE
);
3053 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3054 || !DeviceInfoData
->Reserved
)
3056 SetLastError(ERROR_INVALID_PARAMETER
);
3059 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3060 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3061 && PropertyMap
[Property
].nameA
)
3063 DWORD size
= PropertyBufferSize
;
3064 LONG l
= RegQueryValueExA(devInfo
->key
, PropertyMap
[Property
].nameA
,
3065 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3068 *RequiredSize
= size
;
3069 if (!PropertyBuffer
)
3070 ; /* do nothing, ret is already FALSE, last error is already set */
3079 /***********************************************************************
3080 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3082 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3083 HDEVINFO DeviceInfoSet
,
3084 PSP_DEVINFO_DATA DeviceInfoData
,
3086 PDWORD PropertyRegDataType
,
3087 PBYTE PropertyBuffer
,
3088 DWORD PropertyBufferSize
,
3089 PDWORD RequiredSize
)
3092 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3093 struct DeviceInfo
*devInfo
;
3095 TRACE("%04x %p %d %p %p %d %p\n", (DWORD
)DeviceInfoSet
, DeviceInfoData
,
3096 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3099 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3101 SetLastError(ERROR_INVALID_HANDLE
);
3104 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3106 SetLastError(ERROR_INVALID_HANDLE
);
3109 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3110 || !DeviceInfoData
->Reserved
)
3112 SetLastError(ERROR_INVALID_PARAMETER
);
3115 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3116 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3117 && PropertyMap
[Property
].nameW
)
3119 DWORD size
= PropertyBufferSize
;
3120 LONG l
= RegQueryValueExW(devInfo
->key
, PropertyMap
[Property
].nameW
,
3121 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3124 *RequiredSize
= size
;
3125 if (!PropertyBuffer
)
3126 ; /* do nothing, ret is already FALSE, last error is already set */
3135 /***********************************************************************
3136 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3138 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3139 HDEVINFO DeviceInfoSet
,
3140 PSP_DEVINFO_DATA DeviceInfoData
,
3142 const BYTE
*PropertyBuffer
,
3143 DWORD PropertyBufferSize
)
3146 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3147 struct DeviceInfo
*devInfo
;
3149 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3150 PropertyBuffer
, PropertyBufferSize
);
3152 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3154 SetLastError(ERROR_INVALID_HANDLE
);
3157 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3159 SetLastError(ERROR_INVALID_HANDLE
);
3162 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3163 || !DeviceInfoData
->Reserved
)
3165 SetLastError(ERROR_INVALID_PARAMETER
);
3168 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3169 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3170 && PropertyMap
[Property
].nameA
)
3172 LONG l
= RegSetValueExA(devInfo
->key
, PropertyMap
[Property
].nameA
, 0,
3173 PropertyMap
[Property
].regType
, PropertyBuffer
,
3174 PropertyBufferSize
);
3183 /***********************************************************************
3184 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3186 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3187 HDEVINFO DeviceInfoSet
,
3188 PSP_DEVINFO_DATA DeviceInfoData
,
3190 const BYTE
*PropertyBuffer
,
3191 DWORD PropertyBufferSize
)
3194 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3195 struct DeviceInfo
*devInfo
;
3197 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3198 PropertyBuffer
, PropertyBufferSize
);
3200 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3202 SetLastError(ERROR_INVALID_HANDLE
);
3205 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3207 SetLastError(ERROR_INVALID_HANDLE
);
3210 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3211 || !DeviceInfoData
->Reserved
)
3213 SetLastError(ERROR_INVALID_PARAMETER
);
3216 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3217 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3218 && PropertyMap
[Property
].nameW
)
3220 LONG l
= RegSetValueExW(devInfo
->key
, PropertyMap
[Property
].nameW
, 0,
3221 PropertyMap
[Property
].regType
, PropertyBuffer
,
3222 PropertyBufferSize
);
3231 /***********************************************************************
3232 * SetupDiInstallClassA (SETUPAPI.@)
3234 BOOL WINAPI
SetupDiInstallClassA(
3240 UNICODE_STRING FileNameW
;
3245 SetLastError(ERROR_INVALID_PARAMETER
);
3248 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
3250 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3254 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
3256 RtlFreeUnicodeString(&FileNameW
);
3261 static HKEY
CreateClassKey(HINF hInf
)
3263 static const WCHAR slash
[] = { '\\',0 };
3264 WCHAR FullBuffer
[MAX_PATH
];
3265 WCHAR Buffer
[MAX_PATH
];
3269 if (!SetupGetLineTextW(NULL
,
3277 return INVALID_HANDLE_VALUE
;
3280 lstrcpyW(FullBuffer
, ControlClass
);
3281 lstrcatW(FullBuffer
, slash
);
3282 lstrcatW(FullBuffer
, Buffer
);
3284 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3290 if (!SetupGetLineTextW(NULL
,
3298 return INVALID_HANDLE_VALUE
;
3301 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3305 REG_OPTION_NON_VOLATILE
,
3311 return INVALID_HANDLE_VALUE
;
3316 if (RegSetValueExW(hClassKey
,
3321 RequiredSize
* sizeof(WCHAR
)))
3323 RegCloseKey(hClassKey
);
3324 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3326 return INVALID_HANDLE_VALUE
;
3332 /***********************************************************************
3333 * SetupDiInstallClassW (SETUPAPI.@)
3335 BOOL WINAPI
SetupDiInstallClassW(
3341 WCHAR SectionName
[MAX_PATH
];
3342 DWORD SectionNameLength
= 0;
3344 BOOL bFileQueueCreated
= FALSE
;
3352 SetLastError(ERROR_INVALID_PARAMETER
);
3355 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
3357 SetLastError(ERROR_INVALID_PARAMETER
);
3361 /* Open the .inf file */
3362 hInf
= SetupOpenInfFileW(InfFileName
,
3366 if (hInf
== INVALID_HANDLE_VALUE
)
3372 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3373 hClassKey
= CreateClassKey(hInf
);
3374 if (hClassKey
== INVALID_HANDLE_VALUE
)
3376 SetupCloseInfFile(hInf
);
3381 /* Try to append a layout file */
3382 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3384 /* Retrieve the actual section name */
3385 SetupDiGetActualSectionToInstallW(hInf
,
3393 if (!(Flags
& DI_NOVCP
))
3395 FileQueue
= SetupOpenFileQueue();
3396 if (FileQueue
== INVALID_HANDLE_VALUE
)
3398 SetupCloseInfFile(hInf
);
3402 bFileQueueCreated
= TRUE
;
3407 SetupInstallFromInfSectionW(NULL
,
3410 SPINST_COPYINF
| SPINST_FILES
| SPINST_REGISTRY
,
3416 INVALID_HANDLE_VALUE
,
3419 /* FIXME: More code! */
3421 if (bFileQueueCreated
)
3422 SetupCloseFileQueue(FileQueue
);
3424 SetupCloseInfFile(hInf
);
3430 /***********************************************************************
3431 * SetupDiOpenClassRegKey (SETUPAPI.@)
3433 HKEY WINAPI
SetupDiOpenClassRegKey(
3434 const GUID
* ClassGuid
,
3437 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3438 DIOCR_INSTALLER
, NULL
, NULL
);
3442 /***********************************************************************
3443 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3445 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3446 const GUID
* ClassGuid
,
3452 PWSTR MachineNameW
= NULL
;
3459 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3460 if (MachineNameW
== NULL
)
3461 return INVALID_HANDLE_VALUE
;
3464 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3465 Flags
, MachineNameW
, Reserved
);
3467 MyFree(MachineNameW
);
3473 /***********************************************************************
3474 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3476 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3477 const GUID
* ClassGuid
,
3488 if (MachineName
!= NULL
)
3490 FIXME("Remote access not supported yet!\n");
3491 return INVALID_HANDLE_VALUE
;
3494 if (Flags
== DIOCR_INSTALLER
)
3496 lpKeyName
= ControlClass
;
3498 else if (Flags
== DIOCR_INTERFACE
)
3500 lpKeyName
= DeviceClasses
;
3504 ERR("Invalid Flags parameter!\n");
3505 SetLastError(ERROR_INVALID_PARAMETER
);
3506 return INVALID_HANDLE_VALUE
;
3511 if ((l
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3518 hClassesKey
= INVALID_HANDLE_VALUE
;
3524 WCHAR bracedGuidString
[39];
3526 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3528 if (!(l
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3534 if ((l
= RegOpenKeyExW(hClassesKey
,
3541 key
= INVALID_HANDLE_VALUE
;
3543 RegCloseKey(hClassesKey
);
3548 key
= INVALID_HANDLE_VALUE
;
3554 /***********************************************************************
3555 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3557 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3558 HDEVINFO DeviceInfoSet
,
3561 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3563 FIXME("%p %s %08x %p\n",
3564 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3568 /***********************************************************************
3569 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3571 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3572 HDEVINFO DeviceInfoSet
,
3575 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3577 FIXME("%p %s %08x %p\n", DeviceInfoSet
,
3578 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3582 /***********************************************************************
3583 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3585 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3586 HDEVINFO DeviceInfoSet
,
3587 PSP_DEVINFO_DATA DeviceInfoData
,
3588 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3589 DWORD ClassInstallParamsSize
)
3591 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
3592 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3596 /***********************************************************************
3597 * SetupDiCallClassInstaller (SETUPAPI.@)
3599 BOOL WINAPI
SetupDiCallClassInstaller(
3600 DI_FUNCTION InstallFunction
,
3601 HDEVINFO DeviceInfoSet
,
3602 PSP_DEVINFO_DATA DeviceInfoData
)
3604 FIXME("%d %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3608 /***********************************************************************
3609 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3611 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3612 HDEVINFO DeviceInfoSet
,
3613 PSP_DEVINFO_DATA DeviceInfoData
,
3614 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3616 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3620 static HKEY
SETUPDI_OpenDevKey(struct DeviceInfo
*devInfo
, REGSAM samDesired
)
3622 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
3625 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_ALL_ACCESS
,
3626 NULL
, &enumKey
, NULL
);
3629 RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
3630 RegCloseKey(enumKey
);
3635 static HKEY
SETUPDI_OpenDrvKey(struct DeviceInfo
*devInfo
, REGSAM samDesired
)
3637 static const WCHAR slash
[] = { '\\',0 };
3638 WCHAR classKeyPath
[MAX_PATH
];
3639 HKEY classKey
, key
= INVALID_HANDLE_VALUE
;
3642 lstrcpyW(classKeyPath
, ControlClass
);
3643 lstrcatW(classKeyPath
, slash
);
3644 SETUPDI_GuidToString(&devInfo
->set
->ClassGuid
,
3645 classKeyPath
+ lstrlenW(classKeyPath
));
3646 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, classKeyPath
, 0, NULL
, 0,
3647 KEY_ALL_ACCESS
, NULL
, &classKey
, NULL
);
3650 static const WCHAR fmt
[] = { '%','0','4','u',0 };
3653 sprintfW(devId
, fmt
, devInfo
->devId
);
3654 RegOpenKeyExW(classKey
, devId
, 0, samDesired
, &key
);
3655 RegCloseKey(classKey
);
3660 /***********************************************************************
3661 * SetupDiOpenDevRegKey (SETUPAPI.@)
3663 HKEY WINAPI
SetupDiOpenDevRegKey(
3664 HDEVINFO DeviceInfoSet
,
3665 PSP_DEVINFO_DATA DeviceInfoData
,
3671 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3672 struct DeviceInfo
*devInfo
;
3673 HKEY key
= INVALID_HANDLE_VALUE
;
3675 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
3676 Scope
, HwProfile
, KeyType
, samDesired
);
3678 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3680 SetLastError(ERROR_INVALID_HANDLE
);
3681 return INVALID_HANDLE_VALUE
;
3683 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3685 SetLastError(ERROR_INVALID_HANDLE
);
3686 return INVALID_HANDLE_VALUE
;
3688 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3689 || !DeviceInfoData
->Reserved
)
3691 SetLastError(ERROR_INVALID_PARAMETER
);
3692 return INVALID_HANDLE_VALUE
;
3694 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3696 SetLastError(ERROR_INVALID_FLAGS
);
3697 return INVALID_HANDLE_VALUE
;
3699 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3701 SetLastError(ERROR_INVALID_FLAGS
);
3702 return INVALID_HANDLE_VALUE
;
3704 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3705 if (devInfo
->set
!= set
)
3707 SetLastError(ERROR_INVALID_PARAMETER
);
3708 return INVALID_HANDLE_VALUE
;
3710 if (devInfo
->phantom
)
3712 SetLastError(ERROR_DEVINFO_NOT_REGISTERED
);
3713 return INVALID_HANDLE_VALUE
;
3715 if (Scope
!= DICS_FLAG_GLOBAL
)
3716 FIXME("unimplemented for scope %d\n", Scope
);
3720 key
= SETUPDI_OpenDevKey(devInfo
, samDesired
);
3723 key
= SETUPDI_OpenDrvKey(devInfo
, samDesired
);
3726 WARN("unknown KeyType %d\n", KeyType
);
3731 static BOOL
SETUPDI_DeleteDevKey(struct DeviceInfo
*devInfo
)
3737 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_ALL_ACCESS
,
3738 NULL
, &enumKey
, NULL
);
3741 ret
= RegDeleteTreeW(enumKey
, devInfo
->instanceId
);
3742 RegCloseKey(enumKey
);
3749 static BOOL
SETUPDI_DeleteDrvKey(struct DeviceInfo
*devInfo
)
3751 static const WCHAR slash
[] = { '\\',0 };
3752 WCHAR classKeyPath
[MAX_PATH
];
3757 lstrcpyW(classKeyPath
, ControlClass
);
3758 lstrcatW(classKeyPath
, slash
);
3759 SETUPDI_GuidToString(&devInfo
->set
->ClassGuid
,
3760 classKeyPath
+ lstrlenW(classKeyPath
));
3761 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, classKeyPath
, 0, NULL
, 0,
3762 KEY_ALL_ACCESS
, NULL
, &classKey
, NULL
);
3765 static const WCHAR fmt
[] = { '%','0','4','u',0 };
3768 sprintfW(devId
, fmt
, devInfo
->devId
);
3769 ret
= RegDeleteTreeW(classKey
, devId
);
3770 RegCloseKey(classKey
);
3777 /***********************************************************************
3778 * SetupDiOpenDevRegKey (SETUPAPI.@)
3780 BOOL WINAPI
SetupDiDeleteDevRegKey(
3781 HDEVINFO DeviceInfoSet
,
3782 PSP_DEVINFO_DATA DeviceInfoData
,
3787 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3788 struct DeviceInfo
*devInfo
;
3791 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
3794 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3796 SetLastError(ERROR_INVALID_HANDLE
);
3799 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3801 SetLastError(ERROR_INVALID_HANDLE
);
3804 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3805 || !DeviceInfoData
->Reserved
)
3807 SetLastError(ERROR_INVALID_PARAMETER
);
3810 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3812 SetLastError(ERROR_INVALID_FLAGS
);
3815 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
3817 SetLastError(ERROR_INVALID_FLAGS
);
3820 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3821 if (devInfo
->set
!= set
)
3823 SetLastError(ERROR_INVALID_PARAMETER
);
3826 if (devInfo
->phantom
)
3828 SetLastError(ERROR_DEVINFO_NOT_REGISTERED
);
3831 if (Scope
!= DICS_FLAG_GLOBAL
)
3832 FIXME("unimplemented for scope %d\n", Scope
);
3836 ret
= SETUPDI_DeleteDevKey(devInfo
);
3839 ret
= SETUPDI_DeleteDrvKey(devInfo
);
3842 ret
= SETUPDI_DeleteDevKey(devInfo
);
3844 ret
= SETUPDI_DeleteDrvKey(devInfo
);
3847 WARN("unknown KeyType %d\n", KeyType
);