22a754ca7d968321429bb3ae06b38d5243f10e29
[reactos.git] / reactos / lib / setupapi / devinst.c
1 /*
2 * SetupAPI device installer
3 *
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.com)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26
27 #include <windows.h>
28 #include "setupapi.h"
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31 #include "cfgmgr32.h"
32 #include "initguid.h"
33 #define NTOS_MODE_USER
34 #include <ndk/ntndk.h>
35
36 #include "setupapi_private.h"
37
38
39 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
40
41 /* Unicode constants */
42 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
43 static const WCHAR Class[] = {'C','l','a','s','s',0};
44 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
45 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
46 static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
47 static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
48 static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
49 static const WCHAR NtExtension[] = {'.','N','T',0};
50 static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
51 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
52 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
53 static const WCHAR WinExtension[] = {'.','W','i','n',0};
54
55 /* Registry key and value names */
56 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
57 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
58 'C','o','n','t','r','o','l','\\',
59 'C','l','a','s','s',0};
60
61 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
62 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
63 'C','o','n','t','r','o','l','\\',
64 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
65
66 static const WCHAR EnumKeyName[] = {'S','y','s','t','e','m','\\',
67 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
68 'E','n','u','m',0};
69
70
71 /* FIXME: header mess */
72 DEFINE_GUID(GUID_NULL,
73 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
74 typedef DWORD
75 (CALLBACK* CLASS_INSTALL_PROC) (
76 IN DI_FUNCTION InstallFunction,
77 IN HDEVINFO DeviceInfoSet,
78 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
79 typedef BOOL
80 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
81 IN HDEVINFO DeviceInfoSet,
82 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
83 typedef DWORD
84 (CALLBACK* COINSTALLER_PROC) (
85 IN DI_FUNCTION InstallFunction,
86 IN HDEVINFO DeviceInfoSet,
87 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
88 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
89
90 #define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
91
92 struct CoInstallerElement
93 {
94 LIST_ENTRY ListEntry;
95
96 COINSTALLER_PROC Function;
97 BOOL DoPostProcessing;
98 PVOID PrivateData;
99 };
100
101 struct DeviceInterface /* Element of DeviceInfoElement.InterfaceListHead */
102 {
103 LIST_ENTRY ListEntry;
104
105 struct DeviceInfoElement* DeviceInfo;
106 GUID InterfaceClassGuid;
107
108
109 /* SPINT_ACTIVE : the interface is active/enabled
110 * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
111 * SPINT_REMOVED: the interface is removed
112 */
113 DWORD Flags;
114
115 WCHAR SymbolicLink[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
116 };
117
118 struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
119 {
120 LIST_ENTRY ListEntry;
121
122 DWORD DriverRank;
123 SP_DRVINFO_DATA_V2_W Info;
124 LPWSTR InfPath;
125 LPWSTR InfSection;
126 LPWSTR MatchingId;
127 };
128
129 struct DeviceInfoElement /* Element of DeviceInfoSet.ListHead */
130 {
131 LIST_ENTRY ListEntry;
132
133 /* Information about devnode:
134 * - DeviceName:
135 * "Root\*PNP0501" for example.
136 * It doesn't contain the unique ID for the device
137 * (points into the Data field at the end of the structure)
138 * WARNING: no NULL char exist between DeviceName and UniqueId
139 * in Data field!
140 * - UniqueId
141 * "5&1be2108e&0" or "0000"
142 * If DICD_GENERATE_ID is specified in creation flags,
143 * this unique ID is autogenerated using 4 digits, base 10
144 * (points into the Data field at the end of the structure)
145 * - DeviceDescription
146 * String which identifies the device. Can be NULL. If not NULL,
147 * points into the Data field at the end of the structure
148 * - ClassGuid
149 * Identifies the class of this device. FIXME: can it be GUID_NULL?
150 * - CreationFlags
151 * Is a combination of:
152 * - DICD_GENERATE_ID
153 * the unique ID needs to be generated
154 * - DICD_INHERIT_CLASSDRVS
155 * inherit driver of the device info set (== same pointer)
156 * - hwndParent
157 * Used when doing device-specific actions. Can be NULL
158 */
159 PCWSTR DeviceName;
160 PCWSTR UniqueId;
161 PCWSTR DeviceDescription;
162 GUID ClassGuid;
163 DWORD CreationFlags;
164 HWND hwndParent;
165
166 /* Flags is a combination of:
167 * - DI_DIDCOMPAT
168 * Set when the device driver list is created
169 * FlagsEx is a combination of:
170 */
171 DWORD Flags;
172 DWORD FlagsEx;
173
174 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
175 /* If the driver is not searched/detected, this list is empty */
176 LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */
177 /* Points into DriverListHead list. The pointer is NULL if no driver is
178 * currently chosen. */
179 struct DriverInfoElement *SelectedDriver;
180
181 /* List of interfaces implemented by this device */
182 LIST_ENTRY InterfaceListHead; /* List of struct DeviceInterface */
183
184 WCHAR Data[0];
185 };
186
187 struct DeviceInfoSet /* HDEVINFO */
188 {
189 DWORD magic; /* SETUP_DEV_INFO_SET_MAGIC */
190 GUID ClassGuid; /* If != GUID_NULL, only devices of this class can be in the device info set */
191 HWND hwndParent; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
192 HKEY HKLM; /* Local or distant HKEY_LOCAL_MACHINE registry key */
193
194 /* Flags is a combination of:
195 * - DI_DIDCLASS
196 * Set when the class driver list is created
197 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
198 * Forces SetupDiBuildDriverInfoList to build a class drivers list
199 * FlagsEx is a combination of:
200 */
201 DWORD Flags;
202 DWORD FlagsEx;
203
204 /* If the driver is not searched/detected, this list is empty */
205 LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */
206 /* Points into DriverListHead list. The pointer is NULL if no driver is
207 * currently chosen. */
208 struct DriverInfoElement *SelectedDriver;
209
210 LIST_ENTRY ListHead; /* List of struct DeviceInfoElement */
211 };
212
213 /***********************************************************************
214 * SetupDiBuildClassInfoList (SETUPAPI.@)
215 */
216 BOOL WINAPI SetupDiBuildClassInfoList(
217 DWORD Flags,
218 LPGUID ClassGuidList,
219 DWORD ClassGuidListSize,
220 PDWORD RequiredSize)
221 {
222 TRACE("\n");
223 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
224 ClassGuidListSize, RequiredSize,
225 NULL, NULL);
226 }
227
228 /***********************************************************************
229 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
230 */
231 BOOL WINAPI SetupDiBuildClassInfoListExA(
232 DWORD Flags,
233 LPGUID ClassGuidList,
234 DWORD ClassGuidListSize,
235 PDWORD RequiredSize,
236 LPCSTR MachineName,
237 PVOID Reserved)
238 {
239 LPWSTR MachineNameW = NULL;
240 BOOL bResult;
241
242 TRACE("\n");
243
244 if (MachineName)
245 {
246 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
247 if (MachineNameW == NULL) return FALSE;
248 }
249
250 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
251 ClassGuidListSize, RequiredSize,
252 MachineNameW, Reserved);
253
254 if (MachineNameW)
255 MyFree(MachineNameW);
256
257 return bResult;
258 }
259
260 /***********************************************************************
261 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
262 */
263 BOOL WINAPI SetupDiBuildClassInfoListExW(
264 DWORD Flags,
265 LPGUID ClassGuidList,
266 DWORD ClassGuidListSize,
267 PDWORD RequiredSize,
268 LPCWSTR MachineName,
269 PVOID Reserved)
270 {
271 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
272 HKEY hClassesKey;
273 HKEY hClassKey;
274 DWORD dwLength;
275 DWORD dwIndex;
276 LONG lError;
277 DWORD dwGuidListIndex = 0;
278
279 TRACE("\n");
280
281 if (RequiredSize != NULL)
282 *RequiredSize = 0;
283
284 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
285 KEY_ALL_ACCESS,
286 DIOCR_INSTALLER,
287 MachineName,
288 Reserved);
289 if (hClassesKey == INVALID_HANDLE_VALUE)
290 {
291 return FALSE;
292 }
293
294 for (dwIndex = 0; ; dwIndex++)
295 {
296 dwLength = MAX_GUID_STRING_LEN + 1;
297 lError = RegEnumKeyExW(hClassesKey,
298 dwIndex,
299 szKeyName,
300 &dwLength,
301 NULL,
302 NULL,
303 NULL,
304 NULL);
305 TRACE("RegEnumKeyExW() returns %ld\n", lError);
306 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
307 {
308 TRACE("Key name: %p\n", szKeyName);
309
310 if (RegOpenKeyExW(hClassesKey,
311 szKeyName,
312 0,
313 KEY_ALL_ACCESS,
314 &hClassKey))
315 {
316 RegCloseKey(hClassesKey);
317 return FALSE;
318 }
319
320 if (!RegQueryValueExW(hClassKey,
321 NoUseClass,
322 NULL,
323 NULL,
324 NULL,
325 NULL))
326 {
327 TRACE("'NoUseClass' value found!\n");
328 RegCloseKey(hClassKey);
329 continue;
330 }
331
332 if ((Flags & DIBCI_NOINSTALLCLASS) &&
333 (!RegQueryValueExW(hClassKey,
334 NoInstallClass,
335 NULL,
336 NULL,
337 NULL,
338 NULL)))
339 {
340 TRACE("'NoInstallClass' value found!\n");
341 RegCloseKey(hClassKey);
342 continue;
343 }
344
345 if ((Flags & DIBCI_NODISPLAYCLASS) &&
346 (!RegQueryValueExW(hClassKey,
347 NoDisplayClass,
348 NULL,
349 NULL,
350 NULL,
351 NULL)))
352 {
353 TRACE("'NoDisplayClass' value found!\n");
354 RegCloseKey(hClassKey);
355 continue;
356 }
357
358 RegCloseKey(hClassKey);
359
360 TRACE("Guid: %p\n", szKeyName);
361 if (dwGuidListIndex < ClassGuidListSize)
362 {
363 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
364 {
365 szKeyName[37] = 0;
366 }
367 TRACE("Guid: %p\n", &szKeyName[1]);
368
369 UuidFromStringW(&szKeyName[1],
370 &ClassGuidList[dwGuidListIndex]);
371 }
372
373 dwGuidListIndex++;
374 }
375
376 if (lError != ERROR_SUCCESS)
377 break;
378 }
379
380 RegCloseKey(hClassesKey);
381
382 if (RequiredSize != NULL)
383 *RequiredSize = dwGuidListIndex;
384
385 if (ClassGuidListSize < dwGuidListIndex)
386 {
387 SetLastError(ERROR_INSUFFICIENT_BUFFER);
388 return FALSE;
389 }
390
391 return TRUE;
392 }
393
394 /***********************************************************************
395 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
396 */
397 BOOL WINAPI SetupDiClassGuidsFromNameA(
398 LPCSTR ClassName,
399 LPGUID ClassGuidList,
400 DWORD ClassGuidListSize,
401 PDWORD RequiredSize)
402 {
403 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
404 ClassGuidListSize, RequiredSize,
405 NULL, NULL);
406 }
407
408 /***********************************************************************
409 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
410 */
411 BOOL WINAPI SetupDiClassGuidsFromNameW(
412 LPCWSTR ClassName,
413 LPGUID ClassGuidList,
414 DWORD ClassGuidListSize,
415 PDWORD RequiredSize)
416 {
417 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
418 ClassGuidListSize, RequiredSize,
419 NULL, NULL);
420 }
421
422 /***********************************************************************
423 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
424 */
425 BOOL WINAPI SetupDiClassGuidsFromNameExA(
426 LPCSTR ClassName,
427 LPGUID ClassGuidList,
428 DWORD ClassGuidListSize,
429 PDWORD RequiredSize,
430 LPCSTR MachineName,
431 PVOID Reserved)
432 {
433 LPWSTR ClassNameW = NULL;
434 LPWSTR MachineNameW = NULL;
435 BOOL bResult;
436
437 TRACE("\n");
438
439 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
440 if (ClassNameW == NULL)
441 return FALSE;
442
443 if (MachineNameW)
444 {
445 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
446 if (MachineNameW == NULL)
447 {
448 MyFree(ClassNameW);
449 return FALSE;
450 }
451 }
452
453 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
454 ClassGuidListSize, RequiredSize,
455 MachineNameW, Reserved);
456
457 if (MachineNameW)
458 MyFree(MachineNameW);
459
460 MyFree(ClassNameW);
461
462 return bResult;
463 }
464
465 /***********************************************************************
466 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
467 */
468 BOOL WINAPI SetupDiClassGuidsFromNameExW(
469 LPCWSTR ClassName,
470 LPGUID ClassGuidList,
471 DWORD ClassGuidListSize,
472 PDWORD RequiredSize,
473 LPCWSTR MachineName,
474 PVOID Reserved)
475 {
476 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
477 WCHAR szClassName[256];
478 HKEY hClassesKey;
479 HKEY hClassKey;
480 DWORD dwLength;
481 DWORD dwIndex;
482 LONG lError;
483 DWORD dwGuidListIndex = 0;
484
485 if (RequiredSize != NULL)
486 *RequiredSize = 0;
487
488 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
489 KEY_ENUMERATE_SUB_KEYS,
490 DIOCR_INSTALLER,
491 MachineName,
492 Reserved);
493 if (hClassesKey == INVALID_HANDLE_VALUE)
494 {
495 return FALSE;
496 }
497
498 for (dwIndex = 0; ; dwIndex++)
499 {
500 dwLength = MAX_GUID_STRING_LEN + 1;
501 lError = RegEnumKeyExW(hClassesKey,
502 dwIndex,
503 szKeyName,
504 &dwLength,
505 NULL,
506 NULL,
507 NULL,
508 NULL);
509 TRACE("RegEnumKeyExW() returns %ld\n", lError);
510 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
511 {
512 TRACE("Key name: %p\n", szKeyName);
513
514 if (RegOpenKeyExW(hClassesKey,
515 szKeyName,
516 0,
517 KEY_QUERY_VALUE,
518 &hClassKey))
519 {
520 RegCloseKey(hClassesKey);
521 return FALSE;
522 }
523
524 dwLength = 256 * sizeof(WCHAR);
525 if (!RegQueryValueExW(hClassKey,
526 Class,
527 NULL,
528 NULL,
529 (LPBYTE)szClassName,
530 &dwLength))
531 {
532 TRACE("Class name: %p\n", szClassName);
533
534 if (strcmpiW(szClassName, ClassName) == 0)
535 {
536 TRACE("Found matching class name\n");
537
538 TRACE("Guid: %p\n", szKeyName);
539 if (dwGuidListIndex < ClassGuidListSize)
540 {
541 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
542 {
543 szKeyName[37] = 0;
544 }
545 TRACE("Guid: %p\n", &szKeyName[1]);
546
547 UuidFromStringW(&szKeyName[1],
548 &ClassGuidList[dwGuidListIndex]);
549 }
550
551 dwGuidListIndex++;
552 }
553 }
554
555 RegCloseKey(hClassKey);
556 }
557
558 if (lError != ERROR_SUCCESS)
559 break;
560 }
561
562 RegCloseKey(hClassesKey);
563
564 if (RequiredSize != NULL)
565 *RequiredSize = dwGuidListIndex;
566
567 if (ClassGuidListSize < dwGuidListIndex)
568 {
569 SetLastError(ERROR_INSUFFICIENT_BUFFER);
570 return FALSE;
571 }
572
573 return TRUE;
574 }
575
576 /***********************************************************************
577 * SetupDiClassNameFromGuidA (SETUPAPI.@)
578 */
579 BOOL WINAPI SetupDiClassNameFromGuidA(
580 const GUID* ClassGuid,
581 PSTR ClassName,
582 DWORD ClassNameSize,
583 PDWORD RequiredSize)
584 {
585 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
586 ClassNameSize, RequiredSize,
587 NULL, NULL);
588 }
589
590 /***********************************************************************
591 * SetupDiClassNameFromGuidW (SETUPAPI.@)
592 */
593 BOOL WINAPI SetupDiClassNameFromGuidW(
594 const GUID* ClassGuid,
595 PWSTR ClassName,
596 DWORD ClassNameSize,
597 PDWORD RequiredSize)
598 {
599 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
600 ClassNameSize, RequiredSize,
601 NULL, NULL);
602 }
603
604 /***********************************************************************
605 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
606 */
607 BOOL WINAPI SetupDiClassNameFromGuidExA(
608 const GUID* ClassGuid,
609 PSTR ClassName,
610 DWORD ClassNameSize,
611 PDWORD RequiredSize,
612 PCSTR MachineName,
613 PVOID Reserved)
614 {
615 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
616 LPWSTR MachineNameW = NULL;
617 BOOL ret;
618
619 if (MachineName)
620 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
621 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
622 NULL, MachineNameW, Reserved);
623 if (ret)
624 {
625 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
626 ClassNameSize, NULL, NULL);
627
628 if (!ClassNameSize && RequiredSize)
629 *RequiredSize = len;
630 }
631 MyFree(MachineNameW);
632 return ret;
633 }
634
635 /***********************************************************************
636 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
637 */
638 BOOL WINAPI SetupDiClassNameFromGuidExW(
639 const GUID* ClassGuid,
640 PWSTR ClassName,
641 DWORD ClassNameSize,
642 PDWORD RequiredSize,
643 PCWSTR MachineName,
644 PVOID Reserved)
645 {
646 HKEY hKey;
647 DWORD dwLength;
648 LONG rc;
649
650 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
651 KEY_QUERY_VALUE,
652 DIOCR_INSTALLER,
653 MachineName,
654 Reserved);
655 if (hKey == INVALID_HANDLE_VALUE)
656 {
657 return FALSE;
658 }
659
660 if (RequiredSize != NULL)
661 {
662 dwLength = 0;
663 rc = RegQueryValueExW(hKey,
664 Class,
665 NULL,
666 NULL,
667 NULL,
668 &dwLength);
669 if (rc != ERROR_SUCCESS)
670 {
671 SetLastError(rc);
672 RegCloseKey(hKey);
673 return FALSE;
674 }
675
676 *RequiredSize = dwLength / sizeof(WCHAR);
677 }
678
679 dwLength = ClassNameSize * sizeof(WCHAR);
680 rc = RegQueryValueExW(hKey,
681 Class,
682 NULL,
683 NULL,
684 (LPBYTE)ClassName,
685 &dwLength);
686 if (rc != ERROR_SUCCESS)
687 {
688 SetLastError(rc);
689 RegCloseKey(hKey);
690 return FALSE;
691 }
692
693 RegCloseKey(hKey);
694
695 return TRUE;
696 }
697
698 /***********************************************************************
699 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
700 */
701 HDEVINFO WINAPI
702 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
703 HWND hwndParent)
704 {
705 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
706 }
707
708 /***********************************************************************
709 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
710 */
711 HDEVINFO WINAPI
712 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
713 HWND hwndParent,
714 PCSTR MachineName,
715 PVOID Reserved)
716 {
717 LPWSTR MachineNameW = NULL;
718 HDEVINFO hDevInfo;
719
720 TRACE("%p %p %s %p\n", ClassGuid, hwndParent, MachineName, Reserved);
721
722 if (MachineName)
723 {
724 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
725 if (MachineNameW == NULL)
726 return (HDEVINFO)INVALID_HANDLE_VALUE;
727 }
728
729 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
730 MachineNameW, Reserved);
731
732 if (MachineNameW)
733 MyFree(MachineNameW);
734
735 return hDevInfo;
736 }
737
738 /***********************************************************************
739 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
740 */
741 HDEVINFO WINAPI
742 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
743 HWND hwndParent,
744 PCWSTR MachineName,
745 PVOID Reserved)
746 {
747 struct DeviceInfoSet *list;
748 DWORD rc;
749
750 TRACE("%p %p %S %p\n", ClassGuid, hwndParent, MachineName, Reserved);
751
752 list = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet));
753 if (!list)
754 {
755 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
756 return (HDEVINFO)INVALID_HANDLE_VALUE;
757 }
758
759 list->magic = SETUP_DEV_INFO_SET_MAGIC;
760 memcpy(
761 &list->ClassGuid,
762 ClassGuid ? ClassGuid : &GUID_NULL,
763 sizeof(list->ClassGuid));
764 list->hwndParent = hwndParent;
765 if (MachineName)
766 {
767 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
768 if (rc != ERROR_SUCCESS)
769 {
770 SetLastError(rc);
771 HeapFree(GetProcessHeap(), 0, list);
772 return (HDEVINFO)INVALID_HANDLE_VALUE;
773 }
774 }
775 else
776 {
777 list->HKLM = HKEY_LOCAL_MACHINE;
778 }
779 list->Flags = 0; /* FIXME */
780 list->FlagsEx = 0; /* FIXME */
781 InitializeListHead(&list->DriverListHead);
782 InitializeListHead(&list->ListHead);
783 return (HDEVINFO)list;
784 }
785
786 /***********************************************************************
787 * SetupDiEnumDeviceInfo (SETUPAPI.@)
788 */
789 BOOL WINAPI SetupDiEnumDeviceInfo(
790 HDEVINFO DeviceInfoSet,
791 DWORD MemberIndex,
792 PSP_DEVINFO_DATA DeviceInfoData)
793 {
794 BOOL ret = FALSE;
795
796 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
797 if (!DeviceInfoData)
798 SetLastError(ERROR_INVALID_PARAMETER);
799 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
800 {
801 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
802
803 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
804 SetLastError(ERROR_INVALID_HANDLE);
805 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
806 SetLastError(ERROR_INVALID_USER_BUFFER);
807 else
808 {
809 PLIST_ENTRY ItemList = list->ListHead.Flink;
810 while (ItemList != &list->ListHead && MemberIndex-- > 0)
811 ItemList = ItemList->Flink;
812 if (ItemList == &list->ListHead)
813 SetLastError(ERROR_NO_MORE_ITEMS);
814 else
815 {
816 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
817 memcpy(&DeviceInfoData->ClassGuid,
818 &DevInfo->ClassGuid,
819 sizeof(GUID));
820 DeviceInfoData->DevInst = 0; /* FIXME */
821 /* Note: this appears to be dangerous, passing a private
822 * pointer a heap-allocated datum to the caller. However, the
823 * expected lifetime of the device data is the same as the
824 * HDEVINFO; once that is closed, the data are no longer valid.
825 */
826 DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
827 ret = TRUE;
828 }
829 }
830 }
831 else
832 SetLastError(ERROR_INVALID_HANDLE);
833 return ret;
834 }
835
836 /***********************************************************************
837 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
838 */
839 BOOL WINAPI SetupDiGetActualSectionToInstallA(
840 HINF InfHandle,
841 PCSTR InfSectionName,
842 PSTR InfSectionWithExt,
843 DWORD InfSectionWithExtSize,
844 PDWORD RequiredSize,
845 PSTR *Extension)
846 {
847 LPWSTR InfSectionNameW = NULL;
848 PWSTR InfSectionWithExtW = NULL;
849 PWSTR ExtensionW;
850 BOOL bResult = FALSE;
851
852 TRACE("\n");
853
854 if (InfSectionName)
855 {
856 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
857 if (InfSectionNameW == NULL) goto end;
858 }
859 if (InfSectionWithExt)
860 {
861 InfSectionWithExtW = HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize * sizeof(WCHAR));
862 if (InfSectionWithExtW == NULL) goto end;
863 }
864
865 bResult = SetupDiGetActualSectionToInstallW(InfHandle, InfSectionNameW,
866 InfSectionWithExt ? InfSectionNameW : NULL,
867 InfSectionWithExtSize, RequiredSize,
868 Extension ? &ExtensionW : NULL);
869
870 if (bResult && InfSectionWithExt)
871 {
872 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
873 InfSectionWithExtSize, NULL, NULL) != 0;
874 }
875 if (bResult && Extension)
876 {
877 if (ExtensionW == NULL)
878 *Extension = NULL;
879 else
880 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
881 }
882
883 end:
884 if (InfSectionNameW) MyFree(InfSectionNameW);
885 if (InfSectionWithExtW) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW);
886
887 return bResult;
888 }
889
890 /***********************************************************************
891 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
892 */
893 BOOL WINAPI SetupDiGetActualSectionToInstallW(
894 HINF InfHandle,
895 PCWSTR InfSectionName,
896 PWSTR InfSectionWithExt,
897 DWORD InfSectionWithExtSize,
898 PDWORD RequiredSize,
899 PWSTR *Extension)
900 {
901 WCHAR szBuffer[MAX_PATH];
902 DWORD dwLength;
903 DWORD dwFullLength;
904 LONG lLineCount = -1;
905
906 lstrcpyW(szBuffer, InfSectionName);
907 dwLength = lstrlenW(szBuffer);
908
909 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
910 {
911 /* Test section name with '.NTx86' extension */
912 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
913 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
914
915 if (lLineCount == -1)
916 {
917 /* Test section name with '.NT' extension */
918 lstrcpyW(&szBuffer[dwLength], NtExtension);
919 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
920 }
921 }
922 else
923 {
924 /* Test section name with '.Win' extension */
925 lstrcpyW(&szBuffer[dwLength], WinExtension);
926 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
927 }
928
929 if (lLineCount == -1)
930 {
931 /* Test section name without extension */
932 szBuffer[dwLength] = 0;
933 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
934 }
935
936 if (lLineCount == -1)
937 {
938 SetLastError(ERROR_INVALID_PARAMETER);
939 return FALSE;
940 }
941
942 dwFullLength = lstrlenW(szBuffer);
943
944 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
945 {
946 if (InfSectionWithExtSize < (dwFullLength + 1))
947 {
948 SetLastError(ERROR_INSUFFICIENT_BUFFER);
949 return FALSE;
950 }
951
952 lstrcpyW(InfSectionWithExt, szBuffer);
953 if (Extension != NULL)
954 {
955 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
956 }
957 }
958
959 if (RequiredSize != NULL)
960 {
961 *RequiredSize = dwFullLength + 1;
962 }
963
964 return TRUE;
965 }
966
967 /***********************************************************************
968 * SetupDiGetClassDescriptionA (SETUPAPI.@)
969 */
970 BOOL WINAPI SetupDiGetClassDescriptionA(
971 const GUID* ClassGuid,
972 PSTR ClassDescription,
973 DWORD ClassDescriptionSize,
974 PDWORD RequiredSize)
975 {
976 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
977 ClassDescriptionSize,
978 RequiredSize, NULL, NULL);
979 }
980
981 /***********************************************************************
982 * SetupDiGetClassDescriptionW (SETUPAPI.@)
983 */
984 BOOL WINAPI SetupDiGetClassDescriptionW(
985 const GUID* ClassGuid,
986 PWSTR ClassDescription,
987 DWORD ClassDescriptionSize,
988 PDWORD RequiredSize)
989 {
990 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
991 ClassDescriptionSize,
992 RequiredSize, NULL, NULL);
993 }
994
995 /***********************************************************************
996 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
997 */
998 BOOL WINAPI SetupDiGetClassDescriptionExA(
999 const GUID* ClassGuid,
1000 PSTR ClassDescription,
1001 DWORD ClassDescriptionSize,
1002 PDWORD RequiredSize,
1003 PCSTR MachineName,
1004 PVOID Reserved)
1005 {
1006 PWCHAR ClassDescriptionW;
1007 LPWSTR MachineNameW = NULL;
1008 BOOL ret;
1009
1010 TRACE("\n");
1011 if (ClassDescriptionSize > 0)
1012 {
1013 ClassDescriptionW = HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize * sizeof(WCHAR));
1014 if (!ClassDescriptionW)
1015 {
1016 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1017 ret = FALSE;
1018 goto end;
1019 }
1020 }
1021 else
1022 ClassDescriptionW = NULL;
1023
1024 if (MachineName)
1025 {
1026 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1027 if (!MachineNameW)
1028 {
1029 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1030 ret = FALSE;
1031 goto end;
1032 }
1033 }
1034
1035 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, ClassDescriptionSize * sizeof(WCHAR),
1036 NULL, MachineNameW, Reserved);
1037 if (ret)
1038 {
1039 int len = WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
1040 ClassDescriptionSize, NULL, NULL);
1041
1042 if (!ClassDescriptionSize && RequiredSize)
1043 *RequiredSize = len;
1044 }
1045
1046 end:
1047 HeapFree(GetProcessHeap(), 0, ClassDescriptionW);
1048 MyFree(MachineNameW);
1049 return ret;
1050 }
1051
1052 /***********************************************************************
1053 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1054 */
1055 BOOL WINAPI SetupDiGetClassDescriptionExW(
1056 const GUID* ClassGuid,
1057 PWSTR ClassDescription,
1058 DWORD ClassDescriptionSize,
1059 PDWORD RequiredSize,
1060 PCWSTR MachineName,
1061 PVOID Reserved)
1062 {
1063 HKEY hKey;
1064 DWORD dwLength;
1065
1066 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1067 KEY_ALL_ACCESS,
1068 DIOCR_INSTALLER,
1069 MachineName,
1070 Reserved);
1071 if (hKey == INVALID_HANDLE_VALUE)
1072 {
1073 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1074 return FALSE;
1075 }
1076
1077 if (RequiredSize != NULL)
1078 {
1079 dwLength = 0;
1080 if (RegQueryValueExW(hKey,
1081 NULL,
1082 NULL,
1083 NULL,
1084 NULL,
1085 &dwLength))
1086 {
1087 RegCloseKey(hKey);
1088 return FALSE;
1089 }
1090
1091 *RequiredSize = dwLength / sizeof(WCHAR);
1092 }
1093
1094 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1095 if (RegQueryValueExW(hKey,
1096 NULL,
1097 NULL,
1098 NULL,
1099 (LPBYTE)ClassDescription,
1100 &dwLength))
1101 {
1102 RegCloseKey(hKey);
1103 return FALSE;
1104 }
1105
1106 RegCloseKey(hKey);
1107
1108 return TRUE;
1109 }
1110
1111 /***********************************************************************
1112 * SetupDiGetClassDevsA (SETUPAPI.@)
1113 */
1114 HDEVINFO WINAPI SetupDiGetClassDevsA(
1115 CONST GUID *class,
1116 LPCSTR enumstr,
1117 HWND parent,
1118 DWORD flags)
1119 {
1120 return SetupDiGetClassDevsExA(class, enumstr, parent,
1121 flags, NULL, NULL, NULL);
1122 }
1123
1124 /***********************************************************************
1125 * SetupDiGetClassDevsW (SETUPAPI.@)
1126 */
1127 HDEVINFO WINAPI SetupDiGetClassDevsW(
1128 CONST GUID *class,
1129 LPCWSTR enumstr,
1130 HWND parent,
1131 DWORD flags)
1132 {
1133 return SetupDiGetClassDevsExW(class, enumstr, parent,
1134 flags, NULL, NULL, NULL);
1135 }
1136
1137 /***********************************************************************
1138 * SetupDiGetClassDevsExA (SETUPAPI.@)
1139 */
1140 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1141 CONST GUID *class,
1142 LPCSTR enumstr,
1143 HWND parent,
1144 DWORD flags,
1145 HDEVINFO deviceset,
1146 LPCSTR machine,
1147 PVOID reserved)
1148 {
1149 HDEVINFO ret;
1150 LPWSTR enumstrW = NULL;
1151 LPWSTR machineW = NULL;
1152
1153 if (enumstr)
1154 {
1155 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1156 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1157 if (!enumstrW)
1158 {
1159 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1160 goto end;
1161 }
1162 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1163 }
1164 if (machine)
1165 {
1166 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1167 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1168 if (!machineW)
1169 {
1170 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1171 goto end;
1172 }
1173 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1174 }
1175 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, machineW, reserved);
1176
1177 end:
1178 HeapFree(GetProcessHeap(), 0, enumstrW);
1179 HeapFree(GetProcessHeap(), 0, machineW);
1180 return ret;
1181 }
1182
1183 static BOOL
1184 CreateDeviceInfoElement(
1185 IN LPCWSTR InstancePath,
1186 LPCGUID pClassGuid,
1187 OUT struct DeviceInfoElement **pDeviceInfo)
1188 {
1189 struct DeviceInfoElement *deviceInfo;
1190
1191 *pDeviceInfo = NULL;
1192 if (IsEqualIID(&pClassGuid, &GUID_NULL)) { FIXME("Bad argument!!!"); return FALSE; }/* FIXME: remove */
1193
1194 deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR));
1195 if (!deviceInfo)
1196 {
1197 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1198 return FALSE;
1199 }
1200 wcscpy(deviceInfo->Data, InstancePath);
1201 deviceInfo->DeviceName = deviceInfo->Data;
1202 deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
1203 deviceInfo->DeviceDescription = NULL;
1204 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
1205 deviceInfo->CreationFlags = 0;
1206 deviceInfo->hwndParent = NULL;
1207 deviceInfo->Flags = 0; /* FIXME */
1208 deviceInfo->FlagsEx = 0; /* FIXME */
1209 deviceInfo->SelectedDriver = NULL;
1210 InitializeListHead(&deviceInfo->DriverListHead);
1211 InitializeListHead(&deviceInfo->InterfaceListHead);
1212
1213 *pDeviceInfo = deviceInfo;
1214 return TRUE;
1215 }
1216
1217 static BOOL
1218 CreateDeviceInterface(
1219 IN struct DeviceInfoElement* deviceInfo,
1220 IN LPCWSTR SymbolicLink,
1221 IN LPCGUID pInterfaceGuid,
1222 OUT struct DeviceInterface **pDeviceInterface)
1223 {
1224 struct DeviceInterface *deviceInterface;
1225
1226 *pDeviceInterface = NULL;
1227
1228 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
1229 if (!deviceInterface)
1230 {
1231 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1232 return FALSE;
1233 }
1234 deviceInterface->DeviceInfo = deviceInfo;
1235 wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
1236 deviceInterface->Flags = 0; /* FIXME */
1237 memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
1238
1239 *pDeviceInterface = deviceInterface;
1240 return TRUE;
1241 }
1242
1243 static LONG SETUP_CreateDevListFromEnumerator(
1244 struct DeviceInfoSet *list,
1245 LPCGUID pClassGuid OPTIONAL,
1246 LPCWSTR Enumerator,
1247 HKEY hEnumeratorKey) /* handle to Enumerator registry key */
1248 {
1249 HKEY hDeviceIdKey, hInstanceIdKey;
1250 WCHAR KeyBuffer[MAX_PATH];
1251 WCHAR InstancePath[MAX_PATH];
1252 LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
1253 struct DeviceInfoElement *deviceInfo;
1254 DWORD i = 0, j;
1255 DWORD dwLength, dwRegType;
1256 DWORD rc;
1257
1258 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1259 while (TRUE)
1260 {
1261 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1262 rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1263 if (rc == ERROR_NO_MORE_ITEMS)
1264 break;
1265 if (rc != ERROR_SUCCESS)
1266 return rc;
1267 i++;
1268
1269 /* Open device id sub key */
1270 rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
1271 if (rc != ERROR_SUCCESS)
1272 return rc;
1273 wcscpy(InstancePath, Enumerator);
1274 wcscat(InstancePath, L"\\");
1275 wcscat(InstancePath, KeyBuffer);
1276 wcscat(InstancePath, L"\\");
1277 pEndOfInstancePath = &InstancePath[wcslen(InstancePath)];
1278
1279 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1280 j = 0;
1281 while (TRUE)
1282 {
1283 GUID KeyGuid;
1284
1285 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1286 rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1287 if (rc == ERROR_NO_MORE_ITEMS)
1288 break;
1289 if (rc != ERROR_SUCCESS)
1290 {
1291 RegCloseKey(hDeviceIdKey);
1292 return rc;
1293 }
1294 j++;
1295
1296 /* Open instance id sub key */
1297 rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
1298 if (rc != ERROR_SUCCESS)
1299 {
1300 RegCloseKey(hDeviceIdKey);
1301 return rc;
1302 }
1303 *pEndOfInstancePath = '\0';
1304 wcscat(InstancePath, KeyBuffer);
1305
1306 /* Read ClassGUID value */
1307 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1308 rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength);
1309 RegCloseKey(hInstanceIdKey);
1310 if (rc == ERROR_FILE_NOT_FOUND)
1311 {
1312 if (pClassGuid)
1313 /* Skip this bad entry as we can't verify it */
1314 continue;
1315 }
1316 else if (rc != ERROR_SUCCESS)
1317 {
1318 RegCloseKey(hDeviceIdKey);
1319 return rc;
1320 }
1321 else if (dwRegType != REG_SZ)
1322 {
1323 RegCloseKey(hDeviceIdKey);
1324 return ERROR_GEN_FAILURE;
1325 }
1326
1327 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1328 if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
1329 {
1330 RegCloseKey(hDeviceIdKey);
1331 return GetLastError();
1332 }
1333 if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
1334 {
1335 /* Skip this entry as it is not the right device class */
1336 continue;
1337 }
1338
1339 /* Add the entry to the list */
1340 if (!CreateDeviceInfoElement(InstancePath, &KeyGuid, &deviceInfo))
1341 {
1342 RegCloseKey(hDeviceIdKey);
1343 return GetLastError();
1344 }
1345 TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
1346 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1347 }
1348 RegCloseKey(hDeviceIdKey);
1349 }
1350
1351 return ERROR_SUCCESS;
1352 }
1353
1354 static LONG SETUP_CreateDevList(
1355 struct DeviceInfoSet *list,
1356 PCWSTR MachineName OPTIONAL,
1357 LPGUID class OPTIONAL,
1358 PCWSTR Enumerator OPTIONAL)
1359 {
1360 HKEY HKLM, hEnumKey, hEnumeratorKey;
1361 WCHAR KeyBuffer[MAX_PATH];
1362 DWORD i;
1363 DWORD dwLength;
1364 DWORD rc;
1365
1366 if (IsEqualIID(class, &GUID_NULL))
1367 class = NULL;
1368
1369 /* Open Enum key */
1370 if (MachineName != NULL)
1371 {
1372 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
1373 if (rc != ERROR_SUCCESS)
1374 return rc;
1375 }
1376 else
1377 HKLM = HKEY_LOCAL_MACHINE;
1378
1379 rc = RegOpenKeyExW(HKLM,
1380 EnumKeyName,
1381 0,
1382 KEY_ENUMERATE_SUB_KEYS,
1383 &hEnumKey);
1384 if (MachineName != NULL) RegCloseKey(HKLM);
1385 if (rc != ERROR_SUCCESS)
1386 return rc;
1387
1388 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1389 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1390 * for each one.
1391 */
1392 if (Enumerator)
1393 {
1394 rc = RegOpenKeyExW(
1395 hEnumKey,
1396 Enumerator,
1397 0,
1398 KEY_ENUMERATE_SUB_KEYS,
1399 &hEnumeratorKey);
1400 RegCloseKey(hEnumKey);
1401 if (rc != ERROR_SUCCESS)
1402 return rc;
1403 rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey);
1404 RegCloseKey(hEnumeratorKey);
1405 return rc;
1406 }
1407 else
1408 {
1409 /* Enumerate enumerators */
1410 i = 0;
1411 while (TRUE)
1412 {
1413 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1414 rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1415 if (rc == ERROR_NO_MORE_ITEMS)
1416 break;
1417 if (rc != ERROR_SUCCESS)
1418 {
1419 RegCloseKey(hEnumKey);
1420 return rc;
1421 }
1422 i++;
1423
1424 /* Open sub key */
1425 rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
1426 if (rc != ERROR_SUCCESS)
1427 {
1428 RegCloseKey(hEnumKey);
1429 return rc;
1430 }
1431
1432 /* Call SETUP_CreateDevListFromEnumerator */
1433 rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey);
1434 RegCloseKey(hEnumeratorKey);
1435 if (rc != ERROR_SUCCESS)
1436 {
1437 RegCloseKey(hEnumKey);
1438 return rc;
1439 }
1440 }
1441 RegCloseKey(hEnumKey);
1442 return ERROR_SUCCESS;
1443 }
1444 }
1445
1446 #ifndef __REACTOS__
1447 static LONG SETUP_CreateSerialDeviceList(
1448 struct DeviceInfoSet *list,
1449 PCWSTR MachineName,
1450 LPGUID InterfaceGuid,
1451 PCWSTR DeviceInstanceW)
1452 {
1453 static const size_t initialSize = 100;
1454 size_t size;
1455 WCHAR buf[initialSize];
1456 LPWSTR devices;
1457 static const WCHAR devicePrefixW[] = { 'C','O','M',0 };
1458 LPWSTR ptr;
1459 struct DeviceInfoElement *deviceInfo;
1460
1461 if (MachineName)
1462 WARN("'MachineName' is ignored on Wine!\n");
1463 if (DeviceInstanceW)
1464 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1465
1466 devices = buf;
1467 size = initialSize;
1468 while (TRUE)
1469 {
1470 if (QueryDosDeviceW(NULL, devices, size) != 0)
1471 break;
1472 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1473 {
1474 size *= 2;
1475 if (devices != buf)
1476 HeapFree(GetProcessHeap(), 0, devices);
1477 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1478 if (!devices)
1479 return ERROR_NOT_ENOUGH_MEMORY;
1480 *devices = '\0';
1481 }
1482 else
1483 {
1484 if (devices != buf)
1485 HeapFree(GetProcessHeap(), 0, devices);
1486 return GetLastError();
1487 }
1488 }
1489
1490 /* 'devices' is a MULTI_SZ string */
1491 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
1492 {
1493 if (strncmpW(devicePrefixW, ptr, sizeof(devicePrefixW) / sizeof(devicePrefixW[0]) - 1) == 0)
1494 {
1495 /* We have found a device */
1496 struct DeviceInterface *interfaceInfo;
1497 TRACE("Adding %s to list\n", debugstr_w(ptr));
1498 /* Step 1. Create a device info element */
1499 if (!CreateDeviceInfoElement(ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
1500 {
1501 if (devices != buf)
1502 HeapFree(GetProcessHeap(), 0, devices);
1503 return GetLastError();
1504 }
1505 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1506
1507 /* Step 2. Create an interface list for this element */
1508 if (!CreateDeviceInterface(deviceInfo, ptr, InterfaceGuid, &interfaceInfo))
1509 {
1510 if (devices != buf)
1511 HeapFree(GetProcessHeap(), 0, devices);
1512 return GetLastError();
1513 }
1514 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1515 }
1516 }
1517 if (devices != buf)
1518 HeapFree(GetProcessHeap(), 0, devices);
1519 return ERROR_SUCCESS;
1520 }
1521
1522 #else /* __REACTOS__ */
1523
1524 static LONG SETUP_CreateInterfaceList(
1525 struct DeviceInfoSet *list,
1526 PCWSTR MachineName,
1527 LPGUID InterfaceGuid,
1528 PCWSTR DeviceInstanceW /* OPTIONAL */)
1529 {
1530 HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1531 HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1532 HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1533 HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1534 HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1535 LONG rc;
1536 WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
1537 PWSTR InstancePath;
1538 DWORD i, j;
1539 DWORD dwLength, dwInstancePathLength;
1540 DWORD dwRegType;
1541 GUID ClassGuid;
1542 struct DeviceInfoElement *deviceInfo;
1543
1544 /* Open registry key related to this interface */
1545 hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
1546 if (hInterfaceKey == INVALID_HANDLE_VALUE)
1547 return GetLastError();
1548
1549 /* Enumerate sub keys of hInterfaceKey */
1550 i = 0;
1551 while (TRUE)
1552 {
1553 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1554 rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1555 if (rc == ERROR_NO_MORE_ITEMS)
1556 break;
1557 if (rc != ERROR_SUCCESS)
1558 {
1559 RegCloseKey(hInterfaceKey);
1560 return rc;
1561 }
1562 i++;
1563
1564 /* Open sub key */
1565 rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
1566 if (rc != ERROR_SUCCESS)
1567 {
1568 RegCloseKey(hInterfaceKey);
1569 return rc;
1570 }
1571
1572 /* Read DeviceInstance */
1573 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
1574 if (rc != ERROR_SUCCESS )
1575 {
1576 RegCloseKey(hDeviceInstanceKey);
1577 RegCloseKey(hInterfaceKey);
1578 return rc;
1579 }
1580 if (dwRegType != REG_SZ)
1581 {
1582 RegCloseKey(hDeviceInstanceKey);
1583 RegCloseKey(hInterfaceKey);
1584 return ERROR_GEN_FAILURE;
1585 }
1586 InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
1587 if (!InstancePath)
1588 {
1589 RegCloseKey(hDeviceInstanceKey);
1590 RegCloseKey(hInterfaceKey);
1591 return ERROR_NOT_ENOUGH_MEMORY;
1592 }
1593 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
1594 if (rc != ERROR_SUCCESS)
1595 {
1596 HeapFree(GetProcessHeap(), 0, InstancePath);
1597 RegCloseKey(hDeviceInstanceKey);
1598 RegCloseKey(hInterfaceKey);
1599 return rc;
1600 }
1601 InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
1602 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
1603
1604 if (DeviceInstanceW)
1605 {
1606 /* Check if device enumerator is not the right one */
1607 if (wcscmp(DeviceInstanceW, InstancePath) != 0)
1608 {
1609 HeapFree(GetProcessHeap(), 0, InstancePath);
1610 RegCloseKey(hDeviceInstanceKey);
1611 continue;
1612 }
1613 }
1614
1615 /* Find class GUID associated to the device instance */
1616 rc = RegOpenKeyExW(
1617 HKEY_LOCAL_MACHINE,
1618 EnumKeyName,
1619 0, /* Options */
1620 KEY_ENUMERATE_SUB_KEYS,
1621 &hEnumKey);
1622 if (rc != ERROR_SUCCESS)
1623 {
1624 HeapFree(GetProcessHeap(), 0, InstancePath);
1625 RegCloseKey(hDeviceInstanceKey);
1626 RegCloseKey(hInterfaceKey);
1627 return rc;
1628 }
1629 rc = RegOpenKeyExW(
1630 hEnumKey,
1631 InstancePath,
1632 0, /* Options */
1633 KEY_QUERY_VALUE,
1634 &hKey);
1635 RegCloseKey(hEnumKey);
1636 if (rc != ERROR_SUCCESS)
1637 {
1638 HeapFree(GetProcessHeap(), 0, InstancePath);
1639 RegCloseKey(hDeviceInstanceKey);
1640 RegCloseKey(hInterfaceKey);
1641 return rc;
1642 }
1643 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1644 rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1645 RegCloseKey(hKey);
1646 if (rc != ERROR_SUCCESS)
1647 {
1648 HeapFree(GetProcessHeap(), 0, InstancePath);
1649 RegCloseKey(hDeviceInstanceKey);
1650 RegCloseKey(hInterfaceKey);
1651 return rc;
1652 }
1653 KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
1654 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1655 if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
1656 {
1657 HeapFree(GetProcessHeap(), 0, InstancePath);
1658 RegCloseKey(hDeviceInstanceKey);
1659 RegCloseKey(hInterfaceKey);
1660 return ERROR_GEN_FAILURE;
1661 }
1662 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
1663
1664 /* If current device doesn't match the list GUID (if any), skip this entry */
1665 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
1666 {
1667 HeapFree(GetProcessHeap(), 0, InstancePath);
1668 RegCloseKey(hDeviceInstanceKey);
1669 continue;
1670 }
1671
1672 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1673 j = 0;
1674 while (TRUE)
1675 {
1676 LPWSTR pSymbolicLink;
1677 struct DeviceInterface *interfaceInfo;
1678
1679 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1680 rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1681 if (rc == ERROR_NO_MORE_ITEMS)
1682 break;
1683 if (rc != ERROR_SUCCESS)
1684 {
1685 HeapFree(GetProcessHeap(), 0, InstancePath);
1686 RegCloseKey(hDeviceInstanceKey);
1687 RegCloseKey(hInterfaceKey);
1688 return rc;
1689 }
1690 j++;
1691 if (KeyBuffer[0] != '#')
1692 /* This entry doesn't represent an interesting entry */
1693 continue;
1694
1695 /* Open sub key */
1696 rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
1697 if (rc != ERROR_SUCCESS)
1698 {
1699 RegCloseKey(hDeviceInstanceKey);
1700 RegCloseKey(hInterfaceKey);
1701 return rc;
1702 }
1703
1704 /* Read SymbolicLink value */
1705 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
1706 if (rc != ERROR_SUCCESS )
1707 {
1708 RegCloseKey(hReferenceKey);
1709 RegCloseKey(hDeviceInstanceKey);
1710 RegCloseKey(hInterfaceKey);
1711 return rc;
1712 }
1713 if (dwRegType != REG_SZ)
1714 {
1715 RegCloseKey(hReferenceKey);
1716 RegCloseKey(hDeviceInstanceKey);
1717 RegCloseKey(hInterfaceKey);
1718 return ERROR_GEN_FAILURE;
1719 }
1720
1721 /* We have found a device */
1722 /* Step 1. Create a device info element */
1723 if (!CreateDeviceInfoElement(InstancePath, &ClassGuid, &deviceInfo))
1724 {
1725 RegCloseKey(hReferenceKey);
1726 RegCloseKey(hDeviceInstanceKey);
1727 RegCloseKey(hInterfaceKey);
1728 return GetLastError();
1729 }
1730 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
1731 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1732
1733 /* Step 2. Create an interface list for this element */
1734 pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
1735 if (!pSymbolicLink)
1736 {
1737 RegCloseKey(hReferenceKey);
1738 RegCloseKey(hDeviceInstanceKey);
1739 RegCloseKey(hInterfaceKey);
1740 return ERROR_NOT_ENOUGH_MEMORY;
1741 }
1742 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
1743 pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
1744 RegCloseKey(hReferenceKey);
1745 if (rc != ERROR_SUCCESS)
1746 {
1747 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1748 RegCloseKey(hDeviceInstanceKey);
1749 RegCloseKey(hInterfaceKey);
1750 return rc;
1751 }
1752 if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
1753 {
1754 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1755 RegCloseKey(hDeviceInstanceKey);
1756 RegCloseKey(hInterfaceKey);
1757 return GetLastError();
1758 }
1759 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
1760 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1761 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1762 }
1763 RegCloseKey(hDeviceInstanceKey);
1764 }
1765 RegCloseKey(hInterfaceKey);
1766 return ERROR_SUCCESS;
1767 }
1768 #endif /* __REACTOS__ */
1769
1770 /***********************************************************************
1771 * SetupDiGetClassDevsExW (SETUPAPI.@)
1772 */
1773 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1774 CONST GUID *class,
1775 LPCWSTR enumstr,
1776 HWND parent,
1777 DWORD flags,
1778 HDEVINFO deviceset,
1779 LPCWSTR machine,
1780 PVOID reserved)
1781 {
1782 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1783 struct DeviceInfoSet *list;
1784 LPGUID pClassGuid;
1785 LONG rc;
1786
1787 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr),
1788 parent, flags, deviceset, debugstr_w(machine), reserved);
1789
1790 /* Create the deviceset if not set */
1791 if (deviceset)
1792 {
1793 list = (struct DeviceInfoSet *)deviceset;
1794 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
1795 {
1796 SetLastError(ERROR_INVALID_HANDLE);
1797 return INVALID_HANDLE_VALUE;
1798 }
1799 hDeviceInfo = deviceset;
1800 }
1801 else
1802 {
1803 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
1804 flags & DIGCF_DEVICEINTERFACE ? NULL : class,
1805 NULL, machine, NULL);
1806 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1807 return INVALID_HANDLE_VALUE;
1808 list = (struct DeviceInfoSet *)hDeviceInfo;
1809 }
1810
1811 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1812 pClassGuid = NULL;
1813 else
1814 pClassGuid = &list->ClassGuid;
1815
1816 if (flags & DIGCF_PRESENT)
1817 FIXME(": flag DIGCF_PRESENT ignored\n");
1818 if (flags & DIGCF_PROFILE)
1819 FIXME(": flag DIGCF_PROFILE ignored\n");
1820
1821 if (flags & DIGCF_ALLCLASSES)
1822 {
1823 rc = SETUP_CreateDevList(list, machine, pClassGuid, enumstr);
1824 if (rc != ERROR_SUCCESS)
1825 {
1826 SetLastError(rc);
1827 if (!deviceset)
1828 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1829 return INVALID_HANDLE_VALUE;
1830 }
1831 return hDeviceInfo;
1832 }
1833 else if (flags & DIGCF_DEVICEINTERFACE)
1834 {
1835 if (class == NULL)
1836 {
1837 SetLastError(ERROR_INVALID_PARAMETER);
1838 if (!deviceset)
1839 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1840 return INVALID_HANDLE_VALUE;
1841 }
1842
1843 #ifndef __REACTOS__
1844 /* Special case: find serial ports by calling QueryDosDevice */
1845 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
1846 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1847 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
1848 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1849 else
1850 {
1851 ERR("Wine can only enumerate serial devices at the moment!\n");
1852 rc = ERROR_INVALID_PARAMETER;
1853 }
1854 #else /* __REACTOS__ */
1855 rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
1856 #endif /* __REACTOS__ */
1857 if (rc != ERROR_SUCCESS)
1858 {
1859 SetLastError(rc);
1860 if (!deviceset)
1861 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1862 return INVALID_HANDLE_VALUE;
1863 }
1864 return hDeviceInfo;
1865 }
1866 else
1867 {
1868 rc = SETUP_CreateDevList(list, machine, (LPGUID)class, enumstr);
1869 if (rc != ERROR_SUCCESS)
1870 {
1871 SetLastError(rc);
1872 if (!deviceset)
1873 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1874 return INVALID_HANDLE_VALUE;
1875 }
1876 return hDeviceInfo;
1877 }
1878 }
1879
1880 /***********************************************************************
1881 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1882 */
1883 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1884 HDEVINFO DeviceInfoSet,
1885 PSP_DEVINFO_DATA DeviceInfoData,
1886 CONST GUID * InterfaceClassGuid,
1887 DWORD MemberIndex,
1888 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1889 {
1890 BOOL ret = FALSE;
1891
1892 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
1893 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1894
1895 if (!DeviceInterfaceData)
1896 SetLastError(ERROR_INVALID_PARAMETER);
1897 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
1898 SetLastError(ERROR_INVALID_USER_BUFFER);
1899 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
1900 {
1901 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
1902
1903 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
1904 {
1905 PLIST_ENTRY ItemList = list->ListHead.Flink;
1906 BOOL Found = FALSE;
1907 while (ItemList != &list->ListHead && !Found)
1908 {
1909 PLIST_ENTRY InterfaceListEntry;
1910 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
1911 if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
1912 {
1913 /* We are not searching for this element */
1914 ItemList = ItemList->Flink;
1915 continue;
1916 }
1917 InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
1918 while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
1919 {
1920 struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
1921 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
1922 {
1923 InterfaceListEntry = InterfaceListEntry->Flink;
1924 continue;
1925 }
1926 if (MemberIndex-- == 0)
1927 {
1928 /* return this item */
1929 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
1930 &DevItf->InterfaceClassGuid,
1931 sizeof(GUID));
1932 DeviceInterfaceData->Flags = 0; /* FIXME */
1933 /* Note: this appears to be dangerous, passing a private
1934 * pointer a heap-allocated datum to the caller. However, the
1935 * expected lifetime of the device data is the same as the
1936 * HDEVINFO; once that is closed, the data are no longer valid.
1937 */
1938 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
1939 Found = TRUE;
1940 }
1941 InterfaceListEntry = InterfaceListEntry->Flink;
1942 }
1943 ItemList = ItemList->Flink;
1944 }
1945 if (!Found)
1946 SetLastError(ERROR_NO_MORE_ITEMS);
1947 else
1948 ret = TRUE;
1949 }
1950 else
1951 SetLastError(ERROR_INVALID_HANDLE);
1952 }
1953 else
1954 SetLastError(ERROR_INVALID_HANDLE);
1955 return ret;
1956 }
1957
1958 /***********************************************************************
1959 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1960 */
1961 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1962 {
1963 BOOL ret = FALSE;
1964
1965 TRACE("%p\n", devinfo);
1966 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1967 {
1968 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1969
1970 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
1971 {
1972 PLIST_ENTRY ListEntry, InterfaceEntry;
1973 struct DeviceInfoElement *deviceInfo;
1974 while (!IsListEmpty(&list->ListHead))
1975 {
1976 ListEntry = RemoveHeadList(&list->ListHead);
1977 deviceInfo = (struct DeviceInfoElement *)ListEntry;
1978 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
1979 {
1980 InterfaceEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
1981 HeapFree(GetProcessHeap(), 0, InterfaceEntry);
1982 }
1983 HeapFree(GetProcessHeap(), 0, ListEntry);
1984 }
1985 if (list->HKLM != HKEY_LOCAL_MACHINE)
1986 RegCloseKey(list->HKLM);
1987 HeapFree(GetProcessHeap(), 0, list);
1988 ret = TRUE;
1989 }
1990 else
1991 SetLastError(ERROR_INVALID_HANDLE);
1992 }
1993 else
1994 SetLastError(ERROR_INVALID_HANDLE);
1995
1996 TRACE("Returning %d\n", ret);
1997 return ret;
1998 }
1999
2000 /***********************************************************************
2001 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2002 */
2003 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2004 HDEVINFO DeviceInfoSet,
2005 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2006 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2007 DWORD DeviceInterfaceDetailDataSize,
2008 PDWORD RequiredSize,
2009 PSP_DEVINFO_DATA DeviceInfoData)
2010 {
2011 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2012 DWORD sizeW = 0, sizeA;
2013 BOOL ret = FALSE;
2014
2015 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
2016 DeviceInterfaceData, DeviceInterfaceDetailData,
2017 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2018
2019 if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2020 SetLastError(ERROR_INVALID_USER_BUFFER);
2021 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2022 SetLastError(ERROR_INVALID_PARAMETER);
2023 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
2024 SetLastError(ERROR_INVALID_PARAMETER);
2025 else
2026 {
2027 if (DeviceInterfaceDetailData != NULL)
2028 {
2029 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2030 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2031 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
2032 if (!DeviceInterfaceDetailDataW)
2033 {
2034 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2035 }
2036 }
2037 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2038 {
2039 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2040 ret = SetupDiGetDeviceInterfaceDetailW(
2041 DeviceInfoSet,
2042 DeviceInterfaceData,
2043 DeviceInterfaceDetailDataW,
2044 sizeW,
2045 &sizeW,
2046 DeviceInfoData);
2047 sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2048 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2049 if (RequiredSize)
2050 *RequiredSize = sizeA;
2051 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
2052 {
2053 if (!WideCharToMultiByte(
2054 CP_ACP, 0,
2055 DeviceInterfaceDetailDataW->DevicePath, -1,
2056 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2057 NULL, NULL))
2058 {
2059 ret = FALSE;
2060 }
2061 }
2062 }
2063 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
2064 }
2065
2066 TRACE("Returning %d\n", ret);
2067 return ret;
2068 }
2069
2070 /***********************************************************************
2071 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2072 */
2073 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2074 HDEVINFO DeviceInfoSet,
2075 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2076 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2077 DWORD DeviceInterfaceDetailDataSize,
2078 PDWORD RequiredSize,
2079 PSP_DEVINFO_DATA DeviceInfoData)
2080 {
2081 BOOL ret = FALSE;
2082
2083 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
2084 DeviceInterfaceData, DeviceInterfaceDetailData,
2085 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2086
2087 if (!DeviceInfoSet || !DeviceInterfaceData)
2088 SetLastError(ERROR_INVALID_PARAMETER);
2089 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2090 SetLastError(ERROR_INVALID_HANDLE);
2091 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2092 SetLastError(ERROR_INVALID_HANDLE);
2093 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2094 SetLastError(ERROR_INVALID_USER_BUFFER);
2095 else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
2096 SetLastError(ERROR_INVALID_USER_BUFFER);
2097 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2098 SetLastError(ERROR_INVALID_USER_BUFFER);
2099 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2100 SetLastError(ERROR_INVALID_PARAMETER);
2101 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
2102 SetLastError(ERROR_INVALID_PARAMETER);
2103 else
2104 {
2105 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2106 LPCWSTR devName = deviceInterface->SymbolicLink;
2107 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
2108 (lstrlenW(devName) + 1) * sizeof(WCHAR);
2109
2110 if (sizeRequired > DeviceInterfaceDetailDataSize)
2111 {
2112 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2113 if (RequiredSize)
2114 *RequiredSize = sizeRequired;
2115 }
2116 else
2117 {
2118 wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
2119 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
2120 if (DeviceInfoData)
2121 {
2122 memcpy(&DeviceInfoData->ClassGuid,
2123 &deviceInterface->DeviceInfo->ClassGuid,
2124 sizeof(GUID));
2125 DeviceInfoData->DevInst = 0; /* FIXME */
2126 /* Note: this appears to be dangerous, passing a private
2127 * pointer a heap-allocated datum to the caller. However, the
2128 * expected lifetime of the device data is the same as the
2129 * HDEVINFO; once that is closed, the data are no longer valid.
2130 */
2131 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
2132 }
2133 ret = TRUE;
2134 }
2135 }
2136
2137 TRACE("Returning %d\n", ret);
2138 return ret;
2139 }
2140
2141 /***********************************************************************
2142 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2143 */
2144 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2145 HDEVINFO devinfo,
2146 PSP_DEVINFO_DATA DeviceInfoData,
2147 DWORD Property,
2148 PDWORD PropertyRegDataType,
2149 PBYTE PropertyBuffer,
2150 DWORD PropertyBufferSize,
2151 PDWORD RequiredSize)
2152 {
2153 BOOL bResult;
2154 BOOL bIsStringProperty;
2155 DWORD RegType;
2156 DWORD RequiredSizeA, RequiredSizeW;
2157 DWORD PropertyBufferSizeW;
2158 PBYTE PropertyBufferW;
2159
2160 TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
2161 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2162 RequiredSize);
2163
2164 PropertyBufferSizeW = PropertyBufferSize * 2;
2165 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
2166
2167 bResult = SetupDiGetDeviceRegistryPropertyW(
2168 devinfo,
2169 DeviceInfoData,
2170 Property,
2171 &RegType,
2172 PropertyBufferW,
2173 PropertyBufferSizeW,
2174 &RequiredSizeW);
2175
2176 if (bResult || GetLastError() == ERROR_MORE_DATA)
2177 {
2178 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
2179
2180 if (bIsStringProperty)
2181 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
2182 else
2183 RequiredSizeA = RequiredSizeW;
2184 if (RequiredSize)
2185 *RequiredSize = RequiredSizeA;
2186 if (PropertyRegDataType)
2187 *PropertyRegDataType = RegType;
2188 }
2189
2190 if (!bResult)
2191 {
2192 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2193 return bResult;
2194 }
2195
2196 if (RequiredSizeA <= PropertyBufferSize)
2197 {
2198 if (bIsStringProperty && PropertyBufferSize > 0)
2199 {
2200 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
2201 {
2202 /* Last error is already set by WideCharToMultiByte */
2203 bResult = FALSE;
2204 }
2205 }
2206 else
2207 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
2208 }
2209 else
2210 {
2211 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2212 bResult = FALSE;
2213 }
2214
2215 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2216 return bResult;
2217 }
2218
2219 /***********************************************************************
2220 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2221 */
2222 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2223 HDEVINFO DeviceInfoSet,
2224 PSP_DEVINFO_DATA DeviceInfoData,
2225 DWORD Property,
2226 PDWORD PropertyRegDataType,
2227 PBYTE PropertyBuffer,
2228 DWORD PropertyBufferSize,
2229 PDWORD RequiredSize)
2230 {
2231 HKEY hEnumKey, hKey;
2232 DWORD rc;
2233 BOOL ret = FALSE;
2234
2235 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
2236 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2237 RequiredSize);
2238
2239 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2240 SetLastError(ERROR_INVALID_HANDLE);
2241 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2242 SetLastError(ERROR_INVALID_HANDLE);
2243 else if (!DeviceInfoData)
2244 SetLastError(ERROR_INVALID_PARAMETER);
2245 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2246 SetLastError(ERROR_INVALID_USER_BUFFER);
2247 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
2248 SetLastError(ERROR_INVALID_PARAMETER);
2249 else
2250 {
2251 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2252 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2253
2254 switch (Property)
2255 {
2256 case SPDRP_CAPABILITIES:
2257 case SPDRP_CLASS:
2258 case SPDRP_CLASSGUID:
2259 case SPDRP_COMPATIBLEIDS:
2260 case SPDRP_CONFIGFLAGS:
2261 case SPDRP_DEVICEDESC:
2262 case SPDRP_DRIVER:
2263 case SPDRP_FRIENDLYNAME:
2264 case SPDRP_HARDWAREID:
2265 case SPDRP_LOCATION_INFORMATION:
2266 case SPDRP_LOWERFILTERS:
2267 case SPDRP_MFG:
2268 case SPDRP_SECURITY:
2269 case SPDRP_SERVICE:
2270 case SPDRP_UI_NUMBER:
2271 case SPDRP_UPPERFILTERS:
2272 {
2273 LPCWSTR RegistryPropertyName;
2274 DWORD BufferSize;
2275
2276 switch (Property)
2277 {
2278 case SPDRP_CAPABILITIES:
2279 RegistryPropertyName = L"Capabilities"; break;
2280 case SPDRP_CLASS:
2281 RegistryPropertyName = L"Class"; break;
2282 case SPDRP_CLASSGUID:
2283 RegistryPropertyName = L"ClassGUID"; break;
2284 case SPDRP_COMPATIBLEIDS:
2285 RegistryPropertyName = L"CompatibleIDs"; break;
2286 case SPDRP_CONFIGFLAGS:
2287 RegistryPropertyName = L"ConfigFlags"; break;
2288 case SPDRP_DEVICEDESC:
2289 RegistryPropertyName = L"DeviceDesc"; break;
2290 case SPDRP_DRIVER:
2291 RegistryPropertyName = L"Driver"; break;
2292 case SPDRP_FRIENDLYNAME:
2293 RegistryPropertyName = L"FriendlyName"; break;
2294 case SPDRP_HARDWAREID:
2295 RegistryPropertyName = L"HardwareID"; break;
2296 case SPDRP_LOCATION_INFORMATION:
2297 RegistryPropertyName = L"LocationInformation"; break;
2298 case SPDRP_LOWERFILTERS:
2299 RegistryPropertyName = L"LowerFilters"; break;
2300 case SPDRP_MFG:
2301 RegistryPropertyName = L"Mfg"; break;
2302 case SPDRP_SECURITY:
2303 RegistryPropertyName = L"Security"; break;
2304 case SPDRP_SERVICE:
2305 RegistryPropertyName = L"Service"; break;
2306 case SPDRP_UI_NUMBER:
2307 RegistryPropertyName = L"UINumber"; break;
2308 case SPDRP_UPPERFILTERS:
2309 RegistryPropertyName = L"UpperFilters"; break;
2310 default:
2311 /* Should not happen */
2312 RegistryPropertyName = NULL; break;
2313 }
2314
2315 /* Open registry key name */
2316 rc = RegOpenKeyExW(
2317 list->HKLM,
2318 EnumKeyName,
2319 0, /* Options */
2320 KEY_ENUMERATE_SUB_KEYS,
2321 &hEnumKey);
2322 if (rc != ERROR_SUCCESS)
2323 {
2324 SetLastError(rc);
2325 break;
2326 }
2327 rc = RegOpenKeyExW(
2328 hEnumKey,
2329 DevInfo->Data,
2330 0, /* Options */
2331 KEY_QUERY_VALUE,
2332 &hKey);
2333 RegCloseKey(hEnumKey);
2334 if (rc != ERROR_SUCCESS)
2335 {
2336 SetLastError(rc);
2337 break;
2338 }
2339 /* Read registry entry */
2340 BufferSize = PropertyBufferSize;
2341 rc = RegQueryValueExW(
2342 hKey,
2343 RegistryPropertyName,
2344 NULL, /* Reserved */
2345 PropertyRegDataType,
2346 PropertyBuffer,
2347 &BufferSize);
2348 if (RequiredSize)
2349 *RequiredSize = BufferSize;
2350 if (rc == ERROR_SUCCESS)
2351 ret = TRUE;
2352 else
2353 SetLastError(rc);
2354 RegCloseKey(hKey);
2355 break;
2356 }
2357
2358 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
2359 {
2360 DWORD required = (wcslen(DevInfo->Data) + 1) * sizeof(WCHAR);
2361
2362 if (PropertyRegDataType)
2363 *PropertyRegDataType = REG_SZ;
2364 if (RequiredSize)
2365 *RequiredSize = required;
2366 if (PropertyBufferSize >= required)
2367 {
2368 wcscpy((LPWSTR)PropertyBuffer, DevInfo->Data);
2369 ret = TRUE;
2370 }
2371 else
2372 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2373 break;
2374 }
2375
2376 /*case SPDRP_BUSTYPEGUID:
2377 case SPDRP_LEGACYBUSTYPE:
2378 case SPDRP_BUSNUMBER:
2379 case SPDRP_ENUMERATOR_NAME:
2380 case SPDRP_SECURITY_SDS:
2381 case SPDRP_DEVTYPE:
2382 case SPDRP_EXCLUSIVE:
2383 case SPDRP_CHARACTERISTICS:
2384 case SPDRP_ADDRESS:
2385 case SPDRP_UI_NUMBER_DESC_FORMAT:
2386 case SPDRP_DEVICE_POWER_DATA:*/
2387 #if (WINVER >= 0x501)
2388 /*case SPDRP_REMOVAL_POLICY:
2389 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2390 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2391 case SPDRP_INSTALL_STATE:*/
2392 #endif
2393
2394 default:
2395 {
2396 FIXME("Property 0x%lx not implemented\n", Property);
2397 SetLastError(ERROR_NOT_SUPPORTED);
2398 }
2399 }
2400 }
2401
2402 TRACE("Returning %d\n", ret);
2403 return ret;
2404 }
2405
2406
2407 /***********************************************************************
2408 * SetupDiInstallClassA (SETUPAPI.@)
2409 */
2410 BOOL WINAPI SetupDiInstallClassA(
2411 HWND hwndParent,
2412 PCSTR InfFileName,
2413 DWORD Flags,
2414 HSPFILEQ FileQueue)
2415 {
2416 UNICODE_STRING FileNameW;
2417 BOOL Result;
2418
2419 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2420 {
2421 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2422 return FALSE;
2423 }
2424
2425 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2426
2427 RtlFreeUnicodeString(&FileNameW);
2428
2429 return Result;
2430 }
2431
2432 static HKEY CreateClassKey(HINF hInf)
2433 {
2434 WCHAR FullBuffer[MAX_PATH];
2435 WCHAR Buffer[MAX_PATH];
2436 DWORD RequiredSize;
2437 HKEY hClassKey;
2438
2439 Buffer[0] = '\\';
2440 if (!SetupGetLineTextW(NULL,
2441 hInf,
2442 Version,
2443 ClassGUID,
2444 &Buffer[1],
2445 MAX_PATH - 1,
2446 &RequiredSize))
2447 {
2448 return INVALID_HANDLE_VALUE;
2449 }
2450
2451 lstrcpyW(FullBuffer, ControlClass);
2452 lstrcatW(FullBuffer, Buffer);
2453
2454
2455 if (!SetupGetLineTextW(NULL,
2456 hInf,
2457 Version,
2458 Class,
2459 Buffer,
2460 MAX_PATH,
2461 &RequiredSize))
2462 {
2463 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2464 return INVALID_HANDLE_VALUE;
2465 }
2466
2467 if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2468 FullBuffer,
2469 0,
2470 NULL,
2471 REG_OPTION_NON_VOLATILE,
2472 KEY_ALL_ACCESS,
2473 NULL,
2474 &hClassKey,
2475 NULL))
2476 {
2477 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2478 return INVALID_HANDLE_VALUE;
2479 }
2480
2481 if (ERROR_SUCCESS != RegSetValueExW(hClassKey,
2482 Class,
2483 0,
2484 REG_SZ,
2485 (LPBYTE)Buffer,
2486 RequiredSize * sizeof(WCHAR)))
2487 {
2488 RegCloseKey(hClassKey);
2489 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2490 return INVALID_HANDLE_VALUE;
2491 }
2492
2493 return hClassKey;
2494 }
2495
2496 /***********************************************************************
2497 * SetupDiInstallClassW (SETUPAPI.@)
2498 */
2499 BOOL WINAPI SetupDiInstallClassW(
2500 HWND hwndParent,
2501 PCWSTR InfFileName,
2502 DWORD Flags,
2503 HSPFILEQ FileQueue)
2504 {
2505 WCHAR SectionName[MAX_PATH];
2506 DWORD SectionNameLength = 0;
2507 HINF hInf;
2508 BOOL bFileQueueCreated = FALSE;
2509 HKEY hClassKey;
2510
2511 FIXME("not fully implemented\n");
2512
2513 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2514 {
2515 SetLastError(ERROR_INVALID_PARAMETER);
2516 return FALSE;
2517 }
2518
2519 /* Open the .inf file */
2520 hInf = SetupOpenInfFileW(InfFileName,
2521 NULL,
2522 INF_STYLE_WIN4,
2523 NULL);
2524 if (hInf == INVALID_HANDLE_VALUE)
2525 {
2526
2527 return FALSE;
2528 }
2529
2530 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2531 hClassKey = CreateClassKey(hInf);
2532 if (hClassKey == INVALID_HANDLE_VALUE)
2533 {
2534 SetupCloseInfFile(hInf);
2535 return FALSE;
2536 }
2537
2538
2539
2540 /* Try to append a layout file */
2541 #if 0
2542 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2543 #endif
2544
2545 /* Retrieve the actual section name */
2546 SetupDiGetActualSectionToInstallW(hInf,
2547 ClassInstall32,
2548 SectionName,
2549 MAX_PATH,
2550 &SectionNameLength,
2551 NULL);
2552
2553 #if 0
2554 if (!(Flags & DI_NOVCP))
2555 {
2556 FileQueue = SetupOpenFileQueue();
2557 if (FileQueue == INVALID_HANDLE_VALUE)
2558 {
2559 SetupCloseInfFile(hInf);
2560 RegCloseKey(hClassKey);
2561 return FALSE;
2562 }
2563
2564 bFileQueueCreated = TRUE;
2565
2566 }
2567 #endif
2568
2569 SetupInstallFromInfSectionW(NULL,
2570 hInf,
2571 SectionName,
2572 SPINST_REGISTRY,
2573 hClassKey,
2574 NULL,
2575 0,
2576 NULL,
2577 NULL,
2578 INVALID_HANDLE_VALUE,
2579 NULL);
2580
2581 /* FIXME: More code! */
2582
2583 if (bFileQueueCreated)
2584 SetupCloseFileQueue(FileQueue);
2585
2586 SetupCloseInfFile(hInf);
2587
2588 RegCloseKey(hClassKey);
2589 return TRUE;
2590 }
2591
2592
2593 /***********************************************************************
2594 * SetupDiOpenClassRegKey (SETUPAPI.@)
2595 */
2596 HKEY WINAPI SetupDiOpenClassRegKey(
2597 const GUID* ClassGuid,
2598 REGSAM samDesired)
2599 {
2600 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2601 DIOCR_INSTALLER, NULL, NULL);
2602 }
2603
2604
2605 /***********************************************************************
2606 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2607 */
2608 HKEY WINAPI SetupDiOpenClassRegKeyExA(
2609 const GUID* ClassGuid,
2610 REGSAM samDesired,
2611 DWORD Flags,
2612 PCSTR MachineName,
2613 PVOID Reserved)
2614 {
2615 PWSTR MachineNameW = NULL;
2616 HKEY hKey;
2617
2618 TRACE("\n");
2619
2620 if (MachineName)
2621 {
2622 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2623 if (MachineNameW == NULL)
2624 return INVALID_HANDLE_VALUE;
2625 }
2626
2627 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2628 Flags, MachineNameW, Reserved);
2629
2630 if (MachineNameW)
2631 MyFree(MachineNameW);
2632
2633 return hKey;
2634 }
2635
2636
2637 /***********************************************************************
2638 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2639 */
2640 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2641 const GUID* ClassGuid,
2642 REGSAM samDesired,
2643 DWORD Flags,
2644 PCWSTR MachineName,
2645 PVOID Reserved)
2646 {
2647 LPWSTR lpGuidString;
2648 LPWSTR lpFullGuidString;
2649 DWORD dwLength;
2650 HKEY HKLM;
2651 HKEY hClassesKey;
2652 HKEY hClassKey;
2653 DWORD rc;
2654 LPCWSTR lpKeyName;
2655
2656 if (Flags == DIOCR_INSTALLER)
2657 {
2658 lpKeyName = ControlClass;
2659 }
2660 else if (Flags == DIOCR_INTERFACE)
2661 {
2662 lpKeyName = DeviceClasses;
2663 }
2664 else
2665 {
2666 ERR("Invalid Flags parameter!\n");
2667 SetLastError(ERROR_INVALID_PARAMETER);
2668 return INVALID_HANDLE_VALUE;
2669 }
2670
2671 if (MachineName != NULL)
2672 {
2673 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
2674 if (rc != ERROR_SUCCESS)
2675 {
2676 SetLastError(rc);
2677 return INVALID_HANDLE_VALUE;
2678 }
2679 }
2680 else
2681 HKLM = HKEY_LOCAL_MACHINE;
2682
2683 rc = RegOpenKeyExW(HKLM,
2684 lpKeyName,
2685 0,
2686 KEY_ALL_ACCESS,
2687 &hClassesKey);
2688 if (MachineName != NULL) RegCloseKey(HKLM);
2689 if (rc != ERROR_SUCCESS)
2690 {
2691 SetLastError(rc);
2692 return INVALID_HANDLE_VALUE;
2693 }
2694
2695 if (ClassGuid == NULL)
2696 return hClassesKey;
2697
2698 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
2699 {
2700 SetLastError(ERROR_GEN_FAILURE);
2701 RegCloseKey(hClassesKey);
2702 return INVALID_HANDLE_VALUE;
2703 }
2704
2705 dwLength = lstrlenW(lpGuidString);
2706 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR));
2707 if (!lpFullGuidString)
2708 {
2709 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2710 RpcStringFreeW(&lpGuidString);
2711 return INVALID_HANDLE_VALUE;
2712 }
2713 lpFullGuidString[0] = '{';
2714 memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR));
2715 lpFullGuidString[dwLength + 1] = '}';
2716 lpFullGuidString[dwLength + 2] = '\0';
2717 RpcStringFreeW(&lpGuidString);
2718
2719 rc = RegOpenKeyExW(hClassesKey,
2720 lpFullGuidString,
2721 0,
2722 KEY_ALL_ACCESS,
2723 &hClassKey);
2724 if (rc != ERROR_SUCCESS)
2725 {
2726 SetLastError(rc);
2727 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
2728 RegCloseKey(hClassesKey);
2729 return INVALID_HANDLE_VALUE;
2730 }
2731
2732 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
2733 RegCloseKey(hClassesKey);
2734
2735 return hClassKey;
2736 }
2737
2738 /***********************************************************************
2739 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2740 */
2741 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2742 HDEVINFO DeviceInfoSet,
2743 PCWSTR DevicePath,
2744 DWORD OpenFlags,
2745 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2746 {
2747 FIXME("%p %s %08lx %p\n",
2748 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2749 return FALSE;
2750 }
2751
2752 /***********************************************************************
2753 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2754 */
2755 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
2756 HDEVINFO DeviceInfoSet,
2757 PCSTR DevicePath,
2758 DWORD OpenFlags,
2759 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2760 {
2761 FIXME("%p %s %08lx %p\n", DeviceInfoSet,
2762 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
2763 return FALSE;
2764 }
2765
2766 /***********************************************************************
2767 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2768 */
2769 BOOL WINAPI SetupDiSetClassInstallParamsA(
2770 HDEVINFO DeviceInfoSet,
2771 PSP_DEVINFO_DATA DeviceInfoData,
2772 PSP_CLASSINSTALL_HEADER ClassInstallParams,
2773 DWORD ClassInstallParamsSize)
2774 {
2775 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
2776 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
2777 return FALSE;
2778 }
2779
2780 /***********************************************************************
2781 * SetupDiCallClassInstaller (SETUPAPI.@)
2782 */
2783 BOOL WINAPI SetupDiCallClassInstaller(
2784 IN DI_FUNCTION InstallFunction,
2785 IN HDEVINFO DeviceInfoSet,
2786 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
2787 {
2788 BOOL ret = FALSE;
2789
2790 TRACE("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
2791
2792 if (!DeviceInfoSet)
2793 SetLastError(ERROR_INVALID_PARAMETER);
2794 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2795 SetLastError(ERROR_INVALID_HANDLE);
2796 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2797 SetLastError(ERROR_INVALID_HANDLE);
2798 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
2799 SetLastError(ERROR_INVALID_HANDLE);
2800 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2801 SetLastError(ERROR_INVALID_USER_BUFFER);
2802 else
2803 {
2804 #define CLASS_COINSTALLER 0x1
2805 #define DEVICE_COINSTALLER 0x2
2806 #define CLASS_INSTALLER 0x4
2807 UCHAR CanHandle = 0;
2808 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
2809
2810 switch (InstallFunction)
2811 {
2812 case DIF_ALLOW_INSTALL:
2813 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
2814 break;
2815 case DIF_DESTROYPRIVATEDATA:
2816 CanHandle = CLASS_INSTALLER;
2817 break;
2818 case DIF_INSTALLDEVICE:
2819 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
2820 DefaultHandler = SetupDiInstallDevice;
2821 break;
2822 case DIF_INSTALLDEVICEFILES:
2823 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
2824 DefaultHandler = SetupDiInstallDriverFiles;
2825 break;
2826 case DIF_INSTALLINTERFACES:
2827 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
2828 DefaultHandler = SetupDiInstallDeviceInterfaces;
2829 break;
2830 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
2831 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
2832 break;
2833 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
2834 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
2835 break;
2836 case DIF_NEWDEVICEWIZARD_PREANALYZE:
2837 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
2838 break;
2839 case DIF_REGISTER_COINSTALLERS:
2840 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
2841 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
2842 break;
2843 case DIF_SELECTBESTCOMPATDRV:
2844 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
2845 DefaultHandler = SetupDiSelectBestCompatDrv;
2846 break;
2847 default:
2848 FIXME("Install function %ld not implemented\n", InstallFunction);
2849 SetLastError(ERROR_INVALID_PARAMETER);
2850 }
2851
2852 if (CanHandle != 0)
2853 {
2854 LIST_ENTRY ClassCoInstallersListHead;
2855 LIST_ENTRY DeviceCoInstallersListHead;
2856 CLASS_INSTALL_PROC ClassInstaller = NULL;
2857 COINSTALLER_CONTEXT_DATA Context;
2858 PLIST_ENTRY ListEntry;
2859 HKEY hKey;
2860 DWORD dwRegType, dwLength;
2861 DWORD rc = NO_ERROR;
2862
2863 InitializeListHead(&ClassCoInstallersListHead);
2864 InitializeListHead(&DeviceCoInstallersListHead);
2865
2866 if (CanHandle & DEVICE_COINSTALLER)
2867 {
2868 FIXME("Doesn't use Device co-installers at the moment\n");
2869 }
2870 if (CanHandle & CLASS_COINSTALLER)
2871 {
2872 rc = RegOpenKeyEx(
2873 HKEY_LOCAL_MACHINE,
2874 L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2875 0, /* Options */
2876 KEY_QUERY_VALUE,
2877 &hKey);
2878 if (rc == ERROR_SUCCESS)
2879 {
2880 LPWSTR lpGuidString;
2881 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
2882 {
2883 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
2884 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
2885 {
2886 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
2887 if (KeyBuffer != NULL)
2888 {
2889 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
2890 if (rc == ERROR_SUCCESS)
2891 {
2892 LPCWSTR ptr;
2893 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
2894 {
2895 /* Add coinstaller to ClassCoInstallersListHead list */
2896 FIXME("Class coinstaller is '%S'. UNIMPLEMENTED!\n", ptr);
2897 }
2898 }
2899 HeapFree(GetProcessHeap(), 0, KeyBuffer);
2900 }
2901 }
2902 RpcStringFreeW(&lpGuidString);
2903 }
2904 RegCloseKey(hKey);
2905 }
2906 }
2907 if (CanHandle & CLASS_INSTALLER)
2908 {
2909 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
2910 if (hKey != INVALID_HANDLE_VALUE)
2911 {
2912 rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
2913 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
2914 {
2915 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
2916 if (KeyBuffer != NULL)
2917 {
2918 rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
2919 if (rc == ERROR_SUCCESS)
2920 {
2921 /* Set ClassInstaller function pointer */
2922 FIXME("Installer is '%S'\n", KeyBuffer);
2923 }
2924 HeapFree(GetProcessHeap(), 0, KeyBuffer);
2925 }
2926 }
2927 RegCloseKey(hKey);
2928 }
2929 }
2930
2931 /* Call Class co-installers */
2932 Context.PostProcessing = FALSE;
2933 rc = NO_ERROR;
2934 ListEntry = ClassCoInstallersListHead.Flink;
2935 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
2936 {
2937 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
2938 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
2939 coinstaller->PrivateData = Context.PrivateData;
2940 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
2941 {
2942 coinstaller->DoPostProcessing = TRUE;
2943 rc = NO_ERROR;
2944 }
2945 ListEntry = ListEntry->Flink;
2946 }
2947
2948 /* Call Device co-installers */
2949 ListEntry = DeviceCoInstallersListHead.Flink;
2950 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
2951 {
2952 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
2953 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
2954 coinstaller->PrivateData = Context.PrivateData;
2955 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
2956 {
2957 coinstaller->DoPostProcessing = TRUE;
2958 rc = NO_ERROR;
2959 }
2960 ListEntry = ListEntry->Flink;
2961 }
2962
2963 /* Call Class installer */
2964 if (ClassInstaller)
2965 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
2966 else
2967 rc = ERROR_DI_DO_DEFAULT;
2968
2969 /* Call default handler */
2970 if (rc == ERROR_DI_DO_DEFAULT)
2971 {
2972 if (DefaultHandler /*FIXME && DI_NODI_DEFAULTACTION not set */)
2973 {
2974 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
2975 rc = NO_ERROR;
2976 else
2977 rc = GetLastError();
2978 }
2979 else
2980 rc = NO_ERROR;
2981 }
2982
2983 /* Call Class co-installers that required postprocessing */
2984 Context.PostProcessing = TRUE;
2985 ListEntry = ClassCoInstallersListHead.Flink;
2986 while (ListEntry != &ClassCoInstallersListHead)
2987 {
2988 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
2989 if (coinstaller->DoPostProcessing)
2990 {
2991 Context.InstallResult = rc;
2992 Context.PrivateData = coinstaller->PrivateData;
2993 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
2994 }
2995 ListEntry = ListEntry->Flink;
2996 }
2997
2998 /* Call Device co-installers that required postprocessing */
2999 ListEntry = DeviceCoInstallersListHead.Flink;
3000 while (ListEntry != &DeviceCoInstallersListHead)
3001 {
3002 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3003 if (coinstaller->DoPostProcessing)
3004 {
3005 Context.InstallResult = rc;
3006 Context.PrivateData = coinstaller->PrivateData;
3007 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3008 }
3009 ListEntry = ListEntry->Flink;
3010 }
3011
3012 /* Free allocated memory */
3013 while (!IsListEmpty(&ClassCoInstallersListHead))
3014 {
3015 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
3016 HeapFree(GetProcessHeap(), 0, ListEntry);
3017 }
3018 while (!IsListEmpty(&DeviceCoInstallersListHead))
3019 {
3020 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
3021 HeapFree(GetProcessHeap(), 0, ListEntry);
3022 }
3023
3024 ret = (rc == NO_ERROR);
3025 }
3026 }
3027
3028 TRACE("Returning %d\n", ret);
3029 return ret;
3030 }
3031
3032 /***********************************************************************
3033 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3034 */
3035 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3036 IN HDEVINFO DeviceInfoSet,
3037 IN PSP_DEVINFO_DATA DeviceInfoData,
3038 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3039 {
3040 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
3041 BOOL ret = FALSE;
3042
3043 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3044
3045 if (DeviceInstallParams == NULL)
3046 SetLastError(ERROR_INVALID_PARAMETER);
3047 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
3048 SetLastError(ERROR_INVALID_USER_BUFFER);
3049 else
3050 {
3051 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3052 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
3053
3054 if (ret)
3055 {
3056 /* Do W->A conversion */
3057 memcpy(
3058 DeviceInstallParams,
3059 &deviceInstallParamsW,
3060 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
3061 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
3062 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
3063 {
3064 DeviceInstallParams->DriverPath[0] = '\0';
3065 ret = FALSE;
3066 }
3067 }
3068 }
3069
3070 TRACE("Returning %d\n", ret);
3071 return ret;
3072 }
3073
3074 /***********************************************************************
3075 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3076 */
3077 BOOL WINAPI SetupDiGetDeviceInstallParamsW(
3078 IN HDEVINFO DeviceInfoSet,
3079 IN PSP_DEVINFO_DATA DeviceInfoData,
3080 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3081 {
3082 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3083 return FALSE;
3084 }
3085
3086 /***********************************************************************
3087 * SetupDiOpenDevRegKey (SETUPAPI.@)
3088 */
3089 HKEY WINAPI SetupDiOpenDevRegKey(
3090 HDEVINFO DeviceInfoSet,
3091 PSP_DEVINFO_DATA DeviceInfoData,
3092 DWORD Scope,
3093 DWORD HwProfile,
3094 DWORD KeyType,
3095 REGSAM samDesired)
3096 {
3097 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
3098 Scope, HwProfile, KeyType, samDesired);
3099 return INVALID_HANDLE_VALUE;
3100 }
3101
3102 /***********************************************************************
3103 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3104 */
3105 BOOL WINAPI SetupDiCreateDeviceInfoA(
3106 HDEVINFO DeviceInfoSet,
3107 PCSTR DeviceName,
3108 CONST GUID *ClassGuid,
3109 PCSTR DeviceDescription,
3110 HWND hwndParent,
3111 DWORD CreationFlags,
3112 PSP_DEVINFO_DATA DeviceInfoData)
3113 {
3114 LPWSTR DeviceNameW = NULL;
3115 LPWSTR DeviceDescriptionW = NULL;
3116 BOOL bResult;
3117
3118 TRACE("\n");
3119
3120 if (DeviceName)
3121 {
3122 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
3123 if (DeviceNameW == NULL) return FALSE;
3124 }
3125 if (DeviceDescription)
3126 {
3127 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
3128 if (DeviceDescriptionW == NULL)
3129 {
3130 if (DeviceNameW) MyFree(DeviceNameW);
3131 return FALSE;
3132 }
3133 }
3134
3135 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
3136 ClassGuid, DeviceDescriptionW,
3137 hwndParent, CreationFlags,
3138 DeviceInfoData);
3139
3140 if (DeviceNameW) MyFree(DeviceNameW);
3141 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
3142
3143 return bResult;
3144 }
3145
3146 /***********************************************************************
3147 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3148 */
3149 BOOL WINAPI SetupDiCreateDeviceInfoW(
3150 HDEVINFO DeviceInfoSet,
3151 PCWSTR DeviceName,
3152 CONST GUID *ClassGuid,
3153 PCWSTR DeviceDescription,
3154 HWND hwndParent,
3155 DWORD CreationFlags,
3156 PSP_DEVINFO_DATA DeviceInfoData)
3157 {
3158 struct DeviceInfoSet *list;
3159 BOOL ret = FALSE;
3160
3161 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
3162 debugstr_guid(ClassGuid), DeviceDescription,
3163 hwndParent, CreationFlags, DeviceInfoData);
3164
3165 if (!DeviceInfoSet)
3166 SetLastError(ERROR_INVALID_HANDLE);
3167 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3168 SetLastError(ERROR_INVALID_HANDLE);
3169 else if (!ClassGuid)
3170 SetLastError(ERROR_INVALID_PARAMETER);
3171 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
3172 SetLastError(ERROR_CLASS_MISMATCH);
3173 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
3174 {
3175 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
3176 SetLastError(ERROR_INVALID_PARAMETER);
3177 }
3178 else
3179 {
3180 SP_DEVINFO_DATA DevInfo;
3181
3182 if (CreationFlags & DICD_GENERATE_ID)
3183 {
3184 /* Generate a new unique ID for this device */
3185 SetLastError(ERROR_GEN_FAILURE);
3186 FIXME("not implemented\n");
3187 }
3188 else
3189 {
3190 /* Device name is fully qualified. Try to open it */
3191 BOOL rc;
3192
3193 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
3194 rc = SetupDiOpenDeviceInfoW(
3195 DeviceInfoSet,
3196 DeviceName,
3197 NULL, /* hwndParent */
3198 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
3199 &DevInfo);
3200
3201 if (rc)
3202 {
3203 /* SetupDiOpenDeviceInfoW has already added
3204 * the device info to the device info set
3205 */
3206 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
3207 }
3208 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
3209 {
3210 struct DeviceInfoElement *deviceInfo;
3211
3212 /* FIXME: ClassGuid can be NULL */
3213 if (CreateDeviceInfoElement(DeviceName, ClassGuid, &deviceInfo))
3214 {
3215 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
3216
3217 if (!DeviceInfoData)
3218 ret = TRUE;
3219 else
3220 {
3221 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
3222 {
3223 SetLastError(ERROR_INVALID_USER_BUFFER);
3224 }
3225 else
3226 {
3227 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
3228 DeviceInfoData->DevInst = 0; /* FIXME */
3229 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
3230 ret = TRUE;
3231 }
3232 }
3233 }
3234 }
3235 }
3236 }
3237
3238 TRACE("Returning %d\n", ret);
3239 return ret;
3240 }
3241
3242 /***********************************************************************
3243 * Helper functions for SetupDiBuildDriverInfoList
3244 */
3245 static BOOL
3246 AddDriverToList(
3247 IN PLIST_ENTRY DriverListHead,
3248 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3249 IN INFCONTEXT ContextDevice,
3250 IN LPCWSTR InfFile,
3251 IN LPCWSTR ProviderName,
3252 IN LPCWSTR ManufacturerName,
3253 IN LPCWSTR MatchingId,
3254 FILETIME DriverDate,
3255 DWORDLONG DriverVersion,
3256 IN DWORD Rank)
3257 {
3258 struct DriverInfoElement *driverInfo = NULL;
3259 DWORD RequiredSize = 128; /* Initial buffer size */
3260 BOOL Result = FALSE;
3261 PLIST_ENTRY PreviousEntry;
3262 LPWSTR DeviceDescription = NULL;
3263 LPWSTR InfInstallSection = NULL;
3264 BOOL ret = FALSE;
3265
3266 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
3267 if (!driverInfo)
3268 {
3269 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3270 goto cleanup;
3271 }
3272 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
3273
3274 /* Fill InfSection field */
3275 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3276 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3277 {
3278 HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
3279 driverInfo->InfSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3280 if (!driverInfo->InfSection)
3281 {
3282 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3283 goto cleanup;
3284 }
3285 Result = SetupGetStringFieldW(
3286 &ContextDevice,
3287 1,
3288 driverInfo->InfSection, RequiredSize,
3289 &RequiredSize);
3290 }
3291 if (!Result)
3292 goto cleanup;
3293
3294 /* Copy InfFile information */
3295 driverInfo->InfPath = HeapAlloc(GetProcessHeap(), 0, (wcslen(InfFile) + 1) * sizeof(WCHAR));
3296 if (!driverInfo->InfPath)
3297 {
3298 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3299 goto cleanup;
3300 }
3301 RtlCopyMemory(driverInfo->InfPath, InfFile, (wcslen(InfFile) + 1) * sizeof(WCHAR));
3302
3303 /* Copy MatchingId information */
3304 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
3305 if (!driverInfo->MatchingId)
3306 {
3307 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3308 goto cleanup;
3309 }
3310 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
3311
3312 /* Get device description */
3313 Result = FALSE;
3314 RequiredSize = 128; /* Initial buffer size */
3315 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3316 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3317 {
3318 HeapFree(GetProcessHeap(), 0, DeviceDescription);
3319 DeviceDescription = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3320 if (!DeviceDescription)
3321 goto cleanup;
3322 Result = SetupGetStringFieldW(
3323 &ContextDevice,
3324 0, /* Field index */
3325 DeviceDescription, RequiredSize,
3326 &RequiredSize);
3327 }
3328 if (!Result)
3329 goto cleanup;
3330
3331 /* Get inf install section */
3332 Result = FALSE;
3333 RequiredSize = 128; /* Initial buffer size */
3334 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3335 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3336 {
3337 HeapFree(GetProcessHeap(), 0, InfInstallSection);
3338 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3339 if (!InfInstallSection)
3340 goto cleanup;
3341 Result = SetupGetStringFieldW(
3342 &ContextDevice,
3343 1, /* Field index */
3344 InfInstallSection, RequiredSize,
3345 &RequiredSize);
3346 }
3347 if (!Result)
3348 goto cleanup;
3349
3350 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3351 DeviceDescription, InfFile, InfInstallSection, Rank);
3352
3353 driverInfo->DriverRank = Rank;
3354 driverInfo->Info.DriverType = DriverType;
3355 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
3356 wcsncpy(driverInfo->Info.Description, DeviceDescription, LINE_LEN - 1);
3357 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
3358 wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
3359 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
3360 if (ProviderName)
3361 {
3362 wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
3363 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
3364 }
3365 else
3366 driverInfo->Info.ProviderName[0] = '\0';
3367 driverInfo->Info.DriverDate = DriverDate;
3368 driverInfo->Info.DriverVersion = DriverVersion;
3369
3370 /* Insert current driver in driver list, according to its rank */
3371 PreviousEntry = DriverListHead->Flink;
3372 while (PreviousEntry != DriverListHead)
3373 {
3374 if (((struct DriverInfoElement *)PreviousEntry)->DriverRank >= Rank)
3375 {
3376 /* Insert before the current item */
3377 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
3378 break;
3379 }
3380 }
3381 if (PreviousEntry == DriverListHead)
3382 {
3383 /* Insert at the end of the list */
3384 InsertTailList(DriverListHead, &driverInfo->ListEntry);
3385 }
3386
3387 ret = TRUE;
3388
3389 cleanup:
3390 if (!ret)
3391 {
3392 if (driverInfo)
3393 {
3394 HeapFree(GetProcessHeap(), 0, driverInfo->InfPath);
3395 HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
3396 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
3397 }
3398 HeapFree(GetProcessHeap(), 0, driverInfo);
3399 }
3400 HeapFree(GetProcessHeap(), 0, DeviceDescription);
3401 HeapFree(GetProcessHeap(), 0, InfInstallSection);
3402
3403 return ret;
3404 }
3405
3406 static BOOL
3407 GetVersionInformationFromInfFile(
3408 IN HINF hInf,
3409 OUT LPGUID ClassGuid,
3410 OUT LPWSTR* pProviderName,
3411 OUT FILETIME* DriverDate,
3412 OUT DWORDLONG* DriverVersion)
3413 {
3414 DWORD RequiredSize;
3415 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
3416 LPWSTR DriverVer = NULL;
3417 LPWSTR ProviderName = NULL;
3418 LPWSTR pComma; /* Points into DriverVer */
3419 LPWSTR pVersion = NULL; /* Points into DriverVer */
3420 SYSTEMTIME SystemTime;
3421 BOOL Result;
3422 BOOL ret = FALSE; /* Final result */
3423
3424 /* Get class Guid */
3425 if (!SetupGetLineTextW(
3426 NULL, /* Context */
3427 hInf,
3428 L"Version", L"ClassGUID",
3429 guidW, sizeof(guidW),
3430 NULL /* Required size */))
3431 {
3432 goto cleanup;
3433 }
3434 guidW[37] = '\0'; /* Replace the } by a NULL character */
3435 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
3436 {
3437 SetLastError(ERROR_GEN_FAILURE);
3438 goto cleanup;
3439 }
3440
3441 /* Get provider name */
3442 Result = SetupGetLineTextW(
3443 NULL, /* Context */
3444 hInf, L"Version", L"Provider",
3445 NULL, 0,
3446 &RequiredSize);
3447 if (Result)
3448 {
3449 /* We know know the needed buffer size */
3450 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3451 if (!ProviderName)
3452 {
3453 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3454 goto cleanup;
3455 }
3456 Result = SetupGetLineTextW(
3457 NULL, /* Context */
3458 hInf, L"Version", L"Provider",
3459 ProviderName, RequiredSize,
3460 &RequiredSize);
3461 }
3462 if (!Result)
3463 goto cleanup;
3464 *pProviderName = ProviderName;
3465
3466 /* Read the "DriverVer" value */
3467 Result = SetupGetLineTextW(
3468 NULL, /* Context */
3469 hInf, L"Version", L"DriverVer",
3470 NULL, 0,
3471 &RequiredSize);
3472 if (Result)
3473 {
3474 /* We know know the needed buffer size */
3475 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3476 if (!DriverVer)
3477 {
3478 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3479 goto cleanup;
3480 }
3481 Result = SetupGetLineTextW(
3482 NULL, /* Context */
3483 hInf, L"Version", L"DriverVer",
3484 DriverVer, RequiredSize,
3485 &RequiredSize);
3486 }
3487 if (!Result)
3488 goto cleanup;
3489
3490 /* Get driver date and driver version, by analyzing the "DriverVer" value */
3491 pComma = wcschr(DriverVer, ',');
3492 if (pComma != NULL)
3493 {
3494 *pComma = UNICODE_NULL;
3495 pVersion = pComma + 1;
3496 }
3497 /* Get driver date version. Invalid date = 00/00/00 */
3498 memset(DriverDate, 0, sizeof(FILETIME));
3499 if (wcslen(DriverVer) == 10
3500 && (DriverVer[2] == '-' || DriverVer[2] == '/')
3501 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
3502 {
3503 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
3504 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
3505 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
3506 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
3507 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
3508 SystemTimeToFileTime(&SystemTime, DriverDate);
3509 }
3510 /* Get driver version. Invalid version = 0.0.0.0 */
3511 *DriverVersion = 0;
3512 /* FIXME: use pVersion to fill DriverVersion variable */
3513
3514 ret = TRUE;
3515
3516 cleanup:
3517 if (!ret)
3518 HeapFree(GetProcessHeap(), 0, ProviderName);
3519 HeapFree(GetProcessHeap(), 0, DriverVer);
3520
3521 TRACE("Returning %d\n", ret);
3522 return ret;
3523 }
3524
3525 /***********************************************************************
3526 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3527 */
3528 BOOL WINAPI
3529 SetupDiBuildDriverInfoList(
3530 IN HDEVINFO DeviceInfoSet,
3531 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
3532 IN DWORD DriverType)
3533 {
3534 struct DeviceInfoSet *list;
3535 PVOID Buffer = NULL;
3536 HINF hInf = INVALID_HANDLE_VALUE;
3537 LPWSTR ProviderName = NULL;
3538 LPWSTR ManufacturerName = NULL;
3539 LPWSTR ManufacturerSection = NULL;
3540 LPWSTR HardwareIDs = NULL;
3541 LPWSTR CompatibleIDs = NULL;
3542 FILETIME DriverDate;
3543 DWORDLONG DriverVersion = 0;
3544 DWORD RequiredSize;
3545 BOOL ret = FALSE;
3546
3547 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
3548
3549 if (!DeviceInfoSet)
3550 SetLastError(ERROR_INVALID_HANDLE);
3551 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3552 SetLastError(ERROR_INVALID_HANDLE);
3553 else if (list->HKLM != HKEY_LOCAL_MACHINE)
3554 SetLastError(ERROR_INVALID_HANDLE);
3555 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
3556 SetLastError(ERROR_INVALID_PARAMETER);
3557 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
3558 SetLastError(ERROR_INVALID_PARAMETER);
3559 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
3560 SetLastError(ERROR_INVALID_PARAMETER);
3561 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3562 SetLastError(ERROR_INVALID_USER_BUFFER);
3563 else
3564 {
3565 BOOL Result = FALSE;
3566
3567 if (DriverType == SPDIT_COMPATDRIVER)
3568 {
3569 /* Get hardware IDs list */
3570 Result = FALSE;
3571 RequiredSize = 512; /* Initial buffer size */
3572 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3573 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3574 {
3575 HeapFree(GetProcessHeap(), 0, HardwareIDs);
3576 HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
3577 if (!HardwareIDs)
3578 {
3579 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3580 goto done;
3581 }
3582 Result = SetupDiGetDeviceRegistryPropertyW(
3583 DeviceInfoSet,
3584 DeviceInfoData,
3585 SPDRP_HARDWAREID,
3586 NULL,
3587 (PBYTE)HardwareIDs,
3588 RequiredSize,
3589 &RequiredSize);
3590 }
3591 if (!Result)
3592 goto done;
3593
3594 /* Get compatible IDs list */
3595 Result = FALSE;
3596 RequiredSize = 512; /* Initial buffer size */
3597 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3598 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3599 {
3600 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
3601 CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
3602 if (!CompatibleIDs)
3603 {
3604 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3605 goto done;
3606 }
3607 Result = SetupDiGetDeviceRegistryPropertyW(
3608 DeviceInfoSet,
3609 DeviceInfoData,
3610 SPDRP_COMPATIBLEIDS,
3611 NULL,
3612 (PBYTE)CompatibleIDs,
3613 RequiredSize,
3614 &RequiredSize);
3615 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
3616 {
3617 /* No compatible ID for this device */
3618 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
3619 CompatibleIDs = NULL;
3620 Result = TRUE;
3621 }
3622 }
3623 if (!Result)
3624 goto done;
3625 }
3626
3627 /* Enumerate .inf files */
3628 Result = FALSE;
3629 RequiredSize = 32768; /* Initial buffer size */
3630 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3631 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3632 {
3633 HeapFree(GetProcessHeap(), 0, Buffer);
3634 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3635 if (!Buffer)
3636 {
3637 Result = FALSE;
3638 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3639 break;
3640 }
3641 Result = SetupGetInfFileListW(
3642 NULL, /* Directory path */
3643 INF_STYLE_WIN4,
3644 Buffer, RequiredSize,
3645 &RequiredSize);
3646 }
3647 if (Result)
3648 {
3649 LPCWSTR filename;
3650
3651 for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
3652 {
3653 INFCONTEXT ContextManufacturer, ContextDevice;
3654 GUID ClassGuid;
3655 TRACE("Opening file %S\n", filename);
3656
3657 hInf = SetupOpenInfFileW(filename, NULL, INF_STYLE_WIN4, NULL);
3658 if (hInf == INVALID_HANDLE_VALUE)
3659 continue;
3660
3661 if (!GetVersionInformationFromInfFile(
3662 hInf,
3663 &ClassGuid,
3664 &ProviderName,
3665 &DriverDate,
3666 &DriverVersion))
3667 {
3668 SetupCloseInfFile(hInf);
3669 hInf = INVALID_HANDLE_VALUE;
3670 continue;
3671 }
3672
3673 if (DriverType == SPDIT_CLASSDRIVER)
3674 {
3675 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3676 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
3677 {
3678 goto next;
3679 }
3680 }
3681
3682 /* Get the manufacturers list */
3683 Result = SetupFindFirstLineW(hInf, L"Manufacturer", NULL, &ContextManufacturer);
3684 while (Result)
3685 {
3686 Result = SetupGetStringFieldW(
3687 &ContextManufacturer,
3688 0, /* Field index */
3689 NULL, 0,
3690 &RequiredSize);
3691 if (Result)
3692 {
3693 /* We got the needed size for the buffer */
3694 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3695 if (!ManufacturerName)
3696 {
3697 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3698 goto done;
3699 }
3700 Result = SetupGetStringFieldW(
3701 &ContextManufacturer,
3702 0, /* Field index */
3703 ManufacturerName, RequiredSize,
3704 &RequiredSize);
3705 }
3706 Result = SetupGetStringFieldW(
3707 &ContextManufacturer,
3708 1, /* Field index */
3709 NULL, 0,
3710 &RequiredSize);
3711 if (Result)
3712 {
3713 /* We got the needed size for the buffer */
3714 ManufacturerSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3715 if (!ManufacturerSection)
3716 {
3717 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3718 goto done;
3719 }
3720 Result = SetupGetStringFieldW(
3721 &ContextManufacturer,
3722 1, /* Field index */
3723 ManufacturerSection, RequiredSize,
3724 &RequiredSize);
3725 }
3726
3727 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
3728 Result = SetupFindFirstLineW(hInf, ManufacturerSection, NULL, &ContextDevice);
3729 while (Result)
3730 {
3731 if (DriverType == SPDIT_CLASSDRIVER)
3732 {
3733 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3734 if (!AddDriverToList(
3735 &list->DriverListHead,
3736 DriverType,
3737 ContextDevice,
3738 filename,
3739 ProviderName,
3740 ManufacturerName,
3741 NULL,
3742 DriverDate, DriverVersion,
3743 0))
3744 {
3745 break;
3746 }
3747 }
3748 else /* DriverType = SPDIT_COMPATDRIVER */
3749 {
3750 /* 1. Get all fields */
3751 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
3752 DWORD DriverRank;
3753 DWORD i;
3754 LPCWSTR currentId;
3755 BOOL DriverAlreadyAdded;
3756
3757 for (i = 2; i <= FieldCount; i++)
3758 {
3759 LPWSTR DeviceId = NULL;
3760 Result = FALSE;
3761 RequiredSize = 128; /* Initial buffer size */
3762 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3763 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3764 {
3765 HeapFree(GetProcessHeap(), 0, DeviceId);
3766 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3767 if (!DeviceId)
3768 {
3769 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3770 goto done;
3771 }
3772 Result = SetupGetStringFieldW(
3773 &ContextDevice,
3774 i,
3775 DeviceId, RequiredSize,
3776 &RequiredSize);
3777 }
3778 if (!Result)
3779 {
3780 HeapFree(GetProcessHeap(), 0, DeviceId);
3781 goto done;
3782 }
3783 DriverAlreadyAdded = FALSE;
3784 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
3785 {
3786 if (wcscmp(DeviceId, currentId) == 0)
3787 {
3788 AddDriverToList(
3789 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
3790 DriverType,
3791 ContextDevice,
3792 filename,
3793 ProviderName,
3794 ManufacturerName,
3795 currentId,
3796 DriverDate, DriverVersion,
3797 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
3798 DriverAlreadyAdded = TRUE;
3799 }
3800 }
3801 if (CompatibleIDs)
3802 {
3803 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
3804 {
3805 if (wcscmp(DeviceId, currentId) == 0)
3806 {
3807 AddDriverToList(
3808 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
3809 DriverType,
3810 ContextDevice,
3811 filename,
3812 ProviderName,
3813 ManufacturerName,
3814 currentId,
3815 DriverDate, DriverVersion,
3816 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
3817 DriverAlreadyAdded = TRUE;
3818 }
3819 }
3820 }
3821 HeapFree(GetProcessHeap(), 0, DeviceId);
3822 }
3823 }
3824 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
3825 }
3826
3827 HeapFree(GetProcessHeap(), 0, ManufacturerName);
3828 HeapFree(GetProcessHeap(), 0, ManufacturerSection);
3829 ManufacturerName = ManufacturerSection = NULL;
3830 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
3831 }
3832
3833 ret = TRUE;
3834 next:
3835 HeapFree(GetProcessHeap(), 0, ProviderName);
3836 ProviderName = NULL;
3837
3838 SetupCloseInfFile(hInf);
3839 hInf = INVALID_HANDLE_VALUE;
3840 }
3841 ret = TRUE;
3842 }
3843 }
3844
3845 done:
3846 if (ret)
3847 {
3848 if (DeviceInfoData)
3849 {
3850 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
3851 deviceInfo->Flags |= DI_DIDCOMPAT;
3852 }
3853 else
3854 list->Flags |= DI_DIDCLASS;
3855 }
3856
3857 HeapFree(GetProcessHeap(), 0, ProviderName);
3858 HeapFree(GetProcessHeap(), 0, ManufacturerName);
3859 HeapFree(GetProcessHeap(), 0, ManufacturerSection);
3860 HeapFree(GetProcessHeap(), 0, HardwareIDs);
3861 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
3862 if (hInf != INVALID_HANDLE_VALUE)
3863 SetupCloseInfFile(hInf);
3864 HeapFree(GetProcessHeap(), 0, Buffer);
3865
3866 TRACE("Returning %d\n", ret);
3867 return ret;
3868 }
3869
3870 /***********************************************************************
3871 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3872 */
3873 BOOL WINAPI
3874 SetupDiDeleteDeviceInfo(
3875 IN HDEVINFO DeviceInfoSet,
3876 IN PSP_DEVINFO_DATA DeviceInfoData)
3877 {
3878 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
3879
3880 FIXME("not implemented\n");
3881 SetLastError(ERROR_GEN_FAILURE);
3882 return FALSE;
3883 }
3884
3885
3886 /***********************************************************************
3887 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3888 */
3889 BOOL WINAPI
3890 SetupDiDestroyDriverInfoList(
3891 IN HDEVINFO DeviceInfoSet,
3892 IN PSP_DEVINFO_DATA DeviceInfoData,
3893 IN DWORD DriverType)
3894 {
3895 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
3896
3897 FIXME("not implemented\n");
3898 SetLastError(ERROR_GEN_FAILURE);
3899 return FALSE;
3900 }
3901
3902
3903 /***********************************************************************
3904 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3905 */
3906 BOOL WINAPI
3907 SetupDiOpenDeviceInfoA(
3908 IN HDEVINFO DeviceInfoSet,
3909 IN PCSTR DeviceInstanceId,
3910 IN HWND hwndParent OPTIONAL,
3911 IN DWORD OpenFlags,
3912 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3913 {
3914 LPWSTR DeviceInstanceIdW = NULL;
3915 BOOL bResult;
3916
3917 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
3918
3919 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
3920 if (DeviceInstanceIdW == NULL)
3921 return FALSE;
3922
3923 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
3924 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
3925
3926 MyFree(DeviceInstanceIdW);
3927
3928 return bResult;
3929 }
3930
3931
3932 /***********************************************************************
3933 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3934 */
3935 BOOL WINAPI
3936 SetupDiOpenDeviceInfoW(
3937 IN HDEVINFO DeviceInfoSet,
3938 IN PCWSTR DeviceInstanceId,
3939 IN HWND hwndParent OPTIONAL,
3940 IN DWORD OpenFlags,
3941 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3942 {
3943 struct DeviceInfoSet *list;
3944 HKEY hEnumKey, hKey;
3945 DWORD rc;
3946 BOOL ret = FALSE;
3947
3948 TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
3949
3950 if (OpenFlags & DIOD_CANCEL_REMOVE)
3951 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3952
3953 if (!DeviceInfoSet)
3954 SetLastError(ERROR_INVALID_HANDLE);
3955 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3956 SetLastError(ERROR_INVALID_HANDLE);
3957 else if (!DeviceInstanceId)
3958 SetLastError(ERROR_INVALID_PARAMETER);
3959 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
3960 {
3961 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
3962 SetLastError(ERROR_INVALID_PARAMETER);
3963 }
3964 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3965 SetLastError(ERROR_INVALID_USER_BUFFER);
3966 else
3967 {
3968 struct DeviceInfoElement *deviceInfo = NULL;
3969 /* Search if device already exists in DeviceInfoSet.
3970 * If yes, return the existing element
3971 * If no, create a new element using informations in registry
3972 */
3973 PLIST_ENTRY ItemList = list->ListHead.Flink;
3974 while (ItemList != &list->ListHead)
3975 {
3976 // TODO
3977 //if (good one)
3978 // break;
3979 FIXME("not implemented\n");
3980 ItemList = ItemList->Flink;
3981 }
3982
3983 if (deviceInfo)
3984 {
3985 /* good one found */
3986 ret = TRUE;
3987 }
3988 else
3989 {
3990 /* Open supposed registry key */
3991 rc = RegOpenKeyExW(
3992 list->HKLM,
3993 EnumKeyName,
3994 0, /* Options */
3995 KEY_ENUMERATE_SUB_KEYS,
3996 &hEnumKey);
3997 if (rc != ERROR_SUCCESS)
3998 {
3999 SetLastError(rc);
4000 return FALSE;
4001 }
4002 rc = RegOpenKeyExW(
4003 hEnumKey,
4004 DeviceInstanceId,
4005 0, /* Options */
4006 KEY_QUERY_VALUE,
4007 &hKey);
4008 RegCloseKey(hEnumKey);
4009 if (rc != ERROR_SUCCESS)
4010 {
4011 SetLastError(rc);
4012 return FALSE;
4013 }
4014
4015 /* FIXME: GUID_NULL is not allowed */
4016 if (!CreateDeviceInfoElement(DeviceInstanceId, &GUID_NULL /* FIXME */, &deviceInfo))
4017 {
4018 RegCloseKey(hKey);
4019 return FALSE;
4020 }
4021 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4022
4023 RegCloseKey(hKey);
4024 ret = TRUE;
4025 }
4026
4027 if (ret && deviceInfo && DeviceInfoData)
4028 {
4029 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
4030 DeviceInfoData->DevInst = 0; /* FIXME */
4031 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4032 }
4033 }
4034
4035 return ret;
4036 }
4037
4038
4039 /***********************************************************************
4040 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4041 */
4042 BOOL WINAPI
4043 SetupDiEnumDriverInfoA(
4044 IN HDEVINFO DeviceInfoSet,
4045 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4046 IN DWORD DriverType,
4047 IN DWORD MemberIndex,
4048 OUT PSP_DRVINFO_DATA_A DriverInfoData)
4049 {
4050 SP_DRVINFO_DATA_V2_W driverInfoData2W;
4051 BOOL ret = FALSE;
4052
4053 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
4054 DriverType, MemberIndex, DriverInfoData);
4055
4056 if (DriverInfoData == NULL)
4057 SetLastError(ERROR_INVALID_PARAMETER);
4058 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
4059 SetLastError(ERROR_INVALID_USER_BUFFER);
4060 else
4061 {
4062 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
4063 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
4064 DriverType, MemberIndex, &driverInfoData2W);
4065
4066 if (ret)
4067 {
4068 /* Do W->A conversion */
4069 DriverInfoData->DriverType = driverInfoData2W.DriverType;
4070 DriverInfoData->Reserved = driverInfoData2W.Reserved;
4071 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
4072 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
4073 {
4074 DriverInfoData->Description[0] = '\0';
4075 ret = FALSE;
4076 }
4077 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
4078 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
4079 {
4080 DriverInfoData->MfgName[0] = '\0';
4081 ret = FALSE;
4082 }
4083 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
4084 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
4085 {
4086 DriverInfoData->ProviderName[0] = '\0';
4087 ret = FALSE;
4088 }
4089 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
4090 {
4091 /* Copy more fields */
4092 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
4093 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
4094 }
4095 }
4096 }
4097
4098 TRACE("Returning %d\n", ret);
4099 return ret;
4100 }
4101
4102
4103 /***********************************************************************
4104 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4105 */
4106 BOOL WINAPI
4107 SetupDiEnumDriverInfoW(
4108 IN HDEVINFO DeviceInfoSet,
4109 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4110 IN DWORD DriverType,
4111 IN DWORD MemberIndex,
4112 OUT PSP_DRVINFO_DATA_W DriverInfoData)
4113 {
4114 PLIST_ENTRY ListHead;
4115 BOOL ret = FALSE;
4116
4117 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
4118 DriverType, MemberIndex, DriverInfoData);
4119
4120 if (!DeviceInfoSet || !DriverInfoData)
4121 SetLastError(ERROR_INVALID_PARAMETER);
4122 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4123 SetLastError(ERROR_INVALID_HANDLE);
4124 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4125 SetLastError(ERROR_INVALID_HANDLE);
4126 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4127 SetLastError(ERROR_INVALID_PARAMETER);
4128 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
4129 SetLastError(ERROR_INVALID_PARAMETER);
4130 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4131 SetLastError(ERROR_INVALID_PARAMETER);
4132 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
4133 SetLastError(ERROR_INVALID_USER_BUFFER);
4134 else
4135 {
4136 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4137 PLIST_ENTRY ItemList;
4138 if (DriverType == SPDIT_CLASSDRIVER ||
4139 devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
4140 {
4141 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
4142 }
4143 else
4144 {
4145 ListHead = &devInfo->DriverListHead;
4146 }
4147
4148 ItemList = ListHead->Flink;
4149 while (ItemList != ListHead && MemberIndex-- > 0)
4150 ItemList = ItemList->Flink;
4151 if (ItemList == ListHead)
4152 SetLastError(ERROR_NO_MORE_ITEMS);
4153 else
4154 {
4155 struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
4156
4157 memcpy(
4158 &DriverInfoData->DriverType,
4159 &DrvInfo->Info.DriverType,
4160 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
4161 ret = TRUE;
4162 }
4163 }
4164
4165 TRACE("Returning %d\n", ret);
4166 return ret;
4167 }
4168
4169 /***********************************************************************
4170 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4171 */
4172 BOOL WINAPI
4173 SetupDiGetSelectedDriverW(
4174 IN HDEVINFO DeviceInfoSet,
4175 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4176 OUT PSP_DRVINFO_DATA_W DriverInfoData)
4177 {
4178 BOOL ret = FALSE;
4179
4180 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
4181
4182 if (!DeviceInfoSet || !DriverInfoData)
4183 SetLastError(ERROR_INVALID_PARAMETER);
4184 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4185 SetLastError(ERROR_INVALID_HANDLE);
4186 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4187 SetLastError(ERROR_INVALID_HANDLE);
4188 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4189 SetLastError(ERROR_INVALID_USER_BUFFER);
4190 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
4191 SetLastError(ERROR_INVALID_USER_BUFFER);
4192 else
4193 {
4194 struct DriverInfoElement *driverInfo;
4195
4196 if (DeviceInfoData)
4197 driverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
4198 else
4199 driverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
4200
4201 if (driverInfo == NULL)
4202 SetLastError(ERROR_NO_DRIVER_SELECTED);
4203 else
4204 {
4205 memcpy(
4206 &DriverInfoData->DriverType,
4207 &driverInfo->Info.DriverType,
4208 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
4209 ret = TRUE;
4210 }
4211 }
4212
4213 TRACE("Returning %d\n", ret);
4214 return ret;
4215 }
4216
4217 /***********************************************************************
4218 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4219 */
4220 BOOL WINAPI
4221 SetupDiSetSelectedDriverW(
4222 IN HDEVINFO DeviceInfoSet,
4223 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4224 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
4225 {
4226 BOOL ret = FALSE;
4227
4228 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
4229
4230 if (!DeviceInfoSet)
4231 SetLastError(ERROR_INVALID_PARAMETER);
4232 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4233 SetLastError(ERROR_INVALID_HANDLE);
4234 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4235 SetLastError(ERROR_INVALID_HANDLE);
4236 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4237 SetLastError(ERROR_INVALID_USER_BUFFER);
4238 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
4239 SetLastError(ERROR_INVALID_USER_BUFFER);
4240 else
4241 {
4242 struct DriverInfoElement **pDriverInfo;
4243 PLIST_ENTRY ListHead, ItemList;
4244
4245 if (DeviceInfoData)
4246 {
4247 pDriverInfo = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
4248 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
4249 }
4250 else
4251 {
4252 pDriverInfo = &((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
4253 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
4254 }
4255
4256 if (!DriverInfoData)
4257 {
4258 *pDriverInfo = NULL;
4259 ret = TRUE;
4260 }
4261 else
4262 {
4263 /* Search selected driver in list */
4264 ItemList = ListHead->Flink;
4265 while (ItemList != ListHead)
4266 {
4267 if (DriverInfoData->Reserved != 0)
4268 {
4269 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
4270 break;
4271 }
4272 else
4273 {
4274 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4275 struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
4276 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
4277 && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
4278 && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
4279 {
4280 break;
4281 }
4282 }
4283 }
4284 if (ItemList == ListHead)
4285 SetLastError(ERROR_INVALID_PARAMETER);
4286 else
4287 {
4288 *pDriverInfo = (struct DriverInfoElement *)ItemList;
4289 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
4290 ret = TRUE;
4291 TRACE("Choosing driver whose rank is 0x%lx\n",
4292 ((struct DriverInfoElement *)ItemList)->DriverRank);
4293 }
4294 }
4295 }
4296
4297 TRACE("Returning %d\n", ret);
4298 return ret;
4299 }
4300
4301 /***********************************************************************
4302 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4303 */
4304 BOOL WINAPI
4305 SetupDiSelectBestCompatDrv(
4306 IN HDEVINFO DeviceInfoSet,
4307 IN PSP_DEVINFO_DATA DeviceInfoData)
4308 {
4309 SP_DRVINFO_DATA_W drvInfoData;
4310 BOOL ret;
4311
4312 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4313
4314 /* Drivers are sorted by rank in the driver list, so
4315 * the first driver in the list is the best one.
4316 */
4317 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
4318 ret = SetupDiEnumDriverInfoW(
4319 DeviceInfoSet,
4320 DeviceInfoData,
4321 SPDIT_COMPATDRIVER,
4322 0, /* Member index */
4323 &drvInfoData);
4324
4325 if (ret)
4326 {
4327 ret = SetupDiSetSelectedDriverW(
4328 DeviceInfoSet,
4329 DeviceInfoData,
4330 &drvInfoData);
4331 }
4332
4333 TRACE("Returning %d\n", ret);
4334 return ret;
4335 }
4336
4337 /***********************************************************************
4338 * SetupDiInstallDriverFiles (SETUPAPI.@)
4339 */
4340 BOOL WINAPI
4341 SetupDiInstallDriverFiles(
4342 IN HDEVINFO DeviceInfoSet,
4343 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4344 {
4345 BOOL ret = FALSE;
4346
4347 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4348
4349 if (!DeviceInfoSet)
4350 SetLastError(ERROR_INVALID_PARAMETER);
4351 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4352 SetLastError(ERROR_INVALID_HANDLE);
4353 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4354 SetLastError(ERROR_INVALID_HANDLE);
4355 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4356 SetLastError(ERROR_INVALID_USER_BUFFER);
4357 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver == NULL)
4358 SetLastError(ERROR_INVALID_PARAMETER);
4359 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver == NULL)
4360 SetLastError(ERROR_INVALID_PARAMETER);
4361 else
4362 {
4363 struct DriverInfoElement *DriverInfo;
4364 HWND hWnd;
4365 HINF hInf;
4366
4367 if (DeviceInfoData)
4368 {
4369 DriverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
4370 hWnd = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->hwndParent;
4371 }
4372 else
4373 {
4374 DriverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
4375 hWnd = ((struct DeviceInfoSet *)DeviceInfoSet)->hwndParent;
4376 }
4377
4378 hInf = SetupOpenInfFileW(DriverInfo->InfPath, NULL, INF_STYLE_WIN4, NULL);
4379 if (hInf != INVALID_HANDLE_VALUE)
4380 {
4381 WCHAR SectionName[MAX_PATH];
4382 DWORD SectionNameLength = 0;
4383
4384 ret = SetupDiGetActualSectionToInstallW(hInf, DriverInfo->InfSection,
4385 SectionName, MAX_PATH, &SectionNameLength, NULL);
4386 if (ret)
4387 {
4388 PVOID callback_context = SetupInitDefaultQueueCallback(hWnd);
4389 ret = SetupInstallFromInfSectionW(hWnd, hInf, SectionName,
4390 SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
4391 SetupDefaultQueueCallbackW, callback_context,
4392 NULL, NULL);
4393 SetupTermDefaultQueueCallback(callback_context);
4394 }
4395 SetupCloseInfFile(hInf);
4396 }
4397 }
4398
4399 TRACE("Returning %d\n", ret);
4400 return ret;
4401 }
4402
4403 /***********************************************************************
4404 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4405 */
4406 BOOL WINAPI
4407 SetupDiRegisterCoDeviceInstallers(
4408 IN HDEVINFO DeviceInfoSet,
4409 IN PSP_DEVINFO_DATA DeviceInfoData)
4410 {
4411 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4412
4413 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4414 //SetLastError(ERROR_GEN_FAILURE);
4415 //return FALSE;
4416 return TRUE;
4417 }
4418
4419 /***********************************************************************
4420 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4421 */
4422 BOOL WINAPI
4423 SetupDiInstallDeviceInterfaces(
4424 IN HDEVINFO DeviceInfoSet,
4425 IN PSP_DEVINFO_DATA DeviceInfoData)
4426 {
4427 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4428
4429 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4430 //SetLastError(ERROR_GEN_FAILURE);
4431 //return FALSE;
4432 return TRUE;
4433 }
4434
4435 /***********************************************************************
4436 * SetupDiInstallDevice (SETUPAPI.@)
4437 */
4438 BOOL WINAPI
4439 SetupDiInstallDevice(
4440 IN HDEVINFO DeviceInfoSet,
4441 IN PSP_DEVINFO_DATA DeviceInfoData)
4442 {
4443 struct DriverInfoElement *DriverInfo;
4444 struct DeviceInfoSet *DevInfoSet = (struct DeviceInfoSet *)DeviceInfoSet;
4445 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4446 SYSTEMTIME DriverDate;
4447 WCHAR SectionName[MAX_PATH];
4448 WCHAR Buffer[32];
4449 DWORD SectionNameLength = 0;
4450 BOOL Result = FALSE;
4451 INFCONTEXT ContextService;
4452 INT Flags;
4453 DWORD RequiredSize;
4454 HINF hInf = INVALID_HANDLE_VALUE;
4455 LPCWSTR AssociatedService = NULL;
4456 LPWSTR pSectionName = NULL;
4457 LPWSTR ClassName = NULL;
4458 GUID ClassGuid;
4459 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
4460 BOOL RebootRequired = FALSE;
4461 HKEY hEnumKey, hKey = INVALID_HANDLE_VALUE;
4462 HKEY hClassKey = INVALID_HANDLE_VALUE;
4463 LPWSTR DriverKey = NULL; /* {GUID}\Index */
4464 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
4465 DWORD Index; /* Index used in the DriverKey name */
4466 LONG rc;
4467 HWND hWnd;
4468 PVOID callback_context;
4469 BOOL ret = FALSE; /* Return value */
4470
4471 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4472
4473 if (!DeviceInfoSet)
4474 SetLastError(ERROR_INVALID_PARAMETER);
4475 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4476 SetLastError(ERROR_INVALID_HANDLE);
4477 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4478 SetLastError(ERROR_INVALID_HANDLE);
4479 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4480 SetLastError(ERROR_INVALID_USER_BUFFER);
4481 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver == NULL)
4482 SetLastError(ERROR_INVALID_PARAMETER);
4483 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver == NULL)
4484 SetLastError(ERROR_INVALID_PARAMETER);
4485 else
4486 Result = TRUE;
4487
4488 if (!Result)
4489 {
4490 /* One parameter is bad */
4491 goto cleanup;
4492 }
4493
4494 /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
4495
4496 if (DeviceInfoData)
4497 {
4498 DriverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
4499 hWnd = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->hwndParent;
4500 }
4501 else
4502 {
4503 DriverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
4504 hWnd = ((struct DeviceInfoSet *)DeviceInfoSet)->hwndParent;
4505 }
4506 FileTimeToSystemTime(&DriverInfo->Info.DriverDate, &DriverDate);
4507
4508 hInf = SetupOpenInfFileW(DriverInfo->InfPath, NULL, INF_STYLE_WIN4, NULL);
4509 if (hInf == INVALID_HANDLE_VALUE)
4510 goto cleanup;
4511
4512 Result = SetupDiGetActualSectionToInstallW(hInf, DriverInfo->InfSection,
4513 SectionName, MAX_PATH, &SectionNameLength, NULL);
4514 if (!Result || SectionNameLength > MAX_PATH - 9)
4515 goto cleanup;
4516 pSectionName = &SectionName[wcslen(SectionName)];
4517
4518 /* Get information from [Version] section */
4519 ClassName = NULL;
4520 RequiredSize = 0;
4521 if (!SetupDiGetINFClassW(DriverInfo->InfPath, &ClassGuid, ClassName, RequiredSize, &RequiredSize))
4522 {
4523 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
4524 goto cleanup;
4525 ClassName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4526 if (!ClassName)
4527 {
4528 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4529 goto cleanup;
4530 }
4531 if (!SetupDiGetINFClassW(DriverInfo->InfPath, &ClassGuid, ClassName, RequiredSize, &RequiredSize))
4532 goto cleanup;
4533 }
4534 /* Format ClassGuid to a string */
4535 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
4536 goto cleanup;
4537 RequiredSize = lstrlenW(lpGuidString);
4538 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
4539 if (!lpFullGuidString)
4540 {
4541 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4542 goto cleanup;
4543 }
4544 lpFullGuidString[0] = '{';
4545 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
4546 lpFullGuidString[RequiredSize + 1] = '}';
4547 lpFullGuidString[RequiredSize + 2] = '\0';
4548
4549 /* Create driver key information */
4550 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\{#ID} */
4551 DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpFullGuidString) + 6) * sizeof(WCHAR));
4552 if (!DriverKey)
4553 {
4554 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4555 goto cleanup;
4556 }
4557 wcscpy(DriverKey, lpFullGuidString);
4558 wcscat(DriverKey, L"\\");
4559 pDeviceInstance = &DriverKey[wcslen(DriverKey)];
4560 rc = RegOpenKeyExW(DevInfoSet->HKLM,
4561 ControlClass,
4562 0,
4563 KEY_CREATE_SUB_KEY,
4564 &hClassKey);
4565 if (rc != ERROR_SUCCESS)
4566 {
4567 SetLastError(rc);
4568 goto cleanup;
4569 }
4570 /* Try all values for Index between 0 and 9999 */
4571 Index = 0;
4572 while (Index <= 9999)
4573 {
4574 DWORD Disposition;
4575 wsprintf(pDeviceInstance, L"%04lu", Index);
4576 rc = RegCreateKeyEx(hClassKey,
4577 DriverKey,
4578 0,
4579 NULL,
4580 REG_OPTION_NON_VOLATILE,
4581 KEY_SET_VALUE,
4582 NULL,
4583 &hKey,
4584 &Disposition);
4585 if (rc != ERROR_SUCCESS)
4586 {
4587 SetLastError(rc);
4588 goto cleanup;
4589 }
4590 if (Disposition == REG_CREATED_NEW_KEY)
4591 break;
4592 RegCloseKey(hKey);
4593 hKey = INVALID_HANDLE_VALUE;
4594 Index++;
4595 }
4596 if (Index > 9999)
4597 {
4598 /* Unable to create more than 9999 devices within the same class */
4599 SetLastError(ERROR_GEN_FAILURE);
4600 goto cleanup;
4601 }
4602
4603 /* Write information to driver key */
4604 *pSectionName = UNICODE_NULL;
4605 TRACE("Write information to driver key\n");
4606 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
4607 TRACE("DriverDesc : '%S'\n", DriverInfo->Info.Description);
4608 TRACE("DriverVersion : '%u.%u.%u.%u'\n", DriverInfo->Info.DriverVersion & 0xff, (DriverInfo->Info.DriverVersion >> 8) & 0xff, (DriverInfo->Info.DriverVersion >> 16) & 0xff, (DriverInfo->Info.DriverVersion >> 24) & 0xff);
4609 TRACE("InfPath : '%S'\n", DriverInfo->InfPath);
4610 TRACE("InfSection : '%S'\n", DriverInfo->InfSection);
4611 TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(DriverInfo->InfSection)]); /* FIXME */
4612 TRACE("MatchingDeviceId: '%S'\n", DriverInfo->MatchingId);
4613 TRACE("ProviderName : '%S'\n", DriverInfo->Info.ProviderName);
4614 swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
4615 rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
4616 if (rc == ERROR_SUCCESS)
4617 rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&DriverInfo->Info.DriverDate, sizeof(FILETIME));
4618 if (rc == ERROR_SUCCESS)
4619 rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)DriverInfo->Info.Description, (wcslen(DriverInfo->Info.Description) + 1) * sizeof(WCHAR));
4620 if (rc == ERROR_SUCCESS)
4621 {
4622 swprintf(Buffer, L"%u.%u.%u.%u", DriverInfo->Info.DriverVersion & 0xff, (DriverInfo->Info.DriverVersion >> 8) & 0xff, (DriverInfo->Info.DriverVersion >> 16) & 0xff, (DriverInfo->Info.DriverVersion >> 24) & 0xff);
4623 rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
4624 }
4625 if (rc == ERROR_SUCCESS)
4626 rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)DriverInfo->InfPath, (wcslen(DriverInfo->InfPath) + 1) * sizeof(WCHAR));
4627 if (rc == ERROR_SUCCESS)
4628 rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)DriverInfo->InfSection, (wcslen(DriverInfo->InfSection) + 1) * sizeof(WCHAR));
4629 if (rc == ERROR_SUCCESS)
4630 rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(DriverInfo->InfSection)], (wcslen(SectionName) - wcslen(DriverInfo->InfSection) + 1) * sizeof(WCHAR));
4631 if (rc == ERROR_SUCCESS)
4632 rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)DriverInfo->MatchingId, (wcslen(DriverInfo->MatchingId) + 1) * sizeof(WCHAR));
4633 if (rc == ERROR_SUCCESS)
4634 rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)DriverInfo->Info.ProviderName, (wcslen(DriverInfo->Info.ProviderName) + 1) * sizeof(WCHAR));
4635 if (rc != ERROR_SUCCESS)
4636 {
4637 SetLastError(rc);
4638 goto cleanup;
4639 }
4640 RegCloseKey(hKey);
4641 hKey = INVALID_HANDLE_VALUE;
4642
4643 /* Install .Services section */
4644 wcscpy(pSectionName, L".Services");
4645 Result = SetupFindFirstLineW(hInf, SectionName, NULL, &ContextService);
4646 while (Result)
4647 {
4648 LPWSTR ServiceName = NULL;
4649 LPWSTR ServiceSection = NULL;
4650
4651 Result = SetupGetStringFieldW(
4652 &ContextService,
4653 1, /* Field index */
4654 NULL, 0,
4655 &RequiredSize);
4656 if (!Result)
4657 goto nextfile;
4658 if (RequiredSize > 0)
4659 {
4660 /* We got the needed size for the buffer */
4661 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4662 if (!ServiceName)
4663 {
4664 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4665 goto nextfile;
4666 }
4667 Result = SetupGetStringFieldW(
4668 &ContextService,
4669 1, /* Field index */
4670 ServiceName, RequiredSize,
4671 &RequiredSize);
4672 if (!Result)
4673 goto nextfile;
4674 }
4675 Result = SetupGetIntField(
4676 &ContextService,
4677 2, /* Field index */
4678 &Flags);
4679 if (!Result)
4680 {
4681 /* The field may be empty. Ignore the error */
4682 Flags = 0;
4683 }
4684 Result = SetupGetStringFieldW(
4685 &ContextService,
4686 3, /* Field index */
4687 NULL, 0,
4688 &RequiredSize);
4689 if (!Result)
4690 goto nextfile;
4691 if (RequiredSize > 0)
4692 {
4693 /* We got the needed size for the buffer */
4694 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4695 if (!ServiceSection)
4696 {
4697 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4698 goto nextfile;
4699 }
4700 Result = SetupGetStringFieldW(
4701 &ContextService,
4702 3, /* Field index */
4703 ServiceSection, RequiredSize,
4704 &RequiredSize);
4705 if (!Result)
4706 goto nextfile;
4707 }
4708 SetLastError(ERROR_SUCCESS);
4709 Result = SetupInstallServicesFromInfSectionExW(hInf, ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
4710 if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
4711 {
4712 AssociatedService = ServiceName;
4713 ServiceName = NULL;
4714 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
4715 RebootRequired = TRUE;
4716 }
4717 nextfile:
4718 HeapFree(GetProcessHeap(), 0, ServiceName);
4719 HeapFree(GetProcessHeap(), 0, ServiceSection);
4720 if (!Result)
4721 goto cleanup;
4722 Result = SetupFindNextLine(&ContextService, &ContextService);
4723 }
4724
4725 /* Copy .inf file to Inf\ directory */
4726 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
4727
4728 /* Open enum key */
4729 rc = RegOpenKeyExW(DevInfoSet->HKLM,
4730 EnumKeyName,
4731 0,
4732 KEY_ENUMERATE_SUB_KEYS,
4733 &hEnumKey);
4734 if (rc != ERROR_SUCCESS)
4735 {
4736 SetLastError(rc);
4737 goto cleanup;
4738 }
4739 rc = RegOpenKeyExW(
4740 hEnumKey,
4741 DevInfo->DeviceName,
4742 0, /* Options */
4743 KEY_SET_VALUE,
4744 &hKey);
4745 RegCloseKey(hEnumKey);
4746 if (rc != ERROR_SUCCESS)
4747 {
4748 SetLastError(rc);
4749 goto cleanup;
4750 }
4751
4752 /* Install .HW section */
4753 wcscpy(pSectionName, L".HW");
4754 callback_context = SetupInitDefaultQueueCallback(hWnd);
4755 Result = SetupInstallFromInfSectionW(hWnd, hInf, SectionName,
4756 SPINST_REGISTRY, hKey, NULL, 0,
4757 SetupDefaultQueueCallbackW, callback_context,
4758 NULL, NULL);
4759 SetupTermDefaultQueueCallback(callback_context);
4760 if (!Result)
4761 goto cleanup;
4762
4763 /* Write information to enum key */
4764 TRACE("Write information to enum key\n");
4765 TRACE("Service : '%S'\n", AssociatedService);
4766 TRACE("Class : '%S'\n", ClassName);
4767 TRACE("ClassGUID : '%S'\n", lpFullGuidString);
4768 TRACE("DeviceDesc : '%S'\n", DriverInfo->Info.Description);
4769 TRACE("Driver : '%S'\n", DriverKey);
4770 TRACE("Mfg : '%S'\n", DriverInfo->Info.MfgName);
4771 rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
4772 if (rc == ERROR_SUCCESS)
4773 rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
4774 if (rc == ERROR_SUCCESS)
4775 rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
4776 if (rc == ERROR_SUCCESS)
4777 rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)DriverInfo->Info.Description, (wcslen(DriverInfo->Info.Description) + 1) * sizeof(WCHAR));
4778 if (rc == ERROR_SUCCESS)
4779 rc = RegSetValueEx(hKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
4780 if (rc == ERROR_SUCCESS)
4781 rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)DriverInfo->Info.MfgName, (wcslen(DriverInfo->Info.MfgName) + 1) * sizeof(WCHAR));
4782 if (rc != ERROR_SUCCESS)
4783 {
4784 SetLastError(rc);
4785 goto cleanup;
4786 }
4787
4788 /* Start the device */
4789 if (!RebootRequired && !(Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
4790 {
4791 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
4792 NTSTATUS Status;
4793 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
4794 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
4795 ret = NT_SUCCESS(Status);
4796 }
4797 else
4798 ret = TRUE;
4799
4800 cleanup:
4801 /* End of installation */
4802 if (hClassKey != INVALID_HANDLE_VALUE)
4803 RegCloseKey(hClassKey);
4804 if (hKey != INVALID_HANDLE_VALUE)
4805 RegCloseKey(hKey);
4806 if (lpGuidString)
4807 RpcStringFreeW(&lpGuidString);
4808 HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
4809 HeapFree(GetProcessHeap(), 0, DriverKey);
4810 HeapFree(GetProcessHeap(), 0, ClassName);
4811 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
4812 if (hInf != INVALID_HANDLE_VALUE)
4813 SetupCloseInfFile(hInf);
4814
4815 TRACE("Returning %d\n", ret);
4816 return ret;
4817 }