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