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