setupapi: Implement SetupDiCreateDevRegKeyA on top of SetupDiCreateDevRegKeyW.
[wine/hacks.git] / dlls / setupapi / devinst.c
blob1f3d3b9fb03fa413435efe0e2c59b9a18b559ed4
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "setupapi.h"
35 #include "wine/debug.h"
36 #include "wine/list.h"
37 #include "wine/unicode.h"
38 #include "cfgmgr32.h"
39 #include "initguid.h"
40 #include "winioctl.h"
41 #include "rpc.h"
42 #include "rpcdce.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','\\',
73 'E','n','u','m',0};
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
92 valid or not */
93 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
95 struct DeviceInfoSet
97 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
98 GUID ClassGuid;
99 HWND hwndParent;
100 DWORD cDevices;
101 SP_DEVINFO_DATA *devices;
104 /* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */
105 struct InterfaceInfo
107 LPWSTR referenceString;
108 LPWSTR symbolicLink;
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
117 GUID guid;
118 DWORD cInstances;
119 DWORD cInstancesAllocated;
120 SP_DEVICE_INTERFACE_DATA *instances;
121 struct list entry;
124 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
125 struct DeviceInfo
127 struct DeviceInfoSet *set;
128 HKEY key;
129 BOOL phantom;
130 LPWSTR instanceId;
131 struct list interfaces;
134 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
136 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
137 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
138 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
139 '0','2','X','}',0};
141 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
142 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
143 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
146 static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
148 DWORD i;
150 for (i = 0; i < instances->cInstances; i++)
152 struct InterfaceInfo *ifaceInfo =
153 (struct InterfaceInfo *)instances->instances[i].Reserved;
155 if (ifaceInfo->device && ifaceInfo->device->Reserved)
157 struct DeviceInfo *devInfo =
158 (struct DeviceInfo *)ifaceInfo->device->Reserved;
160 if (devInfo->phantom)
161 SetupDiDeleteDeviceInterfaceRegKey(devInfo->set,
162 &instances->instances[i], 0);
164 HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
165 HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
167 HeapFree(GetProcessHeap(), 0, instances->instances);
170 /* Finds the interface with interface class InterfaceClassGuid in the device.
171 * Returns TRUE if found, and updates *interface to point to device's
172 * interfaces member where the given interface was found.
173 * Returns FALSE if not found.
175 static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
176 const GUID *InterfaceClassGuid, struct InterfaceInstances **interface)
178 BOOL found = FALSE;
179 struct InterfaceInstances *iface;
181 TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
183 LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances,
184 entry)
186 if (IsEqualGUID(&iface->guid, InterfaceClassGuid))
188 *interface = iface;
189 found = TRUE;
190 break;
193 TRACE("returning %d (%p)\n", found, found ? *interface : NULL);
194 return found;
197 /* Finds the interface instance with reference string ReferenceString in the
198 * interface instance map. Returns TRUE if found, and updates instanceIndex to
199 * the index of the interface instance's instances member
200 * where the given instance was found. Returns FALSE if not found.
202 static BOOL SETUPDI_FindInterfaceInstance(
203 const struct InterfaceInstances *instances,
204 LPCWSTR ReferenceString, DWORD *instanceIndex)
206 BOOL found = FALSE;
207 DWORD i;
209 TRACE("%s\n", debugstr_w(ReferenceString));
211 for (i = 0; !found && i < instances->cInstances; i++)
213 SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
214 struct InterfaceInfo *ifaceInfo =
215 (struct InterfaceInfo *)ifaceData->Reserved;
217 if (!ReferenceString && !ifaceInfo->referenceString)
219 *instanceIndex = i;
220 found = TRUE;
222 else if (ReferenceString && ifaceInfo->referenceString &&
223 !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
225 *instanceIndex = i;
226 found = TRUE;
229 TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
230 return found;
233 static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
234 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
236 static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
237 WCHAR guidStr[39];
238 DWORD len;
239 LPWSTR ret;
241 SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
242 /* omit length of format specifiers, but include NULL terminator: */
243 len = lstrlenW(fmt) - 4 + 1;
244 len += lstrlenW(instanceId) + lstrlenW(guidStr);
245 if (ReferenceString)
247 /* space for a hash between string and reference string: */
248 len += lstrlenW(ReferenceString) + 1;
250 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
251 if (ret)
253 int printed = sprintfW(ret, fmt, instanceId, guidStr);
254 LPWSTR ptr;
256 /* replace '\\' with '#' after the "\\\\?\\" beginning */
257 for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
258 *ptr = '#';
259 if (ReferenceString)
261 ret[printed - 1] = '\\';
262 lstrcpyW(ret + printed, ReferenceString);
265 return ret;
268 /* Adds an interface with the given interface class and reference string to
269 * the device, if it doesn't already exist in the device. If iface is not
270 * NULL, returns a pointer to the newly added (or already existing) interface.
272 static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData,
273 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
274 SP_DEVICE_INTERFACE_DATA **ifaceData)
276 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
277 BOOL newInterface = FALSE, ret;
278 struct InterfaceInstances *iface = NULL;
280 TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
281 debugstr_w(ReferenceString), iface);
283 if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
285 iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
286 sizeof(struct InterfaceInstances));
287 if (iface)
289 list_add_tail(&devInfo->interfaces, &iface->entry);
290 newInterface = TRUE;
293 if (iface)
295 DWORD instanceIndex = 0;
297 if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
298 &instanceIndex)))
300 SP_DEVICE_INTERFACE_DATA *instance = NULL;
302 if (!iface->cInstancesAllocated)
304 iface->instances = HeapAlloc(GetProcessHeap(), 0,
305 sizeof(SP_DEVICE_INTERFACE_DATA));
306 if (iface->instances)
307 instance = &iface->instances[iface->cInstancesAllocated++];
309 else if (iface->cInstances == iface->cInstancesAllocated)
311 iface->instances = HeapReAlloc(GetProcessHeap(), 0,
312 iface->instances,
313 (iface->cInstancesAllocated + 1) *
314 sizeof(SP_DEVICE_INTERFACE_DATA));
315 if (iface->instances)
316 instance = &iface->instances[iface->cInstancesAllocated++];
318 else
319 instance = &iface->instances[iface->cInstances];
320 if (instance)
322 struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
323 0, sizeof(struct InterfaceInfo));
325 if (ifaceInfo)
327 ret = TRUE;
328 ifaceInfo->device = DeviceInfoData;
329 ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
330 devInfo->instanceId, InterfaceClassGuid,
331 ReferenceString);
332 if (ReferenceString)
334 ifaceInfo->referenceString =
335 HeapAlloc(GetProcessHeap(), 0,
336 (lstrlenW(ReferenceString) + 1) *
337 sizeof(WCHAR));
338 if (ifaceInfo->referenceString)
339 lstrcpyW(ifaceInfo->referenceString,
340 ReferenceString);
341 else
342 ret = FALSE;
344 else
345 ifaceInfo->referenceString = NULL;
346 if (ret)
348 HKEY key;
350 iface->cInstances++;
351 instance->cbSize =
352 sizeof(SP_DEVICE_INTERFACE_DATA);
353 memcpy(&instance->InterfaceClassGuid,
354 InterfaceClassGuid, sizeof(GUID));
355 instance->Flags = SPINT_ACTIVE; /* FIXME */
356 instance->Reserved = (ULONG_PTR)ifaceInfo;
357 if (newInterface)
358 memcpy(&iface->guid, InterfaceClassGuid,
359 sizeof(GUID));
360 key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set,
361 instance, 0, KEY_WRITE, NULL, NULL);
362 if (key != INVALID_HANDLE_VALUE)
364 RegSetValueExW(key, SymbolicLink, 0, REG_SZ,
365 (BYTE *)ifaceInfo->symbolicLink,
366 lstrlenW(ifaceInfo->symbolicLink) *
367 sizeof(WCHAR));
368 RegCloseKey(key);
370 if (ifaceData)
371 *ifaceData = instance;
373 else
374 HeapFree(GetProcessHeap(), 0, ifaceInfo);
378 else
380 if (ifaceData)
381 *ifaceData = &iface->instances[instanceIndex];
384 else
385 ret = FALSE;
386 TRACE("returning %d\n", ret);
387 return ret;
390 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
391 LPCWSTR symbolicLink)
393 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
394 BOOL ret = FALSE;
396 if (info)
398 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
399 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
400 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
401 if (info->symbolicLink)
403 lstrcpyW(info->symbolicLink, symbolicLink);
404 ret = TRUE;
407 return ret;
410 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
411 LPCWSTR instanceId, BOOL phantom)
413 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
414 sizeof(struct DeviceInfo));
416 if (devInfo)
418 devInfo->set = set;
419 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
420 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
421 if (devInfo->instanceId)
423 HKEY enumKey;
424 LONG l;
426 devInfo->key = INVALID_HANDLE_VALUE;
427 devInfo->phantom = phantom;
428 lstrcpyW(devInfo->instanceId, instanceId);
429 struprW(devInfo->instanceId);
430 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
431 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
432 if (!l)
434 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
435 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
436 if (phantom)
437 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
438 (LPBYTE)&phantom, sizeof(phantom));
439 RegCloseKey(enumKey);
441 list_init(&devInfo->interfaces);
443 else
445 HeapFree(GetProcessHeap(), 0, devInfo);
446 devInfo = NULL;
449 return devInfo;
452 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
454 struct InterfaceInstances *iface, *next;
456 if (devInfo->key != INVALID_HANDLE_VALUE)
457 RegCloseKey(devInfo->key);
458 if (devInfo->phantom)
460 HKEY enumKey;
461 LONG l;
463 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
464 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
465 if (!l)
467 RegDeleteTreeW(enumKey, devInfo->instanceId);
468 RegCloseKey(enumKey);
471 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
472 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
473 struct InterfaceInstances, entry)
475 list_remove(&iface->entry);
476 SETUPDI_FreeInterfaceInstances(iface);
477 HeapFree(GetProcessHeap(), 0, iface);
479 HeapFree(GetProcessHeap(), 0, devInfo);
482 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
483 * struct DeviceInfo, and points the returned device info's Reserved member
484 * to it. "Phantom" devices are deleted from the registry when closed.
485 * Returns a pointer to the newly allocated device info.
487 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
488 const GUID *guid,
489 DWORD devInst,
490 LPCWSTR instanceId,
491 BOOL phantom,
492 SP_DEVINFO_DATA **dev)
494 BOOL ret = FALSE;
495 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, instanceId,
496 phantom);
498 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
499 debugstr_w(instanceId), phantom);
501 if (devInfo)
503 if (set->devices)
504 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
505 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
506 else
507 set->devices = HeapAlloc(GetProcessHeap(), 0,
508 sizeof(SP_DEVINFO_DATA));
509 if (set->devices)
511 WCHAR classGuidStr[39];
513 *dev = &set->devices[set->cDevices++];
514 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
515 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
516 (*dev)->DevInst = devInst;
517 (*dev)->Reserved = (ULONG_PTR)devInfo;
518 SETUPDI_GuidToString(guid, classGuidStr);
519 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
520 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
521 lstrlenW(classGuidStr) * sizeof(WCHAR));
522 ret = TRUE;
524 else
526 HeapFree(GetProcessHeap(), 0, devInfo);
527 SetLastError(ERROR_OUTOFMEMORY);
530 return ret;
533 /***********************************************************************
534 * SetupDiBuildClassInfoList (SETUPAPI.@)
536 * Returns a list of setup class GUIDs that identify the classes
537 * that are installed on a local machine.
539 * PARAMS
540 * Flags [I] control exclusion of classes from the list.
541 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
542 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
543 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
545 * RETURNS
546 * Success: TRUE.
547 * Failure: FALSE.
549 BOOL WINAPI SetupDiBuildClassInfoList(
550 DWORD Flags,
551 LPGUID ClassGuidList,
552 DWORD ClassGuidListSize,
553 PDWORD RequiredSize)
555 TRACE("\n");
556 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
557 ClassGuidListSize, RequiredSize,
558 NULL, NULL);
561 /***********************************************************************
562 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
564 * Returns a list of setup class GUIDs that identify the classes
565 * that are installed on a local or remote macine.
567 * PARAMS
568 * Flags [I] control exclusion of classes from the list.
569 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
570 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
571 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
572 * MachineName [I] name of a remote machine.
573 * Reserved [I] must be NULL.
575 * RETURNS
576 * Success: TRUE.
577 * Failure: FALSE.
579 BOOL WINAPI SetupDiBuildClassInfoListExA(
580 DWORD Flags,
581 LPGUID ClassGuidList,
582 DWORD ClassGuidListSize,
583 PDWORD RequiredSize,
584 LPCSTR MachineName,
585 PVOID Reserved)
587 LPWSTR MachineNameW = NULL;
588 BOOL bResult;
590 TRACE("\n");
592 if (MachineName)
594 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
595 if (MachineNameW == NULL) return FALSE;
598 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
599 ClassGuidListSize, RequiredSize,
600 MachineNameW, Reserved);
602 MyFree(MachineNameW);
604 return bResult;
607 /***********************************************************************
608 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
610 * Returns a list of setup class GUIDs that identify the classes
611 * that are installed on a local or remote macine.
613 * PARAMS
614 * Flags [I] control exclusion of classes from the list.
615 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
616 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
617 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
618 * MachineName [I] name of a remote machine.
619 * Reserved [I] must be NULL.
621 * RETURNS
622 * Success: TRUE.
623 * Failure: FALSE.
625 BOOL WINAPI SetupDiBuildClassInfoListExW(
626 DWORD Flags,
627 LPGUID ClassGuidList,
628 DWORD ClassGuidListSize,
629 PDWORD RequiredSize,
630 LPCWSTR MachineName,
631 PVOID Reserved)
633 WCHAR szKeyName[40];
634 HKEY hClassesKey;
635 HKEY hClassKey;
636 DWORD dwLength;
637 DWORD dwIndex;
638 LONG lError;
639 DWORD dwGuidListIndex = 0;
641 TRACE("\n");
643 if (RequiredSize != NULL)
644 *RequiredSize = 0;
646 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
647 KEY_ALL_ACCESS,
648 DIOCR_INSTALLER,
649 MachineName,
650 Reserved);
651 if (hClassesKey == INVALID_HANDLE_VALUE)
653 return FALSE;
656 for (dwIndex = 0; ; dwIndex++)
658 dwLength = 40;
659 lError = RegEnumKeyExW(hClassesKey,
660 dwIndex,
661 szKeyName,
662 &dwLength,
663 NULL,
664 NULL,
665 NULL,
666 NULL);
667 TRACE("RegEnumKeyExW() returns %d\n", lError);
668 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
670 TRACE("Key name: %p\n", szKeyName);
672 if (RegOpenKeyExW(hClassesKey,
673 szKeyName,
675 KEY_ALL_ACCESS,
676 &hClassKey))
678 RegCloseKey(hClassesKey);
679 return FALSE;
682 if (!RegQueryValueExW(hClassKey,
683 NoUseClass,
684 NULL,
685 NULL,
686 NULL,
687 NULL))
689 TRACE("'NoUseClass' value found!\n");
690 RegCloseKey(hClassKey);
691 continue;
694 if ((Flags & DIBCI_NOINSTALLCLASS) &&
695 (!RegQueryValueExW(hClassKey,
696 NoInstallClass,
697 NULL,
698 NULL,
699 NULL,
700 NULL)))
702 TRACE("'NoInstallClass' value found!\n");
703 RegCloseKey(hClassKey);
704 continue;
707 if ((Flags & DIBCI_NODISPLAYCLASS) &&
708 (!RegQueryValueExW(hClassKey,
709 NoDisplayClass,
710 NULL,
711 NULL,
712 NULL,
713 NULL)))
715 TRACE("'NoDisplayClass' value found!\n");
716 RegCloseKey(hClassKey);
717 continue;
720 RegCloseKey(hClassKey);
722 TRACE("Guid: %p\n", szKeyName);
723 if (dwGuidListIndex < ClassGuidListSize)
725 if (szKeyName[0] == '{' && szKeyName[37] == '}')
727 szKeyName[37] = 0;
729 TRACE("Guid: %p\n", &szKeyName[1]);
731 UuidFromStringW(&szKeyName[1],
732 &ClassGuidList[dwGuidListIndex]);
735 dwGuidListIndex++;
738 if (lError != ERROR_SUCCESS)
739 break;
742 RegCloseKey(hClassesKey);
744 if (RequiredSize != NULL)
745 *RequiredSize = dwGuidListIndex;
747 if (ClassGuidListSize < dwGuidListIndex)
749 SetLastError(ERROR_INSUFFICIENT_BUFFER);
750 return FALSE;
753 return TRUE;
756 /***********************************************************************
757 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
759 BOOL WINAPI SetupDiClassGuidsFromNameA(
760 LPCSTR ClassName,
761 LPGUID ClassGuidList,
762 DWORD ClassGuidListSize,
763 PDWORD RequiredSize)
765 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
766 ClassGuidListSize, RequiredSize,
767 NULL, NULL);
770 /***********************************************************************
771 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
773 BOOL WINAPI SetupDiClassGuidsFromNameW(
774 LPCWSTR ClassName,
775 LPGUID ClassGuidList,
776 DWORD ClassGuidListSize,
777 PDWORD RequiredSize)
779 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
780 ClassGuidListSize, RequiredSize,
781 NULL, NULL);
784 /***********************************************************************
785 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
787 BOOL WINAPI SetupDiClassGuidsFromNameExA(
788 LPCSTR ClassName,
789 LPGUID ClassGuidList,
790 DWORD ClassGuidListSize,
791 PDWORD RequiredSize,
792 LPCSTR MachineName,
793 PVOID Reserved)
795 LPWSTR ClassNameW = NULL;
796 LPWSTR MachineNameW = NULL;
797 BOOL bResult;
799 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
800 if (ClassNameW == NULL)
801 return FALSE;
803 if (MachineName)
805 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
806 if (MachineNameW == NULL)
808 MyFree(ClassNameW);
809 return FALSE;
813 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
814 ClassGuidListSize, RequiredSize,
815 MachineNameW, Reserved);
817 MyFree(MachineNameW);
818 MyFree(ClassNameW);
820 return bResult;
823 /***********************************************************************
824 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
826 BOOL WINAPI SetupDiClassGuidsFromNameExW(
827 LPCWSTR ClassName,
828 LPGUID ClassGuidList,
829 DWORD ClassGuidListSize,
830 PDWORD RequiredSize,
831 LPCWSTR MachineName,
832 PVOID Reserved)
834 WCHAR szKeyName[40];
835 WCHAR szClassName[256];
836 HKEY hClassesKey;
837 HKEY hClassKey;
838 DWORD dwLength;
839 DWORD dwIndex;
840 LONG lError;
841 DWORD dwGuidListIndex = 0;
843 if (RequiredSize != NULL)
844 *RequiredSize = 0;
846 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
847 KEY_ALL_ACCESS,
848 DIOCR_INSTALLER,
849 MachineName,
850 Reserved);
851 if (hClassesKey == INVALID_HANDLE_VALUE)
853 return FALSE;
856 for (dwIndex = 0; ; dwIndex++)
858 dwLength = 40;
859 lError = RegEnumKeyExW(hClassesKey,
860 dwIndex,
861 szKeyName,
862 &dwLength,
863 NULL,
864 NULL,
865 NULL,
866 NULL);
867 TRACE("RegEnumKeyExW() returns %d\n", lError);
868 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
870 TRACE("Key name: %p\n", szKeyName);
872 if (RegOpenKeyExW(hClassesKey,
873 szKeyName,
875 KEY_ALL_ACCESS,
876 &hClassKey))
878 RegCloseKey(hClassesKey);
879 return FALSE;
882 dwLength = 256 * sizeof(WCHAR);
883 if (!RegQueryValueExW(hClassKey,
884 Class,
885 NULL,
886 NULL,
887 (LPBYTE)szClassName,
888 &dwLength))
890 TRACE("Class name: %p\n", szClassName);
892 if (strcmpiW(szClassName, ClassName) == 0)
894 TRACE("Found matching class name\n");
896 TRACE("Guid: %p\n", szKeyName);
897 if (dwGuidListIndex < ClassGuidListSize)
899 if (szKeyName[0] == '{' && szKeyName[37] == '}')
901 szKeyName[37] = 0;
903 TRACE("Guid: %p\n", &szKeyName[1]);
905 UuidFromStringW(&szKeyName[1],
906 &ClassGuidList[dwGuidListIndex]);
909 dwGuidListIndex++;
913 RegCloseKey(hClassKey);
916 if (lError != ERROR_SUCCESS)
917 break;
920 RegCloseKey(hClassesKey);
922 if (RequiredSize != NULL)
923 *RequiredSize = dwGuidListIndex;
925 if (ClassGuidListSize < dwGuidListIndex)
927 SetLastError(ERROR_INSUFFICIENT_BUFFER);
928 return FALSE;
931 return TRUE;
934 /***********************************************************************
935 * SetupDiClassNameFromGuidA (SETUPAPI.@)
937 BOOL WINAPI SetupDiClassNameFromGuidA(
938 const GUID* ClassGuid,
939 PSTR ClassName,
940 DWORD ClassNameSize,
941 PDWORD RequiredSize)
943 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
944 ClassNameSize, RequiredSize,
945 NULL, NULL);
948 /***********************************************************************
949 * SetupDiClassNameFromGuidW (SETUPAPI.@)
951 BOOL WINAPI SetupDiClassNameFromGuidW(
952 const GUID* ClassGuid,
953 PWSTR ClassName,
954 DWORD ClassNameSize,
955 PDWORD RequiredSize)
957 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
958 ClassNameSize, RequiredSize,
959 NULL, NULL);
962 /***********************************************************************
963 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
965 BOOL WINAPI SetupDiClassNameFromGuidExA(
966 const GUID* ClassGuid,
967 PSTR ClassName,
968 DWORD ClassNameSize,
969 PDWORD RequiredSize,
970 PCSTR MachineName,
971 PVOID Reserved)
973 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
974 LPWSTR MachineNameW = NULL;
975 BOOL ret;
977 if (MachineName)
978 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
979 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
980 NULL, MachineNameW, Reserved);
981 if (ret)
983 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
984 ClassNameSize, NULL, NULL);
986 if (!ClassNameSize && RequiredSize)
987 *RequiredSize = len;
989 MyFree(MachineNameW);
990 return ret;
993 /***********************************************************************
994 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
996 BOOL WINAPI SetupDiClassNameFromGuidExW(
997 const GUID* ClassGuid,
998 PWSTR ClassName,
999 DWORD ClassNameSize,
1000 PDWORD RequiredSize,
1001 PCWSTR MachineName,
1002 PVOID Reserved)
1004 HKEY hKey;
1005 DWORD dwLength;
1007 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1008 KEY_ALL_ACCESS,
1009 DIOCR_INSTALLER,
1010 MachineName,
1011 Reserved);
1012 if (hKey == INVALID_HANDLE_VALUE)
1014 return FALSE;
1017 if (RequiredSize != NULL)
1019 dwLength = 0;
1020 if (RegQueryValueExW(hKey,
1021 Class,
1022 NULL,
1023 NULL,
1024 NULL,
1025 &dwLength))
1027 RegCloseKey(hKey);
1028 return FALSE;
1031 *RequiredSize = dwLength / sizeof(WCHAR);
1034 dwLength = ClassNameSize * sizeof(WCHAR);
1035 if (RegQueryValueExW(hKey,
1036 Class,
1037 NULL,
1038 NULL,
1039 (LPBYTE)ClassName,
1040 &dwLength))
1042 RegCloseKey(hKey);
1043 return FALSE;
1046 RegCloseKey(hKey);
1048 return TRUE;
1051 /***********************************************************************
1052 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1054 HDEVINFO WINAPI
1055 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1056 HWND hwndParent)
1058 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1061 /***********************************************************************
1062 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1064 HDEVINFO WINAPI
1065 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1066 HWND hwndParent,
1067 PCSTR MachineName,
1068 PVOID Reserved)
1070 LPWSTR MachineNameW = NULL;
1071 HDEVINFO hDevInfo;
1073 TRACE("\n");
1075 if (MachineName)
1077 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1078 if (MachineNameW == NULL)
1079 return (HDEVINFO)INVALID_HANDLE_VALUE;
1082 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1083 MachineNameW, Reserved);
1085 MyFree(MachineNameW);
1087 return hDevInfo;
1090 /***********************************************************************
1091 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1093 * Create an empty DeviceInfoSet list.
1095 * PARAMS
1096 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1097 * with this list.
1098 * hwndParent [I] hwnd needed for interface related actions.
1099 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1100 * local registry will be used.
1101 * Reserved [I] must be NULL
1103 * RETURNS
1104 * Success: empty list.
1105 * Failure: INVALID_HANDLE_VALUE.
1107 HDEVINFO WINAPI
1108 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1109 HWND hwndParent,
1110 PCWSTR MachineName,
1111 PVOID Reserved)
1113 struct DeviceInfoSet *list = NULL;
1114 DWORD size = sizeof(struct DeviceInfoSet);
1116 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1117 debugstr_w(MachineName), Reserved);
1119 if (MachineName != NULL)
1121 FIXME("remote support is not implemented\n");
1122 SetLastError(ERROR_INVALID_MACHINENAME);
1123 return (HDEVINFO)INVALID_HANDLE_VALUE;
1126 if (Reserved != NULL)
1128 SetLastError(ERROR_INVALID_PARAMETER);
1129 return (HDEVINFO)INVALID_HANDLE_VALUE;
1132 list = HeapAlloc(GetProcessHeap(), 0, size);
1133 if (!list)
1135 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1136 return (HDEVINFO)INVALID_HANDLE_VALUE;
1139 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1140 list->hwndParent = hwndParent;
1141 memcpy(&list->ClassGuid,
1142 ClassGuid ? ClassGuid : &GUID_NULL,
1143 sizeof(list->ClassGuid));
1144 list->cDevices = 0;
1145 list->devices = NULL;
1147 return (HDEVINFO)list;
1150 /***********************************************************************
1151 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1153 HKEY WINAPI SetupDiCreateDevRegKeyA(
1154 HDEVINFO DeviceInfoSet,
1155 PSP_DEVINFO_DATA DeviceInfoData,
1156 DWORD Scope,
1157 DWORD HwProfile,
1158 DWORD KeyType,
1159 HINF InfHandle,
1160 PCSTR InfSectionName)
1162 PWSTR InfSectionNameW = NULL;
1163 HKEY key;
1165 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1166 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1168 if (InfHandle)
1170 if (!InfSectionName)
1172 SetLastError(ERROR_INVALID_PARAMETER);
1173 return INVALID_HANDLE_VALUE;
1175 else
1177 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1178 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1181 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1182 HwProfile, KeyType, InfHandle, InfSectionNameW);
1183 MyFree(InfSectionNameW);
1184 return key;
1187 /***********************************************************************
1188 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1190 HKEY WINAPI SetupDiCreateDevRegKeyW(
1191 HDEVINFO DeviceInfoSet,
1192 PSP_DEVINFO_DATA DeviceInfoData,
1193 DWORD Scope,
1194 DWORD HwProfile,
1195 DWORD KeyType,
1196 HINF InfHandle,
1197 PCWSTR InfSectionName)
1199 FIXME("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1200 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1201 return INVALID_HANDLE_VALUE;
1204 /***********************************************************************
1205 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1207 BOOL WINAPI SetupDiCreateDeviceInfoA(
1208 HDEVINFO DeviceInfoSet,
1209 PCSTR DeviceName,
1210 CONST GUID *ClassGuid,
1211 PCSTR DeviceDescription,
1212 HWND hwndParent,
1213 DWORD CreationFlags,
1214 PSP_DEVINFO_DATA DeviceInfoData)
1216 BOOL ret = FALSE;
1217 LPWSTR DeviceNameW = NULL;
1218 LPWSTR DeviceDescriptionW = NULL;
1220 if (DeviceName)
1222 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1223 if (DeviceNameW == NULL) return FALSE;
1225 if (DeviceDescription)
1227 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1228 if (DeviceDescriptionW == NULL)
1230 MyFree(DeviceNameW);
1231 return FALSE;
1235 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1236 hwndParent, CreationFlags, DeviceInfoData);
1238 MyFree(DeviceNameW);
1239 MyFree(DeviceDescriptionW);
1241 return ret;
1244 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1246 LPCWSTR ptr;
1247 DWORD devNameLen = lstrlenW(devName), devInst = 0;
1248 BOOL valid = TRUE;
1250 TRACE("%s\n", debugstr_w(devName));
1251 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1253 if (isdigitW(*ptr))
1255 devInst *= 10;
1256 devInst |= *ptr - '0';
1257 ptr++;
1259 else
1260 valid = FALSE;
1262 TRACE("%d\n", valid ? devInst : 0xffffffff);
1263 return valid ? devInst : 0xffffffff;
1266 /***********************************************************************
1267 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1269 BOOL WINAPI SetupDiCreateDeviceInfoW(
1270 HDEVINFO DeviceInfoSet,
1271 PCWSTR DeviceName,
1272 CONST GUID *ClassGuid,
1273 PCWSTR DeviceDescription,
1274 HWND hwndParent,
1275 DWORD CreationFlags,
1276 PSP_DEVINFO_DATA DeviceInfoData)
1278 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1279 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1280 LPCWSTR instanceId = NULL;
1282 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1283 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1284 hwndParent, CreationFlags, DeviceInfoData);
1286 if (!DeviceName)
1288 SetLastError(ERROR_INVALID_DEVINST_NAME);
1289 return FALSE;
1291 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1293 SetLastError(ERROR_INVALID_HANDLE);
1294 return FALSE;
1296 if (!ClassGuid)
1298 SetLastError(ERROR_INVALID_PARAMETER);
1299 return FALSE;
1301 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1303 SetLastError(ERROR_INVALID_HANDLE);
1304 return FALSE;
1306 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1307 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1309 SetLastError(ERROR_CLASS_MISMATCH);
1310 return FALSE;
1312 if ((CreationFlags & DICD_GENERATE_ID))
1314 if (strchrW(DeviceName, '\\'))
1315 SetLastError(ERROR_INVALID_DEVINST_NAME);
1316 else
1318 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1319 '\\','%','0','4','d',0};
1320 DWORD devId;
1322 if (set->cDevices)
1324 DWORD i, highestDevID = 0;
1326 for (i = 0; i < set->cDevices; i++)
1328 struct DeviceInfo *devInfo =
1329 (struct DeviceInfo *)set->devices[i].Reserved;
1330 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1331 DWORD id;
1333 if (devName)
1334 devName++;
1335 else
1336 devName = devInfo->instanceId;
1337 id = SETUPDI_DevNameToDevID(devName);
1338 if (id != 0xffffffff && id > highestDevID)
1339 highestDevID = id;
1341 devId = highestDevID + 1;
1343 else
1344 devId = 0;
1345 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1346 instanceId = HeapAlloc(GetProcessHeap(), 0,
1347 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1348 if (instanceId)
1350 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1351 devId);
1352 allocatedInstanceId = TRUE;
1353 ret = TRUE;
1355 else
1356 ret = FALSE;
1359 else
1361 DWORD i;
1363 ret = TRUE;
1364 instanceId = DeviceName;
1365 for (i = 0; ret && i < set->cDevices; i++)
1367 struct DeviceInfo *devInfo =
1368 (struct DeviceInfo *)set->devices[i].Reserved;
1370 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1372 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1373 ret = FALSE;
1377 if (ret)
1379 SP_DEVINFO_DATA *dev = NULL;
1381 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1382 instanceId, TRUE, &dev);
1383 if (ret)
1385 if (DeviceDescription)
1386 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1387 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1388 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1389 if (DeviceInfoData)
1391 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1393 SetLastError(ERROR_INVALID_USER_BUFFER);
1394 ret = FALSE;
1396 else
1397 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1401 if (allocatedInstanceId)
1402 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1404 return ret;
1407 /***********************************************************************
1408 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1410 BOOL WINAPI SetupDiRegisterDeviceInfo(
1411 HDEVINFO DeviceInfoSet,
1412 PSP_DEVINFO_DATA DeviceInfoData,
1413 DWORD Flags,
1414 PSP_DETSIG_CMPPROC CompareProc,
1415 PVOID CompareContext,
1416 PSP_DEVINFO_DATA DupDeviceInfoData)
1418 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1419 struct DeviceInfo *devInfo;
1421 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1422 CompareProc, CompareContext, DupDeviceInfoData);
1424 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1426 SetLastError(ERROR_INVALID_HANDLE);
1427 return FALSE;
1429 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1431 SetLastError(ERROR_INVALID_HANDLE);
1432 return FALSE;
1434 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1435 || !DeviceInfoData->Reserved)
1437 SetLastError(ERROR_INVALID_PARAMETER);
1438 return FALSE;
1440 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1441 if (devInfo->set != set)
1443 SetLastError(ERROR_INVALID_PARAMETER);
1444 return FALSE;
1446 if (devInfo->phantom)
1448 devInfo->phantom = FALSE;
1449 RegDeleteValueW(devInfo->key, Phantom);
1451 return TRUE;
1454 /***********************************************************************
1455 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1457 BOOL WINAPI SetupDiEnumDeviceInfo(
1458 HDEVINFO devinfo,
1459 DWORD index,
1460 PSP_DEVINFO_DATA info)
1462 BOOL ret = FALSE;
1464 TRACE("%p %d %p\n", devinfo, index, info);
1466 if(info==NULL)
1468 SetLastError(ERROR_INVALID_PARAMETER);
1469 return FALSE;
1471 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1473 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1474 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1476 if (index < list->cDevices)
1478 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1480 memcpy(info, &list->devices[index], info->cbSize);
1481 ret = TRUE;
1483 else
1484 SetLastError(ERROR_INVALID_USER_BUFFER);
1486 else
1487 SetLastError(ERROR_NO_MORE_ITEMS);
1489 else
1490 SetLastError(ERROR_INVALID_HANDLE);
1492 else
1493 SetLastError(ERROR_INVALID_HANDLE);
1494 return ret;
1497 /***********************************************************************
1498 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1500 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1501 HDEVINFO DeviceInfoSet,
1502 PSP_DEVINFO_DATA DeviceInfoData,
1503 PSTR DeviceInstanceId,
1504 DWORD DeviceInstanceIdSize,
1505 PDWORD RequiredSize)
1507 BOOL ret = FALSE;
1508 DWORD size;
1509 PWSTR instanceId;
1511 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1512 DeviceInstanceIdSize, RequiredSize);
1514 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1515 DeviceInfoData,
1516 NULL,
1518 &size);
1519 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1520 return FALSE;
1521 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1522 if (instanceId)
1524 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1525 DeviceInfoData,
1526 instanceId,
1527 size,
1528 &size);
1529 if (ret)
1531 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1532 DeviceInstanceId,
1533 DeviceInstanceIdSize, NULL, NULL);
1535 if (!len)
1536 ret = FALSE;
1537 else
1539 if (len > DeviceInstanceIdSize)
1541 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1542 ret = FALSE;
1544 if (RequiredSize)
1545 *RequiredSize = len;
1548 HeapFree(GetProcessHeap(), 0, instanceId);
1550 return ret;
1553 /***********************************************************************
1554 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1556 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1557 HDEVINFO DeviceInfoSet,
1558 PSP_DEVINFO_DATA DeviceInfoData,
1559 PWSTR DeviceInstanceId,
1560 DWORD DeviceInstanceIdSize,
1561 PDWORD RequiredSize)
1563 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1564 struct DeviceInfo *devInfo;
1566 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1567 DeviceInstanceIdSize, RequiredSize);
1569 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1571 SetLastError(ERROR_INVALID_HANDLE);
1572 return FALSE;
1574 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1576 SetLastError(ERROR_INVALID_HANDLE);
1577 return FALSE;
1579 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1580 || !DeviceInfoData->Reserved)
1582 SetLastError(ERROR_INVALID_PARAMETER);
1583 return FALSE;
1585 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1586 if (devInfo->set != set)
1588 SetLastError(ERROR_INVALID_PARAMETER);
1589 return FALSE;
1591 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1592 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1594 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1595 if (RequiredSize)
1596 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1597 return FALSE;
1599 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1600 if (RequiredSize)
1601 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1602 return TRUE;
1605 /***********************************************************************
1606 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1608 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1609 HINF InfHandle,
1610 PCSTR InfSectionName,
1611 PSTR InfSectionWithExt,
1612 DWORD InfSectionWithExtSize,
1613 PDWORD RequiredSize,
1614 PSTR *Extension)
1616 FIXME("\n");
1617 return FALSE;
1620 /***********************************************************************
1621 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1623 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1624 HINF InfHandle,
1625 PCWSTR InfSectionName,
1626 PWSTR InfSectionWithExt,
1627 DWORD InfSectionWithExtSize,
1628 PDWORD RequiredSize,
1629 PWSTR *Extension)
1631 WCHAR szBuffer[MAX_PATH];
1632 DWORD dwLength;
1633 DWORD dwFullLength;
1634 LONG lLineCount = -1;
1636 lstrcpyW(szBuffer, InfSectionName);
1637 dwLength = lstrlenW(szBuffer);
1639 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1641 /* Test section name with '.NTx86' extension */
1642 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1643 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1645 if (lLineCount == -1)
1647 /* Test section name with '.NT' extension */
1648 lstrcpyW(&szBuffer[dwLength], NtExtension);
1649 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1652 else
1654 /* Test section name with '.Win' extension */
1655 lstrcpyW(&szBuffer[dwLength], WinExtension);
1656 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1659 if (lLineCount == -1)
1661 /* Test section name without extension */
1662 szBuffer[dwLength] = 0;
1663 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1666 if (lLineCount == -1)
1668 SetLastError(ERROR_INVALID_PARAMETER);
1669 return FALSE;
1672 dwFullLength = lstrlenW(szBuffer);
1674 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1676 if (InfSectionWithExtSize < (dwFullLength + 1))
1678 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1679 return FALSE;
1682 lstrcpyW(InfSectionWithExt, szBuffer);
1683 if (Extension != NULL)
1685 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1689 if (RequiredSize != NULL)
1691 *RequiredSize = dwFullLength + 1;
1694 return TRUE;
1697 /***********************************************************************
1698 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1700 BOOL WINAPI SetupDiGetClassDescriptionA(
1701 const GUID* ClassGuid,
1702 PSTR ClassDescription,
1703 DWORD ClassDescriptionSize,
1704 PDWORD RequiredSize)
1706 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1707 ClassDescriptionSize,
1708 RequiredSize, NULL, NULL);
1711 /***********************************************************************
1712 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1714 BOOL WINAPI SetupDiGetClassDescriptionW(
1715 const GUID* ClassGuid,
1716 PWSTR ClassDescription,
1717 DWORD ClassDescriptionSize,
1718 PDWORD RequiredSize)
1720 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1721 ClassDescriptionSize,
1722 RequiredSize, NULL, NULL);
1725 /***********************************************************************
1726 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1728 BOOL WINAPI SetupDiGetClassDescriptionExA(
1729 const GUID* ClassGuid,
1730 PSTR ClassDescription,
1731 DWORD ClassDescriptionSize,
1732 PDWORD RequiredSize,
1733 PCSTR MachineName,
1734 PVOID Reserved)
1736 HKEY hKey;
1737 DWORD dwLength;
1738 BOOL ret;
1740 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1741 KEY_ALL_ACCESS,
1742 DIOCR_INSTALLER,
1743 MachineName,
1744 Reserved);
1745 if (hKey == INVALID_HANDLE_VALUE)
1747 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1748 return FALSE;
1751 dwLength = ClassDescriptionSize;
1752 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1753 (LPBYTE)ClassDescription, &dwLength );
1754 if (RequiredSize) *RequiredSize = dwLength;
1755 RegCloseKey(hKey);
1756 return ret;
1759 /***********************************************************************
1760 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1762 BOOL WINAPI SetupDiGetClassDescriptionExW(
1763 const GUID* ClassGuid,
1764 PWSTR ClassDescription,
1765 DWORD ClassDescriptionSize,
1766 PDWORD RequiredSize,
1767 PCWSTR MachineName,
1768 PVOID Reserved)
1770 HKEY hKey;
1771 DWORD dwLength;
1772 BOOL ret;
1774 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1775 KEY_ALL_ACCESS,
1776 DIOCR_INSTALLER,
1777 MachineName,
1778 Reserved);
1779 if (hKey == INVALID_HANDLE_VALUE)
1781 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1782 return FALSE;
1785 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1786 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1787 (LPBYTE)ClassDescription, &dwLength );
1788 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1789 RegCloseKey(hKey);
1790 return ret;
1793 /***********************************************************************
1794 * SetupDiGetClassDevsA (SETUPAPI.@)
1796 HDEVINFO WINAPI SetupDiGetClassDevsA(
1797 CONST GUID *class,
1798 LPCSTR enumstr,
1799 HWND parent,
1800 DWORD flags)
1802 HDEVINFO ret;
1803 LPWSTR enumstrW = NULL;
1805 if (enumstr)
1807 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1808 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1809 if (!enumstrW)
1811 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1812 goto end;
1814 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1816 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
1817 NULL);
1818 HeapFree(GetProcessHeap(), 0, enumstrW);
1820 end:
1821 return ret;
1824 /***********************************************************************
1825 * SetupDiGetClassDevsExA (SETUPAPI.@)
1827 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1828 const GUID *class,
1829 PCSTR enumstr,
1830 HWND parent,
1831 DWORD flags,
1832 HDEVINFO deviceset,
1833 PCSTR machine,
1834 PVOID reserved)
1836 HDEVINFO ret;
1837 LPWSTR enumstrW = NULL, machineW = NULL;
1839 if (enumstr)
1841 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1842 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1843 if (!enumstrW)
1845 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1846 goto end;
1848 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1850 if (machine)
1852 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1853 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1854 if (!machineW)
1856 HeapFree(GetProcessHeap(), 0, enumstrW);
1857 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1858 goto end;
1860 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1862 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
1863 machineW, reserved);
1864 HeapFree(GetProcessHeap(), 0, enumstrW);
1865 HeapFree(GetProcessHeap(), 0, machineW);
1867 end:
1868 return ret;
1871 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
1872 const GUID *interface)
1874 DWORD i, len;
1875 WCHAR subKeyName[MAX_PATH];
1876 LONG l = ERROR_SUCCESS;
1878 for (i = 0; !l; i++)
1880 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1881 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1882 if (!l)
1884 HKEY subKey;
1885 SP_DEVICE_INTERFACE_DATA *iface = NULL;
1887 /* The subkey name is the reference string, with a '#' prepended */
1888 SETUPDI_AddInterfaceInstance(dev, interface, subKeyName + 1,
1889 &iface);
1890 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1891 if (!l)
1893 WCHAR symbolicLink[MAX_PATH];
1894 DWORD dataType;
1896 len = sizeof(symbolicLink);
1897 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
1898 (BYTE *)symbolicLink, &len);
1899 if (!l && dataType == REG_SZ)
1900 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
1901 RegCloseKey(subKey);
1905 /* FIXME: find and add all the device's interfaces to the device */
1908 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1909 HKEY key, const GUID *interface, LPCWSTR enumstr)
1911 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1912 DWORD i, len;
1913 WCHAR subKeyName[MAX_PATH];
1914 LONG l;
1915 HKEY enumKey = INVALID_HANDLE_VALUE;
1917 TRACE("%s\n", debugstr_w(enumstr));
1919 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1920 &enumKey, NULL);
1921 for (i = 0; !l; i++)
1923 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1924 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1925 if (!l)
1927 HKEY subKey;
1929 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1930 if (!l)
1932 WCHAR deviceInst[MAX_PATH * 3];
1933 DWORD dataType;
1935 len = sizeof(deviceInst);
1936 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1937 (BYTE *)deviceInst, &len);
1938 if (!l && dataType == REG_SZ)
1940 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1941 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1943 HKEY deviceKey;
1945 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1946 &deviceKey);
1947 if (!l)
1949 WCHAR deviceClassStr[40];
1951 len = sizeof(deviceClassStr);
1952 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1953 &dataType, (BYTE *)deviceClassStr, &len);
1954 if (!l && dataType == REG_SZ &&
1955 deviceClassStr[0] == '{' &&
1956 deviceClassStr[37] == '}')
1958 GUID deviceClass;
1959 SP_DEVINFO_DATA *dev;
1961 deviceClassStr[37] = 0;
1962 UuidFromStringW(&deviceClassStr[1],
1963 &deviceClass);
1964 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
1965 0 /* FIXME: DevInst */, deviceInst,
1966 FALSE, &dev))
1967 SETUPDI_AddDeviceInterfaces(dev, subKey,
1968 interface);
1970 RegCloseKey(deviceKey);
1974 RegCloseKey(subKey);
1978 if (enumKey != INVALID_HANDLE_VALUE)
1979 RegCloseKey(enumKey);
1982 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1983 const GUID *interface, LPCWSTR enumstr, DWORD flags)
1985 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1986 DIOCR_INTERFACE, NULL, NULL);
1988 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1989 debugstr_w(enumstr), flags);
1991 if (interfacesKey != INVALID_HANDLE_VALUE)
1993 if (flags & DIGCF_ALLCLASSES)
1995 DWORD i, len;
1996 WCHAR interfaceGuidStr[40];
1997 LONG l = ERROR_SUCCESS;
1999 for (i = 0; !l; i++)
2001 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
2002 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
2003 NULL, NULL, NULL, NULL);
2004 if (!l)
2006 if (interfaceGuidStr[0] == '{' &&
2007 interfaceGuidStr[37] == '}')
2009 HKEY interfaceKey;
2010 GUID interfaceGuid;
2012 interfaceGuidStr[37] = 0;
2013 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
2014 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
2015 KEY_READ, &interfaceKey);
2016 if (!l)
2018 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2019 interfaceKey, &interfaceGuid, enumstr);
2020 RegCloseKey(interfaceKey);
2026 else
2028 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
2029 * interface's key, so just pass that long
2031 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2032 interfacesKey, interface, enumstr);
2034 RegCloseKey(interfacesKey);
2038 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
2039 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
2041 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2042 DWORD i, len;
2043 WCHAR subKeyName[MAX_PATH];
2044 LONG l = ERROR_SUCCESS;
2046 TRACE("%s\n", debugstr_w(parent));
2048 for (i = 0; !l; i++)
2050 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2051 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2052 if (!l)
2054 HKEY subKey;
2056 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2057 if (!l)
2059 WCHAR classGuid[40];
2060 DWORD dataType;
2062 len = sizeof(classGuid);
2063 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
2064 (BYTE *)classGuid, &len);
2065 if (!l && dataType == REG_SZ)
2067 if (classGuid[0] == '{' && classGuid[37] == '}')
2069 GUID deviceClass;
2071 classGuid[37] = 0;
2072 UuidFromStringW(&classGuid[1], &deviceClass);
2073 if ((flags & DIGCF_ALLCLASSES) ||
2074 IsEqualGUID(class, &deviceClass))
2076 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
2077 LPWSTR instanceId;
2079 instanceId = HeapAlloc(GetProcessHeap(), 0,
2080 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
2081 * sizeof(WCHAR));
2082 if (instanceId)
2084 SP_DEVINFO_DATA *dev;
2086 sprintfW(instanceId, fmt, parent, subKeyName);
2087 SETUPDI_AddDeviceToSet(set, &deviceClass,
2088 0 /* FIXME: DevInst */, instanceId,
2089 FALSE, &dev);
2090 HeapFree(GetProcessHeap(), 0, instanceId);
2095 RegCloseKey(subKey);
2101 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
2102 LPCWSTR enumstr, DWORD flags)
2104 HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
2105 DIOCR_INSTALLER, NULL, NULL);
2107 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
2108 debugstr_w(enumstr), flags);
2110 if (classesKey != INVALID_HANDLE_VALUE)
2112 if (enumstr)
2114 HKEY enumKey;
2115 LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
2116 &enumKey);
2118 if (!l)
2120 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2121 enumKey, class, flags);
2122 RegCloseKey(enumKey);
2125 else
2127 DWORD i, len;
2128 WCHAR subKeyName[MAX_PATH];
2129 LONG l = ERROR_SUCCESS;
2131 for (i = 0; !l; i++)
2133 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2134 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
2135 NULL, NULL, NULL);
2136 if (!l)
2138 HKEY subKey;
2140 l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
2141 &subKey);
2142 if (!l)
2144 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2145 subKeyName, subKey, class, flags);
2146 RegCloseKey(subKey);
2151 RegCloseKey(classesKey);
2155 /***********************************************************************
2156 * SetupDiGetClassDevsW (SETUPAPI.@)
2158 HDEVINFO WINAPI SetupDiGetClassDevsW(
2159 CONST GUID *class,
2160 LPCWSTR enumstr,
2161 HWND parent,
2162 DWORD flags)
2164 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2165 NULL);
2168 /***********************************************************************
2169 * SetupDiGetClassDevsExW (SETUPAPI.@)
2171 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2172 CONST GUID *class,
2173 PCWSTR enumstr,
2174 HWND parent,
2175 DWORD flags,
2176 HDEVINFO deviceset,
2177 PCWSTR machine,
2178 PVOID reserved)
2180 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2181 DIGCF_PROFILE;
2182 HDEVINFO set;
2184 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2185 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2186 reserved);
2188 if (!(flags & DIGCF_ALLCLASSES) && !class)
2190 SetLastError(ERROR_INVALID_PARAMETER);
2191 return NULL;
2193 if (flags & unsupportedFlags)
2194 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2195 if (deviceset)
2196 set = deviceset;
2197 else
2198 set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
2199 if (set)
2201 if (machine)
2202 FIXME("%s: unimplemented for remote machines\n",
2203 debugstr_w(machine));
2204 else if (flags & DIGCF_DEVICEINTERFACE)
2205 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2206 else
2207 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2209 return set;
2212 /***********************************************************************
2213 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2215 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2216 HDEVINFO DeviceInfoSet,
2217 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2219 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2221 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2223 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2225 SetLastError(ERROR_INVALID_HANDLE);
2226 return FALSE;
2228 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2230 SetLastError(ERROR_INVALID_HANDLE);
2231 return FALSE;
2233 if (!DevInfoData ||
2234 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2236 SetLastError(ERROR_INVALID_PARAMETER);
2237 return FALSE;
2239 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2240 DevInfoData->RemoteMachineHandle = NULL;
2241 DevInfoData->RemoteMachineName[0] = '\0';
2242 return TRUE;
2245 /***********************************************************************
2246 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2248 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2249 HDEVINFO DeviceInfoSet,
2250 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2252 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2254 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2256 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2258 SetLastError(ERROR_INVALID_HANDLE);
2259 return FALSE;
2261 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2263 SetLastError(ERROR_INVALID_HANDLE);
2264 return FALSE;
2266 if (!DevInfoData ||
2267 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2269 SetLastError(ERROR_INVALID_PARAMETER);
2270 return FALSE;
2272 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2273 DevInfoData->RemoteMachineHandle = NULL;
2274 DevInfoData->RemoteMachineName[0] = '\0';
2275 return TRUE;
2278 /***********************************************************************
2279 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2281 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2282 HDEVINFO DeviceInfoSet,
2283 PSP_DEVINFO_DATA DeviceInfoData,
2284 const GUID *InterfaceClassGuid,
2285 PCSTR ReferenceString,
2286 DWORD CreationFlags,
2287 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2289 BOOL ret;
2290 LPWSTR ReferenceStringW = NULL;
2292 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2293 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2294 CreationFlags, DeviceInterfaceData);
2296 if (ReferenceString)
2298 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2299 if (ReferenceStringW == NULL) return FALSE;
2302 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2303 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2304 DeviceInterfaceData);
2306 MyFree(ReferenceStringW);
2308 return ret;
2311 /***********************************************************************
2312 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2314 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2315 HDEVINFO DeviceInfoSet,
2316 PSP_DEVINFO_DATA DeviceInfoData,
2317 const GUID *InterfaceClassGuid,
2318 PCWSTR ReferenceString,
2319 DWORD CreationFlags,
2320 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2322 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2323 struct DeviceInfo *devInfo;
2324 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2325 BOOL ret;
2327 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2328 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2329 CreationFlags, DeviceInterfaceData);
2331 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2333 SetLastError(ERROR_INVALID_HANDLE);
2334 return FALSE;
2336 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2338 SetLastError(ERROR_INVALID_HANDLE);
2339 return FALSE;
2341 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2342 || !DeviceInfoData->Reserved)
2344 SetLastError(ERROR_INVALID_PARAMETER);
2345 return FALSE;
2347 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2348 if (devInfo->set != set)
2350 SetLastError(ERROR_INVALID_PARAMETER);
2351 return FALSE;
2353 if (!InterfaceClassGuid)
2355 SetLastError(ERROR_INVALID_USER_BUFFER);
2356 return FALSE;
2358 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2359 ReferenceString, &iface)))
2361 if (DeviceInterfaceData)
2363 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2365 SetLastError(ERROR_INVALID_USER_BUFFER);
2366 ret = FALSE;
2368 else
2369 memcpy(DeviceInterfaceData, iface, sizeof(*iface));
2372 return ret;
2375 /***********************************************************************
2376 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2378 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2379 HDEVINFO DeviceInfoSet,
2380 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2381 DWORD Reserved,
2382 REGSAM samDesired,
2383 HINF InfHandle,
2384 PCSTR InfSectionName)
2386 HKEY key;
2387 PWSTR InfSectionNameW = NULL;
2389 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2390 samDesired, InfHandle, InfSectionName);
2391 if (InfHandle)
2393 if (!InfSectionName)
2395 SetLastError(ERROR_INVALID_PARAMETER);
2396 return INVALID_HANDLE_VALUE;
2398 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2399 if (!InfSectionNameW)
2400 return INVALID_HANDLE_VALUE;
2402 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2403 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2404 InfSectionNameW);
2405 MyFree(InfSectionNameW);
2406 return key;
2409 static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo)
2411 static const WCHAR hash[] = {'#',0};
2412 PWSTR instancePath = NULL;
2414 if (ifaceInfo->referenceString)
2416 instancePath = HeapAlloc(GetProcessHeap(), 0,
2417 (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR));
2418 if (instancePath)
2420 lstrcpyW(instancePath, hash);
2421 lstrcatW(instancePath, ifaceInfo->referenceString);
2423 else
2424 SetLastError(ERROR_OUTOFMEMORY);
2426 else
2428 instancePath = HeapAlloc(GetProcessHeap(), 0,
2429 (lstrlenW(hash) + 1) * sizeof(WCHAR));
2430 if (instancePath)
2431 lstrcpyW(instancePath, hash);
2433 return instancePath;
2436 /***********************************************************************
2437 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2439 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2440 HDEVINFO DeviceInfoSet,
2441 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2442 DWORD Reserved,
2443 REGSAM samDesired,
2444 HINF InfHandle,
2445 PCWSTR InfSectionName)
2447 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2448 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2449 LONG l;
2451 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2452 samDesired, InfHandle, InfSectionName);
2454 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2455 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2457 SetLastError(ERROR_INVALID_HANDLE);
2458 return INVALID_HANDLE_VALUE;
2460 if (!DeviceInterfaceData ||
2461 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2462 !DeviceInterfaceData->Reserved)
2464 SetLastError(ERROR_INVALID_PARAMETER);
2465 return INVALID_HANDLE_VALUE;
2467 if (InfHandle && !InfSectionName)
2469 SetLastError(ERROR_INVALID_PARAMETER);
2470 return INVALID_HANDLE_VALUE;
2472 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2473 samDesired, NULL, &interfacesKey, NULL)))
2475 HKEY parent;
2476 WCHAR bracedGuidString[39];
2478 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2479 bracedGuidString);
2480 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2481 samDesired, NULL, &parent, NULL)))
2483 struct InterfaceInfo *ifaceInfo =
2484 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2485 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2487 if (instancePath)
2489 LONG l;
2491 l = RegCreateKeyExW(parent, instancePath, 0, NULL, 0,
2492 samDesired, NULL, &key, NULL);
2493 if (l)
2495 SetLastError(l);
2496 key = INVALID_HANDLE_VALUE;
2498 else if (InfHandle)
2499 FIXME("INF section installation unsupported\n");
2501 HeapFree(GetProcessHeap(), 0, instancePath);
2502 RegCloseKey(parent);
2504 else
2505 SetLastError(l);
2506 RegCloseKey(interfacesKey);
2508 else
2509 SetLastError(l);
2510 return key;
2513 /***********************************************************************
2514 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2516 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2517 HDEVINFO DeviceInfoSet,
2518 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2519 DWORD Reserved)
2521 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2522 HKEY parent;
2523 BOOL ret = FALSE;
2525 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2527 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2528 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2530 SetLastError(ERROR_INVALID_HANDLE);
2531 return FALSE;
2533 if (!DeviceInterfaceData ||
2534 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2535 !DeviceInterfaceData->Reserved)
2537 SetLastError(ERROR_INVALID_PARAMETER);
2538 return FALSE;
2540 parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid,
2541 KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
2542 if (parent != INVALID_HANDLE_VALUE)
2544 struct InterfaceInfo *ifaceInfo =
2545 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2546 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2548 if (instancePath)
2550 LONG l = RegDeleteKeyW(parent, instancePath);
2552 if (l)
2553 SetLastError(l);
2554 else
2555 ret = TRUE;
2556 HeapFree(GetProcessHeap(), 0, instancePath);
2558 RegCloseKey(parent);
2560 return ret;
2563 /***********************************************************************
2564 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2566 * PARAMS
2567 * DeviceInfoSet [I] Set of devices from which to enumerate
2568 * interfaces
2569 * DeviceInfoData [I] (Optional) If specified, a specific device
2570 * instance from which to enumerate interfaces.
2571 * If it isn't specified, all interfaces for all
2572 * devices in the set are enumerated.
2573 * InterfaceClassGuid [I] The interface class to enumerate.
2574 * MemberIndex [I] An index of the interface instance to enumerate.
2575 * A caller should start with MemberIndex set to 0,
2576 * and continue until the function fails with
2577 * ERROR_NO_MORE_ITEMS.
2578 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2579 * member must be set to
2580 * sizeof(SP_DEVICE_INTERFACE_DATA).
2582 * RETURNS
2583 * Success: non-zero value.
2584 * Failure: FALSE. Call GetLastError() for more info.
2586 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2587 HDEVINFO DeviceInfoSet,
2588 PSP_DEVINFO_DATA DeviceInfoData,
2589 CONST GUID * InterfaceClassGuid,
2590 DWORD MemberIndex,
2591 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2593 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2594 BOOL ret = FALSE;
2596 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2597 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2599 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2600 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2602 SetLastError(ERROR_INVALID_HANDLE);
2603 return FALSE;
2605 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2606 !DeviceInfoData->Reserved))
2608 SetLastError(ERROR_INVALID_PARAMETER);
2609 return FALSE;
2611 if (!DeviceInterfaceData ||
2612 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2614 SetLastError(ERROR_INVALID_PARAMETER);
2615 return FALSE;
2617 if (DeviceInfoData)
2619 struct DeviceInfo *devInfo =
2620 (struct DeviceInfo *)DeviceInfoData->Reserved;
2621 struct InterfaceInstances *iface;
2623 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2625 if (MemberIndex < iface->cInstances)
2626 memcpy(DeviceInterfaceData, &iface->instances[MemberIndex],
2627 sizeof(SP_DEVICE_INTERFACE_DATA));
2628 else
2630 SetLastError(ERROR_NO_MORE_ITEMS);
2631 ret = FALSE;
2634 else
2635 SetLastError(ERROR_NO_MORE_ITEMS);
2637 else
2639 DWORD i, cEnumerated = 0;
2640 BOOL found = FALSE;
2642 for (i = 0; !found && cEnumerated < MemberIndex + 1 &&
2643 i < set->cDevices; i++)
2645 struct DeviceInfo *devInfo =
2646 (struct DeviceInfo *)set->devices[i].Reserved;
2647 struct InterfaceInstances *iface;
2649 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2651 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2652 cEnumerated += iface->cInstances;
2653 else
2655 DWORD instanceIndex = MemberIndex - cEnumerated;
2657 memcpy(DeviceInterfaceData,
2658 &iface->instances[instanceIndex],
2659 sizeof(SP_DEVICE_INTERFACE_DATA));
2660 cEnumerated += instanceIndex + 1;
2661 found = TRUE;
2662 ret = TRUE;
2666 if (!found)
2667 SetLastError(ERROR_NO_MORE_ITEMS);
2669 return ret;
2672 /***********************************************************************
2673 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2675 * Destroy a DeviceInfoList and free all used memory of the list.
2677 * PARAMS
2678 * devinfo [I] DeviceInfoList pointer to list to destroy
2680 * RETURNS
2681 * Success: non zero value.
2682 * Failure: zero value.
2684 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2686 BOOL ret = FALSE;
2688 TRACE("%p\n", devinfo);
2689 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2691 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2693 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2695 DWORD i;
2697 for (i = 0; i < list->cDevices; i++)
2698 SETUPDI_FreeDeviceInfo(
2699 (struct DeviceInfo *)list->devices[i].Reserved);
2700 HeapFree(GetProcessHeap(), 0, list->devices);
2701 HeapFree(GetProcessHeap(), 0, list);
2702 ret = TRUE;
2706 if (ret == FALSE)
2707 SetLastError(ERROR_INVALID_HANDLE);
2709 return ret;
2712 /***********************************************************************
2713 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2715 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2716 HDEVINFO DeviceInfoSet,
2717 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2718 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2719 DWORD DeviceInterfaceDetailDataSize,
2720 PDWORD RequiredSize,
2721 PSP_DEVINFO_DATA DeviceInfoData)
2723 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2724 struct InterfaceInfo *info;
2725 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)
2726 + 1;
2727 BOOL ret = FALSE;
2729 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2730 DeviceInterfaceData, DeviceInterfaceDetailData,
2731 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2733 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2734 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2736 SetLastError(ERROR_INVALID_HANDLE);
2737 return FALSE;
2739 if (!DeviceInterfaceData ||
2740 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2741 !DeviceInterfaceData->Reserved)
2743 SetLastError(ERROR_INVALID_PARAMETER);
2744 return FALSE;
2746 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2747 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) ||
2748 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2750 SetLastError(ERROR_INVALID_USER_BUFFER);
2751 return FALSE;
2753 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2755 SetLastError(ERROR_INVALID_USER_BUFFER);
2756 return FALSE;
2758 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2759 if (info->symbolicLink)
2760 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2761 NULL, 0, NULL, NULL);
2762 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2764 if (info->symbolicLink)
2765 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2766 DeviceInterfaceDetailData->DevicePath,
2767 DeviceInterfaceDetailDataSize -
2768 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2769 NULL, NULL);
2770 else
2771 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2772 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2773 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2774 ret = TRUE;
2776 else
2778 if (RequiredSize)
2779 *RequiredSize = bytesNeeded;
2780 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2782 return ret;
2785 /***********************************************************************
2786 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2788 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2789 HDEVINFO DeviceInfoSet,
2790 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2791 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2792 DWORD DeviceInterfaceDetailDataSize,
2793 PDWORD RequiredSize,
2794 PSP_DEVINFO_DATA DeviceInfoData)
2796 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2797 struct InterfaceInfo *info;
2798 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2799 + sizeof(WCHAR); /* include NULL terminator */
2800 BOOL ret = FALSE;
2802 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2803 DeviceInterfaceData, DeviceInterfaceDetailData,
2804 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2806 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE ||
2807 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2809 SetLastError(ERROR_INVALID_HANDLE);
2810 return FALSE;
2812 if (!DeviceInterfaceData ||
2813 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2814 !DeviceInterfaceData->Reserved)
2816 SetLastError(ERROR_INVALID_PARAMETER);
2817 return FALSE;
2819 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2820 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2821 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2823 SetLastError(ERROR_INVALID_USER_BUFFER);
2824 return FALSE;
2826 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2828 SetLastError(ERROR_INVALID_USER_BUFFER);
2829 return FALSE;
2831 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2832 if (info->symbolicLink)
2833 bytesNeeded += lstrlenW(info->symbolicLink);
2834 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2836 if (info->symbolicLink)
2837 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
2838 else
2839 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2840 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2841 memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA));
2842 ret = TRUE;
2844 else
2846 if (RequiredSize)
2847 *RequiredSize = bytesNeeded;
2848 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2850 return ret;
2853 struct PropertyMapEntry
2855 DWORD regType;
2856 LPCSTR nameA;
2857 LPCWSTR nameW;
2860 static struct PropertyMapEntry PropertyMap[] = {
2861 { REG_SZ, "DeviceDesc", DeviceDesc },
2862 { REG_MULTI_SZ, "HardwareId", HardwareId },
2863 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
2864 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
2865 { REG_SZ, "Service", Service },
2866 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
2867 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
2868 { REG_SZ, "Class", Class },
2869 { REG_SZ, "ClassGUID", ClassGUID },
2870 { REG_SZ, "Driver", Driver },
2871 { REG_DWORD, "ConfigFlags", ConfigFlags },
2872 { REG_SZ, "Mfg", Mfg },
2873 { REG_SZ, "FriendlyName", FriendlyName },
2874 { REG_SZ, "LocationInformation", LocationInformation },
2875 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
2876 { REG_DWORD, "Capabilities", Capabilities },
2877 { REG_DWORD, "UINumber", UINumber },
2878 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
2879 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
2882 /***********************************************************************
2883 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2885 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2886 HDEVINFO DeviceInfoSet,
2887 PSP_DEVINFO_DATA DeviceInfoData,
2888 DWORD Property,
2889 PDWORD PropertyRegDataType,
2890 PBYTE PropertyBuffer,
2891 DWORD PropertyBufferSize,
2892 PDWORD RequiredSize)
2894 BOOL ret = FALSE;
2895 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2896 struct DeviceInfo *devInfo;
2898 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2899 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2900 RequiredSize);
2902 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2904 SetLastError(ERROR_INVALID_HANDLE);
2905 return FALSE;
2907 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2909 SetLastError(ERROR_INVALID_HANDLE);
2910 return FALSE;
2912 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2913 || !DeviceInfoData->Reserved)
2915 SetLastError(ERROR_INVALID_PARAMETER);
2916 return FALSE;
2918 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2919 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2920 && PropertyMap[Property].nameA)
2922 DWORD size = PropertyBufferSize;
2923 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
2924 NULL, PropertyRegDataType, PropertyBuffer, &size);
2926 if (RequiredSize)
2927 *RequiredSize = size;
2928 if (!l)
2929 ret = TRUE;
2930 else
2931 SetLastError(l);
2933 return ret;
2936 /***********************************************************************
2937 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2939 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2940 HDEVINFO DeviceInfoSet,
2941 PSP_DEVINFO_DATA DeviceInfoData,
2942 DWORD Property,
2943 PDWORD PropertyRegDataType,
2944 PBYTE PropertyBuffer,
2945 DWORD PropertyBufferSize,
2946 PDWORD RequiredSize)
2948 BOOL ret = FALSE;
2949 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2950 struct DeviceInfo *devInfo;
2952 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
2953 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2954 RequiredSize);
2956 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2958 SetLastError(ERROR_INVALID_HANDLE);
2959 return FALSE;
2961 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2963 SetLastError(ERROR_INVALID_HANDLE);
2964 return FALSE;
2966 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2967 || !DeviceInfoData->Reserved)
2969 SetLastError(ERROR_INVALID_PARAMETER);
2970 return FALSE;
2972 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2973 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2974 && PropertyMap[Property].nameW)
2976 DWORD size = PropertyBufferSize;
2977 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
2978 NULL, PropertyRegDataType, PropertyBuffer, &size);
2980 if (RequiredSize)
2981 *RequiredSize = size;
2982 if (!l)
2983 ret = TRUE;
2984 else
2985 SetLastError(l);
2987 return ret;
2990 /***********************************************************************
2991 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2993 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2994 HDEVINFO DeviceInfoSet,
2995 PSP_DEVINFO_DATA DeviceInfoData,
2996 DWORD Property,
2997 const BYTE *PropertyBuffer,
2998 DWORD PropertyBufferSize)
3000 BOOL ret = FALSE;
3001 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3002 struct DeviceInfo *devInfo;
3004 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3005 PropertyBuffer, PropertyBufferSize);
3007 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3009 SetLastError(ERROR_INVALID_HANDLE);
3010 return FALSE;
3012 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3014 SetLastError(ERROR_INVALID_HANDLE);
3015 return FALSE;
3017 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3018 || !DeviceInfoData->Reserved)
3020 SetLastError(ERROR_INVALID_PARAMETER);
3021 return FALSE;
3023 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3024 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3025 && PropertyMap[Property].nameA)
3027 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
3028 PropertyMap[Property].regType, PropertyBuffer,
3029 PropertyBufferSize);
3030 if (!l)
3031 ret = TRUE;
3032 else
3033 SetLastError(l);
3035 return ret;
3038 /***********************************************************************
3039 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3041 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3042 HDEVINFO DeviceInfoSet,
3043 PSP_DEVINFO_DATA DeviceInfoData,
3044 DWORD Property,
3045 const BYTE *PropertyBuffer,
3046 DWORD PropertyBufferSize)
3048 BOOL ret = FALSE;
3049 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3050 struct DeviceInfo *devInfo;
3052 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3053 PropertyBuffer, PropertyBufferSize);
3055 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3057 SetLastError(ERROR_INVALID_HANDLE);
3058 return FALSE;
3060 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3062 SetLastError(ERROR_INVALID_HANDLE);
3063 return FALSE;
3065 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3066 || !DeviceInfoData->Reserved)
3068 SetLastError(ERROR_INVALID_PARAMETER);
3069 return FALSE;
3071 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3072 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3073 && PropertyMap[Property].nameW)
3075 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
3076 PropertyMap[Property].regType, PropertyBuffer,
3077 PropertyBufferSize);
3078 if (!l)
3079 ret = TRUE;
3080 else
3081 SetLastError(l);
3083 return ret;
3086 /***********************************************************************
3087 * SetupDiInstallClassA (SETUPAPI.@)
3089 BOOL WINAPI SetupDiInstallClassA(
3090 HWND hwndParent,
3091 PCSTR InfFileName,
3092 DWORD Flags,
3093 HSPFILEQ FileQueue)
3095 UNICODE_STRING FileNameW;
3096 BOOL Result;
3098 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
3100 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3101 return FALSE;
3104 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
3106 RtlFreeUnicodeString(&FileNameW);
3108 return Result;
3111 static HKEY CreateClassKey(HINF hInf)
3113 static const WCHAR slash[] = { '\\',0 };
3114 WCHAR FullBuffer[MAX_PATH];
3115 WCHAR Buffer[MAX_PATH];
3116 DWORD RequiredSize;
3117 HKEY hClassKey;
3119 if (!SetupGetLineTextW(NULL,
3120 hInf,
3121 Version,
3122 ClassGUID,
3123 Buffer,
3124 MAX_PATH,
3125 &RequiredSize))
3127 return INVALID_HANDLE_VALUE;
3130 lstrcpyW(FullBuffer, ControlClass);
3131 lstrcatW(FullBuffer, slash);
3132 lstrcatW(FullBuffer, Buffer);
3134 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3135 FullBuffer,
3137 KEY_ALL_ACCESS,
3138 &hClassKey))
3140 if (!SetupGetLineTextW(NULL,
3141 hInf,
3142 Version,
3143 Class,
3144 Buffer,
3145 MAX_PATH,
3146 &RequiredSize))
3148 return INVALID_HANDLE_VALUE;
3151 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3152 FullBuffer,
3154 NULL,
3155 REG_OPTION_NON_VOLATILE,
3156 KEY_ALL_ACCESS,
3157 NULL,
3158 &hClassKey,
3159 NULL))
3161 return INVALID_HANDLE_VALUE;
3166 if (RegSetValueExW(hClassKey,
3167 Class,
3169 REG_SZ,
3170 (LPBYTE)Buffer,
3171 RequiredSize * sizeof(WCHAR)))
3173 RegCloseKey(hClassKey);
3174 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3175 FullBuffer);
3176 return INVALID_HANDLE_VALUE;
3179 return hClassKey;
3182 /***********************************************************************
3183 * SetupDiInstallClassW (SETUPAPI.@)
3185 BOOL WINAPI SetupDiInstallClassW(
3186 HWND hwndParent,
3187 PCWSTR InfFileName,
3188 DWORD Flags,
3189 HSPFILEQ FileQueue)
3191 WCHAR SectionName[MAX_PATH];
3192 DWORD SectionNameLength = 0;
3193 HINF hInf;
3194 BOOL bFileQueueCreated = FALSE;
3195 HKEY hClassKey;
3198 FIXME("\n");
3200 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
3202 SetLastError(ERROR_INVALID_PARAMETER);
3203 return FALSE;
3206 /* Open the .inf file */
3207 hInf = SetupOpenInfFileW(InfFileName,
3208 NULL,
3209 INF_STYLE_WIN4,
3210 NULL);
3211 if (hInf == INVALID_HANDLE_VALUE)
3214 return FALSE;
3217 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3218 hClassKey = CreateClassKey(hInf);
3219 if (hClassKey == INVALID_HANDLE_VALUE)
3221 SetupCloseInfFile(hInf);
3222 return FALSE;
3226 /* Try to append a layout file */
3227 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3229 /* Retrieve the actual section name */
3230 SetupDiGetActualSectionToInstallW(hInf,
3231 ClassInstall32,
3232 SectionName,
3233 MAX_PATH,
3234 &SectionNameLength,
3235 NULL);
3237 #if 0
3238 if (!(Flags & DI_NOVCP))
3240 FileQueue = SetupOpenFileQueue();
3241 if (FileQueue == INVALID_HANDLE_VALUE)
3243 SetupCloseInfFile(hInf);
3244 return FALSE;
3247 bFileQueueCreated = TRUE;
3250 #endif
3252 SetupInstallFromInfSectionW(NULL,
3253 hInf,
3254 SectionName,
3255 SPINST_COPYINF | SPINST_FILES | SPINST_REGISTRY,
3256 hClassKey,
3257 NULL,
3259 NULL,
3260 NULL,
3261 INVALID_HANDLE_VALUE,
3262 NULL);
3264 /* FIXME: More code! */
3266 if (bFileQueueCreated)
3267 SetupCloseFileQueue(FileQueue);
3269 SetupCloseInfFile(hInf);
3271 return TRUE;
3275 /***********************************************************************
3276 * SetupDiOpenClassRegKey (SETUPAPI.@)
3278 HKEY WINAPI SetupDiOpenClassRegKey(
3279 const GUID* ClassGuid,
3280 REGSAM samDesired)
3282 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3283 DIOCR_INSTALLER, NULL, NULL);
3287 /***********************************************************************
3288 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3290 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3291 const GUID* ClassGuid,
3292 REGSAM samDesired,
3293 DWORD Flags,
3294 PCSTR MachineName,
3295 PVOID Reserved)
3297 PWSTR MachineNameW = NULL;
3298 HKEY hKey;
3300 TRACE("\n");
3302 if (MachineName)
3304 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3305 if (MachineNameW == NULL)
3306 return INVALID_HANDLE_VALUE;
3309 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3310 Flags, MachineNameW, Reserved);
3312 MyFree(MachineNameW);
3314 return hKey;
3318 /***********************************************************************
3319 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3321 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3322 const GUID* ClassGuid,
3323 REGSAM samDesired,
3324 DWORD Flags,
3325 PCWSTR MachineName,
3326 PVOID Reserved)
3328 HKEY hClassesKey;
3329 HKEY key;
3330 LPCWSTR lpKeyName;
3331 LONG l;
3333 if (MachineName != NULL)
3335 FIXME("Remote access not supported yet!\n");
3336 return INVALID_HANDLE_VALUE;
3339 if (Flags == DIOCR_INSTALLER)
3341 lpKeyName = ControlClass;
3343 else if (Flags == DIOCR_INTERFACE)
3345 lpKeyName = DeviceClasses;
3347 else
3349 ERR("Invalid Flags parameter!\n");
3350 SetLastError(ERROR_INVALID_PARAMETER);
3351 return INVALID_HANDLE_VALUE;
3354 if (!ClassGuid)
3356 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3357 lpKeyName,
3359 samDesired,
3360 &hClassesKey)))
3362 SetLastError(l);
3363 hClassesKey = INVALID_HANDLE_VALUE;
3365 key = hClassesKey;
3367 else
3369 WCHAR bracedGuidString[39];
3371 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3373 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3374 lpKeyName,
3376 samDesired,
3377 &hClassesKey)))
3379 if ((l = RegOpenKeyExW(hClassesKey,
3380 bracedGuidString,
3382 samDesired,
3383 &key)))
3385 SetLastError(l);
3386 key = INVALID_HANDLE_VALUE;
3388 RegCloseKey(hClassesKey);
3390 else
3392 SetLastError(l);
3393 key = INVALID_HANDLE_VALUE;
3396 return key;
3399 /***********************************************************************
3400 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3402 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3403 HDEVINFO DeviceInfoSet,
3404 PCWSTR DevicePath,
3405 DWORD OpenFlags,
3406 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3408 FIXME("%p %s %08x %p\n",
3409 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3410 return FALSE;
3413 /***********************************************************************
3414 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3416 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3417 HDEVINFO DeviceInfoSet,
3418 PCSTR DevicePath,
3419 DWORD OpenFlags,
3420 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3422 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3423 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3424 return FALSE;
3427 /***********************************************************************
3428 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3430 BOOL WINAPI SetupDiSetClassInstallParamsA(
3431 HDEVINFO DeviceInfoSet,
3432 PSP_DEVINFO_DATA DeviceInfoData,
3433 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3434 DWORD ClassInstallParamsSize)
3436 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3437 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3438 return FALSE;
3441 /***********************************************************************
3442 * SetupDiCallClassInstaller (SETUPAPI.@)
3444 BOOL WINAPI SetupDiCallClassInstaller(
3445 DI_FUNCTION InstallFunction,
3446 HDEVINFO DeviceInfoSet,
3447 PSP_DEVINFO_DATA DeviceInfoData)
3449 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3450 return FALSE;
3453 /***********************************************************************
3454 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3456 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3457 HDEVINFO DeviceInfoSet,
3458 PSP_DEVINFO_DATA DeviceInfoData,
3459 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3461 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3462 return FALSE;
3465 /***********************************************************************
3466 * SetupDiOpenDevRegKey (SETUPAPI.@)
3468 HKEY WINAPI SetupDiOpenDevRegKey(
3469 HDEVINFO DeviceInfoSet,
3470 PSP_DEVINFO_DATA DeviceInfoData,
3471 DWORD Scope,
3472 DWORD HwProfile,
3473 DWORD KeyType,
3474 REGSAM samDesired)
3476 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3477 Scope, HwProfile, KeyType, samDesired);
3478 return INVALID_HANDLE_VALUE;