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