1 /*
2 * SetupAPI device installer
3 *
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "setupapi.h"
35 #include "wine/debug.h"
36 #include "wine/list.h"
37 #include "wine/unicode.h"
38 #include "cfgmgr32.h"
39 #include "winioctl.h"
40 #include "rpc.h"
41 #include "rpcdce.h"
42
43 #include "setupapi_private.h"
44
45
46 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
47
48 /* Unicode constants */
49 static const WCHAR Chicago[] = {'$','C','h','i','c','a','g','o','$',0};
50 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
51 static const WCHAR Class[] = {'C','l','a','s','s',0};
52 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
53 static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
54 static const WCHAR NoInstallClass[] = {'N','o','I','n','s','t','a','l','l','C','l','a','s','s',0};
55 static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
56 static const WCHAR NtExtension[] = {'.','N','T',0};
57 static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
58 static const WCHAR Signature[] = {'S','i','g','n','a','t','u','r','e',0};
59 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
60 static const WCHAR WinExtension[] = {'.','W','i','n',0};
61
62 /* Registry key and value names */
63 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
64 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
65 'C','o','n','t','r','o','l','\\',
66 'C','l','a','s','s',0};
67
68 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
69 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
70 'C','o','n','t','r','o','l','\\',
71 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
72 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
73 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
74 'E','n','u','m',0};
75 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
76 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
77 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
78 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
79 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
80 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
81 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
82 static const WCHAR Mfg[] = {'M','f','g',0};
83 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
84 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
85 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
86 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
87 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
88 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
89 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
90 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
91
92 /* is used to identify if a DeviceInfoSet pointer is
93 valid or not */
94 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
95
96 struct DeviceInfoSet
97 {
98 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
99 GUID ClassGuid;
100 HWND hwndParent;
101 DWORD cDevices;
102 struct list devices;
103 };
104
105 struct DeviceInstance
106 {
107 struct list entry;
108 SP_DEVINFO_DATA data;
109 };
110
111 /* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */
112 struct InterfaceInfo
113 {
114 LPWSTR referenceString;
115 LPWSTR symbolicLink;
116 PSP_DEVINFO_DATA device;
117 };
118
119 /* A device may have multiple instances of the same interface, so this holds
120 * each instance belonging to a particular interface.
121 */
122 struct InterfaceInstances
123 {
124 GUID guid;
125 DWORD cInstances;
126 DWORD cInstancesAllocated;
127 SP_DEVICE_INTERFACE_DATA *instances;
128 struct list entry;
129 };
130
131 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
132 struct DeviceInfo
133 {
134 struct DeviceInfoSet *set;
135 HKEY key;
136 BOOL phantom;
137 DWORD devId;
138 LPWSTR instanceId;
139 struct list interfaces;
140 };
141
142 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
143 {
144 static const WCHAR fmt[] = {'{','%','','8','X','-','%','','4','X','-',
145 '%','','4','X','-','%','','2','X','%','','2','X','-','%','','2',
146 'X','%','','2','X','%','','2','X','%','','2','X','%','','2','X','%',
147 '','2','X','}',0};
148
149 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
150 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
151 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
152 }
153
154 static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
155 {
156 DWORD i;
157
158 for (i = 0; i < instances->cInstances; i++)
159 {
160 struct InterfaceInfo *ifaceInfo =
161 (struct InterfaceInfo *)instances->instances[i].Reserved;
162
163 if (ifaceInfo->device && ifaceInfo->device->Reserved)
164 {
165 struct DeviceInfo *devInfo =
166 (struct DeviceInfo *)ifaceInfo->device->Reserved;
167
168 if (devInfo->phantom)
169 SetupDiDeleteDeviceInterfaceRegKey(devInfo->set,
170 &instances->instances[i], 0);
171 }
172 HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
173 HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
174 HeapFree(GetProcessHeap(), 0, ifaceInfo);
175 }
176 HeapFree(GetProcessHeap(), 0, instances->instances);
177 }
178
179 /* Finds the interface with interface class InterfaceClassGuid in the device.
180 * Returns TRUE if found, and updates *interface to point to device's
181 * interfaces member where the given interface was found.
182 * Returns FALSE if not found.
183 */
184 static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
185 const GUID *InterfaceClassGuid, struct InterfaceInstances **iface_ret)
186 {
187 BOOL found = FALSE;
188 struct InterfaceInstances *iface;
189
190 TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
191
192 LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances,
193 entry)
194 {
195 if (IsEqualGUID(&iface->guid, InterfaceClassGuid))
196 {
197 *iface_ret = iface;
198 found = TRUE;
199 break;
200 }
201 }
202 TRACE("returning %d (%p)\n", found, found ? *iface_ret : NULL);
203 return found;
204 }
205
206 /* Finds the interface instance with reference string ReferenceString in the
207 * interface instance map. Returns TRUE if found, and updates instanceIndex to
208 * the index of the interface instance's instances member
209 * where the given instance was found. Returns FALSE if not found.
210 */
211 static BOOL SETUPDI_FindInterfaceInstance(
212 const struct InterfaceInstances *instances,
213 LPCWSTR ReferenceString, DWORD *instanceIndex)
214 {
215 BOOL found = FALSE;
216 DWORD i;
217
218 TRACE("%s\n", debugstr_w(ReferenceString));
219
220 for (i = 0; !found && i < instances->cInstances; i++)
221 {
222 SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
223 struct InterfaceInfo *ifaceInfo =
224 (struct InterfaceInfo *)ifaceData->Reserved;
225
226 if (!ReferenceString && !ifaceInfo->referenceString)
227 {
228 *instanceIndex = i;
229 found = TRUE;
230 }
231 else if (ReferenceString && ifaceInfo->referenceString &&
232 !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
233 {
234 *instanceIndex = i;
235 found = TRUE;
236 }
237 }
238 TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
239 return found;
240 }
241
242 static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
243 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
244 {
245 static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
246 WCHAR guidStr[39];
247 DWORD len;
248 LPWSTR ret;
249
250 SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
251 /* omit length of format specifiers, but include NULL terminator: */
252 len = lstrlenW(fmt) - 4 + 1;
253 len += lstrlenW(instanceId) + lstrlenW(guidStr);
254 if (ReferenceString && *ReferenceString)
255 {
256 /* space for a hash between string and reference string: */
257 len += lstrlenW(ReferenceString) + 1;
258 }
259 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
260 if (ret)
261 {
262 int printed = sprintfW(ret, fmt, instanceId, guidStr);
263 LPWSTR ptr;
264
265 /* replace '\\' with '#' after the "\\\\?\\" beginning */
266 for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
267 *ptr = '#';
268 if (ReferenceString && *ReferenceString)
269 {
270 ret[printed] = '\\';
271 lstrcpyW(ret + printed + 1, ReferenceString);
272 }
273 }
274 return ret;
275 }
276
277 /* Adds an interface with the given interface class and reference string to
278 * the device, if it doesn't already exist in the device. If iface is not
279 * NULL, returns a pointer to the newly added (or already existing) interface.
280 */
281 static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData,
282 const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
283 SP_DEVICE_INTERFACE_DATA **ifaceData)
284 {
285 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
286 BOOL newInterface = FALSE, ret;
287 struct InterfaceInstances *iface = NULL;
288
289 TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
290 debugstr_w(ReferenceString), iface);
291
292 if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
293 {
294 iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
295 sizeof(struct InterfaceInstances));
296 if (iface)
297 {
298 list_add_tail(&devInfo->interfaces, &iface->entry);
299 newInterface = TRUE;
300 }
301 }
302 if (iface)
303 {
304 DWORD instanceIndex = 0;
305
306 if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
307 &instanceIndex)))
308 {
309 SP_DEVICE_INTERFACE_DATA *instance = NULL;
310
311 if (!iface->cInstancesAllocated)
312 {
313 iface->instances = HeapAlloc(GetProcessHeap(), 0,
314 sizeof(SP_DEVICE_INTERFACE_DATA));
315 if (iface->instances)
316 instance = &iface->instances[iface->cInstancesAllocated++];
317 }
318 else if (iface->cInstances == iface->cInstancesAllocated)
319 {
320 iface->instances = HeapReAlloc(GetProcessHeap(), 0,
321 iface->instances,
322 (iface->cInstancesAllocated + 1) *
323 sizeof(SP_DEVICE_INTERFACE_DATA));
324 if (iface->instances)
325 instance = &iface->instances[iface->cInstancesAllocated++];
326 }
327 else
328 instance = &iface->instances[iface->cInstances];
329 if (instance)
330 {
331 struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
332 0, sizeof(struct InterfaceInfo));
333
334 if (ifaceInfo)
335 {
336 ret = TRUE;
337 ifaceInfo->device = DeviceInfoData;
338 ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
339 devInfo->instanceId, InterfaceClassGuid,
340 ReferenceString);
341 if (ReferenceString)
342 {
343 ifaceInfo->referenceString =
344 HeapAlloc(GetProcessHeap(), 0,
345 (lstrlenW(ReferenceString) + 1) *
346 sizeof(WCHAR));
347 if (ifaceInfo->referenceString)
348 lstrcpyW(ifaceInfo->referenceString,
349 ReferenceString);
350 else
351 ret = FALSE;
352 }
353 else
354 ifaceInfo->referenceString = NULL;
355 if (ret)
356 {
357 HKEY key;
358
359 iface->cInstances++;
360 instance->cbSize =
361 sizeof(SP_DEVICE_INTERFACE_DATA);
362 instance->InterfaceClassGuid = *InterfaceClassGuid;
363 instance->Flags = SPINT_ACTIVE; /* FIXME */
364 instance->Reserved = (ULONG_PTR)ifaceInfo;
365 if (newInterface)
366 iface->guid = *InterfaceClassGuid;
367 key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set,
368 instance, 0, KEY_WRITE, NULL, NULL);
369 if (key != INVALID_HANDLE_VALUE)
370 {
371 RegSetValueExW(key, SymbolicLink, 0, REG_SZ,
372 (BYTE *)ifaceInfo->symbolicLink,
373 lstrlenW(ifaceInfo->symbolicLink) *
374 sizeof(WCHAR));
375 RegCloseKey(key);
376 }
377 if (ifaceData)
378 *ifaceData = instance;
379 }
380 else
381 HeapFree(GetProcessHeap(), 0, ifaceInfo);
382 }
383 }
384 }
385 else
386 {
387 if (ifaceData)
388 *ifaceData = &iface->instances[instanceIndex];
389 }
390 }
391 else
392 ret = FALSE;
393 TRACE("returning %d\n", ret);
394 return ret;
395 }
396
397 static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
398 LPCWSTR symbolicLink)
399 {
400 struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
401 BOOL ret = FALSE;
402
403 if (info)
404 {
405 HeapFree(GetProcessHeap(), 0, info->symbolicLink);
406 info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
407 (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
408 if (info->symbolicLink)
409 {
410 lstrcpyW(info->symbolicLink, symbolicLink);
411 ret = TRUE;
412 }
413 }
414 return ret;
415 }
416
417 static HKEY SETUPDI_CreateDevKey(struct DeviceInfo *devInfo)
418 {
419 HKEY enumKey, key = INVALID_HANDLE_VALUE;
420 LONG l;
421
422 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
423 NULL, &enumKey, NULL);
424 if (!l)
425 {
426 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
427 KEY_READ | KEY_WRITE, NULL, &key, NULL);
428 RegCloseKey(enumKey);
429 }
430 return key;
431 }
432
433 static HKEY SETUPDI_CreateDrvKey(struct DeviceInfo *devInfo)
434 {
435 static const WCHAR slash[] = { '\\',0 };
436 WCHAR classKeyPath[MAX_PATH];
437 HKEY classKey, key = INVALID_HANDLE_VALUE;
438 LONG l;
439
440 lstrcpyW(classKeyPath, ControlClass);
441 lstrcatW(classKeyPath, slash);
442 SETUPDI_GuidToString(&devInfo->set->ClassGuid,
443 classKeyPath + lstrlenW(classKeyPath));
444 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
445 KEY_ALL_ACCESS, NULL, &classKey, NULL);
446 if (!l)
447 {
448 static const WCHAR fmt[] = { '%','','4','u',0 };
449 WCHAR devId[10];
450
451 sprintfW(devId, fmt, devInfo->devId);
452 RegCreateKeyExW(classKey, devId, 0, NULL, 0, KEY_READ | KEY_WRITE,
453 NULL, &key, NULL);
454 RegCloseKey(classKey);
455 }
456 return key;
457 }
458
459 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
460 DWORD devId, LPCWSTR instanceId, BOOL phantom)
461 {
462 struct DeviceInfo *devInfo = NULL;
463 HANDLE devInst = GlobalAlloc(GMEM_FIXED, sizeof(struct DeviceInfo));
464 if (devInst)
465 devInfo = GlobalLock(devInst);
466
467 if (devInfo)
468 {
469 devInfo->set = set;
470 devInfo->devId = (DWORD)devInst;
471
472 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
473 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
474 if (devInfo->instanceId)
475 {
476 devInfo->key = INVALID_HANDLE_VALUE;
477 devInfo->phantom = phantom;
478 lstrcpyW(devInfo->instanceId, instanceId);
479 struprW(devInfo->instanceId);
480 devInfo->key = SETUPDI_CreateDevKey(devInfo);
481 if (devInfo->key != INVALID_HANDLE_VALUE)
482 {
483 if (phantom)
484 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
485 (LPBYTE)&phantom, sizeof(phantom));
486 }
487 list_init(&devInfo->interfaces);
488 GlobalUnlock(devInst);
489 }
490 else
491 {
492 GlobalUnlock(devInst);
493 GlobalFree(devInst);
494 devInfo = NULL;
495 }
496 }
497 return devInfo;
498 }
499
500 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
501 {
502 struct InterfaceInstances *iface, *next;
503
504 if (devInfo->key != INVALID_HANDLE_VALUE)
505 RegCloseKey(devInfo->key);
506 if (devInfo->phantom)
507 {
508 HKEY enumKey;
509 LONG l;
510
511 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
512 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
513 if (!l)
514 {
515 RegDeleteTreeW(enumKey, devInfo->instanceId);
516 RegCloseKey(enumKey);
517 }
518 }
519 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
520 LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
521 struct InterfaceInstances, entry)
522 {
523 list_remove(&iface->entry);
524 SETUPDI_FreeInterfaceInstances(iface);
525 HeapFree(GetProcessHeap(), 0, iface);
526 }
527 GlobalFree((HANDLE)devInfo->devId);
528 }
529
530 /* Adds a device with GUID guid and identifier devInst to set. Allocates a
531 * struct DeviceInfo, and points the returned device info's Reserved member
532 * to it. "Phantom" devices are deleted from the registry when closed.
533 * Returns a pointer to the newly allocated device info.
534 */
535 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
536 const GUID *guid,
537 DWORD devInst,
538 LPCWSTR instanceId,
539 BOOL phantom,
540 SP_DEVINFO_DATA **dev)
541 {
542 BOOL ret = FALSE;
543 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, set->cDevices,
544 instanceId, phantom);
545
546 TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
547 debugstr_w(instanceId), phantom);
548
549 if (devInfo)
550 {
551 struct DeviceInstance *devInst =
552 HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInstance));
553
554 if (devInst)
555 {
556 WCHAR classGuidStr[39];
557
558 list_add_tail(&set->devices, &devInst->entry);
559 set->cDevices++;
560 devInst->data.cbSize = sizeof(SP_DEVINFO_DATA);
561 devInst->data.ClassGuid = *guid;
562 devInst->data.DevInst = devInfo->devId;
563 devInst->data.Reserved = (ULONG_PTR)devInfo;
564 SETUPDI_GuidToString(guid, classGuidStr);
565 SetupDiSetDeviceRegistryPropertyW(set, &devInst->data,
566 SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
567 lstrlenW(classGuidStr) * sizeof(WCHAR));
568 if (dev) *dev = &devInst->data;
569 ret = TRUE;
570 }
571 else
572 {
573 HeapFree(GetProcessHeap(), 0, devInfo);
574 SetLastError(ERROR_OUTOFMEMORY);
575 }
576 }
577 return ret;
578 }
579
580 /***********************************************************************
581 * SetupDiBuildClassInfoList (SETUPAPI.@)
582 *
583 * Returns a list of setup class GUIDs that identify the classes
584 * that are installed on a local machine.
585 *
586 * PARAMS
587 * Flags [I] control exclusion of classes from the list.
588 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
589 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
590 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
591 *
592 * RETURNS
593 * Success: TRUE.
594 * Failure: FALSE.
595 */
596 BOOL WINAPI SetupDiBuildClassInfoList(
597 DWORD Flags,
598 LPGUID ClassGuidList,
599 DWORD ClassGuidListSize,
600 PDWORD RequiredSize)
601 {
602 TRACE("\n");
603 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
604 ClassGuidListSize, RequiredSize,
605 NULL, NULL);
606 }
607
608 /***********************************************************************
609 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
610 *
611 * Returns a list of setup class GUIDs that identify the classes
612 * that are installed on a local or remote machine.
613 *
614 * PARAMS
615 * Flags [I] control exclusion of classes from the list.
616 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
617 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
618 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
619 * MachineName [I] name of a remote machine.
620 * Reserved [I] must be NULL.
621 *
622 * RETURNS
623 * Success: TRUE.
624 * Failure: FALSE.
625 */
626 BOOL WINAPI SetupDiBuildClassInfoListExA(
627 DWORD Flags,
628 LPGUID ClassGuidList,
629 DWORD ClassGuidListSize,
630 PDWORD RequiredSize,
631 LPCSTR MachineName,
632 PVOID Reserved)
633 {
634 LPWSTR MachineNameW = NULL;
635 BOOL bResult;
636
637 TRACE("\n");
638
639 if (MachineName)
640 {
641 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
642 if (MachineNameW == NULL) return FALSE;
643 }
644
645 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
646 ClassGuidListSize, RequiredSize,
647 MachineNameW, Reserved);
648
649 MyFree(MachineNameW);
650
651 return bResult;
652 }
653
654 /***********************************************************************
655 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
656 *
657 * Returns a list of setup class GUIDs that identify the classes
658 * that are installed on a local or remote machine.
659 *
660 * PARAMS
661 * Flags [I] control exclusion of classes from the list.
662 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
663 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
664 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
665 * MachineName [I] name of a remote machine.
666 * Reserved [I] must be NULL.
667 *
668 * RETURNS
669 * Success: TRUE.
670 * Failure: FALSE.
671 */
672 BOOL WINAPI SetupDiBuildClassInfoListExW(
673 DWORD Flags,
674 LPGUID ClassGuidList,
675 DWORD ClassGuidListSize,
676 PDWORD RequiredSize,
677 LPCWSTR MachineName,
678 PVOID Reserved)
679 {
680 WCHAR szKeyName[40];
681 HKEY hClassesKey;
682 HKEY hClassKey;
683 DWORD dwLength;
684 DWORD dwIndex;
685 LONG lError;
686 DWORD dwGuidListIndex = 0;
687
688 TRACE("\n");
689
690 if (RequiredSize != NULL)
691 *RequiredSize = 0;
692
693 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
694 KEY_ALL_ACCESS,
695 DIOCR_INSTALLER,
696 MachineName,
697 Reserved);
698 if (hClassesKey == INVALID_HANDLE_VALUE)
699 {
700 return FALSE;
701 }
702
703 for (dwIndex = 0; ; dwIndex++)
704 {
705 dwLength = 40;
706 lError = RegEnumKeyExW(hClassesKey,
707 dwIndex,
708 szKeyName,
709 &dwLength,
710 NULL,
711 NULL,
712 NULL,
713 NULL);
714 TRACE("RegEnumKeyExW() returns %d\n", lError);
715 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
716 {
717 TRACE("Key name: %p\n", szKeyName);
718
719 if (RegOpenKeyExW(hClassesKey,
720 szKeyName,
721 0,
722 KEY_ALL_ACCESS,
723 &hClassKey))
724 {
725 RegCloseKey(hClassesKey);
726 return FALSE;
727 }
728
729 if (!RegQueryValueExW(hClassKey,
730 NoUseClass,
731 NULL,
732 NULL,
733 NULL,
734 NULL))
735 {
736 TRACE("'NoUseClass' value found!\n");
737 RegCloseKey(hClassKey);
738 continue;
739 }
740
741 if ((Flags & DIBCI_NOINSTALLCLASS) &&
742 (!RegQueryValueExW(hClassKey,
743 NoInstallClass,
744 NULL,
745 NULL,
746 NULL,
747 NULL)))
748 {
749 TRACE("'NoInstallClass' value found!\n");
750 RegCloseKey(hClassKey);
751 continue;
752 }
753
754 if ((Flags & DIBCI_NODISPLAYCLASS) &&
755 (!RegQueryValueExW(hClassKey,
756 NoDisplayClass,
757 NULL,
758 NULL,
759 NULL,
760 NULL)))
761 {
762 TRACE("'NoDisplayClass' value found!\n");
763 RegCloseKey(hClassKey);
764 continue;
765 }
766
767 RegCloseKey(hClassKey);
768
769 TRACE("Guid: %p\n", szKeyName);
770 if (dwGuidListIndex < ClassGuidListSize)
771 {
772 if (szKeyName[0] == '{' && szKeyName[37] == '}')
773 {
774 szKeyName[37] = 0;
775 }
776 TRACE("Guid: %p\n", &szKeyName[1]);
777
778 UuidFromStringW(&szKeyName[1],
779 &ClassGuidList[dwGuidListIndex]);
780 }
781
782 dwGuidListIndex++;
783 }
784
785 if (lError != ERROR_SUCCESS)
786 break;
787 }
788
789 RegCloseKey(hClassesKey);
790
791 if (RequiredSize != NULL)
792 *RequiredSize = dwGuidListIndex;
793
794 if (ClassGuidListSize < dwGuidListIndex)
795 {
796 SetLastError(ERROR_INSUFFICIENT_BUFFER);
797 return FALSE;
798 }
799
800 return TRUE;
801 }
802
803 /***********************************************************************
804 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
805 */
806 BOOL WINAPI SetupDiClassGuidsFromNameA(
807 LPCSTR ClassName,
808 LPGUID ClassGuidList,
809 DWORD ClassGuidListSize,
810 PDWORD RequiredSize)
811 {
812 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
813 ClassGuidListSize, RequiredSize,
814 NULL, NULL);
815 }
816
817 /***********************************************************************
818 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
819 */
820 BOOL WINAPI SetupDiClassGuidsFromNameW(
821 LPCWSTR ClassName,
822 LPGUID ClassGuidList,
823 DWORD ClassGuidListSize,
824 PDWORD RequiredSize)
825 {
826 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
827 ClassGuidListSize, RequiredSize,
828 NULL, NULL);
829 }
830
831 /***********************************************************************
832 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
833 */
834 BOOL WINAPI SetupDiClassGuidsFromNameExA(
835 LPCSTR ClassName,
836 LPGUID ClassGuidList,
837 DWORD ClassGuidListSize,
838 PDWORD RequiredSize,
839 LPCSTR MachineName,
840 PVOID Reserved)
841 {
842 LPWSTR ClassNameW = NULL;
843 LPWSTR MachineNameW = NULL;
844 BOOL bResult;
845
846 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
847 if (ClassNameW == NULL)
848 return FALSE;
849
850 if (MachineName)
851 {
852 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
853 if (MachineNameW == NULL)
854 {
855 MyFree(ClassNameW);
856 return FALSE;
857 }
858 }
859
860 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
861 ClassGuidListSize, RequiredSize,
862 MachineNameW, Reserved);
863
864 MyFree(MachineNameW);
865 MyFree(ClassNameW);
866
867 return bResult;
868 }
869
870 /***********************************************************************
871 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
872 */
873 BOOL WINAPI SetupDiClassGuidsFromNameExW(
874 LPCWSTR ClassName,
875 LPGUID ClassGuidList,
876 DWORD ClassGuidListSize,
877 PDWORD RequiredSize,
878 LPCWSTR MachineName,
879 PVOID Reserved)
880 {
881 WCHAR szKeyName[40];
882 WCHAR szClassName[256];
883 HKEY hClassesKey;
884 HKEY hClassKey;
885 DWORD dwLength;
886 DWORD dwIndex;
887 LONG lError;
888 DWORD dwGuidListIndex = 0;
889
890 if (RequiredSize != NULL)
891 *RequiredSize = 0;
892
893 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
894 KEY_ALL_ACCESS,
895 DIOCR_INSTALLER,
896 MachineName,
897 Reserved);
898 if (hClassesKey == INVALID_HANDLE_VALUE)
899 {
900 return FALSE;
901 }
902
903 for (dwIndex = 0; ; dwIndex++)
904 {
905 dwLength = 40;
906 lError = RegEnumKeyExW(hClassesKey,
907 dwIndex,
908 szKeyName,
909 &dwLength,
910 NULL,
911 NULL,
912 NULL,
913 NULL);
914 TRACE("RegEnumKeyExW() returns %d\n", lError);
915 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
916 {
917 TRACE("Key name: %p\n", szKeyName);
918
919 if (RegOpenKeyExW(hClassesKey,
920 szKeyName,
921 0,
922 KEY_ALL_ACCESS,
923 &hClassKey))
924 {
925 RegCloseKey(hClassesKey);
926 return FALSE;
927 }
928
929 dwLength = 256 * sizeof(WCHAR);
930 if (!RegQueryValueExW(hClassKey,
931 Class,
932 NULL,
933 NULL,
934 (LPBYTE)szClassName,
935 &dwLength))
936 {
937 TRACE("Class name: %p\n", szClassName);
938
939 if (strcmpiW(szClassName, ClassName) == 0)
940 {
941 TRACE("Found matching class name\n");
942
943 TRACE("Guid: %p\n", szKeyName);
944 if (dwGuidListIndex < ClassGuidListSize)
945 {
946 if (szKeyName[0] == '{' && szKeyName[37] == '}')
947 {
948 szKeyName[37] = 0;
949 }
950 TRACE("Guid: %p\n", &szKeyName[1]);
951
952 UuidFromStringW(&szKeyName[1],
953 &ClassGuidList[dwGuidListIndex]);
954 }
955
956 dwGuidListIndex++;
957 }
958 }
959
960 RegCloseKey(hClassKey);
961 }
962
963 if (lError != ERROR_SUCCESS)
964 break;
965 }
966
967 RegCloseKey(hClassesKey);
968
969 if (RequiredSize != NULL)
970 *RequiredSize = dwGuidListIndex;
971
972 if (ClassGuidListSize < dwGuidListIndex)
973 {
974 SetLastError(ERROR_INSUFFICIENT_BUFFER);
975 return FALSE;
976 }
977
978 return TRUE;
979 }
980
981 /***********************************************************************
982 * SetupDiClassNameFromGuidA (SETUPAPI.@)
983 */
984 BOOL WINAPI SetupDiClassNameFromGuidA(
985 const GUID* ClassGuid,
986 PSTR ClassName,
987 DWORD ClassNameSize,
988 PDWORD RequiredSize)
989 {
990 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
991 ClassNameSize, RequiredSize,
992 NULL, NULL);
993 }
994
995 /***********************************************************************
996 * SetupDiClassNameFromGuidW (SETUPAPI.@)
997 */
998 BOOL WINAPI SetupDiClassNameFromGuidW(
999 const GUID* ClassGuid,
1000 PWSTR ClassName,
1001 DWORD ClassNameSize,
1002 PDWORD RequiredSize)
1003 {
1004 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1005 ClassNameSize, RequiredSize,
1006 NULL, NULL);
1007 }
1008
1009 /***********************************************************************
1010 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1011 */
1012 BOOL WINAPI SetupDiClassNameFromGuidExA(
1013 const GUID* ClassGuid,
1014 PSTR ClassName,
1015 DWORD ClassNameSize,
1016 PDWORD RequiredSize,
1017 PCSTR MachineName,
1018 PVOID Reserved)
1019 {
1020 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1021 LPWSTR MachineNameW = NULL;
1022 BOOL ret;
1023
1024 if (MachineName)
1025 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1026 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1027 NULL, MachineNameW, Reserved);
1028 if (ret)
1029 {
1030 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1031 ClassNameSize, NULL, NULL);
1032
1033 if (!ClassNameSize && RequiredSize)
1034 *RequiredSize = len;
1035 }
1036 MyFree(MachineNameW);
1037 return ret;
1038 }
1039
1040 /***********************************************************************
1041 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1042 */
1043 BOOL WINAPI SetupDiClassNameFromGuidExW(
1044 const GUID* ClassGuid,
1045 PWSTR ClassName,
1046 DWORD ClassNameSize,
1047 PDWORD RequiredSize,
1048 PCWSTR MachineName,
1049 PVOID Reserved)
1050 {
1051 HKEY hKey;
1052 DWORD dwLength;
1053
1054 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1055 KEY_ALL_ACCESS,
1056 DIOCR_INSTALLER,
1057 MachineName,
1058 Reserved);
1059 if (hKey == INVALID_HANDLE_VALUE)
1060 {
1061 return FALSE;
1062 }
1063
1064 if (RequiredSize != NULL)
1065 {
1066 dwLength = 0;
1067 if (RegQueryValueExW(hKey,
1068 Class,
1069 NULL,
1070 NULL,
1071 NULL,
1072 &dwLength))
1073 {
1074 RegCloseKey(hKey);
1075 return FALSE;
1076 }
1077
1078 *RequiredSize = dwLength / sizeof(WCHAR);
1079 }
1080
1081 dwLength = ClassNameSize * sizeof(WCHAR);
1082 if (RegQueryValueExW(hKey,
1083 Class,
1084 NULL,
1085 NULL,
1086 (LPBYTE)ClassName,
1087 &dwLength))
1088 {
1089 RegCloseKey(hKey);
1090 return FALSE;
1091 }
1092
1093 RegCloseKey(hKey);
1094
1095 return TRUE;
1096 }
1097
1098 /***********************************************************************
1099 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1100 */
1101 HDEVINFO WINAPI
1102 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1103 HWND hwndParent)
1104 {
1105 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1106 }
1107
1108 /***********************************************************************
1109 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1110 */
1111 HDEVINFO WINAPI
1112 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1113 HWND hwndParent,
1114 PCSTR MachineName,
1115 PVOID Reserved)
1116 {
1117 LPWSTR MachineNameW = NULL;
1118 HDEVINFO hDevInfo;
1119
1120 TRACE("\n");
1121
1122 if (MachineName)
1123 {
1124 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1125 if (MachineNameW == NULL)
1126 return INVALID_HANDLE_VALUE;
1127 }
1128
1129 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1130 MachineNameW, Reserved);
1131
1132 MyFree(MachineNameW);
1133
1134 return hDevInfo;
1135 }
1136
1137 /***********************************************************************
1138 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1139 *
1140 * Create an empty DeviceInfoSet list.
1141 *
1142 * PARAMS
1143 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1144 * with this list.
1145 * hwndParent [I] hwnd needed for interface related actions.
1146 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1147 * local registry will be used.
1148 * Reserved [I] must be NULL
1149 *
1150 * RETURNS
1151 * Success: empty list.
1152 * Failure: INVALID_HANDLE_VALUE.
1153 */
1154 HDEVINFO WINAPI
1155 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1156 HWND hwndParent,
1157 PCWSTR MachineName,
1158 PVOID Reserved)
1159 {
1160 struct DeviceInfoSet *list = NULL;
1161 DWORD size = sizeof(struct DeviceInfoSet);
1162
1163 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1164 debugstr_w(MachineName), Reserved);
1165
1166 if (MachineName && *MachineName)
1167 {
1168 FIXME("remote support is not implemented\n");
1169 SetLastError(ERROR_INVALID_MACHINENAME);
1170 return INVALID_HANDLE_VALUE;
1171 }
1172
1173 if (Reserved != NULL)
1174 {
1175 SetLastError(ERROR_INVALID_PARAMETER);
1176 return INVALID_HANDLE_VALUE;
1177 }
1178
1179 list = HeapAlloc(GetProcessHeap(), 0, size);
1180 if (!list)
1181 {
1182 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1183 return INVALID_HANDLE_VALUE;
1184 }
1185
1186 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1187 list->hwndParent = hwndParent;
1188 memcpy(&list->ClassGuid,
1189 ClassGuid ? ClassGuid : &GUID_NULL,
1190 sizeof(list->ClassGuid));
1191 list->cDevices = 0;
1192 list_init(&list->devices);
1193
1194 return list;
1195 }
1196
1197 /***********************************************************************
1198 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1199 */
1200 HKEY WINAPI SetupDiCreateDevRegKeyA(
1201 HDEVINFO DeviceInfoSet,
1202 PSP_DEVINFO_DATA DeviceInfoData,
1203 DWORD Scope,
1204 DWORD HwProfile,
1205 DWORD KeyType,
1206 HINF InfHandle,
1207 PCSTR InfSectionName)
1208 {
1209 PWSTR InfSectionNameW = NULL;
1210 HKEY key;
1211
1212 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1213 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1214
1215 if (InfHandle)
1216 {
1217 if (!InfSectionName)
1218 {
1219 SetLastError(ERROR_INVALID_PARAMETER);
1220 return INVALID_HANDLE_VALUE;
1221 }
1222 else
1223 {
1224 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1225 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1226 }
1227 }
1228 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1229 HwProfile, KeyType, InfHandle, InfSectionNameW);
1230 MyFree(InfSectionNameW);
1231 return key;
1232 }
1233
1234 /***********************************************************************
1235 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1236 */
1237 HKEY WINAPI SetupDiCreateDevRegKeyW(
1238 HDEVINFO DeviceInfoSet,
1239 PSP_DEVINFO_DATA DeviceInfoData,
1240 DWORD Scope,
1241 DWORD HwProfile,
1242 DWORD KeyType,
1243 HINF InfHandle,
1244 PCWSTR InfSectionName)
1245 {
1246 struct DeviceInfoSet *set = DeviceInfoSet;
1247 struct DeviceInfo *devInfo;
1248 HKEY key = INVALID_HANDLE_VALUE;
1249
1250 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1251 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1252
1253 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1254 {
1255 SetLastError(ERROR_INVALID_HANDLE);
1256 return INVALID_HANDLE_VALUE;
1257 }
1258 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1259 {
1260 SetLastError(ERROR_INVALID_HANDLE);
1261 return INVALID_HANDLE_VALUE;
1262 }
1263 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1264 || !DeviceInfoData->Reserved)
1265 {
1266 SetLastError(ERROR_INVALID_PARAMETER);
1267 return INVALID_HANDLE_VALUE;
1268 }
1269 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1270 if (devInfo->set != set)
1271 {
1272 SetLastError(ERROR_INVALID_PARAMETER);
1273 return INVALID_HANDLE_VALUE;
1274 }
1275 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1276 {
1277 SetLastError(ERROR_INVALID_FLAGS);
1278 return INVALID_HANDLE_VALUE;
1279 }
1280 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1281 {
1282 SetLastError(ERROR_INVALID_FLAGS);
1283 return INVALID_HANDLE_VALUE;
1284 }
1285 if (devInfo->phantom)
1286 {
1287 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
1288 return INVALID_HANDLE_VALUE;
1289 }
1290 if (Scope != DICS_FLAG_GLOBAL)
1291 FIXME("unimplemented for scope %d\n", Scope);
1292 switch (KeyType)
1293 {
1294 case DIREG_DEV:
1295 key = SETUPDI_CreateDevKey(devInfo);
1296 break;
1297 case DIREG_DRV:
1298 key = SETUPDI_CreateDrvKey(devInfo);
1299 break;
1300 default:
1301 WARN("unknown KeyType %d\n", KeyType);
1302 }
1303 if (InfHandle)
1304 SetupInstallFromInfSectionW(NULL, InfHandle, InfSectionName, SPINST_ALL,
1305 NULL, NULL, SP_COPY_NEWER_ONLY, NULL, NULL, DeviceInfoSet,
1306 DeviceInfoData);
1307 return key;
1308 }
1309
1310 /***********************************************************************
1311 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1312 */
1313 BOOL WINAPI SetupDiCreateDeviceInfoA(
1314 HDEVINFO DeviceInfoSet,
1315 PCSTR DeviceName,
1316 CONST GUID *ClassGuid,
1317 PCSTR DeviceDescription,
1318 HWND hwndParent,
1319 DWORD CreationFlags,
1320 PSP_DEVINFO_DATA DeviceInfoData)
1321 {
1322 BOOL ret = FALSE;
1323 LPWSTR DeviceNameW = NULL;
1324 LPWSTR DeviceDescriptionW = NULL;
1325
1326 if (DeviceName)
1327 {
1328 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1329 if (DeviceNameW == NULL) return FALSE;
1330 }
1331 if (DeviceDescription)
1332 {
1333 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1334 if (DeviceDescriptionW == NULL)
1335 {
1336 MyFree(DeviceNameW);
1337 return FALSE;
1338 }
1339 }
1340
1341 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1342 hwndParent, CreationFlags, DeviceInfoData);
1343
1344 MyFree(DeviceNameW);
1345 MyFree(DeviceDescriptionW);
1346
1347 return ret;
1348 }
1349
1350 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
1351 {
1352 LPCWSTR ptr;
1353 int devNameLen = lstrlenW(devName);
1354 DWORD devInst = 0;
1355 BOOL valid = TRUE;
1356
1357 TRACE("%s\n", debugstr_w(devName));
1358 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
1359 {
1360 if (isdigitW(*ptr))
1361 {
1362 devInst *= 10;
1363 devInst |= *ptr - '';
1364 ptr++;
1365 }
1366 else
1367 valid = FALSE;
1368 }
1369 TRACE("%d\n", valid ? devInst : 0xffffffff);
1370 return valid ? devInst : 0xffffffff;
1371 }
1372
1373 /***********************************************************************
1374 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1375 */
1376 BOOL WINAPI SetupDiCreateDeviceInfoW(
1377 HDEVINFO DeviceInfoSet,
1378 PCWSTR DeviceName,
1379 CONST GUID *ClassGuid,
1380 PCWSTR DeviceDescription,
1381 HWND hwndParent,
1382 DWORD CreationFlags,
1383 PSP_DEVINFO_DATA DeviceInfoData)
1384 {
1385 struct DeviceInfoSet *set = DeviceInfoSet;
1386 BOOL ret = FALSE, allocatedInstanceId = FALSE;
1387 LPCWSTR instanceId = NULL;
1388
1389 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1390 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1391 hwndParent, CreationFlags, DeviceInfoData);
1392
1393 if (!DeviceName)
1394 {
1395 SetLastError(ERROR_INVALID_DEVINST_NAME);
1396 return FALSE;
1397 }
1398 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1399 {
1400 SetLastError(ERROR_INVALID_HANDLE);
1401 return FALSE;
1402 }
1403 if (!ClassGuid)
1404 {
1405 SetLastError(ERROR_INVALID_PARAMETER);
1406 return FALSE;
1407 }
1408 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1409 {
1410 SetLastError(ERROR_INVALID_HANDLE);
1411 return FALSE;
1412 }
1413 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1414 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1415 {
1416 SetLastError(ERROR_CLASS_MISMATCH);
1417 return FALSE;
1418 }
1419 if ((CreationFlags & DICD_GENERATE_ID))
1420 {
1421 if (strchrW(DeviceName, '\\'))
1422 SetLastError(ERROR_INVALID_DEVINST_NAME);
1423 else
1424 {
1425 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
1426 '\\','%','','4','d',0};
1427 DWORD devId;
1428
1429 if (set->cDevices)
1430 {
1431 DWORD highestDevID = 0;
1432 struct DeviceInstance *devInst;
1433
1434 LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
1435 {
1436 struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
1437 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
1438 DWORD id;
1439
1440 if (devName)
1441 devName++;
1442 else
1443 devName = devInfo->instanceId;
1444 id = SETUPDI_DevNameToDevID(devName);
1445 if (id != 0xffffffff && id > highestDevID)
1446 highestDevID = id;
1447 }
1448 devId = highestDevID + 1;
1449 }
1450 else
1451 devId = 0;
1452 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
1453 instanceId = HeapAlloc(GetProcessHeap(), 0,
1454 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
1455 if (instanceId)
1456 {
1457 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1458 devId);
1459 allocatedInstanceId = TRUE;
1460 ret = TRUE;
1461 }
1462 else
1463 ret = FALSE;
1464 }
1465 }
1466 else
1467 {
1468 struct DeviceInstance *devInst;
1469
1470 ret = TRUE;
1471 instanceId = DeviceName;
1472 LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
1473 {
1474 struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
1475
1476 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1477 {
1478 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1479 ret = FALSE;
1480 }
1481 }
1482 }
1483 if (ret)
1484 {
1485 SP_DEVINFO_DATA *dev = NULL;
1486
1487 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1488 instanceId, TRUE, &dev);
1489 if (ret)
1490 {
1491 if (DeviceDescription)
1492 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1493 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1494 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1495 if (DeviceInfoData)
1496 {
1497 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1498 {
1499 SetLastError(ERROR_INVALID_USER_BUFFER);
1500 ret = FALSE;
1501 }
1502 else
1503 *DeviceInfoData = *dev;
1504 }
1505 }
1506 }
1507 if (allocatedInstanceId)
1508 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1509
1510 return ret;
1511 }
1512
1513 /***********************************************************************
1514 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1515 */
1516 BOOL WINAPI SetupDiRegisterDeviceInfo(
1517 HDEVINFO DeviceInfoSet,
1518 PSP_DEVINFO_DATA DeviceInfoData,
1519 DWORD Flags,
1520 PSP_DETSIG_CMPPROC CompareProc,
1521 PVOID CompareContext,
1522 PSP_DEVINFO_DATA DupDeviceInfoData)
1523 {
1524 struct DeviceInfoSet *set = DeviceInfoSet;
1525 struct DeviceInfo *devInfo;
1526
1527 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1528 CompareProc, CompareContext, DupDeviceInfoData);
1529
1530 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1531 {
1532 SetLastError(ERROR_INVALID_HANDLE);
1533 return FALSE;
1534 }
1535 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1536 {
1537 SetLastError(ERROR_INVALID_HANDLE);
1538 return FALSE;
1539 }
1540 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1541 || !DeviceInfoData->Reserved)
1542 {
1543 SetLastError(ERROR_INVALID_PARAMETER);
1544 return FALSE;
1545 }
1546 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1547 if (devInfo->set != set)
1548 {
1549 SetLastError(ERROR_INVALID_PARAMETER);
1550 return FALSE;
1551 }
1552 if (devInfo->phantom)
1553 {
1554 devInfo->phantom = FALSE;
1555 RegDeleteValueW(devInfo->key, Phantom);
1556 }
1557 return TRUE;
1558 }
1559
1560 /***********************************************************************
1561 * SetupDiRemoveDevice (SETUPAPI.@)
1562 */
1563 BOOL WINAPI SetupDiRemoveDevice(
1564 HDEVINFO devinfo,
1565 PSP_DEVINFO_DATA info)
1566 {
1567 FIXME("(%p, %p): stub\n", devinfo, info);
1568 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1569 return FALSE;
1570 }
1571
1572 /***********************************************************************
1573 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1574 */
1575 BOOL WINAPI SetupDiEnumDeviceInfo(
1576 HDEVINFO devinfo,
1577 DWORD index,
1578 PSP_DEVINFO_DATA info)
1579 {
1580 BOOL ret = FALSE;
1581
1582 TRACE("%p %d %p\n", devinfo, index, info);
1583
1584 if(info==NULL)
1585 {
1586 SetLastError(ERROR_INVALID_PARAMETER);
1587 return FALSE;
1588 }
1589 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1590 {
1591 struct DeviceInfoSet *list = devinfo;
1592 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1593 {
1594 if (index < list->cDevices)
1595 {
1596 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1597 {
1598 struct DeviceInstance *devInst;
1599 DWORD i = 0;
1600
1601 LIST_FOR_EACH_ENTRY(devInst, &list->devices,
1602 struct DeviceInstance, entry)
1603 {
1604 if (i++ == index)
1605 {
1606 *info = devInst->data;
1607 break;
1608 }
1609 }
1610 ret = TRUE;
1611 }
1612 else
1613 SetLastError(ERROR_INVALID_USER_BUFFER);
1614 }
1615 else
1616 SetLastError(ERROR_NO_MORE_ITEMS);
1617 }
1618 else
1619 SetLastError(ERROR_INVALID_HANDLE);
1620 }
1621 else
1622 SetLastError(ERROR_INVALID_HANDLE);
1623 return ret;
1624 }
1625
1626 /***********************************************************************
1627 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1628 */
1629 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1630 HDEVINFO DeviceInfoSet,
1631 PSP_DEVINFO_DATA DeviceInfoData,
1632 PSTR DeviceInstanceId,
1633 DWORD DeviceInstanceIdSize,
1634 PDWORD RequiredSize)
1635 {
1636 BOOL ret = FALSE;
1637 DWORD size;
1638 PWSTR instanceId;
1639
1640 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1641 DeviceInstanceIdSize, RequiredSize);
1642
1643 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1644 DeviceInfoData,
1645 NULL,
1646 0,
1647 &size);
1648 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1649 return FALSE;
1650 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1651 if (instanceId)
1652 {
1653 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1654 DeviceInfoData,
1655 instanceId,
1656 size,
1657 &size);
1658 if (ret)
1659 {
1660 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1661 DeviceInstanceId,
1662 DeviceInstanceIdSize, NULL, NULL);
1663
1664 if (!len)
1665 ret = FALSE;
1666 else
1667 {
1668 if (len > DeviceInstanceIdSize)
1669 {
1670 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1671 ret = FALSE;
1672 }
1673 if (RequiredSize)
1674 *RequiredSize = len;
1675 }
1676 }
1677 HeapFree(GetProcessHeap(), 0, instanceId);
1678 }
1679 return ret;
1680 }
1681
1682 /***********************************************************************
1683 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1684 */
1685 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1686 HDEVINFO DeviceInfoSet,
1687 PSP_DEVINFO_DATA DeviceInfoData,
1688 PWSTR DeviceInstanceId,
1689 DWORD DeviceInstanceIdSize,
1690 PDWORD RequiredSize)
1691 {
1692 struct DeviceInfoSet *set = DeviceInfoSet;
1693 struct DeviceInfo *devInfo;
1694
1695 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1696 DeviceInstanceIdSize, RequiredSize);
1697
1698 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1699 {
1700 SetLastError(ERROR_INVALID_HANDLE);
1701 return FALSE;
1702 }
1703 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1704 {
1705 SetLastError(ERROR_INVALID_HANDLE);
1706 return FALSE;
1707 }
1708 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1709 || !DeviceInfoData->Reserved)
1710 {
1711 SetLastError(ERROR_INVALID_PARAMETER);
1712 return FALSE;
1713 }
1714 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1715 if (devInfo->set != set)
1716 {
1717 SetLastError(ERROR_INVALID_PARAMETER);
1718 return FALSE;
1719 }
1720 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1721 if (DeviceInstanceIdSize < strlenW(devInfo->instanceId) + 1)
1722 {
1723 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1724 if (RequiredSize)
1725 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1726 return FALSE;
1727 }
1728 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1729 if (RequiredSize)
1730 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1731 return TRUE;
1732 }
1733
1734 /***********************************************************************
1735 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1736 */
1737 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1738 HINF InfHandle,
1739 PCSTR InfSectionName,
1740 PSTR InfSectionWithExt,
1741 DWORD InfSectionWithExtSize,
1742 PDWORD RequiredSize,
1743 PSTR *Extension)
1744 {
1745 FIXME("\n");
1746 return FALSE;
1747 }
1748
1749 /***********************************************************************
1750 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1751 */
1752 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1753 HINF InfHandle,
1754 PCWSTR InfSectionName,
1755 PWSTR InfSectionWithExt,
1756 DWORD InfSectionWithExtSize,
1757 PDWORD RequiredSize,
1758 PWSTR *Extension)
1759 {
1760 WCHAR szBuffer[MAX_PATH];
1761 DWORD dwLength;
1762 DWORD dwFullLength;
1763 LONG lLineCount = -1;
1764
1765 lstrcpyW(szBuffer, InfSectionName);
1766 dwLength = lstrlenW(szBuffer);
1767
1768 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1769 {
1770 /* Test section name with '.NTx86' extension */
1771 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1772 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1773
1774 if (lLineCount == -1)
1775 {
1776 /* Test section name with '.NT' extension */
1777 lstrcpyW(&szBuffer[dwLength], NtExtension);
1778 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1779 }
1780 }
1781 else
1782 {
1783 /* Test section name with '.Win' extension */
1784 lstrcpyW(&szBuffer[dwLength], WinExtension);
1785 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1786 }
1787
1788 if (lLineCount == -1)
1789 {
1790 /* Test section name without extension */
1791 szBuffer[dwLength] = 0;
1792 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1793 }
1794
1795 if (lLineCount == -1)
1796 {
1797 SetLastError(ERROR_INVALID_PARAMETER);
1798 return FALSE;
1799 }
1800
1801 dwFullLength = lstrlenW(szBuffer);
1802
1803 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1804 {
1805 if (InfSectionWithExtSize < (dwFullLength + 1))
1806 {
1807 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1808 return FALSE;
1809 }
1810
1811 lstrcpyW(InfSectionWithExt, szBuffer);
1812 if (Extension != NULL)
1813 {
1814 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1815 }
1816 }
1817
1818 if (RequiredSize != NULL)
1819 {
1820 *RequiredSize = dwFullLength + 1;
1821 }
1822
1823 return TRUE;
1824 }
1825
1826 /***********************************************************************
1827 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1828 */
1829 BOOL WINAPI SetupDiGetClassDescriptionA(
1830 const GUID* ClassGuid,
1831 PSTR ClassDescription,
1832 DWORD ClassDescriptionSize,
1833 PDWORD RequiredSize)
1834 {
1835 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1836 ClassDescriptionSize,
1837 RequiredSize, NULL, NULL);
1838 }
1839
1840 /***********************************************************************
1841 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1842 */
1843 BOOL WINAPI SetupDiGetClassDescriptionW(
1844 const GUID* ClassGuid,
1845 PWSTR ClassDescription,
1846 DWORD ClassDescriptionSize,
1847 PDWORD RequiredSize)
1848 {
1849 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1850 ClassDescriptionSize,
1851 RequiredSize, NULL, NULL);
1852 }
1853
1854 /***********************************************************************
1855 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1856 */
1857 BOOL WINAPI SetupDiGetClassDescriptionExA(
1858 const GUID* ClassGuid,
1859 PSTR ClassDescription,
1860 DWORD ClassDescriptionSize,
1861 PDWORD RequiredSize,
1862 PCSTR MachineName,
1863 PVOID Reserved)
1864 {
1865 HKEY hKey;
1866 DWORD dwLength;
1867 BOOL ret;
1868
1869 hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1870 KEY_ALL_ACCESS,
1871 DIOCR_INSTALLER,
1872 MachineName,
1873 Reserved);
1874 if (hKey == INVALID_HANDLE_VALUE)
1875 {
1876 WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1877 return FALSE;
1878 }
1879
1880 dwLength = ClassDescriptionSize;
1881 ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1882 (LPBYTE)ClassDescription, &dwLength );
1883 if (RequiredSize) *RequiredSize = dwLength;
1884 RegCloseKey(hKey);
1885 return ret;
1886 }
1887
1888 /***********************************************************************
1889 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1890 */
1891 BOOL WINAPI SetupDiGetClassDescriptionExW(
1892 const GUID* ClassGuid,
1893 PWSTR ClassDescription,
1894 DWORD ClassDescriptionSize,
1895 PDWORD RequiredSize,
1896 PCWSTR MachineName,
1897 PVOID Reserved)
1898 {
1899 HKEY hKey;
1900 DWORD dwLength;
1901 BOOL ret;
1902
1903 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1904 KEY_ALL_ACCESS,
1905 DIOCR_INSTALLER,
1906 MachineName,
1907 Reserved);
1908 if (hKey == INVALID_HANDLE_VALUE)
1909 {
1910 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1911 return FALSE;
1912 }
1913
1914 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1915 ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1916 (LPBYTE)ClassDescription, &dwLength );
1917 if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1918 RegCloseKey(hKey);
1919 return ret;
1920 }
1921
1922 /***********************************************************************
1923 * SetupDiGetClassDevsA (SETUPAPI.@)
1924 */
1925 HDEVINFO WINAPI SetupDiGetClassDevsA(
1926 CONST GUID *class,
1927 LPCSTR enumstr,
1928 HWND parent,
1929 DWORD flags)
1930 {
1931 HDEVINFO ret;
1932 LPWSTR enumstrW = NULL;
1933
1934 if (enumstr)
1935 {
1936 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1937 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1938 if (!enumstrW)
1939 {
1940 ret = INVALID_HANDLE_VALUE;
1941 goto end;
1942 }
1943 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1944 }
1945 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
1946 NULL);
1947 HeapFree(GetProcessHeap(), 0, enumstrW);
1948
1949 end:
1950 return ret;
1951 }
1952
1953 /***********************************************************************
1954 * SetupDiGetClassDevsExA (SETUPAPI.@)
1955 */
1956 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1957 const GUID *class,
1958 PCSTR enumstr,
1959 HWND parent,
1960 DWORD flags,
1961 HDEVINFO deviceset,
1962 PCSTR machine,
1963 PVOID reserved)
1964 {
1965 HDEVINFO ret;
1966 LPWSTR enumstrW = NULL, machineW = NULL;
1967
1968 if (enumstr)
1969 {
1970 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1971 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1972 if (!enumstrW)
1973 {
1974 ret = INVALID_HANDLE_VALUE;
1975 goto end;
1976 }
1977 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1978 }
1979 if (machine)
1980 {
1981 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1982 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1983 if (!machineW)
1984 {
1985 HeapFree(GetProcessHeap(), 0, enumstrW);
1986 ret = INVALID_HANDLE_VALUE;
1987 goto end;
1988 }
1989 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1990 }
1991 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
1992 machineW, reserved);
1993 HeapFree(GetProcessHeap(), 0, enumstrW);
1994 HeapFree(GetProcessHeap(), 0, machineW);
1995
1996 end:
1997 return ret;
1998 }
1999
2000 static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
2001 const GUID *guid)
2002 {
2003 DWORD i, len;
2004 WCHAR subKeyName[MAX_PATH];
2005 LONG l = ERROR_SUCCESS;
2006
2007 for (i = 0; !l; i++)
2008 {
2009 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2010 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2011 if (!l)
2012 {
2013 HKEY subKey;
2014 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2015
2016 if (*subKeyName == '#')
2017 {
2018 /* The subkey name is the reference string, with a '#' prepended */
2019 SETUPDI_AddInterfaceInstance(dev, guid, subKeyName + 1, &iface);
2020 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2021 if (!l)
2022 {
2023 WCHAR symbolicLink[MAX_PATH];
2024 DWORD dataType;
2025
2026 len = sizeof(symbolicLink);
2027 l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
2028 (BYTE *)symbolicLink, &len);
2029 if (!l && dataType == REG_SZ)
2030 SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
2031 RegCloseKey(subKey);
2032 }
2033 }
2034 /* Allow enumeration to continue */
2035 l = ERROR_SUCCESS;
2036 }
2037 }
2038 /* FIXME: find and add all the device's interfaces to the device */
2039 }
2040
2041 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
2042 HKEY key, const GUID *guid, LPCWSTR enumstr)
2043 {
2044 struct DeviceInfoSet *set = DeviceInfoSet;
2045 DWORD i, len;
2046 WCHAR subKeyName[MAX_PATH];
2047 LONG l;
2048 HKEY enumKey = INVALID_HANDLE_VALUE;
2049
2050 TRACE("%s\n", debugstr_w(enumstr));
2051
2052 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
2053 &enumKey, NULL);
2054 for (i = 0; !l; i++)
2055 {
2056 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2057 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2058 if (!l)
2059 {
2060 HKEY subKey;
2061
2062 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2063 if (!l)
2064 {
2065 WCHAR deviceInst[MAX_PATH * 3];
2066 DWORD dataType;
2067
2068 len = sizeof(deviceInst);
2069 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
2070 (BYTE *)deviceInst, &len);
2071 if (!l && dataType == REG_SZ)
2072 {
2073 TRACE("found instance ID %s\n", debugstr_w(deviceInst));
2074 if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
2075 {
2076 HKEY deviceKey;
2077
2078 l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
2079 &deviceKey);
2080 if (!l)
2081 {
2082 WCHAR deviceClassStr[40];
2083
2084 len = sizeof(deviceClassStr);
2085 l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
2086 &dataType, (BYTE *)deviceClassStr, &len);
2087 if (!l && dataType == REG_SZ &&
2088 deviceClassStr[0] == '{' &&
2089 deviceClassStr[37] == '}')
2090 {
2091 GUID deviceClass;
2092 SP_DEVINFO_DATA *dev;
2093
2094 deviceClassStr[37] = 0;
2095 UuidFromStringW(&deviceClassStr[1],
2096 &deviceClass);
2097 if (SETUPDI_AddDeviceToSet(set, &deviceClass,
2098 0 /* FIXME: DevInst */, deviceInst,
2099 FALSE, &dev))
2100 SETUPDI_AddDeviceInterfaces(dev, subKey, guid);
2101 }
2102 RegCloseKey(deviceKey);
2103 }
2104 }
2105 }
2106 RegCloseKey(subKey);
2107 }
2108 /* Allow enumeration to continue */
2109 l = ERROR_SUCCESS;
2110 }
2111 }
2112 if (enumKey != INVALID_HANDLE_VALUE)
2113 RegCloseKey(enumKey);
2114 }
2115
2116 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
2117 const GUID *guid, LPCWSTR enumstr, DWORD flags)
2118 {
2119 HKEY interfacesKey = SetupDiOpenClassRegKeyExW(guid, KEY_READ,
2120 DIOCR_INTERFACE, NULL, NULL);
2121
2122 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(guid),
2123 debugstr_w(enumstr), flags);
2124
2125 if (interfacesKey != INVALID_HANDLE_VALUE)
2126 {
2127 if (flags & DIGCF_ALLCLASSES)
2128 {
2129 DWORD i, len;
2130 WCHAR interfaceGuidStr[40];
2131 LONG l = ERROR_SUCCESS;
2132
2133 for (i = 0; !l; i++)
2134 {
2135 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
2136 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
2137 NULL, NULL, NULL, NULL);
2138 if (!l)
2139 {
2140 if (interfaceGuidStr[0] == '{' &&
2141 interfaceGuidStr[37] == '}')
2142 {
2143 HKEY interfaceKey;
2144 GUID interfaceGuid;
2145
2146 interfaceGuidStr[37] = 0;
2147 UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
2148 l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
2149 KEY_READ, &interfaceKey);
2150 if (!l)
2151 {
2152 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2153 interfaceKey, &interfaceGuid, enumstr);
2154 RegCloseKey(interfaceKey);
2155 }
2156 }
2157 }
2158 }
2159 }
2160 else
2161 {
2162 /* In this case, SetupDiOpenClassRegKeyExW opened the specific
2163 * interface's key, so just pass that long
2164 */
2165 SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
2166 interfacesKey, guid, enumstr);
2167 }
2168 RegCloseKey(interfacesKey);
2169 }
2170 }
2171
2172 static void SETUPDI_EnumerateMatchingDeviceInstances(struct DeviceInfoSet *set,
2173 LPCWSTR enumerator, LPCWSTR deviceName, HKEY deviceKey,
2174 const GUID *class, DWORD flags)
2175 {
2176 DWORD i, len;
2177 WCHAR deviceInstance[MAX_PATH];
2178 LONG l = ERROR_SUCCESS;
2179
2180 TRACE("%s %s\n", debugstr_w(enumerator), debugstr_w(deviceName));
2181
2182 for (i = 0; !l; i++)
2183 {
2184 len = sizeof(deviceInstance) / sizeof(deviceInstance[0]);
2185 l = RegEnumKeyExW(deviceKey, i, deviceInstance, &len, NULL, NULL, NULL,
2186 NULL);
2187 if (!l)
2188 {
2189 HKEY subKey;
2190
2191 l = RegOpenKeyExW(deviceKey, deviceInstance, 0, KEY_READ, &subKey);
2192 if (!l)
2193 {
2194 WCHAR classGuid[40];
2195 DWORD dataType;
2196
2197 len = sizeof(classGuid);
2198 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
2199 (BYTE *)classGuid, &len);
2200 if (!l && dataType == REG_SZ)
2201 {
2202 if (classGuid[0] == '{' && classGuid[37] == '}')
2203 {
2204 GUID deviceClass;
2205
2206 classGuid[37] = 0;
2207 UuidFromStringW(&classGuid[1], &deviceClass);
2208 if ((flags & DIGCF_ALLCLASSES) ||
2209 IsEqualGUID(class, &deviceClass))
2210 {
2211 static const WCHAR fmt[] =
2212 {'%','s','\\','%','s','\\','%','s',0};
2213 LPWSTR instanceId;
2214
2215 instanceId = HeapAlloc(GetProcessHeap(), 0,
2216 (lstrlenW(enumerator) + lstrlenW(deviceName) +
2217 lstrlenW(deviceInstance) + 3) * sizeof(WCHAR));
2218 if (instanceId)
2219 {
2220 sprintfW(instanceId, fmt, enumerator,
2221 deviceName, deviceInstance);
2222 SETUPDI_AddDeviceToSet(set, &deviceClass,
2223 0 /* FIXME: DevInst */, instanceId,
2224 FALSE, NULL);
2225 HeapFree(GetProcessHeap(), 0, instanceId);
2226 }
2227 }
2228 }
2229 }
2230 RegCloseKey(subKey);
2231 }
2232 /* Allow enumeration to continue */
2233 l = ERROR_SUCCESS;
2234 }
2235 }
2236 }
2237
2238 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
2239 LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
2240 {
2241 struct DeviceInfoSet *set = DeviceInfoSet;
2242 DWORD i, len;
2243 WCHAR subKeyName[MAX_PATH];
2244 LONG l = ERROR_SUCCESS;
2245
2246 TRACE("%s\n", debugstr_w(parent));
2247
2248 for (i = 0; !l; i++)
2249 {
2250 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2251 l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
2252 if (!l)
2253 {
2254 HKEY subKey;
2255
2256 l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
2257 if (!l)
2258 {
2259 TRACE("%s\n", debugstr_w(subKeyName));
2260 SETUPDI_EnumerateMatchingDeviceInstances(set, parent,
2261 subKeyName, subKey, class, flags);
2262 RegCloseKey(subKey);
2263 }
2264 /* Allow enumeration to continue */
2265 l = ERROR_SUCCESS;
2266 }
2267 }
2268 }
2269
2270 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
2271 LPCWSTR enumstr, DWORD flags)
2272 {
2273 HKEY enumKey;
2274 LONG l;
2275
2276 TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
2277 debugstr_w(enumstr), flags);
2278
2279 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
2280 &enumKey, NULL);
2281 if (enumKey != INVALID_HANDLE_VALUE)
2282 {
2283 if (enumstr)
2284 {
2285 HKEY enumStrKey;
2286
2287 l = RegOpenKeyExW(enumKey, enumstr, 0, KEY_READ,
2288 &enumStrKey);
2289 if (!l)
2290 {
2291 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
2292 enumStrKey, class, flags);
2293 RegCloseKey(enumStrKey);
2294 }
2295 }
2296 else
2297 {
2298 DWORD i, len;
2299 WCHAR subKeyName[MAX_PATH];
2300
2301 l = ERROR_SUCCESS;
2302 for (i = 0; !l; i++)
2303 {
2304 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
2305 l = RegEnumKeyExW(enumKey, i, subKeyName, &len, NULL,
2306 NULL, NULL, NULL);
2307 if (!l)
2308 {
2309 HKEY subKey;
2310
2311 l = RegOpenKeyExW(enumKey, subKeyName, 0, KEY_READ,
2312 &subKey);
2313 if (!l)
2314 {
2315 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
2316 subKeyName, subKey, class, flags);
2317 RegCloseKey(subKey);
2318 }
2319 /* Allow enumeration to continue */
2320 l = ERROR_SUCCESS;
2321 }
2322 }
2323 }
2324 RegCloseKey(enumKey);
2325 }
2326 }
2327
2328 /***********************************************************************
2329 * SetupDiGetClassDevsW (SETUPAPI.@)
2330 */
2331 HDEVINFO WINAPI SetupDiGetClassDevsW(
2332 CONST GUID *class,
2333 LPCWSTR enumstr,
2334 HWND parent,
2335 DWORD flags)
2336 {
2337 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2338 NULL);
2339 }
2340
2341 /***********************************************************************
2342 * SetupDiGetClassDevsExW (SETUPAPI.@)
2343 */
2344 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2345 CONST GUID *class,
2346 PCWSTR enumstr,
2347 HWND parent,
2348 DWORD flags,
2349 HDEVINFO deviceset,
2350 PCWSTR machine,
2351 PVOID reserved)
2352 {
2353 static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
2354 DIGCF_PROFILE;
2355 HDEVINFO set;
2356
2357 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2358 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2359 reserved);
2360
2361 if (!(flags & DIGCF_ALLCLASSES) && !class)
2362 {
2363 SetLastError(ERROR_INVALID_PARAMETER);
2364 return NULL;
2365 }
2366 if (flags & unsupportedFlags)
2367 WARN("unsupported flags %08x\n", flags & unsupportedFlags);
2368 if (deviceset)
2369 set = deviceset;
2370 else
2371 set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
2372 if (set)
2373 {
2374 if (machine && *machine)
2375 FIXME("%s: unimplemented for remote machines\n",
2376 debugstr_w(machine));
2377 else if (flags & DIGCF_DEVICEINTERFACE)
2378 SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
2379 else
2380 SETUPDI_EnumerateDevices(set, class, enumstr, flags);
2381 }
2382 return set;
2383 }
2384
2385 /***********************************************************************
2386 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2387 */
2388 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2389 HDEVINFO DeviceInfoSet,
2390 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2391 {
2392 struct DeviceInfoSet *set = DeviceInfoSet;
2393
2394 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2395
2396 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2397 {
2398 SetLastError(ERROR_INVALID_HANDLE);
2399 return FALSE;
2400 }
2401 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2402 {
2403 SetLastError(ERROR_INVALID_HANDLE);
2404 return FALSE;
2405 }
2406 if (!DevInfoData ||
2407 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2408 {
2409 SetLastError(ERROR_INVALID_PARAMETER);
2410 return FALSE;
2411 }
2412 DevInfoData->ClassGuid = set->ClassGuid;
2413 DevInfoData->RemoteMachineHandle = NULL;
2414 DevInfoData->RemoteMachineName[0] = '\0';
2415 return TRUE;
2416 }
2417
2418 /***********************************************************************
2419 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2420 */
2421 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2422 HDEVINFO DeviceInfoSet,
2423 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2424 {
2425 struct DeviceInfoSet *set = DeviceInfoSet;
2426
2427 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2428
2429 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2430 {
2431 SetLastError(ERROR_INVALID_HANDLE);
2432 return FALSE;
2433 }
2434 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2435 {
2436 SetLastError(ERROR_INVALID_HANDLE);
2437 return FALSE;
2438 }
2439 if (!DevInfoData ||
2440 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2441 {
2442 SetLastError(ERROR_INVALID_PARAMETER);
2443 return FALSE;
2444 }
2445 DevInfoData->ClassGuid = set->ClassGuid;
2446 DevInfoData->RemoteMachineHandle = NULL;
2447 DevInfoData->RemoteMachineName[0] = '\0';
2448 return TRUE;
2449 }
2450
2451 /***********************************************************************
2452 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2453 */
2454 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2455 HDEVINFO DeviceInfoSet,
2456 PSP_DEVINFO_DATA DeviceInfoData,
2457 const GUID *InterfaceClassGuid,
2458 PCSTR ReferenceString,
2459 DWORD CreationFlags,
2460 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2461 {
2462 BOOL ret;
2463 LPWSTR ReferenceStringW = NULL;
2464
2465 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2466 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2467 CreationFlags, DeviceInterfaceData);
2468
2469 if (ReferenceString)
2470 {
2471 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2472 if (ReferenceStringW == NULL) return FALSE;
2473 }
2474
2475 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2476 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2477 DeviceInterfaceData);
2478
2479 MyFree(ReferenceStringW);
2480
2481 return ret;
2482 }
2483
2484 /***********************************************************************
2485 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2486 */
2487 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2488 HDEVINFO DeviceInfoSet,
2489 PSP_DEVINFO_DATA DeviceInfoData,
2490 const GUID *InterfaceClassGuid,
2491 PCWSTR ReferenceString,
2492 DWORD CreationFlags,
2493 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2494 {
2495 struct DeviceInfoSet *set = DeviceInfoSet;
2496 struct DeviceInfo *devInfo;
2497 SP_DEVICE_INTERFACE_DATA *iface = NULL;
2498 BOOL ret;
2499
2500 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2501 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2502 CreationFlags, DeviceInterfaceData);
2503
2504 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2505 {
2506 SetLastError(ERROR_INVALID_HANDLE);
2507 return FALSE;
2508 }
2509 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2510 {
2511 SetLastError(ERROR_INVALID_HANDLE);
2512 return FALSE;
2513 }
2514 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2515 || !DeviceInfoData->Reserved)
2516 {
2517 SetLastError(ERROR_INVALID_PARAMETER);
2518 return FALSE;
2519 }
2520 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2521 if (devInfo->set != set)
2522 {
2523 SetLastError(ERROR_INVALID_PARAMETER);
2524 return FALSE;
2525 }
2526 if (!InterfaceClassGuid)
2527 {
2528 SetLastError(ERROR_INVALID_USER_BUFFER);
2529 return FALSE;
2530 }
2531 if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
2532 ReferenceString, &iface)))
2533 {
2534 if (DeviceInterfaceData)
2535 {
2536 if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2537 {
2538 SetLastError(ERROR_INVALID_USER_BUFFER);
2539 ret = FALSE;
2540 }
2541 else
2542 *DeviceInterfaceData = *iface;
2543 }
2544 }
2545 return ret;
2546 }
2547
2548 /***********************************************************************
2549 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2550 */
2551 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2552 HDEVINFO DeviceInfoSet,
2553 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2554 DWORD Reserved,
2555 REGSAM samDesired,
2556 HINF InfHandle,
2557 PCSTR InfSectionName)
2558 {
2559 HKEY key;
2560 PWSTR InfSectionNameW = NULL;
2561
2562 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2563 samDesired, InfHandle, InfSectionName);
2564 if (InfHandle)
2565 {
2566 if (!InfSectionName)
2567 {
2568 SetLastError(ERROR_INVALID_PARAMETER);
2569 return INVALID_HANDLE_VALUE;
2570 }
2571 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2572 if (!InfSectionNameW)
2573 return INVALID_HANDLE_VALUE;
2574 }
2575 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2576 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2577 InfSectionNameW);
2578 MyFree(InfSectionNameW);
2579 return key;
2580 }
2581
2582 static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo)
2583 {
2584 static const WCHAR hash[] = {'#',0};
2585 PWSTR instancePath = NULL;
2586
2587 if (ifaceInfo->referenceString)
2588 {
2589 instancePath = HeapAlloc(GetProcessHeap(), 0,
2590 (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR));
2591 if (instancePath)
2592 {
2593 lstrcpyW(instancePath, hash);
2594 lstrcatW(instancePath, ifaceInfo->referenceString);
2595 }
2596 else
2597 SetLastError(ERROR_OUTOFMEMORY);
2598 }
2599 else
2600 {
2601 instancePath = HeapAlloc(GetProcessHeap(), 0,
2602 (lstrlenW(hash) + 1) * sizeof(WCHAR));
2603 if (instancePath)
2604 lstrcpyW(instancePath, hash);
2605 }
2606 return instancePath;
2607 }
2608
2609 /***********************************************************************
2610 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2611 */
2612 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2613 HDEVINFO DeviceInfoSet,
2614 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2615 DWORD Reserved,
2616 REGSAM samDesired,
2617 HINF InfHandle,
2618 PCWSTR InfSectionName)
2619 {
2620 struct DeviceInfoSet *set = DeviceInfoSet;
2621 HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
2622 LONG l;
2623
2624 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2625 samDesired, InfHandle, InfSectionName);
2626
2627 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2628 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2629 {
2630 SetLastError(ERROR_INVALID_HANDLE);
2631 return INVALID_HANDLE_VALUE;
2632 }
2633 if (!DeviceInterfaceData ||
2634 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2635 !DeviceInterfaceData->Reserved)
2636 {
2637 SetLastError(ERROR_INVALID_PARAMETER);
2638 return INVALID_HANDLE_VALUE;
2639 }
2640 if (InfHandle && !InfSectionName)
2641 {
2642 SetLastError(ERROR_INVALID_PARAMETER);
2643 return INVALID_HANDLE_VALUE;
2644 }
2645 if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
2646 samDesired, NULL, &interfacesKey, NULL)))
2647 {
2648 HKEY parent;
2649 WCHAR bracedGuidString[39];
2650
2651 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
2652 bracedGuidString);
2653 if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
2654 samDesired, NULL, &parent, NULL)))
2655 {
2656 struct InterfaceInfo *ifaceInfo =
2657 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2658 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2659 PWSTR interfKeyName = HeapAlloc(GetProcessHeap(), 0,
2660 (lstrlenW(ifaceInfo->symbolicLink) + 1) * sizeof(WCHAR));
2661 HKEY interfKey;
2662 WCHAR *ptr;
2663
2664 lstrcpyW(interfKeyName, ifaceInfo->symbolicLink);
2665 if (lstrlenW(ifaceInfo->symbolicLink) > 3)
2666 {
2667 interfKeyName[0] = '#';
2668 interfKeyName[1] = '#';
2669 interfKeyName[3] = '#';
2670 }
2671 ptr = strchrW(interfKeyName, '\\');
2672 if (ptr)
2673 *ptr = 0;
2674 l = RegCreateKeyExW(parent, interfKeyName, 0, NULL, 0,
2675 samDesired, NULL, &interfKey, NULL);
2676 if (!l)
2677 {
2678 struct DeviceInfo *devInfo =
2679 (struct DeviceInfo *)ifaceInfo->device->Reserved;
2680
2681 l = RegSetValueExW(interfKey, DeviceInstance, 0, REG_SZ,
2682 (BYTE *)devInfo->instanceId,
2683 (lstrlenW(devInfo->instanceId) + 1) * sizeof(WCHAR));
2684 if (!l)
2685 {
2686 if (instancePath)
2687 {
2688 LONG l;
2689
2690 l = RegCreateKeyExW(interfKey, instancePath, 0, NULL, 0,
2691 samDesired, NULL, &key, NULL);
2692 if (l)
2693 {
2694 SetLastError(l);
2695 key = INVALID_HANDLE_VALUE;
2696 }
2697 else if (InfHandle)
2698 FIXME("INF section installation unsupported\n");
2699 }
2700 }
2701 else
2702 SetLastError(l);
2703 RegCloseKey(interfKey);
2704 }
2705 else
2706 SetLastError(l);
2707 HeapFree(GetProcessHeap(), 0, interfKeyName);
2708 HeapFree(GetProcessHeap(), 0, instancePath);
2709 RegCloseKey(parent);
2710 }
2711 else
2712 SetLastError(l);
2713 RegCloseKey(interfacesKey);
2714 }
2715 else
2716 SetLastError(l);
2717 return key;
2718 }
2719
2720 /***********************************************************************
2721 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2722 */
2723 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2724 HDEVINFO DeviceInfoSet,
2725 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2726 DWORD Reserved)
2727 {
2728 struct DeviceInfoSet *set = DeviceInfoSet;
2729 HKEY parent;
2730 BOOL ret = FALSE;
2731
2732 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2733
2734 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2735 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2736 {
2737 SetLastError(ERROR_INVALID_HANDLE);
2738 return FALSE;
2739 }
2740 if (!DeviceInterfaceData ||
2741 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2742 !DeviceInterfaceData->Reserved)
2743 {
2744 SetLastError(ERROR_INVALID_PARAMETER);
2745 return FALSE;
2746 }
2747 parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid,
2748 KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
2749 if (parent != INVALID_HANDLE_VALUE)
2750 {
2751 struct InterfaceInfo *ifaceInfo =
2752 (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2753 PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
2754
2755 if (instancePath)
2756 {
2757 LONG l = RegDeleteKeyW(parent, instancePath);
2758
2759 if (l)
2760 SetLastError(l);
2761 else
2762 ret = TRUE;
2763 HeapFree(GetProcessHeap(), 0, instancePath);
2764 }
2765 RegCloseKey(parent);
2766 }
2767 return ret;
2768 }
2769
2770 /***********************************************************************
2771 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2772 *
2773 * PARAMS
2774 * DeviceInfoSet [I] Set of devices from which to enumerate
2775 * interfaces
2776 * DeviceInfoData [I] (Optional) If specified, a specific device
2777 * instance from which to enumerate interfaces.
2778 * If it isn't specified, all interfaces for all
2779 * devices in the set are enumerated.
2780 * InterfaceClassGuid [I] The interface class to enumerate.
2781 * MemberIndex [I] An index of the interface instance to enumerate.
2782 * A caller should start with MemberIndex set to 0,
2783 * and continue until the function fails with
2784 * ERROR_NO_MORE_ITEMS.
2785 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2786 * member must be set to
2787 * sizeof(SP_DEVICE_INTERFACE_DATA).
2788 *
2789 * RETURNS
2790 * Success: non-zero value.
2791 * Failure: FALSE. Call GetLastError() for more info.
2792 */
2793 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2794 HDEVINFO DeviceInfoSet,
2795 PSP_DEVINFO_DATA DeviceInfoData,
2796 CONST GUID * InterfaceClassGuid,
2797 DWORD MemberIndex,
2798 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2799 {
2800 struct DeviceInfoSet *set = DeviceInfoSet;
2801 BOOL ret = FALSE;
2802
2803 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2804 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2805
2806 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2807 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2808 {
2809 SetLastError(ERROR_INVALID_HANDLE);
2810 return FALSE;
2811 }
2812 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2813 !DeviceInfoData->Reserved))
2814 {
2815 SetLastError(ERROR_INVALID_PARAMETER);
2816 return FALSE;
2817 }
2818 if (!DeviceInterfaceData ||
2819 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2820 {
2821 SetLastError(ERROR_INVALID_PARAMETER);
2822 return FALSE;
2823 }
2824 /* In case application fails to check return value, clear output */
2825 memset(DeviceInterfaceData, 0, sizeof(*DeviceInterfaceData));
2826 if (DeviceInfoData)
2827 {
2828 struct DeviceInfo *devInfo =
2829 (struct DeviceInfo *)DeviceInfoData->Reserved;
2830 struct InterfaceInstances *iface;
2831
2832 if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
2833 {
2834 if (MemberIndex < iface->cInstances)
2835 *DeviceInterfaceData = iface->instances[MemberIndex];
2836 else
2837 {
2838 SetLastError(ERROR_NO_MORE_ITEMS);
2839 ret = FALSE;
2840 }
2841 }
2842 else
2843 SetLastError(ERROR_NO_MORE_ITEMS);
2844 }
2845 else
2846 {
2847 struct DeviceInstance *devInst;
2848 DWORD cEnumerated = 0;
2849 BOOL found = FALSE;
2850
2851 LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
2852 {
2853 struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
2854 struct InterfaceInstances *iface;
2855
2856 if (found || cEnumerated >= MemberIndex + 1)
2857 break;
2858 if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
2859 {
2860 if (cEnumerated + iface->cInstances < MemberIndex + 1)
2861 cEnumerated += iface->cInstances;
2862 else
2863 {
2864 DWORD instanceIndex = MemberIndex - cEnumerated;
2865
2866 *DeviceInterfaceData = iface->instances[instanceIndex];
2867 cEnumerated += instanceIndex + 1;
2868 found = TRUE;
2869 ret = TRUE;
2870 }
2871 }
2872 }
2873 if (!found)
2874 SetLastError(ERROR_NO_MORE_ITEMS);
2875 }
2876 return ret;
2877 }
2878
2879 /***********************************************************************
2880 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2881 *
2882 * Destroy a DeviceInfoList and free all used memory of the list.
2883 *
2884 * PARAMS
2885 * devinfo [I] DeviceInfoList pointer to list to destroy
2886 *
2887 * RETURNS
2888 * Success: non zero value.
2889 * Failure: zero value.
2890 */
2891 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2892 {
2893 BOOL ret = FALSE;
2894
2895 TRACE("%p\n", devinfo);
2896 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2897 {
2898 struct DeviceInfoSet *list = devinfo;
2899
2900 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2901 {
2902 struct DeviceInstance *devInst, *devInst2;
2903
2904 LIST_FOR_EACH_ENTRY_SAFE(devInst, devInst2, &list->devices,
2905 struct DeviceInstance, entry)
2906 {
2907 SETUPDI_FreeDeviceInfo( (struct DeviceInfo *)devInst->data.Reserved );
2908 list_remove(&devInst->entry);
2909 HeapFree(GetProcessHeap(), 0, devInst);
2910 }
2911 HeapFree(GetProcessHeap(), 0, list);
2912 ret = TRUE;
2913 }
2914 }
2915
2916 if (ret == FALSE)
2917 SetLastError(ERROR_INVALID_HANDLE);
2918
2919 return ret;
2920 }
2921
2922 /***********************************************************************
2923 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2924 */
2925 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2926 HDEVINFO DeviceInfoSet,
2927 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2928 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2929 DWORD DeviceInterfaceDetailDataSize,
2930 PDWORD RequiredSize,
2931 PSP_DEVINFO_DATA DeviceInfoData)
2932 {
2933 struct DeviceInfoSet *set = DeviceInfoSet;
2934 struct InterfaceInfo *info;
2935 DWORD bytesNeeded = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
2936 BOOL ret = FALSE;
2937
2938 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2939 DeviceInterfaceData, DeviceInterfaceDetailData,
2940 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2941
2942 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2943 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2944 {
2945 SetLastError(ERROR_INVALID_HANDLE);
2946 return FALSE;
2947 }
2948 if (!DeviceInterfaceData ||
2949 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2950 !DeviceInterfaceData->Reserved)
2951 {
2952 SetLastError(ERROR_INVALID_PARAMETER);
2953 return FALSE;
2954 }
2955 if (DeviceInterfaceDetailData &&
2956 DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2957 {
2958 SetLastError(ERROR_INVALID_USER_BUFFER);
2959 return FALSE;
2960 }
2961 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2962 {
2963 SetLastError(ERROR_INVALID_USER_BUFFER);
2964 return FALSE;
2965 }
2966 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
2967 if (info->symbolicLink)
2968 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2969 NULL, 0, NULL, NULL);
2970 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
2971 {
2972 if (info->symbolicLink)
2973 WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
2974 DeviceInterfaceDetailData->DevicePath,
2975 DeviceInterfaceDetailDataSize -
2976 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2977 NULL, NULL);
2978 else
2979 DeviceInterfaceDetailData->DevicePath[0] = '\0';
2980 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
2981 *DeviceInfoData = *info->device;
2982 ret = TRUE;
2983 }
2984 else
2985 {
2986 if (RequiredSize)
2987 *RequiredSize = bytesNeeded;
2988 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2989 }
2990 return ret;
2991 }
2992
2993 /***********************************************************************
2994 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2995 */
2996 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2997 HDEVINFO DeviceInfoSet,
2998 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2999 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3000 DWORD DeviceInterfaceDetailDataSize,
3001 PDWORD RequiredSize,
3002 PSP_DEVINFO_DATA DeviceInfoData)
3003 {
3004 struct DeviceInfoSet *set = DeviceInfoSet;
3005 struct InterfaceInfo *info;
3006 DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
3007 + sizeof(WCHAR); /* include NULL terminator */
3008 BOOL ret = FALSE;
3009
3010 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3011 DeviceInterfaceData, DeviceInterfaceDetailData,
3012 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3013
3014 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3015 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3016 {
3017 SetLastError(ERROR_INVALID_HANDLE);
3018 return FALSE;
3019 }
3020 if (!DeviceInterfaceData ||
3021 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3022 !DeviceInterfaceData->Reserved)
3023 {
3024 SetLastError(ERROR_INVALID_PARAMETER);
3025 return FALSE;
3026 }
3027 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
3028 offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
3029 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
3030 {
3031 SetLastError(ERROR_INVALID_USER_BUFFER);
3032 return FALSE;
3033 }
3034 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3035 {
3036 SetLastError(ERROR_INVALID_USER_BUFFER);
3037 return FALSE;
3038 }
3039 info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
3040 if (info->symbolicLink)
3041 bytesNeeded += sizeof(WCHAR)*lstrlenW(info->symbolicLink);
3042 if (DeviceInterfaceDetailDataSize >= bytesNeeded)
3043 {
3044 if (info->symbolicLink)
3045 lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
3046 else
3047 DeviceInterfaceDetailData->DevicePath[0] = '\0';
3048 if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
3049 *DeviceInfoData = *info->device;
3050 ret = TRUE;
3051 }
3052 else
3053 {
3054 if (RequiredSize)
3055 *RequiredSize = bytesNeeded;
3056 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3057 }
3058 return ret;
3059 }
3060
3061 struct PropertyMapEntry
3062 {
3063 DWORD regType;
3064 LPCSTR nameA;
3065 LPCWSTR nameW;
3066 };
3067
3068 static const struct PropertyMapEntry PropertyMap[] = {
3069 { REG_SZ, "DeviceDesc", DeviceDesc },
3070 { REG_MULTI_SZ, "HardwareId", HardwareId },
3071 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
3072 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3073 { REG_SZ, "Service", Service },
3074 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3075 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3076 { REG_SZ, "Class", Class },
3077 { REG_SZ, "ClassGUID", ClassGUID },
3078 { REG_SZ, "Driver", Driver },
3079 { REG_DWORD, "ConfigFlags", ConfigFlags },
3080 { REG_SZ, "Mfg", Mfg },
3081 { REG_SZ, "FriendlyName", FriendlyName },
3082 { REG_SZ, "LocationInformation", LocationInformation },
3083 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3084 { REG_DWORD, "Capabilities", Capabilities },
3085 { REG_DWORD, "UINumber", UINumber },
3086 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
3087 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
3088 };
3089
3090 /***********************************************************************
3091 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3092 */
3093 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3094 HDEVINFO DeviceInfoSet,
3095 PSP_DEVINFO_DATA DeviceInfoData,
3096 DWORD Property,
3097 PDWORD PropertyRegDataType,
3098 PBYTE PropertyBuffer,
3099 DWORD PropertyBufferSize,
3100 PDWORD RequiredSize)
3101 {
3102 BOOL ret = FALSE;
3103 struct DeviceInfoSet *set = DeviceInfoSet;
3104 struct DeviceInfo *devInfo;
3105
3106 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
3107 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3108 RequiredSize);
3109
3110 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3111 {
3112 SetLastError(ERROR_INVALID_HANDLE);
3113 return FALSE;
3114 }
3115 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3116 {
3117 SetLastError(ERROR_INVALID_HANDLE);
3118 return FALSE;
3119 }
3120 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3121 || !DeviceInfoData->Reserved)
3122 {
3123 SetLastError(ERROR_INVALID_PARAMETER);
3124 return FALSE;
3125 }
3126 if (PropertyBufferSize && PropertyBuffer == NULL)
3127 {
3128 SetLastError(ERROR_INVALID_DATA);
3129 return FALSE;
3130 }
3131 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3132 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3133 && PropertyMap[Property].nameA)
3134 {
3135 DWORD size = PropertyBufferSize;
3136 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
3137 NULL, PropertyRegDataType, PropertyBuffer, &size);
3138
3139 if (l == ERROR_MORE_DATA || !PropertyBufferSize)
3140 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3141 else if (!l)
3142 ret = TRUE;
3143 else
3144 SetLastError(l);
3145 if (RequiredSize)
3146 *RequiredSize = size;
3147 }
3148 return ret;
3149 }
3150
3151 /***********************************************************************
3152 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3153 */
3154 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3155 HDEVINFO DeviceInfoSet,
3156 PSP_DEVINFO_DATA DeviceInfoData,
3157 DWORD Property,
3158 PDWORD PropertyRegDataType,
3159 PBYTE PropertyBuffer,
3160 DWORD PropertyBufferSize,
3161 PDWORD RequiredSize)
3162 {
3163 BOOL ret = FALSE;
3164 struct DeviceInfoSet *set = DeviceInfoSet;
3165 struct DeviceInfo *devInfo;
3166
3167 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
3168 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3169 RequiredSize);
3170
3171 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3172 {
3173 SetLastError(ERROR_INVALID_HANDLE);
3174 return FALSE;
3175 }
3176 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3177 {
3178 SetLastError(ERROR_INVALID_HANDLE);
3179 return FALSE;
3180 }
3181 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3182 || !DeviceInfoData->Reserved)
3183 {
3184 SetLastError(ERROR_INVALID_PARAMETER);
3185 return FALSE;
3186 }
3187 if (PropertyBufferSize && PropertyBuffer == NULL)
3188 {
3189 SetLastError(ERROR_INVALID_DATA);
3190 return FALSE;
3191 }
3192 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3193 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3194 && PropertyMap[Property].nameW)
3195 {
3196 DWORD size = PropertyBufferSize;
3197 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
3198 NULL, PropertyRegDataType, PropertyBuffer, &size);
3199
3200 if (l == ERROR_MORE_DATA || !PropertyBufferSize)
3201 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3202 else if (!l)
3203 ret = TRUE;
3204 else
3205 SetLastError(l);
3206 if (RequiredSize)
3207 *RequiredSize = size;
3208 }
3209 return ret;
3210 }
3211
3212 /***********************************************************************
3213 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3214 */
3215 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3216 HDEVINFO DeviceInfoSet,
3217 PSP_DEVINFO_DATA DeviceInfoData,
3218 DWORD Property,
3219 const BYTE *PropertyBuffer,
3220 DWORD PropertyBufferSize)
3221 {
3222 BOOL ret = FALSE;
3223 struct DeviceInfoSet *set = DeviceInfoSet;
3224 struct DeviceInfo *devInfo;
3225
3226 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3227 PropertyBuffer, PropertyBufferSize);
3228
3229 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3230 {
3231 SetLastError(ERROR_INVALID_HANDLE);
3232 return FALSE;
3233 }
3234 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3235 {
3236 SetLastError(ERROR_INVALID_HANDLE);
3237 return FALSE;
3238 }
3239 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3240 || !DeviceInfoData->Reserved)
3241 {
3242 SetLastError(ERROR_INVALID_PARAMETER);
3243 return FALSE;
3244 }
3245 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3246 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3247 && PropertyMap[Property].nameA)
3248 {
3249 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
3250 PropertyMap[Property].regType, PropertyBuffer,
3251 PropertyBufferSize);
3252 if (!l)
3253 ret = TRUE;
3254 else
3255 SetLastError(l);
3256 }
3257 return ret;
3258 }
3259
3260 /***********************************************************************
3261 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3262 */
3263 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3264 HDEVINFO DeviceInfoSet,
3265 PSP_DEVINFO_DATA DeviceInfoData,
3266 DWORD Property,
3267 const BYTE *PropertyBuffer,
3268 DWORD PropertyBufferSize)
3269 {
3270 BOOL ret = FALSE;
3271 struct DeviceInfoSet *set = DeviceInfoSet;
3272 struct DeviceInfo *devInfo;
3273
3274 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3275 PropertyBuffer, PropertyBufferSize);
3276
3277 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3278 {
3279 SetLastError(ERROR_INVALID_HANDLE);
3280 return FALSE;
3281 }
3282 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3283 {
3284 SetLastError(ERROR_INVALID_HANDLE);
3285 return FALSE;
3286 }
3287 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3288 || !DeviceInfoData->Reserved)
3289 {
3290 SetLastError(ERROR_INVALID_PARAMETER);
3291 return FALSE;
3292 }
3293 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3294 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3295 && PropertyMap[Property].nameW)
3296 {
3297 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
3298 PropertyMap[Property].regType, PropertyBuffer,
3299 PropertyBufferSize);
3300 if (!l)
3301 ret = TRUE;
3302 else
3303 SetLastError(l);
3304 }
3305 return ret;
3306 }
3307
3308 /***********************************************************************
3309 * SetupDiInstallClassA (SETUPAPI.@)
3310 */
3311 BOOL WINAPI SetupDiInstallClassA(
3312 HWND hwndParent,
3313 PCSTR InfFileName,
3314 DWORD Flags,
3315 HSPFILEQ FileQueue)
3316 {
3317 UNICODE_STRING FileNameW;
3318 BOOL Result;
3319
3320 if (!InfFileName)
3321 {
3322 SetLastError(ERROR_INVALID_PARAMETER);
3323 return FALSE;
3324 }
3325 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
3326 {
3327 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3328 return FALSE;
3329 }
3330
3331 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
3332
3333 RtlFreeUnicodeString(&FileNameW);
3334
3335 return Result;
3336 }
3337
3338 static HKEY CreateClassKey(HINF hInf)
3339 {
3340 static const WCHAR slash[] = { '\\',0 };
3341 WCHAR FullBuffer[MAX_PATH];
3342 WCHAR Buffer[MAX_PATH];
3343 DWORD RequiredSize;
3344 HKEY hClassKey;
3345
3346 if (!SetupGetLineTextW(NULL,
3347 hInf,
3348 Version,
3349 ClassGUID,
3350 Buffer,
3351 MAX_PATH,
3352 &RequiredSize))
3353 {
3354 return INVALID_HANDLE_VALUE;
3355 }
3356
3357 lstrcpyW(FullBuffer, ControlClass);
3358 lstrcatW(FullBuffer, slash);
3359 lstrcatW(FullBuffer, Buffer);
3360
3361 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3362 FullBuffer,
3363 0,
3364 KEY_ALL_ACCESS,
3365 &hClassKey))
3366 {
3367 if (!SetupGetLineTextW(NULL,
3368 hInf,
3369 Version,
3370 Class,
3371 Buffer,
3372 MAX_PATH,
3373 &RequiredSize))
3374 {
3375 return INVALID_HANDLE_VALUE;
3376 }
3377
3378 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3379 FullBuffer,
3380 0,
3381 NULL,
3382 REG_OPTION_NON_VOLATILE,
3383 KEY_ALL_ACCESS,
3384 NULL,
3385 &hClassKey,
3386 NULL))
3387 {
3388 return INVALID_HANDLE_VALUE;
3389 }
3390
3391 }
3392
3393 if (RegSetValueExW(hClassKey,
3394 Class,
3395 0,
3396 REG_SZ,
3397 (LPBYTE)Buffer,
3398 RequiredSize * sizeof(WCHAR)))
3399 {
3400 RegCloseKey(hClassKey);
3401 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3402 FullBuffer);
3403 return INVALID_HANDLE_VALUE;
3404 }
3405
3406 return hClassKey;
3407 }
3408
3409 /***********************************************************************
3410 * SetupDiInstallClassW (SETUPAPI.@)
3411 */
3412 BOOL WINAPI SetupDiInstallClassW(
3413 HWND hwndParent,
3414 PCWSTR InfFileName,
3415 DWORD Flags,
3416 HSPFILEQ FileQueue)
3417 {
3418 WCHAR SectionName[MAX_PATH];
3419 DWORD SectionNameLength = 0;
3420 HINF hInf;
3421 BOOL bFileQueueCreated = FALSE;
3422 HKEY hClassKey;
3423
3424
3425 FIXME("\n");
3426
3427 if (!InfFileName)
3428 {
3429 SetLastError(ERROR_INVALID_PARAMETER);
3430 return FALSE;
3431 }
3432 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
3433 {
3434 SetLastError(ERROR_INVALID_PARAMETER);
3435 return FALSE;
3436 }
3437
3438 /* Open the .inf file */
3439 hInf = SetupOpenInfFileW(InfFileName,
3440 NULL,
3441 INF_STYLE_WIN4,
3442 NULL);
3443 if (hInf == INVALID_HANDLE_VALUE)
3444 {
3445
3446 return FALSE;
3447 }
3448
3449 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3450 hClassKey = CreateClassKey(hInf);
3451 if (hClassKey == INVALID_HANDLE_VALUE)
3452 {
3453 SetupCloseInfFile(hInf);
3454 return FALSE;
3455 }
3456
3457
3458 /* Try to append a layout file */
3459 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3460
3461 /* Retrieve the actual section name */
3462 SetupDiGetActualSectionToInstallW(hInf,
3463 ClassInstall32,
3464 SectionName,
3465 MAX_PATH,
3466 &SectionNameLength,
3467 NULL);
3468
3469 #if 0
3470 if (!(Flags & DI_NOVCP))
3471 {
3472 FileQueue = SetupOpenFileQueue();
3473 if (FileQueue == INVALID_HANDLE_VALUE)
3474 {
3475 SetupCloseInfFile(hInf);
3476 return FALSE;
3477 }
3478
3479 bFileQueueCreated = TRUE;
3480
3481 }
3482 #endif
3483
3484 SetupInstallFromInfSectionW(NULL,
3485 hInf,
3486 SectionName,
3487 SPINST_COPYINF | SPINST_FILES | SPINST_REGISTRY,
3488 hClassKey,
3489 NULL,
3490 0,
3491 NULL,
3492 NULL,
3493 INVALID_HANDLE_VALUE,
3494 NULL);
3495
3496 /* FIXME: More code! */
3497
3498 if (bFileQueueCreated)
3499 SetupCloseFileQueue(FileQueue);
3500
3501 SetupCloseInfFile(hInf);
3502
3503 return TRUE;
3504 }
3505
3506
3507 /***********************************************************************
3508 * SetupDiOpenClassRegKey (SETUPAPI.@)
3509 */
3510 HKEY WINAPI SetupDiOpenClassRegKey(
3511 const GUID* ClassGuid,
3512 REGSAM samDesired)
3513 {
3514 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3515 DIOCR_INSTALLER, NULL, NULL);
3516 }
3517
3518
3519 /***********************************************************************
3520 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3521 */
3522 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3523 const GUID* ClassGuid,
3524 REGSAM samDesired,
3525 DWORD Flags,
3526 PCSTR MachineName,
3527 PVOID Reserved)
3528 {
3529 PWSTR MachineNameW = NULL;
3530 HKEY hKey;
3531
3532 TRACE("\n");
3533
3534 if (MachineName)
3535 {
3536 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3537 if (MachineNameW == NULL)
3538 return INVALID_HANDLE_VALUE;
3539 }
3540
3541 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3542 Flags, MachineNameW, Reserved);
3543
3544 MyFree(MachineNameW);
3545
3546 return hKey;
3547 }
3548
3549
3550 /***********************************************************************
3551 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3552 */
3553 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3554 const GUID* ClassGuid,
3555 REGSAM samDesired,
3556 DWORD Flags,
3557 PCWSTR MachineName,
3558 PVOID Reserved)
3559 {
3560 HKEY hClassesKey;
3561 HKEY key;
3562 LPCWSTR lpKeyName;
3563 LONG l;
3564
3565 if (MachineName && *MachineName)
3566 {
3567 FIXME("Remote access not supported yet!\n");
3568 return INVALID_HANDLE_VALUE;
3569 }
3570
3571 if (Flags == DIOCR_INSTALLER)
3572 {
3573 lpKeyName = ControlClass;
3574 }
3575 else if (Flags == DIOCR_INTERFACE)
3576 {
3577 lpKeyName = DeviceClasses;
3578 }
3579 else
3580 {
3581 ERR("Invalid Flags parameter!\n");
3582 SetLastError(ERROR_INVALID_PARAMETER);
3583 return INVALID_HANDLE_VALUE;
3584 }
3585
3586 if (!ClassGuid)
3587 {
3588 if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3589 lpKeyName,
3590 0,
3591 samDesired,
3592 &hClassesKey)))
3593 {
3594 SetLastError(l);
3595 hClassesKey = INVALID_HANDLE_VALUE;
3596 }
3597 key = hClassesKey;
3598 }
3599 else
3600 {
3601 WCHAR bracedGuidString[39];
3602
3603 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3604
3605 if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3606 lpKeyName,
3607 0,
3608 samDesired,
3609 &hClassesKey)))
3610 {
3611 if ((l = RegOpenKeyExW(hClassesKey,
3612 bracedGuidString,
3613 0,
3614 samDesired,
3615 &key)))
3616 {
3617 SetLastError(l);
3618 key = INVALID_HANDLE_VALUE;
3619 }
3620 RegCloseKey(hClassesKey);
3621 }
3622 else
3623 {
3624 SetLastError(l);
3625 key = INVALID_HANDLE_VALUE;
3626 }
3627 }
3628 return key;
3629 }
3630
3631 /***********************************************************************
3632 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3633 */
3634 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3635 HDEVINFO DeviceInfoSet,
3636 PCWSTR DevicePath,
3637 DWORD OpenFlags,
3638 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3639 {
3640 FIXME("%p %s %08x %p\n",
3641 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3642 return FALSE;
3643 }
3644
3645 /***********************************************************************
3646 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3647 */
3648 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3649 HDEVINFO DeviceInfoSet,
3650 PCSTR DevicePath,
3651 DWORD OpenFlags,
3652 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3653 {
3654 FIXME("%p %s %08x %p\n", DeviceInfoSet,
3655 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3656 return FALSE;
3657 }
3658
3659 /***********************************************************************
3660 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3661 */
3662 BOOL WINAPI SetupDiSetClassInstallParamsA(
3663 HDEVINFO DeviceInfoSet,
3664 PSP_DEVINFO_DATA DeviceInfoData,
3665 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3666 DWORD ClassInstallParamsSize)
3667 {
3668 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3669 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3670 return FALSE;
3671 }
3672
3673 /***********************************************************************
3674 * SetupDiCallClassInstaller (SETUPAPI.@)
3675 */
3676 BOOL WINAPI SetupDiCallClassInstaller(
3677 DI_FUNCTION InstallFunction,
3678 HDEVINFO DeviceInfoSet,
3679 PSP_DEVINFO_DATA DeviceInfoData)
3680 {
3681 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3682 return FALSE;
3683 }
3684
3685 /***********************************************************************
3686 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3687 */
3688 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3689 HDEVINFO DeviceInfoSet,
3690 PSP_DEVINFO_DATA DeviceInfoData,
3691 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3692 {
3693 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3694 return FALSE;
3695 }
3696
3697 static HKEY SETUPDI_OpenDevKey(struct DeviceInfo *devInfo, REGSAM samDesired)
3698 {
3699 HKEY enumKey, key = INVALID_HANDLE_VALUE;
3700 LONG l;
3701
3702 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
3703 NULL, &enumKey, NULL);
3704 if (!l)
3705 {
3706 RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
3707 RegCloseKey(enumKey);
3708 }
3709 return key;
3710 }
3711
3712 static HKEY SETUPDI_OpenDrvKey(struct DeviceInfo *devInfo, REGSAM samDesired)
3713 {
3714 static const WCHAR slash[] = { '\\',0 };
3715 WCHAR classKeyPath[MAX_PATH];
3716 HKEY classKey, key = INVALID_HANDLE_VALUE;
3717 LONG l;
3718
3719 lstrcpyW(classKeyPath, ControlClass);
3720 lstrcatW(classKeyPath, slash);
3721 SETUPDI_GuidToString(&devInfo->set->ClassGuid,
3722 classKeyPath + lstrlenW(classKeyPath));
3723 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
3724 KEY_ALL_ACCESS, NULL, &classKey, NULL);
3725 if (!l)
3726 {
3727 static const WCHAR fmt[] = { '%','','4','u',0 };
3728 WCHAR devId[10];
3729
3730 sprintfW(devId, fmt, devInfo->devId);
3731 l = RegOpenKeyExW(classKey, devId, 0, samDesired, &key);
3732 RegCloseKey(classKey);
3733 if (l)
3734 {
3735 SetLastError(ERROR_KEY_DOES_NOT_EXIST);
3736 return INVALID_HANDLE_VALUE;
3737 }
3738 }
3739 return key;
3740 }
3741
3742 /***********************************************************************
3743 * SetupDiOpenDevRegKey (SETUPAPI.@)
3744 */
3745 HKEY WINAPI SetupDiOpenDevRegKey(
3746 HDEVINFO DeviceInfoSet,
3747 PSP_DEVINFO_DATA DeviceInfoData,
3748 DWORD Scope,
3749 DWORD HwProfile,
3750 DWORD KeyType,
3751 REGSAM samDesired)
3752 {
3753 struct DeviceInfoSet *set = DeviceInfoSet;
3754 struct DeviceInfo *devInfo;
3755 HKEY key = INVALID_HANDLE_VALUE;
3756
3757 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
3758 Scope, HwProfile, KeyType, samDesired);
3759
3760 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3761 {
3762 SetLastError(ERROR_INVALID_HANDLE);
3763 return INVALID_HANDLE_VALUE;
3764 }
3765 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3766 {
3767 SetLastError(ERROR_INVALID_HANDLE);
3768 return INVALID_HANDLE_VALUE;
3769 }
3770 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3771 || !DeviceInfoData->Reserved)
3772 {
3773 SetLastError(ERROR_INVALID_PARAMETER);
3774 return INVALID_HANDLE_VALUE;
3775 }
3776 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3777 {
3778 SetLastError(ERROR_INVALID_FLAGS);
3779 return INVALID_HANDLE_VALUE;
3780 }
3781 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3782 {
3783 SetLastError(ERROR_INVALID_FLAGS);
3784 return INVALID_HANDLE_VALUE;
3785 }
3786 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3787 if (devInfo->set != set)
3788 {
3789 SetLastError(ERROR_INVALID_PARAMETER);
3790 return INVALID_HANDLE_VALUE;
3791 }
3792 if (devInfo->phantom)
3793 {
3794 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
3795 return INVALID_HANDLE_VALUE;
3796 }
3797 if (Scope != DICS_FLAG_GLOBAL)
3798 FIXME("unimplemented for scope %d\n", Scope);
3799 switch (KeyType)
3800 {
3801 case DIREG_DEV:
3802 key = SETUPDI_OpenDevKey(devInfo, samDesired);
3803 break;
3804 case DIREG_DRV:
3805 key = SETUPDI_OpenDrvKey(devInfo, samDesired);
3806 break;
3807 default:
3808 WARN("unknown KeyType %d\n", KeyType);
3809 }
3810 return key;
3811 }
3812
3813 static BOOL SETUPDI_DeleteDevKey(struct DeviceInfo *devInfo)
3814 {
3815 HKEY enumKey;
3816 BOOL ret = FALSE;
3817 LONG l;
3818
3819 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
3820 NULL, &enumKey, NULL);
3821 if (!l)
3822 {
3823 ret = RegDeleteTreeW(enumKey, devInfo->instanceId);
3824 RegCloseKey(enumKey);
3825 }
3826 else
3827 SetLastError(l);
3828 return ret;
3829 }
3830
3831 static BOOL SETUPDI_DeleteDrvKey(struct DeviceInfo *devInfo)
3832 {
3833 static const WCHAR slash[] = { '\\',0 };
3834 WCHAR classKeyPath[MAX_PATH];
3835 HKEY classKey;
3836 LONG l;
3837 BOOL ret = FALSE;
3838
3839 lstrcpyW(classKeyPath, ControlClass);
3840 lstrcatW(classKeyPath, slash);
3841 SETUPDI_GuidToString(&devInfo->set->ClassGuid,
3842 classKeyPath + lstrlenW(classKeyPath));
3843 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
3844 KEY_ALL_ACCESS, NULL, &classKey, NULL);
3845 if (!l)
3846 {
3847 static const WCHAR fmt[] = { '%','','4','u',0 };
3848 WCHAR devId[10];
3849
3850 sprintfW(devId, fmt, devInfo->devId);
3851 ret = RegDeleteTreeW(classKey, devId);
3852 RegCloseKey(classKey);
3853 }
3854 else
3855 SetLastError(l);
3856 return ret;
3857 }
3858
3859 /***********************************************************************
3860 * SetupDiDeleteDevRegKey (SETUPAPI.@)
3861 */
3862 BOOL WINAPI SetupDiDeleteDevRegKey(
3863 HDEVINFO DeviceInfoSet,
3864 PSP_DEVINFO_DATA DeviceInfoData,
3865 DWORD Scope,
3866 DWORD HwProfile,
3867 DWORD KeyType)
3868 {
3869 struct DeviceInfoSet *set = DeviceInfoSet;
3870 struct DeviceInfo *devInfo;
3871 BOOL ret = FALSE;
3872
3873 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
3874 KeyType);
3875
3876 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3877 {
3878 SetLastError(ERROR_INVALID_HANDLE);
3879 return FALSE;
3880 }
3881 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3882 {
3883 SetLastError(ERROR_INVALID_HANDLE);
3884 return FALSE;
3885 }
3886 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3887 || !DeviceInfoData->Reserved)
3888 {
3889 SetLastError(ERROR_INVALID_PARAMETER);
3890 return FALSE;
3891 }
3892 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3893 {
3894 SetLastError(ERROR_INVALID_FLAGS);
3895 return FALSE;
3896 }
3897 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
3898 {
3899 SetLastError(ERROR_INVALID_FLAGS);
3900 return FALSE;
3901 }
3902 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3903 if (devInfo->set != set)
3904 {
3905 SetLastError(ERROR_INVALID_PARAMETER);
3906 return FALSE;
3907 }
3908 if (devInfo->phantom)
3909 {
3910 SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
3911 return FALSE;
3912 }
3913 if (Scope != DICS_FLAG_GLOBAL)
3914 FIXME("unimplemented for scope %d\n", Scope);
3915 switch (KeyType)
3916 {
3917 case DIREG_DEV:
3918 ret = SETUPDI_DeleteDevKey(devInfo);
3919 break;
3920 case DIREG_DRV:
3921 ret = SETUPDI_DeleteDrvKey(devInfo);
3922 break;
3923 case DIREG_BOTH:
3924 ret = SETUPDI_DeleteDevKey(devInfo);
3925 if (ret)
3926 ret = SETUPDI_DeleteDrvKey(devInfo);
3927 break;
3928 default:
3929 WARN("unknown KeyType %d\n", KeyType);
3930 }
3931 return ret;
3932 }
3933
3934 /***********************************************************************
3935 * CM_Get_Device_IDA (SETUPAPI.@)
3936 */
3937 CONFIGRET WINAPI CM_Get_Device_IDA( DEVINST dnDevInst, PSTR Buffer,
3938 ULONG BufferLen, ULONG ulFlags)
3939 {
3940 struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
3941
3942 TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
3943
3944 if (!devInfo)
3945 return CR_NO_SUCH_DEVINST;
3946
3947 WideCharToMultiByte(CP_ACP, 0, devInfo->instanceId, -1, Buffer, BufferLen, 0, 0);
3948 TRACE("Returning %s\n", debugstr_a(Buffer));
3949 return CR_SUCCESS;
3950 }
3951
3952 /***********************************************************************
3953 * CM_Get_Device_IDW (SETUPAPI.@)
3954 */
3955 CONFIGRET WINAPI CM_Get_Device_IDW( DEVINST dnDevInst, LPWSTR Buffer,
3956 ULONG BufferLen, ULONG ulFlags)
3957 {
3958 struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
3959
3960 TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
3961
3962 if (!devInfo)
3963 {
3964 WARN("dev instance %d not found!\n", dnDevInst);
3965 return CR_NO_SUCH_DEVINST;
3966 }
3967
3968 lstrcpynW(Buffer, devInfo->instanceId, BufferLen);
3969 TRACE("Returning %s\n", debugstr_w(Buffer));
3970 GlobalUnlock((HANDLE)dnDevInst);
3971 return CR_SUCCESS;
3972 }
3973
3974
3975
3976 /***********************************************************************
3977 * CM_Get_Device_ID_Size (SETUPAPI.@)
3978 */
3979 CONFIGRET WINAPI CM_Get_Device_ID_Size( PULONG pulLen, DEVINST dnDevInst,
3980 ULONG ulFlags)
3981 {
3982 struct DeviceInfo *ppdevInfo = GlobalLock((HANDLE)dnDevInst);
3983
3984 TRACE("%x->%p, %p, %u\n", dnDevInst, ppdevInfo, pulLen, ulFlags);
3985
3986 if (!ppdevInfo)
3987 {
3988 WARN("dev instance %d not found!\n", dnDevInst);
3989 return CR_NO_SUCH_DEVINST;
3990 }
3991
3992 *pulLen = lstrlenW(ppdevInfo->instanceId);
3993 GlobalUnlock((HANDLE)dnDevInst);
3994 return CR_SUCCESS;
3995 }
3996
3997 /***********************************************************************
3998 * SetupDiGetINFClassA (SETUPAPI.@)
3999 */
4000 BOOL WINAPI SetupDiGetINFClassA(PCSTR inf, LPGUID class_guid, PSTR class_name,
4001 DWORD size, PDWORD required_size)
4002 {
4003 BOOL retval;
4004 DWORD required_sizeA, required_sizeW;
4005 PWSTR class_nameW = NULL;
4006 UNICODE_STRING infW;
4007
4008 if (inf)
4009 {
4010 if (!RtlCreateUnicodeStringFromAsciiz(&infW, inf))
4011 {
4012 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4013 return FALSE;
4014 }
4015 }
4016 else
4017 infW.Buffer = NULL;
4018
4019 if (class_name && size)
4020 {
4021 if (!(class_nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR))))
4022 {
4023 RtlFreeUnicodeString(&infW);
4024 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4025 return FALSE;
4026 }
4027 }
4028
4029 retval = SetupDiGetINFClassW(infW.Buffer, class_guid, class_nameW, size, &required_sizeW);
4030
4031 if (retval)
4032 {
4033 required_sizeA = WideCharToMultiByte( CP_ACP, 0, class_nameW, required_sizeW,
4034 class_name, size, NULL, NULL);
4035
4036 if(required_size) *required_size = required_sizeA;
4037 }
4038 else
4039 if(required_size) *required_size = required_sizeW;
4040
4041 HeapFree(GetProcessHeap(), 0, class_nameW);
4042 RtlFreeUnicodeString(&infW);
4043 return retval;
4044 }
4045
4046 /***********************************************************************
4047 * SetupDiGetINFClassW (SETUPAPI.@)
4048 */
4049 BOOL WINAPI SetupDiGetINFClassW(PCWSTR inf, LPGUID class_guid, PWSTR class_name,
4050 DWORD size, PDWORD required_size)
4051 {
4052 BOOL have_guid, have_name;
4053 DWORD dret;
4054 WCHAR buffer[MAX_PATH];
4055
4056 if (!inf)
4057 {
4058 SetLastError(ERROR_INVALID_PARAMETER);
4059 return FALSE;
4060 }
4061
4062 if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(inf))
4063 {
4064 FIXME("%s not found. Searching via DevicePath not implemented\n", debugstr_w(inf));
4065 SetLastError(ERROR_FILE_NOT_FOUND);
4066 return FALSE;
4067 }
4068
4069 if (!class_guid || !class_name || !size)
4070 {
4071 SetLastError(ERROR_INVALID_PARAMETER);
4072 return FALSE;
4073 }
4074
4075 if (!GetPrivateProfileStringW(Version, Signature, NULL, buffer, MAX_PATH, inf))
4076 return FALSE;
4077
4078 if (lstrcmpiW(buffer, Chicago))
4079 return FALSE;
4080
4081 buffer[0] = '\0';
4082 have_guid = 0 < GetPrivateProfileStringW(Version, ClassGUID, NULL, buffer, MAX_PATH, inf);
4083 if (have_guid)
4084 {
4085 buffer[lstrlenW(buffer)-1] = 0;
4086 if (RPC_S_OK != UuidFromStringW(buffer + 1, class_guid))
4087 {
4088 FIXME("failed to convert \"%s\" into a guid\n", debugstr_w(buffer));
4089 SetLastError(ERROR_INVALID_PARAMETER);
4090 return FALSE;
4091 }
4092 }
4093
4094 buffer[0] = '\0';
4095 dret = GetPrivateProfileStringW(Version, Class, NULL, buffer, MAX_PATH, inf);
4096 have_name = 0 < dret;
4097
4098 if (dret >= MAX_PATH -1) FIXME("buffer might be too small\n");
4099 if (have_guid && !have_name) FIXME("class name lookup via guid not implemented\n");
4100
4101 if (have_name)
4102 {
4103 if (dret < size) lstrcpyW(class_name, buffer);
4104 else
4105 {
4106 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4107 have_name = FALSE;
4108 }
4109 }
4110
4111 if (required_size) *required_size = dret + ((dret) ? 1 : 0);
4112
4113 return (have_guid || have_name);
4114 }
4115
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.