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