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