po: Update Lithuanian translation.
[wine.git] / dlls / setupapi / devinst.c
blob771fc70395e7e5726c269ecbb90e46f92bee51f2
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/heap.h"
37 #include "wine/list.h"
38 #include "wine/unicode.h"
39 #include "cfgmgr32.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 Chicago[] = {'$','C','h','i','c','a','g','o','$',0};
51 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
52 static const WCHAR Class[] = {'C','l','a','s','s',0};
53 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
54 static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
55 static const WCHAR NoInstallClass[] = {'N','o','I','n','s','t','a','l','l','C','l','a','s','s',0};
56 static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
57 static const WCHAR NtExtension[] = {'.','N','T',0};
58 static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
59 static const WCHAR Signature[] = {'S','i','g','n','a','t','u','r','e',0};
60 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
61 static const WCHAR WinExtension[] = {'.','W','i','n',0};
62 static const WCHAR WindowsNT[] = {'$','W','i','n','d','o','w','s',' ','N','T','$',0};
64 /* Registry key and value names */
65 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
66 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
67 'C','o','n','t','r','o','l','\\',
68 'C','l','a','s','s',0};
70 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
71 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
72 'C','o','n','t','r','o','l','\\',
73 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
74 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
75 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
76 'E','n','u','m',0};
77 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
78 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
79 static const WCHAR DeviceParameters[] = {'D','e','v','i','c','e',' ','P','a','r','a','m','e','t','e','r','s',0};
80 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
81 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
82 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
83 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
84 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
85 static const WCHAR Mfg[] = {'M','f','g',0};
86 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
87 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
88 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
89 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
90 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
91 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
92 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
93 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
94 static const WCHAR Control[] = {'C','o','n','t','r','o','l',0};
95 static const WCHAR Linked[] = {'L','i','n','k','e','d',0};
97 /* is used to identify if a DeviceInfoSet pointer is
98 valid or not */
99 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
101 struct DeviceInfoSet
103 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
104 GUID ClassGuid;
105 HWND hwndParent;
106 DWORD cDevices;
107 struct list devices;
110 struct device
112 struct DeviceInfoSet *set;
113 HKEY key;
114 BOOL phantom;
115 WCHAR *instanceId;
116 struct list interfaces;
117 GUID class;
118 DEVINST devnode;
119 struct list entry;
122 struct device_iface
124 WCHAR *refstr;
125 WCHAR *symlink;
126 struct device *device;
127 GUID class;
128 DWORD flags;
129 struct list entry;
132 static inline void copy_device_data(SP_DEVINFO_DATA *data, const struct device *device)
134 data->ClassGuid = device->class;
135 data->DevInst = device->devnode;
136 data->Reserved = (ULONG_PTR)device;
139 static inline void copy_device_iface_data(SP_DEVICE_INTERFACE_DATA *data,
140 const struct device_iface *iface)
142 data->InterfaceClassGuid = iface->class;
143 data->Flags = iface->flags;
144 data->Reserved = (ULONG_PTR)iface;
147 static struct device **devnode_table;
148 static unsigned int devnode_table_size;
150 static DEVINST alloc_devnode(struct device *device)
152 unsigned int i;
154 for (i = 0; i < devnode_table_size; ++i)
156 if (!devnode_table[i])
157 break;
160 if (i == devnode_table_size)
162 if (devnode_table)
164 devnode_table_size *= 2;
165 devnode_table = heap_realloc_zero(devnode_table,
166 devnode_table_size * sizeof(*devnode_table));
168 else
170 devnode_table_size = 256;
171 devnode_table = heap_alloc_zero(devnode_table_size * sizeof(*devnode_table));
175 devnode_table[i] = device;
176 return i;
179 static void free_devnode(DEVINST devnode)
181 devnode_table[devnode] = NULL;
184 static struct device *get_devnode_device(DEVINST devnode)
186 if (devnode < devnode_table_size)
187 return devnode_table[devnode];
189 WARN("device node %u not found\n", devnode);
190 return NULL;
193 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
195 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
196 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
197 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
198 '0','2','X','}',0};
200 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
201 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
202 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
205 static WCHAR *get_iface_key_path(struct device_iface *iface)
207 const WCHAR slashW[] = {'\\',0};
208 WCHAR *path, *ptr;
209 size_t len = strlenW(DeviceClasses) + 1 + 38 + 1 + strlenW(iface->symlink);
211 if (!(path = heap_alloc((len + 1) * sizeof(WCHAR))))
213 SetLastError(ERROR_OUTOFMEMORY);
214 return NULL;
217 strcpyW(path, DeviceClasses);
218 strcatW(path, slashW);
219 SETUPDI_GuidToString(&iface->class, path + strlenW(path));
220 strcatW(path, slashW);
221 ptr = path + strlenW(path);
222 strcatW(path, iface->symlink);
223 if (strlenW(iface->symlink) > 3)
224 ptr[0] = ptr[1] = ptr[3] = '#';
226 ptr = strchrW(ptr, '\\');
227 if (ptr) *ptr = 0;
229 return path;
232 static WCHAR *get_refstr_key_path(struct device_iface *iface)
234 const WCHAR hashW[] = {'#',0};
235 const WCHAR slashW[] = {'\\',0};
236 WCHAR *path, *ptr;
237 size_t len = strlenW(DeviceClasses) + 1 + 38 + 1 + strlenW(iface->symlink) + 1 + 1;
239 if (iface->refstr)
240 len += strlenW(iface->refstr);
242 if (!(path = heap_alloc((len + 1) * sizeof(WCHAR))))
244 SetLastError(ERROR_OUTOFMEMORY);
245 return NULL;
248 strcpyW(path, DeviceClasses);
249 strcatW(path, slashW);
250 SETUPDI_GuidToString(&iface->class, path + strlenW(path));
251 strcatW(path, slashW);
252 ptr = path + strlenW(path);
253 strcatW(path, iface->symlink);
254 if (strlenW(iface->symlink) > 3)
255 ptr[0] = ptr[1] = ptr[3] = '#';
257 ptr = strchrW(ptr, '\\');
258 if (ptr) *ptr = 0;
260 strcatW(path, slashW);
261 strcatW(path, hashW);
263 if (iface->refstr)
264 strcatW(path, iface->refstr);
266 return path;
269 static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
270 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
272 static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
273 WCHAR guidStr[39];
274 DWORD len;
275 LPWSTR ret;
277 SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
278 /* omit length of format specifiers, but include NULL terminator: */
279 len = lstrlenW(fmt) - 4 + 1;
280 len += lstrlenW(instanceId) + lstrlenW(guidStr);
281 if (ReferenceString && *ReferenceString)
283 /* space for a hash between string and reference string: */
284 len += lstrlenW(ReferenceString) + 1;
286 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
287 if (ret)
289 int printed = sprintfW(ret, fmt, instanceId, guidStr);
290 LPWSTR ptr;
292 /* replace '\\' with '#' after the "\\\\?\\" beginning */
293 for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
294 *ptr = '#';
295 if (ReferenceString && *ReferenceString)
297 ret[printed] = '\\';
298 lstrcpyW(ret + printed + 1, ReferenceString);
301 return ret;
304 static BOOL is_linked(HKEY key)
306 DWORD linked, type, size;
307 HKEY control_key;
308 BOOL ret = FALSE;
310 if (!RegOpenKeyW(key, Control, &control_key))
312 size = sizeof(DWORD);
313 if (!RegQueryValueExW(control_key, Linked, NULL, &type, (BYTE *)&linked, &size)
314 && type == REG_DWORD && linked)
315 ret = TRUE;
317 RegCloseKey(control_key);
320 return ret;
323 static struct device_iface *SETUPDI_CreateDeviceInterface(struct device *device,
324 const GUID *class, const WCHAR *refstr)
326 struct device_iface *iface = NULL;
327 WCHAR *refstr2 = NULL, *symlink = NULL, *path = NULL;
328 HKEY key = NULL;
329 LONG ret;
331 TRACE("%p %s %s\n", device, debugstr_guid(class), debugstr_w(refstr));
333 /* check if it already exists */
334 LIST_FOR_EACH_ENTRY(iface, &device->interfaces, struct device_iface, entry)
336 if (IsEqualGUID(&iface->class, class) && !lstrcmpiW(iface->refstr, refstr))
337 return iface;
340 iface = heap_alloc(sizeof(*iface));
341 symlink = SETUPDI_CreateSymbolicLinkPath(device->instanceId, class, refstr);
343 if (!iface || !symlink)
345 SetLastError(ERROR_OUTOFMEMORY);
346 goto err;
349 if (refstr && !(refstr2 = strdupW(refstr)))
351 SetLastError(ERROR_OUTOFMEMORY);
352 goto err;
354 iface->refstr = refstr2;
355 iface->symlink = symlink;
356 iface->device = device;
357 iface->class = *class;
358 iface->flags = 0;
360 if (!(path = get_iface_key_path(iface)))
362 SetLastError(ERROR_OUTOFMEMORY);
363 goto err;
366 if ((ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, path, &key)))
368 SetLastError(ret);
369 goto err;
371 RegSetValueExW(key, DeviceInstance, 0, REG_SZ, (BYTE *)device->instanceId,
372 lstrlenW(device->instanceId) * sizeof(WCHAR));
373 RegCloseKey(key);
374 heap_free(path);
376 if (!(path = get_refstr_key_path(iface)))
378 SetLastError(ERROR_OUTOFMEMORY);
379 goto err;
382 if ((ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, path, &key)))
384 SetLastError(ret);
385 goto err;
387 RegSetValueExW(key, SymbolicLink, 0, REG_SZ, (BYTE *)iface->symlink,
388 lstrlenW(iface->symlink) * sizeof(WCHAR));
390 if (is_linked(key))
391 iface->flags |= SPINT_ACTIVE;
393 RegCloseKey(key);
394 heap_free(path);
396 list_add_tail(&device->interfaces, &iface->entry);
397 return iface;
399 err:
400 heap_free(iface);
401 heap_free(refstr2);
402 heap_free(symlink);
403 heap_free(path);
404 return NULL;
407 static BOOL SETUPDI_SetInterfaceSymbolicLink(struct device_iface *iface,
408 const WCHAR *symlink)
410 heap_free(iface->symlink);
411 if ((iface->symlink = strdupW(symlink)))
412 return TRUE;
413 return FALSE;
416 static HKEY SETUPDI_CreateDevKey(struct device *device)
418 HKEY enumKey, key = INVALID_HANDLE_VALUE;
419 LONG l;
421 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
422 NULL, &enumKey, NULL);
423 if (!l)
425 RegCreateKeyExW(enumKey, device->instanceId, 0, NULL, 0,
426 KEY_READ | KEY_WRITE, NULL, &key, NULL);
427 RegCloseKey(enumKey);
429 return key;
432 static HKEY SETUPDI_CreateDrvKey(struct device *device)
434 static const WCHAR slash[] = { '\\',0 };
435 WCHAR classKeyPath[MAX_PATH];
436 HKEY classKey, key = INVALID_HANDLE_VALUE;
437 LONG l;
439 lstrcpyW(classKeyPath, ControlClass);
440 lstrcatW(classKeyPath, slash);
441 SETUPDI_GuidToString(&device->set->ClassGuid,
442 classKeyPath + lstrlenW(classKeyPath));
443 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
444 KEY_ALL_ACCESS, NULL, &classKey, NULL);
445 if (!l)
447 static const WCHAR fmt[] = { '%','0','4','u',0 };
448 WCHAR devId[10];
450 sprintfW(devId, fmt, device->devnode);
451 RegCreateKeyExW(classKey, devId, 0, NULL, 0, KEY_READ | KEY_WRITE,
452 NULL, &key, NULL);
453 RegCloseKey(classKey);
455 return key;
458 struct PropertyMapEntry
460 DWORD regType;
461 LPCSTR nameA;
462 LPCWSTR nameW;
465 static const struct PropertyMapEntry PropertyMap[] = {
466 { REG_SZ, "DeviceDesc", DeviceDesc },
467 { REG_MULTI_SZ, "HardwareId", HardwareId },
468 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
469 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
470 { REG_SZ, "Service", Service },
471 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
472 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
473 { REG_SZ, "Class", Class },
474 { REG_SZ, "ClassGUID", ClassGUID },
475 { REG_SZ, "Driver", Driver },
476 { REG_DWORD, "ConfigFlags", ConfigFlags },
477 { REG_SZ, "Mfg", Mfg },
478 { REG_SZ, "FriendlyName", FriendlyName },
479 { REG_SZ, "LocationInformation", LocationInformation },
480 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
481 { REG_DWORD, "Capabilities", Capabilities },
482 { REG_DWORD, "UINumber", UINumber },
483 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
484 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
487 static BOOL SETUPDI_SetDeviceRegistryPropertyW(struct device *device,
488 DWORD prop, const BYTE *buffer, DWORD size)
490 if (prop < ARRAY_SIZE(PropertyMap) && PropertyMap[prop].nameW)
492 LONG ret = RegSetValueExW(device->key, PropertyMap[prop].nameW, 0,
493 PropertyMap[prop].regType, buffer, size);
494 if (!ret)
495 return TRUE;
497 SetLastError(ret);
499 return FALSE;
502 static void SETUPDI_RemoveDevice(struct device *device)
504 struct device_iface *iface, *next;
505 WCHAR *path;
507 if (device->key != INVALID_HANDLE_VALUE)
508 RegCloseKey(device->key);
509 if (device->phantom)
511 HKEY enumKey;
512 LONG l;
514 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
515 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
516 if (!l)
518 RegDeleteTreeW(enumKey, device->instanceId);
519 RegCloseKey(enumKey);
522 heap_free(device->instanceId);
523 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &device->interfaces,
524 struct device_iface, entry)
526 list_remove(&iface->entry);
527 if (device->phantom && (path = get_refstr_key_path(iface)))
529 RegDeleteKeyW(HKEY_LOCAL_MACHINE, path);
530 heap_free(path);
532 heap_free(iface->refstr);
533 heap_free(iface->symlink);
534 heap_free(iface);
536 free_devnode(device->devnode);
537 list_remove(&device->entry);
538 heap_free(device);
541 static struct device *SETUPDI_CreateDeviceInfo(struct DeviceInfoSet *set,
542 const GUID *class, const WCHAR *instanceid, BOOL phantom)
544 struct device *device;
545 WCHAR guidstr[39];
547 TRACE("%p, %s, %s, %d\n", set, debugstr_guid(class),
548 debugstr_w(instanceid), phantom);
550 if (!(device = heap_alloc(sizeof(*device))))
552 SetLastError(ERROR_OUTOFMEMORY);
553 return NULL;
556 if (!(device->instanceId = strdupW(instanceid)))
558 SetLastError(ERROR_OUTOFMEMORY);
559 heap_free(device);
560 return NULL;
563 struprW(device->instanceId);
564 device->set = set;
565 device->key = SETUPDI_CreateDevKey(device);
566 device->phantom = phantom;
567 list_init(&device->interfaces);
568 device->class = *class;
569 device->devnode = alloc_devnode(device);
570 list_add_tail(&set->devices, &device->entry);
571 set->cDevices++;
573 SETUPDI_GuidToString(class, guidstr);
574 SETUPDI_SetDeviceRegistryPropertyW(device, SPDRP_CLASSGUID,
575 (const BYTE *)guidstr, sizeof(guidstr));
576 return device;
579 /***********************************************************************
580 * SetupDiBuildClassInfoList (SETUPAPI.@)
582 * Returns a list of setup class GUIDs that identify the classes
583 * that are installed on a local machine.
585 * PARAMS
586 * Flags [I] control exclusion of classes from the list.
587 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
588 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
589 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
591 * RETURNS
592 * Success: TRUE.
593 * Failure: FALSE.
595 BOOL WINAPI SetupDiBuildClassInfoList(
596 DWORD Flags,
597 LPGUID ClassGuidList,
598 DWORD ClassGuidListSize,
599 PDWORD RequiredSize)
601 TRACE("\n");
602 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
603 ClassGuidListSize, RequiredSize,
604 NULL, NULL);
607 /***********************************************************************
608 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
610 * Returns a list of setup class GUIDs that identify the classes
611 * that are installed on a local or remote machine.
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 SetupDiBuildClassInfoListExA(
626 DWORD Flags,
627 LPGUID ClassGuidList,
628 DWORD ClassGuidListSize,
629 PDWORD RequiredSize,
630 LPCSTR MachineName,
631 PVOID Reserved)
633 LPWSTR MachineNameW = NULL;
634 BOOL bResult;
636 TRACE("\n");
638 if (MachineName)
640 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
641 if (MachineNameW == NULL) return FALSE;
644 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
645 ClassGuidListSize, RequiredSize,
646 MachineNameW, Reserved);
648 MyFree(MachineNameW);
650 return bResult;
653 /***********************************************************************
654 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
656 * Returns a list of setup class GUIDs that identify the classes
657 * that are installed on a local or remote machine.
659 * PARAMS
660 * Flags [I] control exclusion of classes from the list.
661 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
662 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
663 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
664 * MachineName [I] name of a remote machine.
665 * Reserved [I] must be NULL.
667 * RETURNS
668 * Success: TRUE.
669 * Failure: FALSE.
671 BOOL WINAPI SetupDiBuildClassInfoListExW(
672 DWORD Flags,
673 LPGUID ClassGuidList,
674 DWORD ClassGuidListSize,
675 PDWORD RequiredSize,
676 LPCWSTR MachineName,
677 PVOID Reserved)
679 WCHAR szKeyName[40];
680 HKEY hClassesKey;
681 HKEY hClassKey;
682 DWORD dwLength;
683 DWORD dwIndex;
684 LONG lError;
685 DWORD dwGuidListIndex = 0;
687 TRACE("\n");
689 if (RequiredSize != NULL)
690 *RequiredSize = 0;
692 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
693 KEY_ALL_ACCESS,
694 DIOCR_INSTALLER,
695 MachineName,
696 Reserved);
697 if (hClassesKey == INVALID_HANDLE_VALUE)
699 return FALSE;
702 for (dwIndex = 0; ; dwIndex++)
704 dwLength = 40;
705 lError = RegEnumKeyExW(hClassesKey,
706 dwIndex,
707 szKeyName,
708 &dwLength,
709 NULL,
710 NULL,
711 NULL,
712 NULL);
713 TRACE("RegEnumKeyExW() returns %d\n", lError);
714 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
716 TRACE("Key name: %p\n", szKeyName);
718 if (RegOpenKeyExW(hClassesKey,
719 szKeyName,
721 KEY_ALL_ACCESS,
722 &hClassKey))
724 RegCloseKey(hClassesKey);
725 return FALSE;
728 if (!RegQueryValueExW(hClassKey,
729 NoUseClass,
730 NULL,
731 NULL,
732 NULL,
733 NULL))
735 TRACE("'NoUseClass' value found!\n");
736 RegCloseKey(hClassKey);
737 continue;
740 if ((Flags & DIBCI_NOINSTALLCLASS) &&
741 (!RegQueryValueExW(hClassKey,
742 NoInstallClass,
743 NULL,
744 NULL,
745 NULL,
746 NULL)))
748 TRACE("'NoInstallClass' value found!\n");
749 RegCloseKey(hClassKey);
750 continue;
753 if ((Flags & DIBCI_NODISPLAYCLASS) &&
754 (!RegQueryValueExW(hClassKey,
755 NoDisplayClass,
756 NULL,
757 NULL,
758 NULL,
759 NULL)))
761 TRACE("'NoDisplayClass' value found!\n");
762 RegCloseKey(hClassKey);
763 continue;
766 RegCloseKey(hClassKey);
768 TRACE("Guid: %p\n", szKeyName);
769 if (dwGuidListIndex < ClassGuidListSize)
771 if (szKeyName[0] == '{' && szKeyName[37] == '}')
773 szKeyName[37] = 0;
775 TRACE("Guid: %p\n", &szKeyName[1]);
777 UuidFromStringW(&szKeyName[1],
778 &ClassGuidList[dwGuidListIndex]);
781 dwGuidListIndex++;
784 if (lError != ERROR_SUCCESS)
785 break;
788 RegCloseKey(hClassesKey);
790 if (RequiredSize != NULL)
791 *RequiredSize = dwGuidListIndex;
793 if (ClassGuidListSize < dwGuidListIndex)
795 SetLastError(ERROR_INSUFFICIENT_BUFFER);
796 return FALSE;
799 return TRUE;
802 /***********************************************************************
803 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
805 BOOL WINAPI SetupDiClassGuidsFromNameA(
806 LPCSTR ClassName,
807 LPGUID ClassGuidList,
808 DWORD ClassGuidListSize,
809 PDWORD RequiredSize)
811 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
812 ClassGuidListSize, RequiredSize,
813 NULL, NULL);
816 /***********************************************************************
817 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
819 BOOL WINAPI SetupDiClassGuidsFromNameW(
820 LPCWSTR ClassName,
821 LPGUID ClassGuidList,
822 DWORD ClassGuidListSize,
823 PDWORD RequiredSize)
825 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
826 ClassGuidListSize, RequiredSize,
827 NULL, NULL);
830 /***********************************************************************
831 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
833 BOOL WINAPI SetupDiClassGuidsFromNameExA(
834 LPCSTR ClassName,
835 LPGUID ClassGuidList,
836 DWORD ClassGuidListSize,
837 PDWORD RequiredSize,
838 LPCSTR MachineName,
839 PVOID Reserved)
841 LPWSTR ClassNameW = NULL;
842 LPWSTR MachineNameW = NULL;
843 BOOL bResult;
845 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
846 if (ClassNameW == NULL)
847 return FALSE;
849 if (MachineName)
851 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
852 if (MachineNameW == NULL)
854 MyFree(ClassNameW);
855 return FALSE;
859 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
860 ClassGuidListSize, RequiredSize,
861 MachineNameW, Reserved);
863 MyFree(MachineNameW);
864 MyFree(ClassNameW);
866 return bResult;
869 /***********************************************************************
870 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
872 BOOL WINAPI SetupDiClassGuidsFromNameExW(
873 LPCWSTR ClassName,
874 LPGUID ClassGuidList,
875 DWORD ClassGuidListSize,
876 PDWORD RequiredSize,
877 LPCWSTR MachineName,
878 PVOID Reserved)
880 WCHAR szKeyName[40];
881 WCHAR szClassName[256];
882 HKEY hClassesKey;
883 HKEY hClassKey;
884 DWORD dwLength;
885 DWORD dwIndex;
886 LONG lError;
887 DWORD dwGuidListIndex = 0;
889 if (RequiredSize != NULL)
890 *RequiredSize = 0;
892 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
893 KEY_ALL_ACCESS,
894 DIOCR_INSTALLER,
895 MachineName,
896 Reserved);
897 if (hClassesKey == INVALID_HANDLE_VALUE)
899 return FALSE;
902 for (dwIndex = 0; ; dwIndex++)
904 dwLength = ARRAY_SIZE(szKeyName);
905 lError = RegEnumKeyExW(hClassesKey,
906 dwIndex,
907 szKeyName,
908 &dwLength,
909 NULL,
910 NULL,
911 NULL,
912 NULL);
913 TRACE("RegEnumKeyExW() returns %d\n", lError);
914 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
916 TRACE("Key name: %p\n", szKeyName);
918 if (RegOpenKeyExW(hClassesKey,
919 szKeyName,
921 KEY_ALL_ACCESS,
922 &hClassKey))
924 RegCloseKey(hClassesKey);
925 return FALSE;
928 dwLength = sizeof(szClassName);
929 if (!RegQueryValueExW(hClassKey,
930 Class,
931 NULL,
932 NULL,
933 (LPBYTE)szClassName,
934 &dwLength))
936 TRACE("Class name: %p\n", szClassName);
938 if (strcmpiW(szClassName, ClassName) == 0)
940 TRACE("Found matching class name\n");
942 TRACE("Guid: %p\n", szKeyName);
943 if (dwGuidListIndex < ClassGuidListSize)
945 if (szKeyName[0] == '{' && szKeyName[37] == '}')
947 szKeyName[37] = 0;
949 TRACE("Guid: %p\n", &szKeyName[1]);
951 UuidFromStringW(&szKeyName[1],
952 &ClassGuidList[dwGuidListIndex]);
955 dwGuidListIndex++;
959 RegCloseKey(hClassKey);
962 if (lError != ERROR_SUCCESS)
963 break;
966 RegCloseKey(hClassesKey);
968 if (RequiredSize != NULL)
969 *RequiredSize = dwGuidListIndex;
971 if (ClassGuidListSize < dwGuidListIndex)
973 SetLastError(ERROR_INSUFFICIENT_BUFFER);
974 return FALSE;
977 return TRUE;
980 /***********************************************************************
981 * SetupDiClassNameFromGuidA (SETUPAPI.@)
983 BOOL WINAPI SetupDiClassNameFromGuidA(
984 const GUID* ClassGuid,
985 PSTR ClassName,
986 DWORD ClassNameSize,
987 PDWORD RequiredSize)
989 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
990 ClassNameSize, RequiredSize,
991 NULL, NULL);
994 /***********************************************************************
995 * SetupDiClassNameFromGuidW (SETUPAPI.@)
997 BOOL WINAPI SetupDiClassNameFromGuidW(
998 const GUID* ClassGuid,
999 PWSTR ClassName,
1000 DWORD ClassNameSize,
1001 PDWORD RequiredSize)
1003 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1004 ClassNameSize, RequiredSize,
1005 NULL, NULL);
1008 /***********************************************************************
1009 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1011 BOOL WINAPI SetupDiClassNameFromGuidExA(
1012 const GUID* ClassGuid,
1013 PSTR ClassName,
1014 DWORD ClassNameSize,
1015 PDWORD RequiredSize,
1016 PCSTR MachineName,
1017 PVOID Reserved)
1019 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1020 LPWSTR MachineNameW = NULL;
1021 BOOL ret;
1023 if (MachineName)
1024 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1025 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1026 NULL, MachineNameW, Reserved);
1027 if (ret)
1029 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1030 ClassNameSize, NULL, NULL);
1032 if (!ClassNameSize && RequiredSize)
1033 *RequiredSize = len;
1035 MyFree(MachineNameW);
1036 return ret;
1039 /***********************************************************************
1040 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1042 BOOL WINAPI SetupDiClassNameFromGuidExW(
1043 const GUID* ClassGuid,
1044 PWSTR ClassName,
1045 DWORD ClassNameSize,
1046 PDWORD RequiredSize,
1047 PCWSTR MachineName,
1048 PVOID Reserved)
1050 HKEY hKey;
1051 DWORD dwLength;
1053 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1054 KEY_ALL_ACCESS,
1055 DIOCR_INSTALLER,
1056 MachineName,
1057 Reserved);
1058 if (hKey == INVALID_HANDLE_VALUE)
1060 return FALSE;
1063 if (RequiredSize != NULL)
1065 dwLength = 0;
1066 if (RegQueryValueExW(hKey,
1067 Class,
1068 NULL,
1069 NULL,
1070 NULL,
1071 &dwLength))
1073 RegCloseKey(hKey);
1074 return FALSE;
1077 *RequiredSize = dwLength / sizeof(WCHAR);
1080 dwLength = ClassNameSize * sizeof(WCHAR);
1081 if (RegQueryValueExW(hKey,
1082 Class,
1083 NULL,
1084 NULL,
1085 (LPBYTE)ClassName,
1086 &dwLength))
1088 RegCloseKey(hKey);
1089 return FALSE;
1092 RegCloseKey(hKey);
1094 return TRUE;
1097 /***********************************************************************
1098 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1100 HDEVINFO WINAPI
1101 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1102 HWND hwndParent)
1104 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1107 /***********************************************************************
1108 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1110 HDEVINFO WINAPI
1111 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1112 HWND hwndParent,
1113 PCSTR MachineName,
1114 PVOID Reserved)
1116 LPWSTR MachineNameW = NULL;
1117 HDEVINFO hDevInfo;
1119 TRACE("\n");
1121 if (MachineName)
1123 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1124 if (MachineNameW == NULL)
1125 return INVALID_HANDLE_VALUE;
1128 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1129 MachineNameW, Reserved);
1131 MyFree(MachineNameW);
1133 return hDevInfo;
1136 /***********************************************************************
1137 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1139 * Create an empty DeviceInfoSet list.
1141 * PARAMS
1142 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1143 * with this list.
1144 * hwndParent [I] hwnd needed for interface related actions.
1145 * MachineName [I] name of machine to create empty DeviceInfoSet list, if NULL
1146 * local registry will be used.
1147 * Reserved [I] must be NULL
1149 * RETURNS
1150 * Success: empty list.
1151 * Failure: INVALID_HANDLE_VALUE.
1153 HDEVINFO WINAPI
1154 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1155 HWND hwndParent,
1156 PCWSTR MachineName,
1157 PVOID Reserved)
1159 struct DeviceInfoSet *list = NULL;
1160 DWORD size = sizeof(struct DeviceInfoSet);
1162 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1163 debugstr_w(MachineName), Reserved);
1165 if (MachineName && *MachineName)
1167 FIXME("remote support is not implemented\n");
1168 SetLastError(ERROR_INVALID_MACHINENAME);
1169 return INVALID_HANDLE_VALUE;
1172 if (Reserved != NULL)
1174 SetLastError(ERROR_INVALID_PARAMETER);
1175 return INVALID_HANDLE_VALUE;
1178 list = HeapAlloc(GetProcessHeap(), 0, size);
1179 if (!list)
1181 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1182 return INVALID_HANDLE_VALUE;
1185 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1186 list->hwndParent = hwndParent;
1187 memcpy(&list->ClassGuid,
1188 ClassGuid ? ClassGuid : &GUID_NULL,
1189 sizeof(list->ClassGuid));
1190 list->cDevices = 0;
1191 list_init(&list->devices);
1193 return list;
1196 /***********************************************************************
1197 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1199 HKEY WINAPI SetupDiCreateDevRegKeyA(
1200 HDEVINFO DeviceInfoSet,
1201 PSP_DEVINFO_DATA DeviceInfoData,
1202 DWORD Scope,
1203 DWORD HwProfile,
1204 DWORD KeyType,
1205 HINF InfHandle,
1206 PCSTR InfSectionName)
1208 PWSTR InfSectionNameW = NULL;
1209 HKEY key;
1211 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1212 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1214 if (InfHandle)
1216 if (!InfSectionName)
1218 SetLastError(ERROR_INVALID_PARAMETER);
1219 return INVALID_HANDLE_VALUE;
1221 else
1223 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1224 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1227 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1228 HwProfile, KeyType, InfHandle, InfSectionNameW);
1229 MyFree(InfSectionNameW);
1230 return key;
1233 /***********************************************************************
1234 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1236 HKEY WINAPI SetupDiCreateDevRegKeyW(
1237 HDEVINFO DeviceInfoSet,
1238 PSP_DEVINFO_DATA DeviceInfoData,
1239 DWORD Scope,
1240 DWORD HwProfile,
1241 DWORD KeyType,
1242 HINF InfHandle,
1243 PCWSTR InfSectionName)
1245 struct DeviceInfoSet *set = DeviceInfoSet;
1246 struct device *device;
1247 HKEY key = INVALID_HANDLE_VALUE;
1249 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1250 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1252 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1254 SetLastError(ERROR_INVALID_HANDLE);
1255 return INVALID_HANDLE_VALUE;
1257 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1259 SetLastError(ERROR_INVALID_HANDLE);
1260 return INVALID_HANDLE_VALUE;
1262 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1263 || !DeviceInfoData->Reserved)
1265 SetLastError(ERROR_INVALID_PARAMETER);
1266 return INVALID_HANDLE_VALUE;
1268 device = (struct device *)DeviceInfoData->Reserved;
1269 if (device->set != set)
1271 SetLastError(ERROR_INVALID_PARAMETER);
1272 return INVALID_HANDLE_VALUE;
1274 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1276 SetLastError(ERROR_INVALID_FLAGS);
1277 return INVALID_HANDLE_VALUE;
1279 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1281 SetLastError(ERROR_INVALID_FLAGS);
1282 return INVALID_HANDLE_VALUE;
1284 if (device->phantom)
1286 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
1287 return INVALID_HANDLE_VALUE;
1289 if (Scope != DICS_FLAG_GLOBAL)
1290 FIXME("unimplemented for scope %d\n", Scope);
1291 switch (KeyType)
1293 case DIREG_DEV:
1294 key = SETUPDI_CreateDevKey(device);
1295 break;
1296 case DIREG_DRV:
1297 key = SETUPDI_CreateDrvKey(device);
1298 break;
1299 default:
1300 WARN("unknown KeyType %d\n", KeyType);
1302 if (InfHandle)
1303 SetupInstallFromInfSectionW(NULL, InfHandle, InfSectionName, SPINST_ALL,
1304 NULL, NULL, SP_COPY_NEWER_ONLY, NULL, NULL, DeviceInfoSet,
1305 DeviceInfoData);
1306 return key;
1309 /***********************************************************************
1310 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1312 BOOL WINAPI SetupDiCreateDeviceInfoA(HDEVINFO DeviceInfoSet, PCSTR DeviceName,
1313 const GUID *ClassGuid, PCSTR DeviceDescription, HWND hwndParent, DWORD CreationFlags,
1314 PSP_DEVINFO_DATA DeviceInfoData)
1316 BOOL ret = FALSE;
1317 LPWSTR DeviceNameW = NULL;
1318 LPWSTR DeviceDescriptionW = NULL;
1320 if (DeviceName)
1322 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1323 if (DeviceNameW == NULL) return FALSE;
1325 if (DeviceDescription)
1327 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1328 if (DeviceDescriptionW == NULL)
1330 MyFree(DeviceNameW);
1331 return FALSE;
1335 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1336 hwndParent, CreationFlags, DeviceInfoData);
1338 MyFree(DeviceNameW);
1339 MyFree(DeviceDescriptionW);
1341 return ret;
1344 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1346 LPCWSTR ptr;
1347 int devNameLen = lstrlenW(devName);
1348 DWORD devInst = 0;
1349 BOOL valid = TRUE;
1351 TRACE("%s\n", debugstr_w(devName));
1352 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1354 if (isdigitW(*ptr))
1356 devInst *= 10;
1357 devInst |= *ptr - '0';
1358 ptr++;
1360 else
1361 valid = FALSE;
1363 TRACE("%d\n", valid ? devInst : 0xffffffff);
1364 return valid ? devInst : 0xffffffff;
1367 /***********************************************************************
1368 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1370 BOOL WINAPI SetupDiCreateDeviceInfoW(HDEVINFO DeviceInfoSet, PCWSTR DeviceName,
1371 const GUID *ClassGuid, PCWSTR DeviceDescription, HWND hwndParent, DWORD CreationFlags,
1372 SP_DEVINFO_DATA *device_data)
1374 struct DeviceInfoSet *set = DeviceInfoSet;
1375 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1376 LPCWSTR instanceId = NULL;
1378 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1379 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1380 hwndParent, CreationFlags, device_data);
1382 if (!DeviceName)
1384 SetLastError(ERROR_INVALID_DEVINST_NAME);
1385 return FALSE;
1387 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1389 SetLastError(ERROR_INVALID_HANDLE);
1390 return FALSE;
1392 if (!ClassGuid)
1394 SetLastError(ERROR_INVALID_PARAMETER);
1395 return FALSE;
1397 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1399 SetLastError(ERROR_INVALID_HANDLE);
1400 return FALSE;
1402 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1403 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1405 SetLastError(ERROR_CLASS_MISMATCH);
1406 return FALSE;
1408 if ((CreationFlags & DICD_GENERATE_ID))
1410 if (strchrW(DeviceName, '\\'))
1411 SetLastError(ERROR_INVALID_DEVINST_NAME);
1412 else
1414 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1415 '\\','%','0','4','d',0};
1416 DWORD devId;
1418 if (set->cDevices)
1420 DWORD highestDevID = 0;
1421 struct device *device;
1423 LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry)
1425 const WCHAR *devName = strrchrW(device->instanceId, '\\');
1426 DWORD id;
1428 if (devName)
1429 devName++;
1430 else
1431 devName = device->instanceId;
1432 id = SETUPDI_DevNameToDevID(devName);
1433 if (id != 0xffffffff && id > highestDevID)
1434 highestDevID = id;
1436 devId = highestDevID + 1;
1438 else
1439 devId = 0;
1440 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1441 instanceId = HeapAlloc(GetProcessHeap(), 0,
1442 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1443 if (instanceId)
1445 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1446 devId);
1447 allocatedInstanceId = TRUE;
1448 ret = TRUE;
1450 else
1451 ret = FALSE;
1454 else
1456 struct device *device;
1458 ret = TRUE;
1459 instanceId = DeviceName;
1460 LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry)
1462 if (!lstrcmpiW(DeviceName, device->instanceId))
1464 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1465 ret = FALSE;
1469 if (ret)
1471 struct device *device = NULL;
1473 if ((device = SETUPDI_CreateDeviceInfo(set, ClassGuid, instanceId, TRUE)))
1475 if (DeviceDescription)
1476 SETUPDI_SetDeviceRegistryPropertyW(device, SPDRP_DEVICEDESC,
1477 (const BYTE *)DeviceDescription,
1478 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1479 if (device_data)
1481 if (device_data->cbSize != sizeof(SP_DEVINFO_DATA))
1483 SetLastError(ERROR_INVALID_USER_BUFFER);
1484 ret = FALSE;
1486 else
1487 copy_device_data(device_data, device);
1491 if (allocatedInstanceId)
1492 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1494 return ret;
1497 /***********************************************************************
1498 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1500 BOOL WINAPI SetupDiRegisterDeviceInfo(
1501 HDEVINFO DeviceInfoSet,
1502 PSP_DEVINFO_DATA DeviceInfoData,
1503 DWORD Flags,
1504 PSP_DETSIG_CMPPROC CompareProc,
1505 PVOID CompareContext,
1506 PSP_DEVINFO_DATA DupDeviceInfoData)
1508 struct DeviceInfoSet *set = DeviceInfoSet;
1509 struct device *device;
1511 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1512 CompareProc, CompareContext, DupDeviceInfoData);
1514 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1516 SetLastError(ERROR_INVALID_HANDLE);
1517 return FALSE;
1519 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1521 SetLastError(ERROR_INVALID_HANDLE);
1522 return FALSE;
1524 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1525 || !DeviceInfoData->Reserved)
1527 SetLastError(ERROR_INVALID_PARAMETER);
1528 return FALSE;
1530 device = (struct device *)DeviceInfoData->Reserved;
1531 if (device->set != set)
1533 SetLastError(ERROR_INVALID_PARAMETER);
1534 return FALSE;
1536 if (device->phantom)
1538 device->phantom = FALSE;
1539 RegDeleteValueW(device->key, Phantom);
1541 return TRUE;
1544 /***********************************************************************
1545 * SetupDiRemoveDevice (SETUPAPI.@)
1547 BOOL WINAPI SetupDiRemoveDevice(
1548 HDEVINFO devinfo,
1549 PSP_DEVINFO_DATA info)
1551 FIXME("(%p, %p): stub\n", devinfo, info);
1552 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1553 return FALSE;
1556 /***********************************************************************
1557 * SetupDiRemoveDeviceInterface (SETUPAPI.@)
1559 BOOL WINAPI SetupDiRemoveDeviceInterface(HDEVINFO info, PSP_DEVICE_INTERFACE_DATA data)
1561 FIXME("(%p, %p): stub\n", info, data);
1562 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1563 return FALSE;
1566 /***********************************************************************
1567 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1569 BOOL WINAPI SetupDiEnumDeviceInfo(
1570 HDEVINFO devinfo,
1571 DWORD index,
1572 PSP_DEVINFO_DATA info)
1574 BOOL ret = FALSE;
1576 TRACE("%p %d %p\n", devinfo, index, info);
1578 if(info==NULL)
1580 SetLastError(ERROR_INVALID_PARAMETER);
1581 return FALSE;
1583 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1585 struct DeviceInfoSet *list = devinfo;
1586 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1588 if (index < list->cDevices)
1590 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1592 struct device *device;
1593 DWORD i = 0;
1595 LIST_FOR_EACH_ENTRY(device, &list->devices, struct device, entry)
1597 if (i++ == index)
1599 copy_device_data(info, device);
1600 break;
1603 ret = TRUE;
1605 else
1606 SetLastError(ERROR_INVALID_USER_BUFFER);
1608 else
1609 SetLastError(ERROR_NO_MORE_ITEMS);
1611 else
1612 SetLastError(ERROR_INVALID_HANDLE);
1614 else
1615 SetLastError(ERROR_INVALID_HANDLE);
1616 return ret;
1619 /***********************************************************************
1620 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1622 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1623 HDEVINFO DeviceInfoSet,
1624 PSP_DEVINFO_DATA DeviceInfoData,
1625 PSTR DeviceInstanceId,
1626 DWORD DeviceInstanceIdSize,
1627 PDWORD RequiredSize)
1629 BOOL ret = FALSE;
1630 DWORD size;
1631 PWSTR instanceId;
1633 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1634 DeviceInstanceIdSize, RequiredSize);
1636 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1637 DeviceInfoData,
1638 NULL,
1640 &size);
1641 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1642 return FALSE;
1643 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1644 if (instanceId)
1646 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1647 DeviceInfoData,
1648 instanceId,
1649 size,
1650 &size);
1651 if (ret)
1653 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1654 DeviceInstanceId,
1655 DeviceInstanceIdSize, NULL, NULL);
1657 if (!len)
1658 ret = FALSE;
1659 else
1661 if (len > DeviceInstanceIdSize)
1663 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1664 ret = FALSE;
1666 if (RequiredSize)
1667 *RequiredSize = len;
1670 HeapFree(GetProcessHeap(), 0, instanceId);
1672 return ret;
1675 /***********************************************************************
1676 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1678 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1679 HDEVINFO DeviceInfoSet,
1680 PSP_DEVINFO_DATA DeviceInfoData,
1681 PWSTR DeviceInstanceId,
1682 DWORD DeviceInstanceIdSize,
1683 PDWORD RequiredSize)
1685 struct DeviceInfoSet *set = DeviceInfoSet;
1686 struct device *device;
1688 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1689 DeviceInstanceIdSize, RequiredSize);
1691 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1693 SetLastError(ERROR_INVALID_HANDLE);
1694 return FALSE;
1696 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1698 SetLastError(ERROR_INVALID_HANDLE);
1699 return FALSE;
1701 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1702 || !DeviceInfoData->Reserved)
1704 SetLastError(ERROR_INVALID_PARAMETER);
1705 return FALSE;
1707 device = (struct device *)DeviceInfoData->Reserved;
1708 if (device->set != set)
1710 SetLastError(ERROR_INVALID_PARAMETER);
1711 return FALSE;
1713 TRACE("instance ID: %s\n", debugstr_w(device->instanceId));
1714 if (DeviceInstanceIdSize < strlenW(device->instanceId) + 1)
1716 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1717 if (RequiredSize)
1718 *RequiredSize = lstrlenW(device->instanceId) + 1;
1719 return FALSE;
1721 lstrcpyW(DeviceInstanceId, device->instanceId);
1722 if (RequiredSize)
1723 *RequiredSize = lstrlenW(device->instanceId) + 1;
1724 return TRUE;
1727 /***********************************************************************
1728 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1730 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1731 HINF InfHandle,
1732 PCSTR InfSectionName,
1733 PSTR InfSectionWithExt,
1734 DWORD InfSectionWithExtSize,
1735 PDWORD RequiredSize,
1736 PSTR *Extension)
1738 FIXME("\n");
1739 return FALSE;
1742 /***********************************************************************
1743 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1745 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1746 HINF InfHandle,
1747 PCWSTR InfSectionName,
1748 PWSTR InfSectionWithExt,
1749 DWORD InfSectionWithExtSize,
1750 PDWORD RequiredSize,
1751 PWSTR *Extension)
1753 WCHAR szBuffer[MAX_PATH];
1754 DWORD dwLength;
1755 DWORD dwFullLength;
1756 LONG lLineCount = -1;
1758 lstrcpyW(szBuffer, InfSectionName);
1759 dwLength = lstrlenW(szBuffer);
1761 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1763 /* Test section name with '.NTx86' extension */
1764 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1765 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1767 if (lLineCount == -1)
1769 /* Test section name with '.NT' extension */
1770 lstrcpyW(&szBuffer[dwLength], NtExtension);
1771 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1774 else
1776 /* Test section name with '.Win' extension */
1777 lstrcpyW(&szBuffer[dwLength], WinExtension);
1778 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1781 if (lLineCount == -1)
1783 /* Test section name without extension */
1784 szBuffer[dwLength] = 0;
1785 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1788 if (lLineCount == -1)
1790 SetLastError(ERROR_INVALID_PARAMETER);
1791 return FALSE;
1794 dwFullLength = lstrlenW(szBuffer);
1796 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1798 if (InfSectionWithExtSize < (dwFullLength + 1))
1800 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1801 return FALSE;
1804 lstrcpyW(InfSectionWithExt, szBuffer);
1805 if (Extension != NULL)
1807 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1811 if (RequiredSize != NULL)
1813 *RequiredSize = dwFullLength + 1;
1816 return TRUE;
1819 /***********************************************************************
1820 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1822 BOOL WINAPI SetupDiGetClassDescriptionA(
1823 const GUID* ClassGuid,
1824 PSTR ClassDescription,
1825 DWORD ClassDescriptionSize,
1826 PDWORD RequiredSize)
1828 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1829 ClassDescriptionSize,
1830 RequiredSize, NULL, NULL);
1833 /***********************************************************************
1834 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1836 BOOL WINAPI SetupDiGetClassDescriptionW(
1837 const GUID* ClassGuid,
1838 PWSTR ClassDescription,
1839 DWORD ClassDescriptionSize,
1840 PDWORD RequiredSize)
1842 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1843 ClassDescriptionSize,
1844 RequiredSize, NULL, NULL);
1847 /***********************************************************************
1848 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1850 BOOL WINAPI SetupDiGetClassDescriptionExA(
1851 const GUID* ClassGuid,
1852 PSTR ClassDescription,
1853 DWORD ClassDescriptionSize,
1854 PDWORD RequiredSize,
1855 PCSTR MachineName,
1856 PVOID Reserved)
1858 HKEY hKey;
1859 DWORD dwLength;
1860 BOOL ret;
1862 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1863 KEY_ALL_ACCESS,
1864 DIOCR_INSTALLER,
1865 MachineName,
1866 Reserved);
1867 if (hKey == INVALID_HANDLE_VALUE)
1869 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1870 return FALSE;
1873 dwLength = ClassDescriptionSize;
1874 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1875 (LPBYTE)ClassDescription, &dwLength );
1876 if (RequiredSize) *RequiredSize = dwLength;
1877 RegCloseKey(hKey);
1878 return ret;
1881 /***********************************************************************
1882 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1884 BOOL WINAPI SetupDiGetClassDescriptionExW(
1885 const GUID* ClassGuid,
1886 PWSTR ClassDescription,
1887 DWORD ClassDescriptionSize,
1888 PDWORD RequiredSize,
1889 PCWSTR MachineName,
1890 PVOID Reserved)
1892 HKEY hKey;
1893 DWORD dwLength;
1894 BOOL ret;
1896 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1897 KEY_ALL_ACCESS,
1898 DIOCR_INSTALLER,
1899 MachineName,
1900 Reserved);
1901 if (hKey == INVALID_HANDLE_VALUE)
1903 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1904 return FALSE;
1907 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1908 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1909 (LPBYTE)ClassDescription, &dwLength );
1910 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1911 RegCloseKey(hKey);
1912 return ret;
1915 /***********************************************************************
1916 * SetupDiGetClassDevsA (SETUPAPI.@)
1918 HDEVINFO WINAPI SetupDiGetClassDevsA(const GUID *class, LPCSTR enumstr, HWND parent, DWORD flags)
1920 HDEVINFO ret;
1921 LPWSTR enumstrW = NULL;
1923 if (enumstr)
1925 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1926 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1927 if (!enumstrW)
1929 ret = INVALID_HANDLE_VALUE;
1930 goto end;
1932 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1934 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
1935 NULL);
1936 HeapFree(GetProcessHeap(), 0, enumstrW);
1938 end:
1939 return ret;
1942 /***********************************************************************
1943 * SetupDiGetClassDevsExA (SETUPAPI.@)
1945 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1946 const GUID *class,
1947 PCSTR enumstr,
1948 HWND parent,
1949 DWORD flags,
1950 HDEVINFO deviceset,
1951 PCSTR machine,
1952 PVOID reserved)
1954 HDEVINFO ret;
1955 LPWSTR enumstrW = NULL, machineW = NULL;
1957 if (enumstr)
1959 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1960 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1961 if (!enumstrW)
1963 ret = INVALID_HANDLE_VALUE;
1964 goto end;
1966 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1968 if (machine)
1970 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1971 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1972 if (!machineW)
1974 HeapFree(GetProcessHeap(), 0, enumstrW);
1975 ret = INVALID_HANDLE_VALUE;
1976 goto end;
1978 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1980 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
1981 machineW, reserved);
1982 HeapFree(GetProcessHeap(), 0, enumstrW);
1983 HeapFree(GetProcessHeap(), 0, machineW);
1985 end:
1986 return ret;
1989 static void SETUPDI_AddDeviceInterfaces(struct device *device, HKEY key,
1990 const GUID *guid, DWORD flags)
1992 DWORD i, len;
1993 WCHAR subKeyName[MAX_PATH];
1994 LONG l = ERROR_SUCCESS;
1996 for (i = 0; !l; i++)
1998 len = ARRAY_SIZE(subKeyName);
1999 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2000 if (!l)
2002 HKEY subKey;
2003 struct device_iface *iface;
2005 if (*subKeyName == '#')
2007 /* The subkey name is the reference string, with a '#' prepended */
2008 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2009 if (!l)
2011 WCHAR symbolicLink[MAX_PATH];
2012 DWORD dataType;
2014 if (!(flags & DIGCF_PRESENT) || is_linked(subKey))
2016 iface = SETUPDI_CreateDeviceInterface(device, guid, subKeyName + 1);
2018 len = sizeof(symbolicLink);
2019 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
2020 (BYTE *)symbolicLink, &len);
2021 if (!l && dataType == REG_SZ)
2022 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
2023 RegCloseKey(subKey);
2027 /* Allow enumeration to continue */
2028 l = ERROR_SUCCESS;
2031 /* FIXME: find and add all the device's interfaces to the device */
2034 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
2035 HKEY key, const GUID *guid, const WCHAR *enumstr, DWORD flags)
2037 struct DeviceInfoSet *set = DeviceInfoSet;
2038 DWORD i, len;
2039 WCHAR subKeyName[MAX_PATH];
2040 LONG l;
2041 HKEY enumKey = INVALID_HANDLE_VALUE;
2043 TRACE("%s\n", debugstr_w(enumstr));
2045 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
2046 &enumKey, NULL);
2047 for (i = 0; !l; i++)
2049 len = ARRAY_SIZE(subKeyName);
2050 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2051 if (!l)
2053 HKEY subKey;
2055 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2056 if (!l)
2058 WCHAR deviceInst[MAX_PATH * 3];
2059 DWORD dataType;
2061 len = sizeof(deviceInst);
2062 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
2063 (BYTE *)deviceInst, &len);
2064 if (!l && dataType == REG_SZ)
2066 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
2067 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
2069 HKEY deviceKey;
2071 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
2072 &deviceKey);
2073 if (!l)
2075 WCHAR deviceClassStr[40];
2077 len = sizeof(deviceClassStr);
2078 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
2079 &dataType, (BYTE *)deviceClassStr, &len);
2080 if (!l && dataType == REG_SZ &&
2081 deviceClassStr[0] == '{' &&
2082 deviceClassStr[37] == '}')
2084 GUID deviceClass;
2085 struct device *device;
2087 deviceClassStr[37] = 0;
2088 UuidFromStringW(&deviceClassStr[1],
2089 &deviceClass);
2090 if ((device = SETUPDI_CreateDeviceInfo(set,
2091 &deviceClass, deviceInst, FALSE)))
2092 SETUPDI_AddDeviceInterfaces(device, subKey, guid, flags);
2094 RegCloseKey(deviceKey);
2098 RegCloseKey(subKey);
2100 /* Allow enumeration to continue */
2101 l = ERROR_SUCCESS;
2104 if (enumKey != INVALID_HANDLE_VALUE)
2105 RegCloseKey(enumKey);
2108 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
2109 const GUID *guid, LPCWSTR enumstr, DWORD flags)
2111 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(guid, KEY_READ,
2112 DIOCR_INTERFACE, NULL, NULL);
2114 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(guid),
2115 debugstr_w(enumstr), flags);
2117 if (interfacesKey != INVALID_HANDLE_VALUE)
2119 if (flags & DIGCF_ALLCLASSES)
2121 DWORD i, len;
2122 WCHAR interfaceGuidStr[40];
2123 LONG l = ERROR_SUCCESS;
2125 for (i = 0; !l; i++)
2127 len = ARRAY_SIZE(interfaceGuidStr);
2128 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
2129 NULL, NULL, NULL, NULL);
2130 if (!l)
2132 if (interfaceGuidStr[0] == '{' &&
2133 interfaceGuidStr[37] == '}')
2135 HKEY interfaceKey;
2136 GUID interfaceGuid;
2138 interfaceGuidStr[37] = 0;
2139 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
2140 interfaceGuidStr[37] = '}';
2141 interfaceGuidStr[38] = 0;
2142 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
2143 KEY_READ, &interfaceKey);
2144 if (!l)
2146 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2147 interfaceKey, &interfaceGuid, enumstr, flags);
2148 RegCloseKey(interfaceKey);
2154 else
2156 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
2157 * interface's key, so just pass that long
2159 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2160 interfacesKey, guid, enumstr, flags);
2162 RegCloseKey(interfacesKey);
2166 static void SETUPDI_EnumerateMatchingDeviceInstances(struct DeviceInfoSet *set,
2167 LPCWSTR enumerator, LPCWSTR deviceName, HKEY deviceKey,
2168 const GUID *class, DWORD flags)
2170 DWORD i, len;
2171 WCHAR deviceInstance[MAX_PATH];
2172 LONG l = ERROR_SUCCESS;
2174 TRACE("%s %s\n", debugstr_w(enumerator), debugstr_w(deviceName));
2176 for (i = 0; !l; i++)
2178 len = ARRAY_SIZE(deviceInstance);
2179 l = RegEnumKeyExW(deviceKey, i, deviceInstance, &len, NULL, NULL, NULL,
2180 NULL);
2181 if (!l)
2183 HKEY subKey;
2185 l = RegOpenKeyExW(deviceKey, deviceInstance, 0, KEY_READ, &subKey);
2186 if (!l)
2188 WCHAR classGuid[40];
2189 DWORD dataType;
2191 len = sizeof(classGuid);
2192 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
2193 (BYTE *)classGuid, &len);
2194 if (!l && dataType == REG_SZ)
2196 if (classGuid[0] == '{' && classGuid[37] == '}')
2198 GUID deviceClass;
2200 classGuid[37] = 0;
2201 UuidFromStringW(&classGuid[1], &deviceClass);
2202 if ((flags & DIGCF_ALLCLASSES) ||
2203 IsEqualGUID(class, &deviceClass))
2205 static const WCHAR fmt[] =
2206 {'%','s','\\','%','s','\\','%','s',0};
2207 LPWSTR instanceId;
2209 instanceId = HeapAlloc(GetProcessHeap(), 0,
2210 (lstrlenW(enumerator) + lstrlenW(deviceName) +
2211 lstrlenW(deviceInstance) + 3) * sizeof(WCHAR));
2212 if (instanceId)
2214 sprintfW(instanceId, fmt, enumerator,
2215 deviceName, deviceInstance);
2216 SETUPDI_CreateDeviceInfo(set, &deviceClass,
2217 instanceId, FALSE);
2218 HeapFree(GetProcessHeap(), 0, instanceId);
2223 RegCloseKey(subKey);
2225 /* Allow enumeration to continue */
2226 l = ERROR_SUCCESS;
2231 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
2232 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
2234 struct DeviceInfoSet *set = DeviceInfoSet;
2235 DWORD i, len;
2236 WCHAR subKeyName[MAX_PATH];
2237 LONG l = ERROR_SUCCESS;
2239 TRACE("%s\n", debugstr_w(parent));
2241 for (i = 0; !l; i++)
2243 len = ARRAY_SIZE(subKeyName);
2244 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2245 if (!l)
2247 HKEY subKey;
2249 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2250 if (!l)
2252 TRACE("%s\n", debugstr_w(subKeyName));
2253 SETUPDI_EnumerateMatchingDeviceInstances(set, parent,
2254 subKeyName, subKey, class, flags);
2255 RegCloseKey(subKey);
2257 /* Allow enumeration to continue */
2258 l = ERROR_SUCCESS;
2263 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
2264 LPCWSTR enumstr, DWORD flags)
2266 HKEY enumKey;
2267 LONG l;
2269 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
2270 debugstr_w(enumstr), flags);
2272 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
2273 &enumKey, NULL);
2274 if (enumKey != INVALID_HANDLE_VALUE)
2276 if (enumstr)
2278 HKEY enumStrKey;
2280 l = RegOpenKeyExW(enumKey, enumstr, 0, KEY_READ,
2281 &enumStrKey);
2282 if (!l)
2284 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2285 enumStrKey, class, flags);
2286 RegCloseKey(enumStrKey);
2289 else
2291 DWORD i, len;
2292 WCHAR subKeyName[MAX_PATH];
2294 l = ERROR_SUCCESS;
2295 for (i = 0; !l; i++)
2297 len = ARRAY_SIZE(subKeyName);
2298 l = RegEnumKeyExW(enumKey, i, subKeyName, &len, NULL,
2299 NULL, NULL, NULL);
2300 if (!l)
2302 HKEY subKey;
2304 l = RegOpenKeyExW(enumKey, subKeyName, 0, KEY_READ,
2305 &subKey);
2306 if (!l)
2308 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2309 subKeyName, subKey, class, flags);
2310 RegCloseKey(subKey);
2312 /* Allow enumeration to continue */
2313 l = ERROR_SUCCESS;
2317 RegCloseKey(enumKey);
2321 /***********************************************************************
2322 * SetupDiGetClassDevsW (SETUPAPI.@)
2324 HDEVINFO WINAPI SetupDiGetClassDevsW(const GUID *class, LPCWSTR enumstr, HWND parent, DWORD flags)
2326 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2327 NULL);
2330 /***********************************************************************
2331 * SetupDiGetClassDevsExW (SETUPAPI.@)
2333 HDEVINFO WINAPI SetupDiGetClassDevsExW(const GUID *class, PCWSTR enumstr, HWND parent, DWORD flags,
2334 HDEVINFO deviceset, PCWSTR machine, void *reserved)
2336 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PROFILE;
2337 HDEVINFO set;
2339 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2340 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2341 reserved);
2343 if (!(flags & DIGCF_ALLCLASSES) && !class)
2345 SetLastError(ERROR_INVALID_PARAMETER);
2346 return INVALID_HANDLE_VALUE;
2348 if (flags & unsupportedFlags)
2349 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2350 if (deviceset)
2351 set = deviceset;
2352 else
2353 set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
2354 if (set != INVALID_HANDLE_VALUE)
2356 if (machine && *machine)
2357 FIXME("%s: unimplemented for remote machines\n",
2358 debugstr_w(machine));
2359 else if (flags & DIGCF_DEVICEINTERFACE)
2360 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2361 else
2362 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2364 return set;
2367 /***********************************************************************
2368 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2370 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2371 HDEVINFO DeviceInfoSet,
2372 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2374 struct DeviceInfoSet *set = DeviceInfoSet;
2376 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2378 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2380 SetLastError(ERROR_INVALID_HANDLE);
2381 return FALSE;
2383 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2385 SetLastError(ERROR_INVALID_HANDLE);
2386 return FALSE;
2388 if (!DevInfoData ||
2389 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2391 SetLastError(ERROR_INVALID_PARAMETER);
2392 return FALSE;
2394 DevInfoData->ClassGuid = set->ClassGuid;
2395 DevInfoData->RemoteMachineHandle = NULL;
2396 DevInfoData->RemoteMachineName[0] = '\0';
2397 return TRUE;
2400 /***********************************************************************
2401 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2403 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2404 HDEVINFO DeviceInfoSet,
2405 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2407 struct DeviceInfoSet *set = DeviceInfoSet;
2409 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2411 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2413 SetLastError(ERROR_INVALID_HANDLE);
2414 return FALSE;
2416 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2418 SetLastError(ERROR_INVALID_HANDLE);
2419 return FALSE;
2421 if (!DevInfoData ||
2422 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2424 SetLastError(ERROR_INVALID_PARAMETER);
2425 return FALSE;
2427 DevInfoData->ClassGuid = set->ClassGuid;
2428 DevInfoData->RemoteMachineHandle = NULL;
2429 DevInfoData->RemoteMachineName[0] = '\0';
2430 return TRUE;
2433 /***********************************************************************
2434 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2436 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2437 HDEVINFO DeviceInfoSet,
2438 PSP_DEVINFO_DATA DeviceInfoData,
2439 const GUID *InterfaceClassGuid,
2440 PCSTR ReferenceString,
2441 DWORD CreationFlags,
2442 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2444 BOOL ret;
2445 LPWSTR ReferenceStringW = NULL;
2447 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2448 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2449 CreationFlags, DeviceInterfaceData);
2451 if (ReferenceString)
2453 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2454 if (ReferenceStringW == NULL) return FALSE;
2457 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2458 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2459 DeviceInterfaceData);
2461 MyFree(ReferenceStringW);
2463 return ret;
2466 /***********************************************************************
2467 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2469 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2470 HDEVINFO DeviceInfoSet,
2471 PSP_DEVINFO_DATA DeviceInfoData,
2472 const GUID *InterfaceClassGuid,
2473 PCWSTR ReferenceString,
2474 DWORD CreationFlags,
2475 SP_DEVICE_INTERFACE_DATA *iface_data)
2477 struct DeviceInfoSet *set = DeviceInfoSet;
2478 struct device *device;
2479 struct device_iface *iface;
2481 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2482 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2483 CreationFlags, iface_data);
2485 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2487 SetLastError(ERROR_INVALID_HANDLE);
2488 return FALSE;
2490 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2492 SetLastError(ERROR_INVALID_HANDLE);
2493 return FALSE;
2495 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2496 || !DeviceInfoData->Reserved)
2498 SetLastError(ERROR_INVALID_PARAMETER);
2499 return FALSE;
2501 device = (struct device *)DeviceInfoData->Reserved;
2502 if (device->set != set)
2504 SetLastError(ERROR_INVALID_PARAMETER);
2505 return FALSE;
2507 if (!InterfaceClassGuid)
2509 SetLastError(ERROR_INVALID_USER_BUFFER);
2510 return FALSE;
2512 if (!(iface = SETUPDI_CreateDeviceInterface(device, InterfaceClassGuid,
2513 ReferenceString)))
2514 return FALSE;
2516 if (iface_data)
2518 if (iface_data->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2520 SetLastError(ERROR_INVALID_USER_BUFFER);
2521 return FALSE;
2524 copy_device_iface_data(iface_data, iface);
2526 return TRUE;
2529 /***********************************************************************
2530 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2532 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2533 HDEVINFO DeviceInfoSet,
2534 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2535 DWORD Reserved,
2536 REGSAM samDesired,
2537 HINF InfHandle,
2538 PCSTR InfSectionName)
2540 HKEY key;
2541 PWSTR InfSectionNameW = NULL;
2543 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2544 samDesired, InfHandle, InfSectionName);
2545 if (InfHandle)
2547 if (!InfSectionName)
2549 SetLastError(ERROR_INVALID_PARAMETER);
2550 return INVALID_HANDLE_VALUE;
2552 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2553 if (!InfSectionNameW)
2554 return INVALID_HANDLE_VALUE;
2556 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2557 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2558 InfSectionNameW);
2559 MyFree(InfSectionNameW);
2560 return key;
2563 /***********************************************************************
2564 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2566 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(HDEVINFO devinfo,
2567 SP_DEVICE_INTERFACE_DATA *iface_data, DWORD reserved, REGSAM access,
2568 HINF hinf, const WCHAR *section)
2570 struct DeviceInfoSet *set = devinfo;
2571 struct device_iface *iface;
2572 HKEY refstr_key, params_key;
2573 WCHAR *path;
2574 LONG ret;
2576 TRACE("%p %p %d %#x %p %s\n", devinfo, iface_data, reserved, access, hinf,
2577 debugstr_w(section));
2579 if (!devinfo || devinfo == INVALID_HANDLE_VALUE ||
2580 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2582 SetLastError(ERROR_INVALID_HANDLE);
2583 return INVALID_HANDLE_VALUE;
2585 if (!iface_data || iface_data->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2586 !iface_data->Reserved)
2588 SetLastError(ERROR_INVALID_PARAMETER);
2589 return INVALID_HANDLE_VALUE;
2591 if (hinf && !section)
2593 SetLastError(ERROR_INVALID_PARAMETER);
2594 return INVALID_HANDLE_VALUE;
2597 iface = (struct device_iface *)iface_data->Reserved;
2598 if (!(path = get_refstr_key_path(iface)))
2600 SetLastError(ERROR_OUTOFMEMORY);
2601 return INVALID_HANDLE_VALUE;
2604 ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, path, 0, NULL, 0, 0, NULL,
2605 &refstr_key, NULL);
2606 heap_free(path);
2607 if (ret)
2609 SetLastError(ret);
2610 return INVALID_HANDLE_VALUE;
2613 ret = RegCreateKeyExW(refstr_key, DeviceParameters, 0, NULL, 0, access,
2614 NULL, &params_key, NULL);
2615 RegCloseKey(refstr_key);
2616 if (ret)
2618 SetLastError(ret);
2619 return INVALID_HANDLE_VALUE;
2622 return params_key;
2625 /***********************************************************************
2626 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2628 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(HDEVINFO devinfo,
2629 SP_DEVICE_INTERFACE_DATA *iface_data, DWORD reserved)
2631 struct DeviceInfoSet *set = devinfo;
2632 struct device_iface *iface;
2633 HKEY refstr_key;
2634 WCHAR *path;
2635 LONG ret;
2637 TRACE("%p %p %d\n", devinfo, iface_data, reserved);
2639 if (!devinfo || devinfo == INVALID_HANDLE_VALUE ||
2640 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2642 SetLastError(ERROR_INVALID_HANDLE);
2643 return FALSE;
2645 if (!iface_data || iface_data->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2646 !iface_data->Reserved)
2648 SetLastError(ERROR_INVALID_PARAMETER);
2649 return FALSE;
2652 iface = (struct device_iface *)iface_data->Reserved;
2653 if (!(path = get_refstr_key_path(iface)))
2655 SetLastError(ERROR_OUTOFMEMORY);
2656 return FALSE;
2659 ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, path, 0, NULL, 0, 0, NULL,
2660 &refstr_key, NULL);
2661 heap_free(path);
2662 if (ret)
2664 SetLastError(ret);
2665 return FALSE;
2668 ret = RegDeleteKeyW(refstr_key, DeviceParameters);
2669 RegCloseKey(refstr_key);
2670 if (ret)
2672 SetLastError(ret);
2673 return FALSE;
2676 return TRUE;
2679 /***********************************************************************
2680 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2682 * PARAMS
2683 * DeviceInfoSet [I] Set of devices from which to enumerate
2684 * interfaces
2685 * DeviceInfoData [I] (Optional) If specified, a specific device
2686 * instance from which to enumerate interfaces.
2687 * If it isn't specified, all interfaces for all
2688 * devices in the set are enumerated.
2689 * InterfaceClassGuid [I] The interface class to enumerate.
2690 * MemberIndex [I] An index of the interface instance to enumerate.
2691 * A caller should start with MemberIndex set to 0,
2692 * and continue until the function fails with
2693 * ERROR_NO_MORE_ITEMS.
2694 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2695 * member must be set to
2696 * sizeof(SP_DEVICE_INTERFACE_DATA).
2698 * RETURNS
2699 * Success: non-zero value.
2700 * Failure: FALSE. Call GetLastError() for more info.
2702 BOOL WINAPI SetupDiEnumDeviceInterfaces(HDEVINFO devinfo,
2703 SP_DEVINFO_DATA *device_data, const GUID *class, DWORD index,
2704 SP_DEVICE_INTERFACE_DATA *iface_data)
2706 struct DeviceInfoSet *set = devinfo;
2707 struct device *device;
2708 struct device_iface *iface;
2709 DWORD i = 0;
2711 TRACE("%p, %p, %s, %u, %p\n", devinfo, device_data, debugstr_guid(class),
2712 index, iface_data);
2714 if (!devinfo || devinfo == INVALID_HANDLE_VALUE ||
2715 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2717 SetLastError(ERROR_INVALID_HANDLE);
2718 return FALSE;
2720 if (device_data && (device_data->cbSize != sizeof(SP_DEVINFO_DATA) ||
2721 !device_data->Reserved))
2723 SetLastError(ERROR_INVALID_PARAMETER);
2724 return FALSE;
2726 if (!iface_data || iface_data->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2728 SetLastError(ERROR_INVALID_PARAMETER);
2729 return FALSE;
2732 /* In case application fails to check return value, clear output */
2733 memset(iface_data, 0, sizeof(*iface_data));
2734 iface_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
2736 if (device_data)
2738 device = (struct device *)device_data->Reserved;
2740 LIST_FOR_EACH_ENTRY(iface, &device->interfaces, struct device_iface, entry)
2742 if (IsEqualGUID(&iface->class, class))
2744 if (i == index)
2746 copy_device_iface_data(iface_data, iface);
2747 return TRUE;
2749 i++;
2753 else
2755 LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry)
2757 LIST_FOR_EACH_ENTRY(iface, &device->interfaces, struct device_iface, entry)
2759 if (IsEqualGUID(&iface->class, class))
2761 if (i == index)
2763 copy_device_iface_data(iface_data, iface);
2764 return TRUE;
2766 i++;
2772 SetLastError(ERROR_NO_MORE_ITEMS);
2773 return FALSE;
2776 /***********************************************************************
2777 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2779 * Destroy a DeviceInfoList and free all used memory of the list.
2781 * PARAMS
2782 * devinfo [I] DeviceInfoList pointer to list to destroy
2784 * RETURNS
2785 * Success: non zero value.
2786 * Failure: zero value.
2788 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2790 BOOL ret = FALSE;
2792 TRACE("%p\n", devinfo);
2793 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2795 struct DeviceInfoSet *list = devinfo;
2797 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2799 struct device *device, *device2;
2801 LIST_FOR_EACH_ENTRY_SAFE(device, device2, &list->devices,
2802 struct device, entry)
2804 SETUPDI_RemoveDevice(device);
2806 HeapFree(GetProcessHeap(), 0, list);
2807 ret = TRUE;
2811 if (!ret)
2812 SetLastError(ERROR_INVALID_HANDLE);
2814 return ret;
2817 /***********************************************************************
2818 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2820 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2821 HDEVINFO DeviceInfoSet,
2822 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2823 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2824 DWORD DeviceInterfaceDetailDataSize,
2825 PDWORD RequiredSize,
2826 SP_DEVINFO_DATA *device_data)
2828 struct DeviceInfoSet *set = DeviceInfoSet;
2829 struct device_iface *iface;
2830 DWORD bytesNeeded = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
2831 BOOL ret = FALSE;
2833 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2834 DeviceInterfaceData, DeviceInterfaceDetailData,
2835 DeviceInterfaceDetailDataSize, RequiredSize, device_data);
2837 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2838 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2840 SetLastError(ERROR_INVALID_HANDLE);
2841 return FALSE;
2843 if (!DeviceInterfaceData ||
2844 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2845 !DeviceInterfaceData->Reserved)
2847 SetLastError(ERROR_INVALID_PARAMETER);
2848 return FALSE;
2850 if (DeviceInterfaceDetailData &&
2851 DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2853 SetLastError(ERROR_INVALID_USER_BUFFER);
2854 return FALSE;
2856 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2858 SetLastError(ERROR_INVALID_USER_BUFFER);
2859 return FALSE;
2861 iface = (struct device_iface *)DeviceInterfaceData->Reserved;
2862 if (iface->symlink)
2863 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, iface->symlink, -1,
2864 NULL, 0, NULL, NULL);
2865 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2867 if (iface->symlink)
2868 WideCharToMultiByte(CP_ACP, 0, iface->symlink, -1,
2869 DeviceInterfaceDetailData->DevicePath,
2870 DeviceInterfaceDetailDataSize -
2871 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2872 NULL, NULL);
2873 else
2874 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2876 if (device_data && device_data->cbSize == sizeof(SP_DEVINFO_DATA))
2877 copy_device_data(device_data, iface->device);
2879 ret = TRUE;
2881 else
2883 if (RequiredSize)
2884 *RequiredSize = bytesNeeded;
2885 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2887 return ret;
2890 /***********************************************************************
2891 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2893 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2894 HDEVINFO DeviceInfoSet,
2895 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2896 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2897 DWORD DeviceInterfaceDetailDataSize,
2898 PDWORD RequiredSize,
2899 SP_DEVINFO_DATA *device_data)
2901 struct DeviceInfoSet *set = DeviceInfoSet;
2902 struct device_iface *iface;
2903 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2904 + sizeof(WCHAR); /* include NULL terminator */
2905 BOOL ret = FALSE;
2907 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2908 DeviceInterfaceData, DeviceInterfaceDetailData,
2909 DeviceInterfaceDetailDataSize, RequiredSize, device_data);
2911 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2912 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2914 SetLastError(ERROR_INVALID_HANDLE);
2915 return FALSE;
2917 if (!DeviceInterfaceData ||
2918 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2919 !DeviceInterfaceData->Reserved)
2921 SetLastError(ERROR_INVALID_PARAMETER);
2922 return FALSE;
2924 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2925 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
2926 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
2928 SetLastError(ERROR_INVALID_USER_BUFFER);
2929 return FALSE;
2931 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2933 SetLastError(ERROR_INVALID_USER_BUFFER);
2934 return FALSE;
2936 iface = (struct device_iface *)DeviceInterfaceData->Reserved;
2937 if (iface->symlink)
2938 bytesNeeded += sizeof(WCHAR) * lstrlenW(iface->symlink);
2939 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2941 if (iface->symlink)
2942 lstrcpyW(DeviceInterfaceDetailData->DevicePath, iface->symlink);
2943 else
2944 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2946 if (device_data && device_data->cbSize == sizeof(SP_DEVINFO_DATA))
2947 copy_device_data(device_data, iface->device);
2949 ret = TRUE;
2951 else
2953 if (RequiredSize)
2954 *RequiredSize = bytesNeeded;
2955 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2957 return ret;
2960 /***********************************************************************
2961 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2963 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2964 HDEVINFO DeviceInfoSet,
2965 PSP_DEVINFO_DATA DeviceInfoData,
2966 DWORD Property,
2967 PDWORD PropertyRegDataType,
2968 PBYTE PropertyBuffer,
2969 DWORD PropertyBufferSize,
2970 PDWORD RequiredSize)
2972 BOOL ret = FALSE;
2973 struct DeviceInfoSet *set = DeviceInfoSet;
2974 struct device *device;
2976 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
2977 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2978 RequiredSize);
2980 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2982 SetLastError(ERROR_INVALID_HANDLE);
2983 return FALSE;
2985 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2987 SetLastError(ERROR_INVALID_HANDLE);
2988 return FALSE;
2990 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2991 || !DeviceInfoData->Reserved)
2993 SetLastError(ERROR_INVALID_PARAMETER);
2994 return FALSE;
2996 if (PropertyBufferSize && PropertyBuffer == NULL)
2998 SetLastError(ERROR_INVALID_DATA);
2999 return FALSE;
3001 device = (struct device *)DeviceInfoData->Reserved;
3002 if (Property < ARRAY_SIZE(PropertyMap) && PropertyMap[Property].nameA)
3004 DWORD size = PropertyBufferSize;
3005 LONG l = RegQueryValueExA(device->key, PropertyMap[Property].nameA,
3006 NULL, PropertyRegDataType, PropertyBuffer, &size);
3008 if (l == ERROR_FILE_NOT_FOUND)
3009 SetLastError(ERROR_INVALID_DATA);
3010 else if (l == ERROR_MORE_DATA || !PropertyBufferSize)
3011 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3012 else if (!l)
3013 ret = TRUE;
3014 else
3015 SetLastError(l);
3016 if (RequiredSize)
3017 *RequiredSize = size;
3019 return ret;
3022 /***********************************************************************
3023 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3025 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3026 HDEVINFO DeviceInfoSet,
3027 PSP_DEVINFO_DATA DeviceInfoData,
3028 DWORD Property,
3029 PDWORD PropertyRegDataType,
3030 PBYTE PropertyBuffer,
3031 DWORD PropertyBufferSize,
3032 PDWORD RequiredSize)
3034 BOOL ret = FALSE;
3035 struct DeviceInfoSet *set = DeviceInfoSet;
3036 struct device *device;
3038 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3039 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3040 RequiredSize);
3042 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3044 SetLastError(ERROR_INVALID_HANDLE);
3045 return FALSE;
3047 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3049 SetLastError(ERROR_INVALID_HANDLE);
3050 return FALSE;
3052 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3053 || !DeviceInfoData->Reserved)
3055 SetLastError(ERROR_INVALID_PARAMETER);
3056 return FALSE;
3058 if (PropertyBufferSize && PropertyBuffer == NULL)
3060 SetLastError(ERROR_INVALID_DATA);
3061 return FALSE;
3063 device = (struct device *)DeviceInfoData->Reserved;
3064 if (Property < ARRAY_SIZE(PropertyMap) && PropertyMap[Property].nameW)
3066 DWORD size = PropertyBufferSize;
3067 LONG l = RegQueryValueExW(device->key, PropertyMap[Property].nameW,
3068 NULL, PropertyRegDataType, PropertyBuffer, &size);
3070 if (l == ERROR_FILE_NOT_FOUND)
3071 SetLastError(ERROR_INVALID_DATA);
3072 else if (l == ERROR_MORE_DATA || !PropertyBufferSize)
3073 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3074 else if (!l)
3075 ret = TRUE;
3076 else
3077 SetLastError(l);
3078 if (RequiredSize)
3079 *RequiredSize = size;
3081 return ret;
3084 /***********************************************************************
3085 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3087 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3088 HDEVINFO DeviceInfoSet,
3089 PSP_DEVINFO_DATA DeviceInfoData,
3090 DWORD Property,
3091 const BYTE *PropertyBuffer,
3092 DWORD PropertyBufferSize)
3094 BOOL ret = FALSE;
3095 struct DeviceInfoSet *set = DeviceInfoSet;
3096 struct device *device;
3098 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3099 PropertyBuffer, PropertyBufferSize);
3101 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3103 SetLastError(ERROR_INVALID_HANDLE);
3104 return FALSE;
3106 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3108 SetLastError(ERROR_INVALID_HANDLE);
3109 return FALSE;
3111 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3112 || !DeviceInfoData->Reserved)
3114 SetLastError(ERROR_INVALID_PARAMETER);
3115 return FALSE;
3117 device = (struct device *)DeviceInfoData->Reserved;
3118 if (Property < ARRAY_SIZE(PropertyMap) && PropertyMap[Property].nameA)
3120 LONG l = RegSetValueExA(device->key, PropertyMap[Property].nameA, 0,
3121 PropertyMap[Property].regType, PropertyBuffer,
3122 PropertyBufferSize);
3123 if (!l)
3124 ret = TRUE;
3125 else
3126 SetLastError(l);
3128 return ret;
3131 /***********************************************************************
3132 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3134 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(HDEVINFO devinfo,
3135 SP_DEVINFO_DATA *device_data, DWORD prop, const BYTE *buffer, DWORD size)
3137 struct DeviceInfoSet *set = devinfo;
3138 struct device *device;
3140 TRACE("%p %p %d %p %d\n", devinfo, device_data, prop, buffer, size);
3142 if (!devinfo || devinfo == INVALID_HANDLE_VALUE)
3144 SetLastError(ERROR_INVALID_HANDLE);
3145 return FALSE;
3147 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3149 SetLastError(ERROR_INVALID_HANDLE);
3150 return FALSE;
3152 if (!device_data || device_data->cbSize != sizeof(SP_DEVINFO_DATA)
3153 || !device_data->Reserved)
3155 SetLastError(ERROR_INVALID_PARAMETER);
3156 return FALSE;
3159 device = (struct device *)device_data->Reserved;
3160 return SETUPDI_SetDeviceRegistryPropertyW(device, prop, buffer, size);
3163 /***********************************************************************
3164 * SetupDiInstallClassA (SETUPAPI.@)
3166 BOOL WINAPI SetupDiInstallClassA(
3167 HWND hwndParent,
3168 PCSTR InfFileName,
3169 DWORD Flags,
3170 HSPFILEQ FileQueue)
3172 UNICODE_STRING FileNameW;
3173 BOOL Result;
3175 if (!InfFileName)
3177 SetLastError(ERROR_INVALID_PARAMETER);
3178 return FALSE;
3180 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
3182 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3183 return FALSE;
3186 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
3188 RtlFreeUnicodeString(&FileNameW);
3190 return Result;
3193 static HKEY CreateClassKey(HINF hInf)
3195 static const WCHAR slash[] = { '\\',0 };
3196 WCHAR FullBuffer[MAX_PATH];
3197 WCHAR Buffer[MAX_PATH];
3198 DWORD RequiredSize;
3199 HKEY hClassKey;
3201 if (!SetupGetLineTextW(NULL,
3202 hInf,
3203 Version,
3204 ClassGUID,
3205 Buffer,
3206 MAX_PATH,
3207 &RequiredSize))
3209 return INVALID_HANDLE_VALUE;
3212 lstrcpyW(FullBuffer, ControlClass);
3213 lstrcatW(FullBuffer, slash);
3214 lstrcatW(FullBuffer, Buffer);
3216 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3217 FullBuffer,
3219 KEY_ALL_ACCESS,
3220 &hClassKey))
3222 if (!SetupGetLineTextW(NULL,
3223 hInf,
3224 Version,
3225 Class,
3226 Buffer,
3227 MAX_PATH,
3228 &RequiredSize))
3230 return INVALID_HANDLE_VALUE;
3233 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3234 FullBuffer,
3236 NULL,
3237 REG_OPTION_NON_VOLATILE,
3238 KEY_ALL_ACCESS,
3239 NULL,
3240 &hClassKey,
3241 NULL))
3243 return INVALID_HANDLE_VALUE;
3248 if (RegSetValueExW(hClassKey,
3249 Class,
3251 REG_SZ,
3252 (LPBYTE)Buffer,
3253 RequiredSize * sizeof(WCHAR)))
3255 RegCloseKey(hClassKey);
3256 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3257 FullBuffer);
3258 return INVALID_HANDLE_VALUE;
3261 return hClassKey;
3264 /***********************************************************************
3265 * SetupDiInstallClassW (SETUPAPI.@)
3267 BOOL WINAPI SetupDiInstallClassW(
3268 HWND hwndParent,
3269 PCWSTR InfFileName,
3270 DWORD Flags,
3271 HSPFILEQ FileQueue)
3273 WCHAR SectionName[MAX_PATH];
3274 DWORD SectionNameLength = 0;
3275 HINF hInf;
3276 BOOL bFileQueueCreated = FALSE;
3277 HKEY hClassKey;
3280 FIXME("\n");
3282 if (!InfFileName)
3284 SetLastError(ERROR_INVALID_PARAMETER);
3285 return FALSE;
3287 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
3289 SetLastError(ERROR_INVALID_PARAMETER);
3290 return FALSE;
3293 /* Open the .inf file */
3294 hInf = SetupOpenInfFileW(InfFileName,
3295 NULL,
3296 INF_STYLE_WIN4,
3297 NULL);
3298 if (hInf == INVALID_HANDLE_VALUE)
3301 return FALSE;
3304 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3305 hClassKey = CreateClassKey(hInf);
3306 if (hClassKey == INVALID_HANDLE_VALUE)
3308 SetupCloseInfFile(hInf);
3309 return FALSE;
3313 /* Try to append a layout file */
3314 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3316 /* Retrieve the actual section name */
3317 SetupDiGetActualSectionToInstallW(hInf,
3318 ClassInstall32,
3319 SectionName,
3320 MAX_PATH,
3321 &SectionNameLength,
3322 NULL);
3324 #if 0
3325 if (!(Flags & DI_NOVCP))
3327 FileQueue = SetupOpenFileQueue();
3328 if (FileQueue == INVALID_HANDLE_VALUE)
3330 SetupCloseInfFile(hInf);
3331 return FALSE;
3334 bFileQueueCreated = TRUE;
3337 #endif
3339 SetupInstallFromInfSectionW(NULL,
3340 hInf,
3341 SectionName,
3342 SPINST_COPYINF | SPINST_FILES | SPINST_REGISTRY,
3343 hClassKey,
3344 NULL,
3346 NULL,
3347 NULL,
3348 INVALID_HANDLE_VALUE,
3349 NULL);
3351 /* FIXME: More code! */
3353 if (bFileQueueCreated)
3354 SetupCloseFileQueue(FileQueue);
3356 SetupCloseInfFile(hInf);
3358 return TRUE;
3362 /***********************************************************************
3363 * SetupDiOpenClassRegKey (SETUPAPI.@)
3365 HKEY WINAPI SetupDiOpenClassRegKey(
3366 const GUID* ClassGuid,
3367 REGSAM samDesired)
3369 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3370 DIOCR_INSTALLER, NULL, NULL);
3374 /***********************************************************************
3375 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3377 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3378 const GUID* ClassGuid,
3379 REGSAM samDesired,
3380 DWORD Flags,
3381 PCSTR MachineName,
3382 PVOID Reserved)
3384 PWSTR MachineNameW = NULL;
3385 HKEY hKey;
3387 TRACE("\n");
3389 if (MachineName)
3391 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3392 if (MachineNameW == NULL)
3393 return INVALID_HANDLE_VALUE;
3396 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3397 Flags, MachineNameW, Reserved);
3399 MyFree(MachineNameW);
3401 return hKey;
3405 /***********************************************************************
3406 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3408 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3409 const GUID* ClassGuid,
3410 REGSAM samDesired,
3411 DWORD Flags,
3412 PCWSTR MachineName,
3413 PVOID Reserved)
3415 HKEY hClassesKey;
3416 HKEY key;
3417 LPCWSTR lpKeyName;
3418 LONG l;
3420 if (MachineName && *MachineName)
3422 FIXME("Remote access not supported yet!\n");
3423 return INVALID_HANDLE_VALUE;
3426 if (Flags == DIOCR_INSTALLER)
3428 lpKeyName = ControlClass;
3430 else if (Flags == DIOCR_INTERFACE)
3432 lpKeyName = DeviceClasses;
3434 else
3436 ERR("Invalid Flags parameter!\n");
3437 SetLastError(ERROR_INVALID_PARAMETER);
3438 return INVALID_HANDLE_VALUE;
3441 if (!ClassGuid)
3443 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3444 lpKeyName,
3446 samDesired,
3447 &hClassesKey)))
3449 SetLastError(l);
3450 hClassesKey = INVALID_HANDLE_VALUE;
3452 key = hClassesKey;
3454 else
3456 WCHAR bracedGuidString[39];
3458 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3460 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3461 lpKeyName,
3463 samDesired,
3464 &hClassesKey)))
3466 if ((l = RegOpenKeyExW(hClassesKey,
3467 bracedGuidString,
3469 samDesired,
3470 &key)))
3472 SetLastError(l);
3473 key = INVALID_HANDLE_VALUE;
3475 RegCloseKey(hClassesKey);
3477 else
3479 SetLastError(l);
3480 key = INVALID_HANDLE_VALUE;
3483 return key;
3486 /***********************************************************************
3487 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3489 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3490 HDEVINFO DeviceInfoSet,
3491 PCWSTR DevicePath,
3492 DWORD OpenFlags,
3493 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3495 FIXME("%p %s %08x %p\n",
3496 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3497 return FALSE;
3500 /***********************************************************************
3501 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3503 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3504 HDEVINFO DeviceInfoSet,
3505 PCSTR DevicePath,
3506 DWORD OpenFlags,
3507 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3509 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3510 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3511 return FALSE;
3514 /***********************************************************************
3515 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3517 BOOL WINAPI SetupDiSetClassInstallParamsA(
3518 HDEVINFO DeviceInfoSet,
3519 PSP_DEVINFO_DATA DeviceInfoData,
3520 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3521 DWORD ClassInstallParamsSize)
3523 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3524 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3525 return FALSE;
3528 /***********************************************************************
3529 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3531 BOOL WINAPI SetupDiSetClassInstallParamsW(
3532 HDEVINFO DeviceInfoSet,
3533 PSP_DEVINFO_DATA DeviceInfoData,
3534 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3535 DWORD ClassInstallParamsSize)
3537 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3538 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3539 return FALSE;
3542 /***********************************************************************
3543 * SetupDiCallClassInstaller (SETUPAPI.@)
3545 BOOL WINAPI SetupDiCallClassInstaller(
3546 DI_FUNCTION InstallFunction,
3547 HDEVINFO DeviceInfoSet,
3548 PSP_DEVINFO_DATA DeviceInfoData)
3550 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3551 return FALSE;
3554 /***********************************************************************
3555 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3557 BOOL WINAPI SetupDiGetDeviceInstallParamsW(
3558 HDEVINFO DeviceInfoSet,
3559 PSP_DEVINFO_DATA DeviceInfoData,
3560 PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3562 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3563 return FALSE;
3566 /***********************************************************************
3567 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3569 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3570 HDEVINFO DeviceInfoSet,
3571 PSP_DEVINFO_DATA DeviceInfoData,
3572 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3574 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3575 return FALSE;
3578 /***********************************************************************
3579 * SetupDiSetDeviceInstallParamsA (SETUPAPI.@)
3581 BOOL WINAPI SetupDiSetDeviceInstallParamsA(
3582 HDEVINFO DeviceInfoSet,
3583 PSP_DEVINFO_DATA DeviceInfoData,
3584 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3586 FIXME("(%p, %p, %p) stub\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3588 return TRUE;
3591 /***********************************************************************
3592 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3594 BOOL WINAPI SetupDiSetDeviceInstallParamsW(
3595 HDEVINFO DeviceInfoSet,
3596 PSP_DEVINFO_DATA DeviceInfoData,
3597 PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3599 FIXME("(%p, %p, %p) stub\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3601 return TRUE;
3604 static HKEY SETUPDI_OpenDevKey(struct device *device, REGSAM samDesired)
3606 HKEY enumKey, key = INVALID_HANDLE_VALUE;
3607 LONG l;
3609 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
3610 NULL, &enumKey, NULL);
3611 if (!l)
3613 RegOpenKeyExW(enumKey, device->instanceId, 0, samDesired, &key);
3614 RegCloseKey(enumKey);
3616 return key;
3619 static HKEY SETUPDI_OpenDrvKey(struct device *device, REGSAM samDesired)
3621 static const WCHAR slash[] = { '\\',0 };
3622 WCHAR classKeyPath[MAX_PATH];
3623 HKEY classKey, key = INVALID_HANDLE_VALUE;
3624 LONG l;
3626 lstrcpyW(classKeyPath, ControlClass);
3627 lstrcatW(classKeyPath, slash);
3628 SETUPDI_GuidToString(&device->set->ClassGuid,
3629 classKeyPath + lstrlenW(classKeyPath));
3630 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
3631 KEY_ALL_ACCESS, NULL, &classKey, NULL);
3632 if (!l)
3634 static const WCHAR fmt[] = { '%','0','4','u',0 };
3635 WCHAR devId[10];
3637 sprintfW(devId, fmt, device->devnode);
3638 l = RegOpenKeyExW(classKey, devId, 0, samDesired, &key);
3639 RegCloseKey(classKey);
3640 if (l)
3642 SetLastError(ERROR_KEY_DOES_NOT_EXIST);
3643 return INVALID_HANDLE_VALUE;
3646 return key;
3649 /***********************************************************************
3650 * SetupDiOpenDevRegKey (SETUPAPI.@)
3652 HKEY WINAPI SetupDiOpenDevRegKey(
3653 HDEVINFO DeviceInfoSet,
3654 PSP_DEVINFO_DATA DeviceInfoData,
3655 DWORD Scope,
3656 DWORD HwProfile,
3657 DWORD KeyType,
3658 REGSAM samDesired)
3660 struct DeviceInfoSet *set = DeviceInfoSet;
3661 struct device *device;
3662 HKEY key = INVALID_HANDLE_VALUE;
3664 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3665 Scope, HwProfile, KeyType, samDesired);
3667 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3669 SetLastError(ERROR_INVALID_HANDLE);
3670 return INVALID_HANDLE_VALUE;
3672 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3674 SetLastError(ERROR_INVALID_HANDLE);
3675 return INVALID_HANDLE_VALUE;
3677 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3678 || !DeviceInfoData->Reserved)
3680 SetLastError(ERROR_INVALID_PARAMETER);
3681 return INVALID_HANDLE_VALUE;
3683 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3685 SetLastError(ERROR_INVALID_FLAGS);
3686 return INVALID_HANDLE_VALUE;
3688 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3690 SetLastError(ERROR_INVALID_FLAGS);
3691 return INVALID_HANDLE_VALUE;
3693 device = (struct device *)DeviceInfoData->Reserved;
3694 if (device->set != set)
3696 SetLastError(ERROR_INVALID_PARAMETER);
3697 return INVALID_HANDLE_VALUE;
3699 if (device->phantom)
3701 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
3702 return INVALID_HANDLE_VALUE;
3704 if (Scope != DICS_FLAG_GLOBAL)
3705 FIXME("unimplemented for scope %d\n", Scope);
3706 switch (KeyType)
3708 case DIREG_DEV:
3709 key = SETUPDI_OpenDevKey(device, samDesired);
3710 break;
3711 case DIREG_DRV:
3712 key = SETUPDI_OpenDrvKey(device, samDesired);
3713 break;
3714 default:
3715 WARN("unknown KeyType %d\n", KeyType);
3717 return key;
3720 static BOOL SETUPDI_DeleteDevKey(struct device *device)
3722 HKEY enumKey;
3723 BOOL ret = FALSE;
3724 LONG l;
3726 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
3727 NULL, &enumKey, NULL);
3728 if (!l)
3730 ret = RegDeleteTreeW(enumKey, device->instanceId);
3731 RegCloseKey(enumKey);
3733 else
3734 SetLastError(l);
3735 return ret;
3738 static BOOL SETUPDI_DeleteDrvKey(struct device *device)
3740 static const WCHAR slash[] = { '\\',0 };
3741 WCHAR classKeyPath[MAX_PATH];
3742 HKEY classKey;
3743 LONG l;
3744 BOOL ret = FALSE;
3746 lstrcpyW(classKeyPath, ControlClass);
3747 lstrcatW(classKeyPath, slash);
3748 SETUPDI_GuidToString(&device->set->ClassGuid,
3749 classKeyPath + lstrlenW(classKeyPath));
3750 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
3751 KEY_ALL_ACCESS, NULL, &classKey, NULL);
3752 if (!l)
3754 static const WCHAR fmt[] = { '%','0','4','u',0 };
3755 WCHAR devId[10];
3757 sprintfW(devId, fmt, device->devnode);
3758 ret = RegDeleteTreeW(classKey, devId);
3759 RegCloseKey(classKey);
3761 else
3762 SetLastError(l);
3763 return ret;
3766 /***********************************************************************
3767 * SetupDiDeleteDevRegKey (SETUPAPI.@)
3769 BOOL WINAPI SetupDiDeleteDevRegKey(
3770 HDEVINFO DeviceInfoSet,
3771 PSP_DEVINFO_DATA DeviceInfoData,
3772 DWORD Scope,
3773 DWORD HwProfile,
3774 DWORD KeyType)
3776 struct DeviceInfoSet *set = DeviceInfoSet;
3777 struct device *device;
3778 BOOL ret = FALSE;
3780 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
3781 KeyType);
3783 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3785 SetLastError(ERROR_INVALID_HANDLE);
3786 return FALSE;
3788 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3790 SetLastError(ERROR_INVALID_HANDLE);
3791 return FALSE;
3793 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3794 || !DeviceInfoData->Reserved)
3796 SetLastError(ERROR_INVALID_PARAMETER);
3797 return FALSE;
3799 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3801 SetLastError(ERROR_INVALID_FLAGS);
3802 return FALSE;
3804 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
3806 SetLastError(ERROR_INVALID_FLAGS);
3807 return FALSE;
3809 device = (struct device *)DeviceInfoData->Reserved;
3810 if (device->set != set)
3812 SetLastError(ERROR_INVALID_PARAMETER);
3813 return FALSE;
3815 if (device->phantom)
3817 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
3818 return FALSE;
3820 if (Scope != DICS_FLAG_GLOBAL)
3821 FIXME("unimplemented for scope %d\n", Scope);
3822 switch (KeyType)
3824 case DIREG_DEV:
3825 ret = SETUPDI_DeleteDevKey(device);
3826 break;
3827 case DIREG_DRV:
3828 ret = SETUPDI_DeleteDrvKey(device);
3829 break;
3830 case DIREG_BOTH:
3831 ret = SETUPDI_DeleteDevKey(device);
3832 if (ret)
3833 ret = SETUPDI_DeleteDrvKey(device);
3834 break;
3835 default:
3836 WARN("unknown KeyType %d\n", KeyType);
3838 return ret;
3841 /***********************************************************************
3842 * CM_Get_Device_IDA (SETUPAPI.@)
3844 CONFIGRET WINAPI CM_Get_Device_IDA(DEVINST devnode, char *buffer, ULONG len, ULONG flags)
3846 struct device *device = get_devnode_device(devnode);
3848 TRACE("%u, %p, %u, %#x\n", devnode, buffer, len, flags);
3850 if (!device)
3851 return CR_NO_SUCH_DEVINST;
3853 WideCharToMultiByte(CP_ACP, 0, device->instanceId, -1, buffer, len, 0, 0);
3854 TRACE("Returning %s\n", debugstr_a(buffer));
3855 return CR_SUCCESS;
3858 /***********************************************************************
3859 * CM_Get_Device_IDW (SETUPAPI.@)
3861 CONFIGRET WINAPI CM_Get_Device_IDW(DEVINST devnode, WCHAR *buffer, ULONG len, ULONG flags)
3863 struct device *device = get_devnode_device(devnode);
3865 TRACE("%u, %p, %u, %#x\n", devnode, buffer, len, flags);
3867 if (!device)
3868 return CR_NO_SUCH_DEVINST;
3870 lstrcpynW(buffer, device->instanceId, len);
3871 TRACE("Returning %s\n", debugstr_w(buffer));
3872 return CR_SUCCESS;
3875 /***********************************************************************
3876 * CM_Get_Device_ID_Size (SETUPAPI.@)
3878 CONFIGRET WINAPI CM_Get_Device_ID_Size(ULONG *len, DEVINST devnode, ULONG flags)
3880 struct device *device = get_devnode_device(devnode);
3882 TRACE("%p, %u, %#x\n", len, devnode, flags);
3884 if (!device)
3885 return CR_NO_SUCH_DEVINST;
3887 *len = lstrlenW(device->instanceId);
3888 return CR_SUCCESS;
3891 /***********************************************************************
3892 * SetupDiGetINFClassA (SETUPAPI.@)
3894 BOOL WINAPI SetupDiGetINFClassA(PCSTR inf, LPGUID class_guid, PSTR class_name,
3895 DWORD size, PDWORD required_size)
3897 BOOL retval;
3898 DWORD required_sizeA, required_sizeW;
3899 PWSTR class_nameW = NULL;
3900 UNICODE_STRING infW;
3902 if (inf)
3904 if (!RtlCreateUnicodeStringFromAsciiz(&infW, inf))
3906 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3907 return FALSE;
3910 else
3911 infW.Buffer = NULL;
3913 if (class_name && size)
3915 if (!(class_nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR))))
3917 RtlFreeUnicodeString(&infW);
3918 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3919 return FALSE;
3923 retval = SetupDiGetINFClassW(infW.Buffer, class_guid, class_nameW, size, &required_sizeW);
3925 if (retval)
3927 required_sizeA = WideCharToMultiByte( CP_ACP, 0, class_nameW, required_sizeW,
3928 class_name, size, NULL, NULL);
3930 if(required_size) *required_size = required_sizeA;
3932 else
3933 if(required_size) *required_size = required_sizeW;
3935 HeapFree(GetProcessHeap(), 0, class_nameW);
3936 RtlFreeUnicodeString(&infW);
3937 return retval;
3940 /***********************************************************************
3941 * SetupDiGetINFClassW (SETUPAPI.@)
3943 BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name,
3944 DWORD size, PDWORD required_size)
3946 BOOL have_guid, have_name;
3947 DWORD dret;
3948 WCHAR buffer[MAX_PATH];
3950 if (!inf)
3952 SetLastError(ERROR_INVALID_PARAMETER);
3953 return FALSE;
3956 if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(inf))
3958 FIXME("%s not found. Searching via DevicePath not implemented\n", debugstr_w(inf));
3959 SetLastError(ERROR_FILE_NOT_FOUND);
3960 return FALSE;
3963 if (!class_guid || !class_name || !size)
3965 SetLastError(ERROR_INVALID_PARAMETER);
3966 return FALSE;
3969 if (!GetPrivateProfileStringW(Version, Signature, NULL, buffer, MAX_PATH, inf))
3970 return FALSE;
3972 if (lstrcmpiW(buffer, Chicago) && lstrcmpiW(buffer, WindowsNT))
3973 return FALSE;
3975 buffer[0] = '\0';
3976 have_guid = 0 < GetPrivateProfileStringW(Version, ClassGUID, NULL, buffer, MAX_PATH, inf);
3977 if (have_guid)
3979 buffer[lstrlenW(buffer)-1] = 0;
3980 if (RPC_S_OK != UuidFromStringW(buffer + 1, class_guid))
3982 FIXME("failed to convert \"%s\" into a guid\n", debugstr_w(buffer));
3983 SetLastError(ERROR_INVALID_PARAMETER);
3984 return FALSE;
3988 buffer[0] = '\0';
3989 dret = GetPrivateProfileStringW(Version, Class, NULL, buffer, MAX_PATH, inf);
3990 have_name = 0 < dret;
3992 if (dret >= MAX_PATH -1) FIXME("buffer might be too small\n");
3993 if (have_guid && !have_name) FIXME("class name lookup via guid not implemented\n");
3995 if (have_name)
3997 if (dret < size) lstrcpyW(class_name, buffer);
3998 else
4000 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4001 have_name = FALSE;
4005 if (required_size) *required_size = dret + ((dret) ? 1 : 0);
4007 return (have_guid || have_name);
4010 /***********************************************************************
4011 * SetupDiGetDevicePropertyW (SETUPAPI.@)
4013 BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO info_set, PSP_DEVINFO_DATA info_data,
4014 const DEVPROPKEY *prop_key, DEVPROPTYPE *prop_type, BYTE *prop_buff,
4015 DWORD prop_buff_size, DWORD *required_size, DWORD flags)
4017 FIXME("%p, %p, %p, %p, %p, %d, %p, 0x%08x stub\n", info_set, info_data, prop_key,
4018 prop_type, prop_buff, prop_buff_size, required_size, flags);
4020 SetLastError(ERROR_NOT_FOUND);
4021 return FALSE;