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 (HDEVINFO
)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 (HDEVINFO
)INVALID_HANDLE_VALUE
;
1166 if (Reserved
!= NULL
)
1168 SetLastError(ERROR_INVALID_PARAMETER
);
1169 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
1172 list
= HeapAlloc(GetProcessHeap(), 0, size
);
1175 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1176 return (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
!= (HDEVINFO
)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
= (HDEVINFO
)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
= (HDEVINFO
)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
= (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
== (HDEVINFO
)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
!= (HDEVINFO
)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
== (HDEVINFO
)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) ||
2890 DeviceInterfaceDetailData
->cbSize
> sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
2892 SetLastError(ERROR_INVALID_USER_BUFFER
);
2895 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2897 SetLastError(ERROR_INVALID_USER_BUFFER
);
2900 info
= (struct InterfaceInfo
*)DeviceInterfaceData
->Reserved
;
2901 if (info
->symbolicLink
)
2902 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
->symbolicLink
, -1,
2903 NULL
, 0, NULL
, NULL
);
2904 if (DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2906 if (info
->symbolicLink
)
2907 WideCharToMultiByte(CP_ACP
, 0, info
->symbolicLink
, -1,
2908 DeviceInterfaceDetailData
->DevicePath
,
2909 DeviceInterfaceDetailDataSize
-
2910 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2913 DeviceInterfaceDetailData
->DevicePath
[0] = '\0';
2914 if (DeviceInfoData
&& DeviceInfoData
->cbSize
== sizeof(SP_DEVINFO_DATA
))
2915 memcpy(DeviceInfoData
, info
->device
, sizeof(SP_DEVINFO_DATA
));
2921 *RequiredSize
= bytesNeeded
;
2922 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2927 /***********************************************************************
2928 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2930 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2931 HDEVINFO DeviceInfoSet
,
2932 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2933 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2934 DWORD DeviceInterfaceDetailDataSize
,
2935 PDWORD RequiredSize
,
2936 PSP_DEVINFO_DATA DeviceInfoData
)
2938 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2939 struct InterfaceInfo
*info
;
2940 DWORD bytesNeeded
= offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2941 + sizeof(WCHAR
); /* include NULL terminator */
2944 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2945 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2946 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2948 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
||
2949 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2951 SetLastError(ERROR_INVALID_HANDLE
);
2954 if (!DeviceInterfaceData
||
2955 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2956 !DeviceInterfaceData
->Reserved
)
2958 SetLastError(ERROR_INVALID_PARAMETER
);
2961 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
<
2962 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
) ||
2963 DeviceInterfaceDetailData
->cbSize
> sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
)))
2965 SetLastError(ERROR_INVALID_USER_BUFFER
);
2968 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2970 SetLastError(ERROR_INVALID_USER_BUFFER
);
2973 info
= (struct InterfaceInfo
*)DeviceInterfaceData
->Reserved
;
2974 if (info
->symbolicLink
)
2975 bytesNeeded
+= lstrlenW(info
->symbolicLink
);
2976 if (DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2978 if (info
->symbolicLink
)
2979 lstrcpyW(DeviceInterfaceDetailData
->DevicePath
, info
->symbolicLink
);
2981 DeviceInterfaceDetailData
->DevicePath
[0] = '\0';
2982 if (DeviceInfoData
&& DeviceInfoData
->cbSize
== sizeof(SP_DEVINFO_DATA
))
2983 memcpy(DeviceInfoData
, info
->device
, sizeof(SP_DEVINFO_DATA
));
2989 *RequiredSize
= bytesNeeded
;
2990 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2995 struct PropertyMapEntry
3002 static struct PropertyMapEntry PropertyMap
[] = {
3003 { REG_SZ
, "DeviceDesc", DeviceDesc
},
3004 { REG_MULTI_SZ
, "HardwareId", HardwareId
},
3005 { REG_MULTI_SZ
, "CompatibleIDs", CompatibleIDs
},
3006 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3007 { REG_SZ
, "Service", Service
},
3008 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3009 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3010 { REG_SZ
, "Class", Class
},
3011 { REG_SZ
, "ClassGUID", ClassGUID
},
3012 { REG_SZ
, "Driver", Driver
},
3013 { REG_DWORD
, "ConfigFlags", ConfigFlags
},
3014 { REG_SZ
, "Mfg", Mfg
},
3015 { REG_SZ
, "FriendlyName", FriendlyName
},
3016 { REG_SZ
, "LocationInformation", LocationInformation
},
3017 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3018 { REG_DWORD
, "Capabilities", Capabilities
},
3019 { REG_DWORD
, "UINumber", UINumber
},
3020 { REG_MULTI_SZ
, "UpperFilters", UpperFilters
},
3021 { REG_MULTI_SZ
, "LowerFilters", LowerFilters
},
3024 /***********************************************************************
3025 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3027 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3028 HDEVINFO DeviceInfoSet
,
3029 PSP_DEVINFO_DATA DeviceInfoData
,
3031 PDWORD PropertyRegDataType
,
3032 PBYTE PropertyBuffer
,
3033 DWORD PropertyBufferSize
,
3034 PDWORD RequiredSize
)
3037 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3038 struct DeviceInfo
*devInfo
;
3040 TRACE("%04x %p %d %p %p %d %p\n", (DWORD
)DeviceInfoSet
, DeviceInfoData
,
3041 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3044 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3046 SetLastError(ERROR_INVALID_HANDLE
);
3049 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3051 SetLastError(ERROR_INVALID_HANDLE
);
3054 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3055 || !DeviceInfoData
->Reserved
)
3057 SetLastError(ERROR_INVALID_PARAMETER
);
3060 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3061 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3062 && PropertyMap
[Property
].nameA
)
3064 DWORD size
= PropertyBufferSize
;
3065 LONG l
= RegQueryValueExA(devInfo
->key
, PropertyMap
[Property
].nameA
,
3066 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3069 *RequiredSize
= size
;
3070 if (!PropertyBuffer
)
3071 ; /* do nothing, ret is already FALSE, last error is already set */
3080 /***********************************************************************
3081 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3083 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3084 HDEVINFO DeviceInfoSet
,
3085 PSP_DEVINFO_DATA DeviceInfoData
,
3087 PDWORD PropertyRegDataType
,
3088 PBYTE PropertyBuffer
,
3089 DWORD PropertyBufferSize
,
3090 PDWORD RequiredSize
)
3093 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3094 struct DeviceInfo
*devInfo
;
3096 TRACE("%04x %p %d %p %p %d %p\n", (DWORD
)DeviceInfoSet
, DeviceInfoData
,
3097 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3100 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3102 SetLastError(ERROR_INVALID_HANDLE
);
3105 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3107 SetLastError(ERROR_INVALID_HANDLE
);
3110 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3111 || !DeviceInfoData
->Reserved
)
3113 SetLastError(ERROR_INVALID_PARAMETER
);
3116 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3117 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3118 && PropertyMap
[Property
].nameW
)
3120 DWORD size
= PropertyBufferSize
;
3121 LONG l
= RegQueryValueExW(devInfo
->key
, PropertyMap
[Property
].nameW
,
3122 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3125 *RequiredSize
= size
;
3126 if (!PropertyBuffer
)
3127 ; /* do nothing, ret is already FALSE, last error is already set */
3136 /***********************************************************************
3137 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3139 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3140 HDEVINFO DeviceInfoSet
,
3141 PSP_DEVINFO_DATA DeviceInfoData
,
3143 const BYTE
*PropertyBuffer
,
3144 DWORD PropertyBufferSize
)
3147 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3148 struct DeviceInfo
*devInfo
;
3150 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3151 PropertyBuffer
, PropertyBufferSize
);
3153 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3155 SetLastError(ERROR_INVALID_HANDLE
);
3158 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3160 SetLastError(ERROR_INVALID_HANDLE
);
3163 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3164 || !DeviceInfoData
->Reserved
)
3166 SetLastError(ERROR_INVALID_PARAMETER
);
3169 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3170 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3171 && PropertyMap
[Property
].nameA
)
3173 LONG l
= RegSetValueExA(devInfo
->key
, PropertyMap
[Property
].nameA
, 0,
3174 PropertyMap
[Property
].regType
, PropertyBuffer
,
3175 PropertyBufferSize
);
3184 /***********************************************************************
3185 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3187 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3188 HDEVINFO DeviceInfoSet
,
3189 PSP_DEVINFO_DATA DeviceInfoData
,
3191 const BYTE
*PropertyBuffer
,
3192 DWORD PropertyBufferSize
)
3195 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3196 struct DeviceInfo
*devInfo
;
3198 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3199 PropertyBuffer
, PropertyBufferSize
);
3201 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3203 SetLastError(ERROR_INVALID_HANDLE
);
3206 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3208 SetLastError(ERROR_INVALID_HANDLE
);
3211 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3212 || !DeviceInfoData
->Reserved
)
3214 SetLastError(ERROR_INVALID_PARAMETER
);
3217 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3218 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3219 && PropertyMap
[Property
].nameW
)
3221 LONG l
= RegSetValueExW(devInfo
->key
, PropertyMap
[Property
].nameW
, 0,
3222 PropertyMap
[Property
].regType
, PropertyBuffer
,
3223 PropertyBufferSize
);
3232 /***********************************************************************
3233 * SetupDiInstallClassA (SETUPAPI.@)
3235 BOOL WINAPI
SetupDiInstallClassA(
3241 UNICODE_STRING FileNameW
;
3246 SetLastError(ERROR_INVALID_PARAMETER
);
3249 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
3251 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3255 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
3257 RtlFreeUnicodeString(&FileNameW
);
3262 static HKEY
CreateClassKey(HINF hInf
)
3264 static const WCHAR slash
[] = { '\\',0 };
3265 WCHAR FullBuffer
[MAX_PATH
];
3266 WCHAR Buffer
[MAX_PATH
];
3270 if (!SetupGetLineTextW(NULL
,
3278 return INVALID_HANDLE_VALUE
;
3281 lstrcpyW(FullBuffer
, ControlClass
);
3282 lstrcatW(FullBuffer
, slash
);
3283 lstrcatW(FullBuffer
, Buffer
);
3285 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3291 if (!SetupGetLineTextW(NULL
,
3299 return INVALID_HANDLE_VALUE
;
3302 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3306 REG_OPTION_NON_VOLATILE
,
3312 return INVALID_HANDLE_VALUE
;
3317 if (RegSetValueExW(hClassKey
,
3322 RequiredSize
* sizeof(WCHAR
)))
3324 RegCloseKey(hClassKey
);
3325 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3327 return INVALID_HANDLE_VALUE
;
3333 /***********************************************************************
3334 * SetupDiInstallClassW (SETUPAPI.@)
3336 BOOL WINAPI
SetupDiInstallClassW(
3342 WCHAR SectionName
[MAX_PATH
];
3343 DWORD SectionNameLength
= 0;
3345 BOOL bFileQueueCreated
= FALSE
;
3353 SetLastError(ERROR_INVALID_PARAMETER
);
3356 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
3358 SetLastError(ERROR_INVALID_PARAMETER
);
3362 /* Open the .inf file */
3363 hInf
= SetupOpenInfFileW(InfFileName
,
3367 if (hInf
== INVALID_HANDLE_VALUE
)
3373 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3374 hClassKey
= CreateClassKey(hInf
);
3375 if (hClassKey
== INVALID_HANDLE_VALUE
)
3377 SetupCloseInfFile(hInf
);
3382 /* Try to append a layout file */
3383 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3385 /* Retrieve the actual section name */
3386 SetupDiGetActualSectionToInstallW(hInf
,
3394 if (!(Flags
& DI_NOVCP
))
3396 FileQueue
= SetupOpenFileQueue();
3397 if (FileQueue
== INVALID_HANDLE_VALUE
)
3399 SetupCloseInfFile(hInf
);
3403 bFileQueueCreated
= TRUE
;
3408 SetupInstallFromInfSectionW(NULL
,
3411 SPINST_COPYINF
| SPINST_FILES
| SPINST_REGISTRY
,
3417 INVALID_HANDLE_VALUE
,
3420 /* FIXME: More code! */
3422 if (bFileQueueCreated
)
3423 SetupCloseFileQueue(FileQueue
);
3425 SetupCloseInfFile(hInf
);
3431 /***********************************************************************
3432 * SetupDiOpenClassRegKey (SETUPAPI.@)
3434 HKEY WINAPI
SetupDiOpenClassRegKey(
3435 const GUID
* ClassGuid
,
3438 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3439 DIOCR_INSTALLER
, NULL
, NULL
);
3443 /***********************************************************************
3444 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3446 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3447 const GUID
* ClassGuid
,
3453 PWSTR MachineNameW
= NULL
;
3460 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3461 if (MachineNameW
== NULL
)
3462 return INVALID_HANDLE_VALUE
;
3465 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3466 Flags
, MachineNameW
, Reserved
);
3468 MyFree(MachineNameW
);
3474 /***********************************************************************
3475 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3477 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3478 const GUID
* ClassGuid
,
3489 if (MachineName
!= NULL
)
3491 FIXME("Remote access not supported yet!\n");
3492 return INVALID_HANDLE_VALUE
;
3495 if (Flags
== DIOCR_INSTALLER
)
3497 lpKeyName
= ControlClass
;
3499 else if (Flags
== DIOCR_INTERFACE
)
3501 lpKeyName
= DeviceClasses
;
3505 ERR("Invalid Flags parameter!\n");
3506 SetLastError(ERROR_INVALID_PARAMETER
);
3507 return INVALID_HANDLE_VALUE
;
3512 if ((l
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3519 hClassesKey
= INVALID_HANDLE_VALUE
;
3525 WCHAR bracedGuidString
[39];
3527 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3529 if (!(l
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3535 if ((l
= RegOpenKeyExW(hClassesKey
,
3542 key
= INVALID_HANDLE_VALUE
;
3544 RegCloseKey(hClassesKey
);
3549 key
= INVALID_HANDLE_VALUE
;
3555 /***********************************************************************
3556 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3558 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3559 HDEVINFO DeviceInfoSet
,
3562 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3564 FIXME("%p %s %08x %p\n",
3565 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3569 /***********************************************************************
3570 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3572 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3573 HDEVINFO DeviceInfoSet
,
3576 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3578 FIXME("%p %s %08x %p\n", DeviceInfoSet
,
3579 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3583 /***********************************************************************
3584 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3586 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3587 HDEVINFO DeviceInfoSet
,
3588 PSP_DEVINFO_DATA DeviceInfoData
,
3589 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3590 DWORD ClassInstallParamsSize
)
3592 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
3593 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3597 /***********************************************************************
3598 * SetupDiCallClassInstaller (SETUPAPI.@)
3600 BOOL WINAPI
SetupDiCallClassInstaller(
3601 DI_FUNCTION InstallFunction
,
3602 HDEVINFO DeviceInfoSet
,
3603 PSP_DEVINFO_DATA DeviceInfoData
)
3605 FIXME("%d %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3609 /***********************************************************************
3610 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3612 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3613 HDEVINFO DeviceInfoSet
,
3614 PSP_DEVINFO_DATA DeviceInfoData
,
3615 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3617 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3621 static HKEY
SETUPDI_OpenDevKey(struct DeviceInfo
*devInfo
, REGSAM samDesired
)
3623 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
3626 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_ALL_ACCESS
,
3627 NULL
, &enumKey
, NULL
);
3630 RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
3631 RegCloseKey(enumKey
);
3636 static HKEY
SETUPDI_OpenDrvKey(struct DeviceInfo
*devInfo
, REGSAM samDesired
)
3638 static const WCHAR slash
[] = { '\\',0 };
3639 WCHAR classKeyPath
[MAX_PATH
];
3640 HKEY classKey
, key
= INVALID_HANDLE_VALUE
;
3643 lstrcpyW(classKeyPath
, ControlClass
);
3644 lstrcatW(classKeyPath
, slash
);
3645 SETUPDI_GuidToString(&devInfo
->set
->ClassGuid
,
3646 classKeyPath
+ lstrlenW(classKeyPath
));
3647 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, classKeyPath
, 0, NULL
, 0,
3648 KEY_ALL_ACCESS
, NULL
, &classKey
, NULL
);
3651 static const WCHAR fmt
[] = { '%','0','4','u',0 };
3654 sprintfW(devId
, fmt
, devInfo
->devId
);
3655 RegOpenKeyExW(classKey
, devId
, 0, samDesired
, &key
);
3656 RegCloseKey(classKey
);
3661 /***********************************************************************
3662 * SetupDiOpenDevRegKey (SETUPAPI.@)
3664 HKEY WINAPI
SetupDiOpenDevRegKey(
3665 HDEVINFO DeviceInfoSet
,
3666 PSP_DEVINFO_DATA DeviceInfoData
,
3672 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3673 struct DeviceInfo
*devInfo
;
3674 HKEY key
= INVALID_HANDLE_VALUE
;
3676 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
3677 Scope
, HwProfile
, KeyType
, samDesired
);
3679 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3681 SetLastError(ERROR_INVALID_HANDLE
);
3682 return INVALID_HANDLE_VALUE
;
3684 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3686 SetLastError(ERROR_INVALID_HANDLE
);
3687 return INVALID_HANDLE_VALUE
;
3689 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3690 || !DeviceInfoData
->Reserved
)
3692 SetLastError(ERROR_INVALID_PARAMETER
);
3693 return INVALID_HANDLE_VALUE
;
3695 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3697 SetLastError(ERROR_INVALID_FLAGS
);
3698 return INVALID_HANDLE_VALUE
;
3700 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3702 SetLastError(ERROR_INVALID_FLAGS
);
3703 return INVALID_HANDLE_VALUE
;
3705 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3706 if (devInfo
->set
!= set
)
3708 SetLastError(ERROR_INVALID_PARAMETER
);
3709 return INVALID_HANDLE_VALUE
;
3711 if (devInfo
->phantom
)
3713 SetLastError(ERROR_DEVINFO_NOT_REGISTERED
);
3714 return INVALID_HANDLE_VALUE
;
3716 if (Scope
!= DICS_FLAG_GLOBAL
)
3717 FIXME("unimplemented for scope %d\n", Scope
);
3721 key
= SETUPDI_OpenDevKey(devInfo
, samDesired
);
3724 key
= SETUPDI_OpenDrvKey(devInfo
, samDesired
);
3727 WARN("unknown KeyType %d\n", KeyType
);
3732 static BOOL
SETUPDI_DeleteDevKey(struct DeviceInfo
*devInfo
)
3738 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, Enum
, 0, NULL
, 0, KEY_ALL_ACCESS
,
3739 NULL
, &enumKey
, NULL
);
3742 ret
= RegDeleteTreeW(enumKey
, devInfo
->instanceId
);
3743 RegCloseKey(enumKey
);
3750 static BOOL
SETUPDI_DeleteDrvKey(struct DeviceInfo
*devInfo
)
3752 static const WCHAR slash
[] = { '\\',0 };
3753 WCHAR classKeyPath
[MAX_PATH
];
3758 lstrcpyW(classKeyPath
, ControlClass
);
3759 lstrcatW(classKeyPath
, slash
);
3760 SETUPDI_GuidToString(&devInfo
->set
->ClassGuid
,
3761 classKeyPath
+ lstrlenW(classKeyPath
));
3762 l
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, classKeyPath
, 0, NULL
, 0,
3763 KEY_ALL_ACCESS
, NULL
, &classKey
, NULL
);
3766 static const WCHAR fmt
[] = { '%','0','4','u',0 };
3769 sprintfW(devId
, fmt
, devInfo
->devId
);
3770 ret
= RegDeleteTreeW(classKey
, devId
);
3771 RegCloseKey(classKey
);
3778 /***********************************************************************
3779 * SetupDiOpenDevRegKey (SETUPAPI.@)
3781 BOOL WINAPI
SetupDiDeleteDevRegKey(
3782 HDEVINFO DeviceInfoSet
,
3783 PSP_DEVINFO_DATA DeviceInfoData
,
3788 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3789 struct DeviceInfo
*devInfo
;
3792 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
3795 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3797 SetLastError(ERROR_INVALID_HANDLE
);
3800 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3802 SetLastError(ERROR_INVALID_HANDLE
);
3805 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3806 || !DeviceInfoData
->Reserved
)
3808 SetLastError(ERROR_INVALID_PARAMETER
);
3811 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3813 SetLastError(ERROR_INVALID_FLAGS
);
3816 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3818 SetLastError(ERROR_INVALID_FLAGS
);
3821 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3822 if (devInfo
->set
!= set
)
3824 SetLastError(ERROR_INVALID_PARAMETER
);
3827 if (devInfo
->phantom
)
3829 SetLastError(ERROR_DEVINFO_NOT_REGISTERED
);
3832 if (Scope
!= DICS_FLAG_GLOBAL
)
3833 FIXME("unimplemented for scope %d\n", Scope
);
3837 ret
= SETUPDI_DeleteDevKey(devInfo
);
3840 ret
= SETUPDI_DeleteDrvKey(devInfo
);
3843 ret
= SETUPDI_DeleteDevKey(devInfo
);
3845 ret
= SETUPDI_DeleteDrvKey(devInfo
);
3848 WARN("unknown KeyType %d\n", KeyType
);