implemented SetupDiCreateDevRegKeyA
[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 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3490 */
3491 HKEY WINAPI SetupDiCreateDevRegKeyA(
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 PCSTR InfSectionName OPTIONAL)
3499 {
3500 PCWSTR InfSectionNameW = NULL;
3501 HKEY ret = INVALID_HANDLE_VALUE;
3502
3503 if (InfSectionName)
3504 {
3505 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
3506 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
3507 }
3508
3509 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
3510 DeviceInfoData,
3511 Scope,
3512 HwProfile,
3513 KeyType,
3514 InfHandle,
3515 InfSectionNameW);
3516
3517 if (InfSectionNameW != NULL)
3518 MyFree((PVOID)InfSectionNameW);
3519
3520 return ret;
3521 }
3522
3523 /***********************************************************************
3524 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3525 */
3526 HKEY WINAPI SetupDiCreateDevRegKeyW(
3527 IN HDEVINFO DeviceInfoSet,
3528 IN PSP_DEVINFO_DATA DeviceInfoData,
3529 IN DWORD Scope,
3530 IN DWORD HwProfile,
3531 IN DWORD KeyType,
3532 IN HINF InfHandle OPTIONAL,
3533 IN PCWSTR InfSectionName OPTIONAL)
3534 {
3535 struct DeviceInfoSet *list;
3536 HKEY ret = INVALID_HANDLE_VALUE;
3537
3538 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
3539 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
3540
3541 if (!DeviceInfoSet)
3542 SetLastError(ERROR_INVALID_HANDLE);
3543 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3544 SetLastError(ERROR_INVALID_HANDLE);
3545 else if (!DeviceInfoData)
3546 SetLastError(ERROR_INVALID_PARAMETER);
3547 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3548 SetLastError(ERROR_INVALID_USER_BUFFER);
3549 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3550 SetLastError(ERROR_INVALID_PARAMETER);
3551 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3552 SetLastError(ERROR_INVALID_PARAMETER);
3553 else if (InfHandle && !InfSectionName)
3554 SetLastError(ERROR_INVALID_PARAMETER);
3555 else if (!InfHandle && InfSectionName)
3556 SetLastError(ERROR_INVALID_PARAMETER);
3557 else
3558 {
3559 LPWSTR lpGuidString = NULL;
3560 LPWSTR DriverKey = NULL; /* {GUID}\Index */
3561 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
3562 DWORD Index; /* Index used in the DriverKey name */
3563 DWORD rc;
3564 HKEY hClassKey = INVALID_HANDLE_VALUE;
3565 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
3566 HKEY hKey = INVALID_HANDLE_VALUE;
3567
3568 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
3569 {
3570 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3571 goto cleanup;
3572 }
3573
3574 if (KeyType == DIREG_DEV)
3575 {
3576 FIXME("DIREG_DEV case unimplemented\n");
3577 }
3578 else /* KeyType == DIREG_DRV */
3579 {
3580 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
3581 goto cleanup;
3582 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3583 DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
3584 if (!DriverKey)
3585 {
3586 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3587 goto cleanup;
3588 }
3589 wcscpy(DriverKey, L"{");
3590 wcscat(DriverKey, lpGuidString);
3591 wcscat(DriverKey, L"}\\");
3592 pDeviceInstance = &DriverKey[wcslen(DriverKey)];
3593 rc = RegOpenKeyExW(list->HKLM,
3594 ControlClass,
3595 0,
3596 KEY_CREATE_SUB_KEY,
3597 &hClassKey);
3598 if (rc != ERROR_SUCCESS)
3599 {
3600 SetLastError(rc);
3601 goto cleanup;
3602 }
3603
3604 /* Try all values for Index between 0 and 9999 */
3605 Index = 0;
3606 while (Index <= 9999)
3607 {
3608 DWORD Disposition;
3609 wsprintf(pDeviceInstance, L"%04lu", Index);
3610 rc = RegCreateKeyEx(hClassKey,
3611 DriverKey,
3612 0,
3613 NULL,
3614 REG_OPTION_NON_VOLATILE,
3615 #if _WIN32_WINNT >= 0x502
3616 KEY_READ | KEY_WRITE,
3617 #else
3618 KEY_ALL_ACCESS,
3619 #endif
3620 NULL,
3621 &hKey,
3622 &Disposition);
3623 if (rc != ERROR_SUCCESS)
3624 {
3625 SetLastError(rc);
3626 goto cleanup;
3627 }
3628 if (Disposition == REG_CREATED_NEW_KEY)
3629 break;
3630 RegCloseKey(hKey);
3631 hKey = INVALID_HANDLE_VALUE;
3632 Index++;
3633 }
3634 if (Index > 9999)
3635 {
3636 /* Unable to create more than 9999 devices within the same class */
3637 SetLastError(ERROR_GEN_FAILURE);
3638 goto cleanup;
3639 }
3640
3641 /* Open device key, to write Driver value */
3642 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
3643 if (hDeviceKey == INVALID_HANDLE_VALUE)
3644 goto cleanup;
3645 rc = RegSetValueEx(hDeviceKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
3646 if (rc != ERROR_SUCCESS)
3647 {
3648 SetLastError(rc);
3649 goto cleanup;
3650 }
3651 }
3652
3653 /* Do installation of the specified section */
3654 if (InfHandle)
3655 {
3656 FIXME("Need to install section %s in file %p\n",
3657 debugstr_w(InfSectionName), InfHandle);
3658 }
3659 ret = hKey;
3660
3661 cleanup:
3662 if (lpGuidString)
3663 RpcStringFreeW(&lpGuidString);
3664 HeapFree(GetProcessHeap(), 0, DriverKey);
3665 if (hClassKey != INVALID_HANDLE_VALUE)
3666 RegCloseKey(hClassKey);
3667 if (hDeviceKey != INVALID_HANDLE_VALUE)
3668 RegCloseKey(hDeviceKey);
3669 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
3670 RegCloseKey(hKey);
3671 }
3672
3673 TRACE("Returning 0x%p\n", ret);
3674 return ret;
3675 }
3676
3677 /***********************************************************************
3678 * SetupDiOpenDevRegKey (SETUPAPI.@)
3679 */
3680 HKEY WINAPI SetupDiOpenDevRegKey(
3681 HDEVINFO DeviceInfoSet,
3682 PSP_DEVINFO_DATA DeviceInfoData,
3683 DWORD Scope,
3684 DWORD HwProfile,
3685 DWORD KeyType,
3686 REGSAM samDesired)
3687 {
3688 struct DeviceInfoSet *list;
3689 HKEY ret = INVALID_HANDLE_VALUE;
3690
3691 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
3692 Scope, HwProfile, KeyType, samDesired);
3693
3694 if (!DeviceInfoSet)
3695 SetLastError(ERROR_INVALID_HANDLE);
3696 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3697 SetLastError(ERROR_INVALID_HANDLE);
3698 else if (!DeviceInfoData)
3699 SetLastError(ERROR_INVALID_PARAMETER);
3700 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3701 SetLastError(ERROR_INVALID_USER_BUFFER);
3702 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3703 SetLastError(ERROR_INVALID_PARAMETER);
3704 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3705 SetLastError(ERROR_INVALID_PARAMETER);
3706 else
3707 {
3708 HKEY hKey = INVALID_HANDLE_VALUE;
3709 HKEY hRootKey = INVALID_HANDLE_VALUE;
3710 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
3711 LPWSTR DriverKey = NULL;
3712 DWORD dwLength = 0;
3713 DWORD dwRegType;
3714 DWORD rc;
3715
3716 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
3717 {
3718 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3719 }
3720 else /* Scope == DICS_FLAG_GLOBAL */
3721 {
3722 rc = RegOpenKeyExW(
3723 list->HKLM,
3724 EnumKeyName,
3725 0, /* Options */
3726 KEY_ENUMERATE_SUB_KEYS,
3727 &hRootKey);
3728 if (rc != ERROR_SUCCESS)
3729 {
3730 SetLastError(rc);
3731 goto cleanup;
3732 }
3733 rc = RegOpenKeyExW(
3734 hRootKey,
3735 deviceInfo->DeviceName,
3736 0, /* Options */
3737 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
3738 &hKey);
3739 RegCloseKey(hRootKey);
3740 hRootKey = INVALID_HANDLE_VALUE;
3741 if (rc != ERROR_SUCCESS)
3742 {
3743 SetLastError(rc);
3744 goto cleanup;
3745 }
3746 if (KeyType == DIREG_DEV)
3747 {
3748 /* We're done. Just return the hKey handle */
3749 ret = hKey;
3750 goto cleanup;
3751 }
3752 /* Read the 'Driver' key */
3753 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, NULL, &dwLength);
3754 if (rc != ERROR_SUCCESS)
3755 {
3756 SetLastError(rc);
3757 goto cleanup;
3758 }
3759 if (dwRegType != REG_SZ)
3760 {
3761 SetLastError(ERROR_GEN_FAILURE);
3762 goto cleanup;
3763 }
3764 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
3765 if (!DriverKey)
3766 {
3767 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3768 goto cleanup;
3769 }
3770 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
3771 if (rc != ERROR_SUCCESS)
3772 {
3773 SetLastError(rc);
3774 goto cleanup;
3775 }
3776 RegCloseKey(hKey);
3777 hKey = INVALID_HANDLE_VALUE;
3778 /* Need to open the driver key */
3779 rc = RegOpenKeyExW(
3780 list->HKLM,
3781 ControlClass,
3782 0, /* Options */
3783 KEY_ENUMERATE_SUB_KEYS,
3784 &hRootKey);
3785 if (rc != ERROR_SUCCESS)
3786 {
3787 SetLastError(rc);
3788 goto cleanup;
3789 }
3790 rc = RegOpenKeyExW(
3791 hRootKey,
3792 DriverKey,
3793 0, /* Options */
3794 samDesired,
3795 &hKey);
3796 if (rc != ERROR_SUCCESS)
3797 {
3798 SetLastError(rc);
3799 goto cleanup;
3800 }
3801 ret = hKey;
3802 }
3803 cleanup:
3804 if (hRootKey != INVALID_HANDLE_VALUE)
3805 RegCloseKey(hRootKey);
3806 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
3807 RegCloseKey(hKey);
3808 }
3809
3810 TRACE("Returning 0x%p\n", ret);
3811 return ret;
3812 }
3813
3814 /***********************************************************************
3815 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3816 */
3817 BOOL WINAPI SetupDiCreateDeviceInfoA(
3818 HDEVINFO DeviceInfoSet,
3819 PCSTR DeviceName,
3820 CONST GUID *ClassGuid,
3821 PCSTR DeviceDescription,
3822 HWND hwndParent,
3823 DWORD CreationFlags,
3824 PSP_DEVINFO_DATA DeviceInfoData)
3825 {
3826 LPWSTR DeviceNameW = NULL;
3827 LPWSTR DeviceDescriptionW = NULL;
3828 BOOL bResult;
3829
3830 TRACE("\n");
3831
3832 if (DeviceName)
3833 {
3834 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
3835 if (DeviceNameW == NULL) return FALSE;
3836 }
3837 if (DeviceDescription)
3838 {
3839 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
3840 if (DeviceDescriptionW == NULL)
3841 {
3842 if (DeviceNameW) MyFree(DeviceNameW);
3843 return FALSE;
3844 }
3845 }
3846
3847 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
3848 ClassGuid, DeviceDescriptionW,
3849 hwndParent, CreationFlags,
3850 DeviceInfoData);
3851
3852 if (DeviceNameW) MyFree(DeviceNameW);
3853 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
3854
3855 return bResult;
3856 }
3857
3858 /***********************************************************************
3859 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3860 */
3861 BOOL WINAPI SetupDiCreateDeviceInfoW(
3862 HDEVINFO DeviceInfoSet,
3863 PCWSTR DeviceName,
3864 CONST GUID *ClassGuid,
3865 PCWSTR DeviceDescription,
3866 HWND hwndParent,
3867 DWORD CreationFlags,
3868 PSP_DEVINFO_DATA DeviceInfoData)
3869 {
3870 struct DeviceInfoSet *list;
3871 BOOL ret = FALSE;
3872
3873 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
3874 debugstr_guid(ClassGuid), DeviceDescription,
3875 hwndParent, CreationFlags, DeviceInfoData);
3876
3877 if (!DeviceInfoSet)
3878 SetLastError(ERROR_INVALID_HANDLE);
3879 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3880 SetLastError(ERROR_INVALID_HANDLE);
3881 else if (!ClassGuid)
3882 SetLastError(ERROR_INVALID_PARAMETER);
3883 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
3884 SetLastError(ERROR_CLASS_MISMATCH);
3885 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
3886 {
3887 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
3888 SetLastError(ERROR_INVALID_PARAMETER);
3889 }
3890 else
3891 {
3892 SP_DEVINFO_DATA DevInfo;
3893
3894 if (CreationFlags & DICD_GENERATE_ID)
3895 {
3896 /* Generate a new unique ID for this device */
3897 SetLastError(ERROR_GEN_FAILURE);
3898 FIXME("not implemented\n");
3899 }
3900 else
3901 {
3902 /* Device name is fully qualified. Try to open it */
3903 BOOL rc;
3904
3905 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
3906 rc = SetupDiOpenDeviceInfoW(
3907 DeviceInfoSet,
3908 DeviceName,
3909 NULL, /* hwndParent */
3910 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
3911 &DevInfo);
3912
3913 if (rc)
3914 {
3915 /* SetupDiOpenDeviceInfoW has already added
3916 * the device info to the device info set
3917 */
3918 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
3919 }
3920 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
3921 {
3922 struct DeviceInfoElement *deviceInfo;
3923
3924 /* FIXME: ClassGuid can be NULL */
3925 if (CreateDeviceInfoElement(DeviceName, ClassGuid, &deviceInfo))
3926 {
3927 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
3928
3929 if (!DeviceInfoData)
3930 ret = TRUE;
3931 else
3932 {
3933 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
3934 {
3935 SetLastError(ERROR_INVALID_USER_BUFFER);
3936 }
3937 else
3938 {
3939 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
3940 DeviceInfoData->DevInst = 0; /* FIXME */
3941 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
3942 ret = TRUE;
3943 }
3944 }
3945 }
3946 }
3947 }
3948 }
3949
3950 TRACE("Returning %d\n", ret);
3951 return ret;
3952 }
3953
3954 /***********************************************************************
3955 * Helper functions for SetupDiBuildDriverInfoList
3956 */
3957 static BOOL
3958 AddDriverToList(
3959 IN PLIST_ENTRY DriverListHead,
3960 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3961 IN LPGUID ClassGuid,
3962 IN INFCONTEXT ContextDevice,
3963 IN struct InfFileDetails *InfFileDetails,
3964 IN LPCWSTR InfFile,
3965 IN LPCWSTR ProviderName,
3966 IN LPCWSTR ManufacturerName,
3967 IN LPCWSTR MatchingId,
3968 FILETIME DriverDate,
3969 DWORDLONG DriverVersion,
3970 IN DWORD Rank)
3971 {
3972 struct DriverInfoElement *driverInfo = NULL;
3973 HANDLE hFile = INVALID_HANDLE_VALUE;
3974 DWORD RequiredSize = 128; /* Initial buffer size */
3975 BOOL Result = FALSE;
3976 PLIST_ENTRY PreviousEntry;
3977 LPWSTR InfInstallSection = NULL;
3978 BOOL ret = FALSE;
3979
3980 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
3981 if (!driverInfo)
3982 {
3983 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3984 goto cleanup;
3985 }
3986 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
3987
3988 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
3989 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
3990
3991 /* Copy InfFileName field */
3992 wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
3993 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
3994
3995 /* Fill InfDate field */
3996 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3997 GENERIC_READ, FILE_SHARE_READ,
3998 NULL, OPEN_EXISTING, 0, NULL);
3999 if (hFile == INVALID_HANDLE_VALUE)
4000 goto cleanup;
4001 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4002 if (!Result)
4003 goto cleanup;*/
4004
4005 /* Fill SectionName field */
4006 Result = SetupGetStringFieldW(
4007 &ContextDevice,
4008 1,
4009 driverInfo->Details.SectionName, LINE_LEN,
4010 NULL);
4011 if (!Result)
4012 goto cleanup;
4013
4014 /* Fill DrvDescription field */
4015 Result = SetupGetStringFieldW(
4016 &ContextDevice,
4017 0, /* Field index */
4018 driverInfo->Details.DrvDescription, LINE_LEN,
4019 NULL);
4020
4021 /* Copy MatchingId information */
4022 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4023 if (!driverInfo->MatchingId)
4024 {
4025 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4026 goto cleanup;
4027 }
4028 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4029
4030 /* Get inf install section */
4031 Result = FALSE;
4032 RequiredSize = 128; /* Initial buffer size */
4033 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4034 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4035 {
4036 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4037 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4038 if (!InfInstallSection)
4039 goto cleanup;
4040 Result = SetupGetStringFieldW(
4041 &ContextDevice,
4042 1, /* Field index */
4043 InfInstallSection, RequiredSize,
4044 &RequiredSize);
4045 }
4046 if (!Result)
4047 goto cleanup;
4048
4049 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4050 driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
4051
4052 driverInfo->DriverRank = Rank;
4053 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
4054 driverInfo->Info.DriverType = DriverType;
4055 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
4056 wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
4057 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
4058 wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
4059 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
4060 if (ProviderName)
4061 {
4062 wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
4063 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
4064 }
4065 else
4066 driverInfo->Info.ProviderName[0] = '\0';
4067 driverInfo->Info.DriverDate = DriverDate;
4068 driverInfo->Info.DriverVersion = DriverVersion;
4069 ReferenceInfFile(InfFileDetails);
4070 driverInfo->InfFileDetails = InfFileDetails;
4071
4072 /* Insert current driver in driver list, according to its rank */
4073 PreviousEntry = DriverListHead->Flink;
4074 while (PreviousEntry != DriverListHead)
4075 {
4076 if (((struct DriverInfoElement *)PreviousEntry)->DriverRank >= Rank)
4077 {
4078 /* Insert before the current item */
4079 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
4080 break;
4081 }
4082 PreviousEntry = PreviousEntry->Flink;
4083 }
4084 if (PreviousEntry == DriverListHead)
4085 {
4086 /* Insert at the end of the list */
4087 InsertTailList(DriverListHead, &driverInfo->ListEntry);
4088 }
4089
4090 ret = TRUE;
4091
4092 cleanup:
4093 if (!ret)
4094 {
4095 if (driverInfo)
4096 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
4097 HeapFree(GetProcessHeap(), 0, driverInfo);
4098 }
4099 if (hFile != INVALID_HANDLE_VALUE)
4100 CloseHandle(hFile);
4101 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4102
4103 return ret;
4104 }
4105
4106 static BOOL
4107 GetVersionInformationFromInfFile(
4108 IN HINF hInf,
4109 OUT LPGUID ClassGuid,
4110 OUT LPWSTR* pProviderName,
4111 OUT FILETIME* DriverDate,
4112 OUT DWORDLONG* DriverVersion)
4113 {
4114 DWORD RequiredSize;
4115 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
4116 LPWSTR DriverVer = NULL;
4117 LPWSTR ProviderName = NULL;
4118 LPWSTR pComma; /* Points into DriverVer */
4119 LPWSTR pVersion = NULL; /* Points into DriverVer */
4120 SYSTEMTIME SystemTime;
4121 BOOL Result;
4122 BOOL ret = FALSE; /* Final result */
4123
4124 /* Get class Guid */
4125 if (!SetupGetLineTextW(
4126 NULL, /* Context */
4127 hInf,
4128 L"Version", L"ClassGUID",
4129 guidW, sizeof(guidW),
4130 NULL /* Required size */))
4131 {
4132 goto cleanup;
4133 }
4134 guidW[37] = '\0'; /* Replace the } by a NULL character */
4135 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
4136 {
4137 SetLastError(ERROR_GEN_FAILURE);
4138 goto cleanup;
4139 }
4140
4141 /* Get provider name */
4142 Result = SetupGetLineTextW(
4143 NULL, /* Context */
4144 hInf, L"Version", L"Provider",
4145 NULL, 0,
4146 &RequiredSize);
4147 if (Result)
4148 {
4149 /* We know know the needed buffer size */
4150 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4151 if (!ProviderName)
4152 {
4153 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4154 goto cleanup;
4155 }
4156 Result = SetupGetLineTextW(
4157 NULL, /* Context */
4158 hInf, L"Version", L"Provider",
4159 ProviderName, RequiredSize,
4160 &RequiredSize);
4161 }
4162 if (!Result)
4163 goto cleanup;
4164 *pProviderName = ProviderName;
4165
4166 /* Read the "DriverVer" value */
4167 Result = SetupGetLineTextW(
4168 NULL, /* Context */
4169 hInf, L"Version", L"DriverVer",
4170 NULL, 0,
4171 &RequiredSize);
4172 if (Result)
4173 {
4174 /* We know know the needed buffer size */
4175 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4176 if (!DriverVer)
4177 {
4178 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4179 goto cleanup;
4180 }
4181 Result = SetupGetLineTextW(
4182 NULL, /* Context */
4183 hInf, L"Version", L"DriverVer",
4184 DriverVer, RequiredSize,
4185 &RequiredSize);
4186 }
4187 if (!Result)
4188 goto cleanup;
4189
4190 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4191 pComma = wcschr(DriverVer, ',');
4192 if (pComma != NULL)
4193 {
4194 *pComma = UNICODE_NULL;
4195 pVersion = pComma + 1;
4196 }
4197 /* Get driver date version. Invalid date = 00/00/00 */
4198 memset(DriverDate, 0, sizeof(FILETIME));
4199 if (wcslen(DriverVer) == 10
4200 && (DriverVer[2] == '-' || DriverVer[2] == '/')
4201 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
4202 {
4203 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
4204 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
4205 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
4206 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
4207 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
4208 SystemTimeToFileTime(&SystemTime, DriverDate);
4209 }
4210 /* Get driver version. Invalid version = 0.0.0.0 */
4211 *DriverVersion = 0;
4212 /* FIXME: use pVersion to fill DriverVersion variable */
4213
4214 ret = TRUE;
4215
4216 cleanup:
4217 if (!ret)
4218 HeapFree(GetProcessHeap(), 0, ProviderName);
4219 HeapFree(GetProcessHeap(), 0, DriverVer);
4220
4221 TRACE("Returning %d\n", ret);
4222 return ret;
4223 }
4224
4225 /***********************************************************************
4226 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4227 */
4228 BOOL WINAPI
4229 SetupDiBuildDriverInfoList(
4230 IN HDEVINFO DeviceInfoSet,
4231 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4232 IN DWORD DriverType)
4233 {
4234 struct DeviceInfoSet *list;
4235 SP_DEVINSTALL_PARAMS_W InstallParams;
4236 PVOID Buffer = NULL;
4237 struct InfFileDetails *currentInfFileDetails = NULL;
4238 LPWSTR ProviderName = NULL;
4239 LPWSTR ManufacturerName = NULL;
4240 WCHAR ManufacturerSection[LINE_LEN + 1];
4241 LPWSTR HardwareIDs = NULL;
4242 LPWSTR CompatibleIDs = NULL;
4243 LPWSTR FullInfFileName = NULL;
4244 FILETIME DriverDate;
4245 DWORDLONG DriverVersion = 0;
4246 DWORD RequiredSize;
4247 BOOL ret = FALSE;
4248
4249 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
4250
4251 if (!DeviceInfoSet)
4252 SetLastError(ERROR_INVALID_HANDLE);
4253 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4254 SetLastError(ERROR_INVALID_HANDLE);
4255 else if (list->HKLM != HKEY_LOCAL_MACHINE)
4256 SetLastError(ERROR_INVALID_HANDLE);
4257 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4258 SetLastError(ERROR_INVALID_PARAMETER);
4259 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
4260 SetLastError(ERROR_INVALID_PARAMETER);
4261 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4262 SetLastError(ERROR_INVALID_PARAMETER);
4263 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4264 SetLastError(ERROR_INVALID_USER_BUFFER);
4265 else
4266 {
4267 BOOL Result;
4268
4269 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
4270 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4271 if (!Result)
4272 goto done;
4273
4274 if (DriverType == SPDIT_COMPATDRIVER)
4275 {
4276 /* Get hardware IDs list */
4277 Result = FALSE;
4278 RequiredSize = 512; /* Initial buffer size */
4279 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4280 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4281 {
4282 HeapFree(GetProcessHeap(), 0, HardwareIDs);
4283 HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
4284 if (!HardwareIDs)
4285 {
4286 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4287 goto done;
4288 }
4289 Result = SetupDiGetDeviceRegistryPropertyW(
4290 DeviceInfoSet,
4291 DeviceInfoData,
4292 SPDRP_HARDWAREID,
4293 NULL,
4294 (PBYTE)HardwareIDs,
4295 RequiredSize,
4296 &RequiredSize);
4297 }
4298 if (!Result)
4299 goto done;
4300
4301 /* Get compatible IDs list */
4302 Result = FALSE;
4303 RequiredSize = 512; /* Initial buffer size */
4304 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4305 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4306 {
4307 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4308 CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
4309 if (!CompatibleIDs)
4310 {
4311 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4312 goto done;
4313 }
4314 Result = SetupDiGetDeviceRegistryPropertyW(
4315 DeviceInfoSet,
4316 DeviceInfoData,
4317 SPDRP_COMPATIBLEIDS,
4318 NULL,
4319 (PBYTE)CompatibleIDs,
4320 RequiredSize,
4321 &RequiredSize);
4322 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
4323 {
4324 /* No compatible ID for this device */
4325 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4326 CompatibleIDs = NULL;
4327 Result = TRUE;
4328 }
4329 }
4330 if (!Result)
4331 goto done;
4332 }
4333
4334 /* Enumerate .inf files */
4335 Result = FALSE;
4336 RequiredSize = 32768; /* Initial buffer size */
4337 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4338 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4339 {
4340 HeapFree(GetProcessHeap(), 0, Buffer);
4341 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4342 if (!Buffer)
4343 {
4344 Result = FALSE;
4345 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4346 break;
4347 }
4348 Result = SetupGetInfFileListW(
4349 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
4350 INF_STYLE_WIN4,
4351 Buffer, RequiredSize,
4352 &RequiredSize);
4353 }
4354 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
4355 {
4356 /* No .inf file in specified directory. So, we should
4357 * success as we created an empty driver info list.
4358 */
4359 ret = TRUE;
4360 goto done;
4361 }
4362 if (Result)
4363 {
4364 LPCWSTR filename;
4365 LPWSTR pFullFilename;
4366
4367 if (*InstallParams.DriverPath)
4368 {
4369 DWORD len;
4370 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
4371 if (len == 0)
4372 goto done;
4373 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
4374 if (!FullInfFileName)
4375 goto done;
4376 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
4377 if (len == 0)
4378 goto done;
4379 if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
4380 wcscat(FullInfFileName, L"\\");
4381 pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
4382 }
4383 else
4384 {
4385 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4386 if (!FullInfFileName)
4387 goto done;
4388 pFullFilename = &FullInfFileName[0];
4389 }
4390
4391 for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
4392 {
4393 INFCONTEXT ContextManufacturer, ContextDevice;
4394 GUID ClassGuid;
4395
4396 wcscpy(pFullFilename, filename);
4397 TRACE("Opening file %S\n", FullInfFileName);
4398
4399 currentInfFileDetails = HeapAlloc(GetProcessHeap(), 0, sizeof(struct InfFileDetails));
4400 if (!currentInfFileDetails)
4401 continue;
4402 memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
4403
4404 currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
4405 ReferenceInfFile(currentInfFileDetails);
4406 if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
4407 {
4408 HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
4409 currentInfFileDetails = NULL;
4410 continue;
4411 }
4412
4413 if (!GetVersionInformationFromInfFile(
4414 currentInfFileDetails->hInf,
4415 &ClassGuid,
4416 &ProviderName,
4417 &DriverDate,
4418 &DriverVersion))
4419 {
4420 SetupCloseInfFile(currentInfFileDetails->hInf);
4421 HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
4422 currentInfFileDetails = NULL;
4423 continue;
4424 }
4425
4426 if (DriverType == SPDIT_CLASSDRIVER)
4427 {
4428 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4429 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
4430 {
4431 goto next;
4432 }
4433 }
4434
4435 /* Get the manufacturers list */
4436 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
4437 while (Result)
4438 {
4439 Result = SetupGetStringFieldW(
4440 &ContextManufacturer,
4441 0, /* Field index */
4442 NULL, 0,
4443 &RequiredSize);
4444 if (Result)
4445 {
4446 /* We got the needed size for the buffer */
4447 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4448 if (!ManufacturerName)
4449 {
4450 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4451 goto done;
4452 }
4453 Result = SetupGetStringFieldW(
4454 &ContextManufacturer,
4455 0, /* Field index */
4456 ManufacturerName, RequiredSize,
4457 &RequiredSize);
4458 }
4459 /* Get manufacturer section name */
4460 Result = SetupGetStringFieldW(
4461 &ContextManufacturer,
4462 1, /* Field index */
4463 ManufacturerSection, LINE_LEN,
4464 &RequiredSize);
4465 if (Result)
4466 {
4467 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
4468 /* Add (possible) extension to manufacturer section name */
4469 Result = SetupDiGetActualSectionToInstallW(
4470 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
4471 if (Result)
4472 {
4473 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
4474 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
4475 }
4476 }
4477 while (Result)
4478 {
4479 if (DriverType == SPDIT_CLASSDRIVER)
4480 {
4481 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4482 if (!AddDriverToList(
4483 &list->DriverListHead,
4484 DriverType,
4485 &ClassGuid,
4486 ContextDevice,
4487 currentInfFileDetails,
4488 filename,
4489 ProviderName,
4490 ManufacturerName,
4491 NULL,
4492 DriverDate, DriverVersion,
4493 0))
4494 {
4495 break;
4496 }
4497 }
4498 else /* DriverType = SPDIT_COMPATDRIVER */
4499 {
4500 /* 1. Get all fields */
4501 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
4502 DWORD DriverRank;
4503 DWORD i;
4504 LPCWSTR currentId;
4505 BOOL DriverAlreadyAdded;
4506
4507 for (i = 2; i <= FieldCount; i++)
4508 {
4509 LPWSTR DeviceId = NULL;
4510 Result = FALSE;
4511 RequiredSize = 128; /* Initial buffer size */
4512 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4513 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4514 {
4515 HeapFree(GetProcessHeap(), 0, DeviceId);
4516 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4517 if (!DeviceId)
4518 {
4519 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4520 goto done;
4521 }
4522 Result = SetupGetStringFieldW(
4523 &ContextDevice,
4524 i,
4525 DeviceId, RequiredSize,
4526 &RequiredSize);
4527 }
4528 if (!Result)
4529 {
4530 HeapFree(GetProcessHeap(), 0, DeviceId);
4531 goto done;
4532 }
4533 DriverAlreadyAdded = FALSE;
4534 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
4535 {
4536 if (wcscmp(DeviceId, currentId) == 0)
4537 {
4538 AddDriverToList(
4539 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
4540 DriverType,
4541 &ClassGuid,
4542 ContextDevice,
4543 currentInfFileDetails,
4544 filename,
4545 ProviderName,
4546 ManufacturerName,
4547 currentId,
4548 DriverDate, DriverVersion,
4549 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
4550 DriverAlreadyAdded = TRUE;
4551 }
4552 }
4553 if (CompatibleIDs)
4554 {
4555 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
4556 {
4557 if (wcscmp(DeviceId, currentId) == 0)
4558 {
4559 AddDriverToList(
4560 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
4561 DriverType,
4562 &ClassGuid,
4563 ContextDevice,
4564 currentInfFileDetails,
4565 filename,
4566 ProviderName,
4567 ManufacturerName,
4568 currentId,
4569 DriverDate, DriverVersion,
4570 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
4571 DriverAlreadyAdded = TRUE;
4572 }
4573 }
4574 }
4575 HeapFree(GetProcessHeap(), 0, DeviceId);
4576 }
4577 }
4578 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
4579 }
4580
4581 HeapFree(GetProcessHeap(), 0, ManufacturerName);
4582 ManufacturerName = NULL;
4583 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
4584 }
4585
4586 ret = TRUE;
4587 next:
4588 HeapFree(GetProcessHeap(), 0, ProviderName);
4589 ProviderName = NULL;
4590
4591 DereferenceInfFile(currentInfFileDetails);
4592 currentInfFileDetails = NULL;
4593 }
4594 ret = TRUE;
4595 }
4596 }
4597
4598 done:
4599 if (ret)
4600 {
4601 if (DeviceInfoData)
4602 {
4603 InstallParams.Flags |= DI_DIDCOMPAT;
4604 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
4605 }
4606 else
4607 {
4608 InstallParams.Flags |= DI_DIDCLASS;
4609 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
4610 }
4611 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4612 }
4613
4614 HeapFree(GetProcessHeap(), 0, ProviderName);
4615 HeapFree(GetProcessHeap(), 0, ManufacturerName);
4616 HeapFree(GetProcessHeap(), 0, HardwareIDs);
4617 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4618 HeapFree(GetProcessHeap(), 0, FullInfFileName);
4619 if (currentInfFileDetails)
4620 DereferenceInfFile(currentInfFileDetails);
4621 HeapFree(GetProcessHeap(), 0, Buffer);
4622
4623 TRACE("Returning %d\n", ret);
4624 return ret;
4625 }
4626
4627 /***********************************************************************
4628 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4629 */
4630 BOOL WINAPI
4631 SetupDiDeleteDeviceInfo(
4632 IN HDEVINFO DeviceInfoSet,
4633 IN PSP_DEVINFO_DATA DeviceInfoData)
4634 {
4635 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4636
4637 FIXME("not implemented\n");
4638 SetLastError(ERROR_GEN_FAILURE);
4639 return FALSE;
4640 }
4641
4642
4643 /***********************************************************************
4644 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4645 */
4646 BOOL WINAPI
4647 SetupDiDestroyDriverInfoList(
4648 IN HDEVINFO DeviceInfoSet,
4649 IN PSP_DEVINFO_DATA DeviceInfoData,
4650 IN DWORD DriverType)
4651 {
4652 struct DeviceInfoSet *list;
4653 BOOL ret = FALSE;
4654
4655 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
4656
4657 if (!DeviceInfoSet)
4658 SetLastError(ERROR_INVALID_HANDLE);
4659 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4660 SetLastError(ERROR_INVALID_HANDLE);
4661 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4662 SetLastError(ERROR_INVALID_PARAMETER);
4663 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4664 SetLastError(ERROR_INVALID_PARAMETER);
4665 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4666 SetLastError(ERROR_INVALID_USER_BUFFER);
4667 else
4668 {
4669 PLIST_ENTRY ListEntry;
4670 struct DriverInfoElement *driverInfo;
4671 SP_DEVINSTALL_PARAMS_W InstallParams;
4672
4673 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4674 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
4675 goto done;
4676
4677 if (!DeviceInfoData)
4678 /* Fall back to destroying class driver list */
4679 DriverType = SPDIT_CLASSDRIVER;
4680
4681 if (DriverType == SPDIT_CLASSDRIVER)
4682 {
4683 while (!IsListEmpty(&list->DriverListHead))
4684 {
4685 ListEntry = RemoveHeadList(&list->DriverListHead);
4686 driverInfo = (struct DriverInfoElement *)ListEntry;
4687 DestroyDriverInfoElement(driverInfo);
4688 }
4689 InstallParams.Reserved = 0;
4690 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
4691 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
4692 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
4693 }
4694 else
4695 {
4696 SP_DEVINSTALL_PARAMS_W InstallParamsSet;
4697 struct DeviceInfoElement *deviceInfo;
4698
4699 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4700 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
4701 goto done;
4702 deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4703 while (!IsListEmpty(&deviceInfo->DriverListHead))
4704 {
4705 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
4706 driverInfo = (struct DriverInfoElement *)ListEntry;
4707 if ((PVOID)InstallParamsSet.Reserved == driverInfo)
4708 {
4709 InstallParamsSet.Reserved = 0;
4710 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
4711 }
4712 DestroyDriverInfoElement(driverInfo);
4713 }
4714 InstallParams.Reserved = 0;
4715 InstallParams.Flags &= ~DI_DIDCOMPAT;
4716 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
4717 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4718 }
4719 }
4720
4721 done:
4722 TRACE("Returning %d\n", ret);
4723 return ret;
4724 }
4725
4726
4727 /***********************************************************************
4728 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4729 */
4730 BOOL WINAPI
4731 SetupDiOpenDeviceInfoA(
4732 IN HDEVINFO DeviceInfoSet,
4733 IN PCSTR DeviceInstanceId,
4734 IN HWND hwndParent OPTIONAL,
4735 IN DWORD OpenFlags,
4736 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4737 {
4738 LPWSTR DeviceInstanceIdW = NULL;
4739 BOOL bResult;
4740
4741 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4742
4743 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
4744 if (DeviceInstanceIdW == NULL)
4745 return FALSE;
4746
4747 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
4748 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
4749
4750 MyFree(DeviceInstanceIdW);
4751
4752 return bResult;
4753 }
4754
4755
4756 /***********************************************************************
4757 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4758 */
4759 BOOL WINAPI
4760 SetupDiOpenDeviceInfoW(
4761 IN HDEVINFO DeviceInfoSet,
4762 IN PCWSTR DeviceInstanceId,
4763 IN HWND hwndParent OPTIONAL,
4764 IN DWORD OpenFlags,
4765 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4766 {
4767 struct DeviceInfoSet *list;
4768 HKEY hEnumKey, hKey;
4769 DWORD rc;
4770 BOOL ret = FALSE;
4771
4772 TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4773
4774 if (OpenFlags & DIOD_CANCEL_REMOVE)
4775 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4776
4777 if (!DeviceInfoSet)
4778 SetLastError(ERROR_INVALID_HANDLE);
4779 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4780 SetLastError(ERROR_INVALID_HANDLE);
4781 else if (!DeviceInstanceId)
4782 SetLastError(ERROR_INVALID_PARAMETER);
4783 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
4784 {
4785 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
4786 SetLastError(ERROR_INVALID_PARAMETER);
4787 }
4788 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4789 SetLastError(ERROR_INVALID_USER_BUFFER);
4790 else
4791 {
4792 struct DeviceInfoElement *deviceInfo = NULL;
4793 /* Search if device already exists in DeviceInfoSet.
4794 * If yes, return the existing element
4795 * If no, create a new element using informations in registry
4796 */
4797 PLIST_ENTRY ItemList = list->ListHead.Flink;
4798 while (ItemList != &list->ListHead)
4799 {
4800 // TODO
4801 //if (good one)
4802 // break;
4803 FIXME("not implemented\n");
4804 ItemList = ItemList->Flink;
4805 }
4806
4807 if (deviceInfo)
4808 {
4809 /* good one found */
4810 ret = TRUE;
4811 }
4812 else
4813 {
4814 /* Open supposed registry key */
4815 rc = RegOpenKeyExW(
4816 list->HKLM,
4817 EnumKeyName,
4818 0, /* Options */
4819 KEY_ENUMERATE_SUB_KEYS,
4820 &hEnumKey);
4821 if (rc != ERROR_SUCCESS)
4822 {
4823 SetLastError(rc);
4824 return FALSE;
4825 }
4826 rc = RegOpenKeyExW(
4827 hEnumKey,
4828 DeviceInstanceId,
4829 0, /* Options */
4830 KEY_QUERY_VALUE,
4831 &hKey);
4832 RegCloseKey(hEnumKey);
4833 if (rc != ERROR_SUCCESS)
4834 {
4835 SetLastError(rc);
4836 return FALSE;
4837 }
4838
4839 /* FIXME: GUID_NULL is not allowed */
4840 if (!CreateDeviceInfoElement(DeviceInstanceId, &GUID_NULL /* FIXME */, &deviceInfo))
4841 {
4842 RegCloseKey(hKey);
4843 return FALSE;
4844 }
4845 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4846
4847 RegCloseKey(hKey);
4848 ret = TRUE;
4849 }
4850
4851 if (ret && deviceInfo && DeviceInfoData)
4852 {
4853 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
4854 DeviceInfoData->DevInst = 0; /* FIXME */
4855 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4856 }
4857 }
4858
4859 return ret;
4860 }
4861
4862
4863 /***********************************************************************
4864 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4865 */
4866 BOOL WINAPI
4867 SetupDiEnumDriverInfoA(
4868 IN HDEVINFO DeviceInfoSet,
4869 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4870 IN DWORD DriverType,
4871 IN DWORD MemberIndex,
4872 OUT PSP_DRVINFO_DATA_A DriverInfoData)
4873 {
4874 SP_DRVINFO_DATA_V2_W driverInfoData2W;
4875 BOOL ret = FALSE;
4876
4877 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
4878 DriverType, MemberIndex, DriverInfoData);
4879
4880 if (DriverInfoData == NULL)
4881 SetLastError(ERROR_INVALID_PARAMETER);
4882 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
4883 SetLastError(ERROR_INVALID_USER_BUFFER);
4884 else
4885 {
4886 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
4887 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
4888 DriverType, MemberIndex, &driverInfoData2W);
4889
4890 if (ret)
4891 {
4892 /* Do W->A conversion */
4893 DriverInfoData->DriverType = driverInfoData2W.DriverType;
4894 DriverInfoData->Reserved = driverInfoData2W.Reserved;
4895 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
4896 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
4897 {
4898 DriverInfoData->Description[0] = '\0';
4899 ret = FALSE;
4900 }
4901 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
4902 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
4903 {
4904 DriverInfoData->MfgName[0] = '\0';
4905 ret = FALSE;
4906 }
4907 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
4908 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
4909 {
4910 DriverInfoData->ProviderName[0] = '\0';
4911 ret = FALSE;
4912 }
4913 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
4914 {
4915 /* Copy more fields */
4916 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
4917 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
4918 }
4919 }
4920 }
4921
4922 TRACE("Returning %d\n", ret);
4923 return ret;
4924 }
4925
4926
4927 /***********************************************************************
4928 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4929 */
4930 BOOL WINAPI
4931 SetupDiEnumDriverInfoW(
4932 IN HDEVINFO DeviceInfoSet,
4933 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4934 IN DWORD DriverType,
4935 IN DWORD MemberIndex,
4936 OUT PSP_DRVINFO_DATA_W DriverInfoData)
4937 {
4938 PLIST_ENTRY ListHead;
4939 BOOL ret = FALSE;
4940
4941 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
4942 DriverType, MemberIndex, DriverInfoData);
4943
4944 if (!DeviceInfoSet || !DriverInfoData)
4945 SetLastError(ERROR_INVALID_PARAMETER);
4946 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4947 SetLastError(ERROR_INVALID_HANDLE);
4948 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4949 SetLastError(ERROR_INVALID_HANDLE);
4950 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4951 SetLastError(ERROR_INVALID_PARAMETER);
4952 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
4953 SetLastError(ERROR_INVALID_PARAMETER);
4954 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4955 SetLastError(ERROR_INVALID_PARAMETER);
4956 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
4957 SetLastError(ERROR_INVALID_USER_BUFFER);
4958 else
4959 {
4960 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4961 PLIST_ENTRY ItemList;
4962 if (DriverType == SPDIT_CLASSDRIVER ||
4963 devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
4964 {
4965 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
4966 }
4967 else
4968 {
4969 ListHead = &devInfo->DriverListHead;
4970 }
4971
4972 ItemList = ListHead->Flink;
4973 while (ItemList != ListHead && MemberIndex-- > 0)
4974 ItemList = ItemList->Flink;
4975 if (ItemList == ListHead)
4976 SetLastError(ERROR_NO_MORE_ITEMS);
4977 else
4978 {
4979 struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
4980
4981 memcpy(
4982 &DriverInfoData->DriverType,
4983 &DrvInfo->Info.DriverType,
4984 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
4985 ret = TRUE;
4986 }
4987 }
4988
4989 TRACE("Returning %d\n", ret);
4990 return ret;
4991 }
4992
4993
4994 /***********************************************************************
4995 * SetupDiGetSelectedDriverA (SETUPAPI.@)
4996 */
4997 BOOL WINAPI
4998 SetupDiGetSelectedDriverA(
4999 IN HDEVINFO DeviceInfoSet,
5000 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5001 OUT PSP_DRVINFO_DATA_A DriverInfoData)
5002 {
5003 SP_DRVINFO_DATA_V2_W driverInfoData2W;
5004 BOOL ret = FALSE;
5005
5006 if (DriverInfoData == NULL)
5007 SetLastError(ERROR_INVALID_PARAMETER);
5008 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
5009 SetLastError(ERROR_INVALID_USER_BUFFER);
5010 else
5011 {
5012 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5013
5014 ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
5015 DeviceInfoData,
5016 &driverInfoData2W);
5017
5018 if (ret)
5019 {
5020 /* Do W->A conversion */
5021 DriverInfoData->DriverType = driverInfoData2W.DriverType;
5022 DriverInfoData->Reserved = driverInfoData2W.Reserved;
5023 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
5024 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
5025 {
5026 DriverInfoData->Description[0] = '\0';
5027 ret = FALSE;
5028 }
5029 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
5030 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
5031 {
5032 DriverInfoData->MfgName[0] = '\0';
5033 ret = FALSE;
5034 }
5035 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
5036 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
5037 {
5038 DriverInfoData->ProviderName[0] = '\0';
5039 ret = FALSE;
5040 }
5041 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5042 {
5043 /* Copy more fields */
5044 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
5045 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
5046 }
5047 }
5048 }
5049
5050 return ret;
5051 }
5052
5053
5054 /***********************************************************************
5055 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5056 */
5057 BOOL WINAPI
5058 SetupDiGetSelectedDriverW(
5059 IN HDEVINFO DeviceInfoSet,
5060 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5061 OUT PSP_DRVINFO_DATA_W DriverInfoData)
5062 {
5063 BOOL ret = FALSE;
5064
5065 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5066
5067 if (!DeviceInfoSet || !DriverInfoData)
5068 SetLastError(ERROR_INVALID_PARAMETER);
5069 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5070 SetLastError(ERROR_INVALID_HANDLE);
5071 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5072 SetLastError(ERROR_INVALID_HANDLE);
5073 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5074 SetLastError(ERROR_INVALID_USER_BUFFER);
5075 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5076 SetLastError(ERROR_INVALID_USER_BUFFER);
5077 else
5078 {
5079 SP_DEVINSTALL_PARAMS InstallParams;
5080
5081 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
5082 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
5083 {
5084 struct DriverInfoElement *driverInfo;
5085 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
5086 if (driverInfo == NULL)
5087 SetLastError(ERROR_NO_DRIVER_SELECTED);
5088 else
5089 {
5090 memcpy(
5091 &DriverInfoData->DriverType,
5092 &driverInfo->Info.DriverType,
5093 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
5094 ret = TRUE;
5095 }
5096 }
5097 }
5098
5099 TRACE("Returning %d\n", ret);
5100 return ret;
5101 }
5102
5103
5104 /***********************************************************************
5105 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5106 */
5107 BOOL WINAPI
5108 SetupDiSetSelectedDriverA(
5109 IN HDEVINFO DeviceInfoSet,
5110 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5111 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
5112 {
5113 SP_DRVINFO_DATA_V1_W DriverInfoDataW;
5114 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
5115 BOOL ret = FALSE;
5116
5117 if (DriverInfoData != NULL)
5118 {
5119 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
5120 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
5121 {
5122 SetLastError(ERROR_INVALID_PARAMETER);
5123 return FALSE;
5124 }
5125
5126 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5127 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5128
5129 if (DriverInfoDataW.Reserved == 0)
5130 {
5131 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5132
5133 /* convert the strings to unicode */
5134 if (!MultiByteToWideChar(CP_ACP,
5135 0,
5136 DriverInfoData->Description,
5137 LINE_LEN,
5138 DriverInfoDataW.Description,
5139 LINE_LEN) ||
5140 !MultiByteToWideChar(CP_ACP,
5141 0,
5142 DriverInfoData->ProviderName,
5143 LINE_LEN,
5144 DriverInfoDataW.ProviderName,
5145 LINE_LEN))
5146 {
5147 return FALSE;
5148 }
5149 }
5150
5151 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
5152 }
5153
5154 ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
5155 DeviceInfoData,
5156 pDriverInfoDataW);
5157
5158 if (ret && pDriverInfoDataW != NULL)
5159 {
5160 DriverInfoData->Reserved = DriverInfoDataW.Reserved;
5161 }
5162
5163 return ret;
5164 }
5165
5166
5167 /***********************************************************************
5168 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5169 */
5170 BOOL WINAPI
5171 SetupDiSetSelectedDriverW(
5172 IN HDEVINFO DeviceInfoSet,
5173 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5174 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
5175 {
5176 BOOL ret = FALSE;
5177
5178 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5179
5180 if (!DeviceInfoSet)
5181 SetLastError(ERROR_INVALID_PARAMETER);
5182 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5183 SetLastError(ERROR_INVALID_HANDLE);
5184 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5185 SetLastError(ERROR_INVALID_HANDLE);
5186 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5187 SetLastError(ERROR_INVALID_USER_BUFFER);
5188 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5189 SetLastError(ERROR_INVALID_USER_BUFFER);
5190 else
5191 {
5192 struct DriverInfoElement **pDriverInfo;
5193 PLIST_ENTRY ListHead, ItemList;
5194
5195 if (DeviceInfoData)
5196 {
5197 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
5198 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
5199 }
5200 else
5201 {
5202 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
5203 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
5204 }
5205
5206 if (!DriverInfoData)
5207 {
5208 *pDriverInfo = NULL;
5209 ret = TRUE;
5210 }
5211 else
5212 {
5213 /* Search selected driver in list */
5214 ItemList = ListHead->Flink;
5215 while (ItemList != ListHead)
5216 {
5217 if (DriverInfoData->Reserved != 0)
5218 {
5219 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
5220 break;
5221 }
5222 else
5223 {
5224 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5225 struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
5226 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
5227 && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
5228 && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
5229 {
5230 break;
5231 }
5232 }
5233 }
5234 if (ItemList == ListHead)
5235 SetLastError(ERROR_INVALID_PARAMETER);
5236 else
5237 {
5238 *pDriverInfo = (struct DriverInfoElement *)ItemList;
5239 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
5240 ret = TRUE;
5241 TRACE("Choosing driver whose rank is 0x%lx\n",
5242 ((struct DriverInfoElement *)ItemList)->DriverRank);
5243 if (DeviceInfoData)
5244 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
5245 }
5246 }
5247 }
5248
5249 TRACE("Returning %d\n", ret);
5250 return ret;
5251 }
5252
5253 /***********************************************************************
5254 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5255 */
5256 BOOL WINAPI
5257 SetupDiGetDriverInfoDetailA(
5258 IN HDEVINFO DeviceInfoSet,
5259 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5260 IN PSP_DRVINFO_DATA_A DriverInfoData,
5261 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
5262 IN DWORD DriverInfoDetailDataSize,
5263 OUT PDWORD RequiredSize OPTIONAL)
5264 {
5265 SP_DRVINFO_DATA_V2_W DriverInfoDataW;
5266 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
5267 DWORD BufSize = 0;
5268 DWORD HardwareIDLen = 0;
5269 BOOL ret = FALSE;
5270
5271 /* do some sanity checks, the unicode version might do more thorough checks */
5272 if (DriverInfoData == NULL ||
5273 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
5274 (DriverInfoDetailData != NULL &&
5275 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
5276 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
5277 {
5278 SetLastError(ERROR_INVALID_PARAMETER);
5279 goto Cleanup;
5280 }
5281
5282 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5283 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
5284 {
5285 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5286 }
5287 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5288 {
5289 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5290 }
5291 else
5292 {
5293 SetLastError(ERROR_INVALID_PARAMETER);
5294 goto Cleanup;
5295 }
5296 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5297 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5298
5299 /* convert the strings to unicode */
5300 if (MultiByteToWideChar(CP_ACP,
5301 0,
5302 DriverInfoData->Description,
5303 LINE_LEN,
5304 DriverInfoDataW.Description,
5305 LINE_LEN) &&
5306 MultiByteToWideChar(CP_ACP,
5307 0,
5308 DriverInfoData->MfgName,
5309 LINE_LEN,
5310 DriverInfoDataW.MfgName,
5311 LINE_LEN) &&
5312 MultiByteToWideChar(CP_ACP,
5313 0,
5314 DriverInfoData->ProviderName,
5315 LINE_LEN,
5316 DriverInfoDataW.ProviderName,
5317 LINE_LEN))
5318 {
5319 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
5320 {
5321 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
5322 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
5323 }
5324
5325 if (DriverInfoDetailData != NULL)
5326 {
5327 /* calculate the unicode buffer size from the ansi buffer size */
5328 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
5329 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
5330 (HardwareIDLen * sizeof(WCHAR));
5331
5332 DriverInfoDetailDataW = MyMalloc(BufSize);
5333 if (DriverInfoDetailDataW == NULL)
5334 {
5335 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5336 goto Cleanup;
5337 }
5338
5339 /* initialize the buffer */
5340 ZeroMemory(DriverInfoDetailDataW,
5341 BufSize);
5342 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
5343 }
5344
5345 /* call the unicode version */
5346 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
5347 DeviceInfoData,
5348 &DriverInfoDataW,
5349 DriverInfoDetailDataW,
5350 BufSize,
5351 RequiredSize);
5352
5353 if (ret)
5354 {
5355 if (DriverInfoDetailDataW != NULL)
5356 {
5357 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5358 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
5359 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
5360 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
5361 if (WideCharToMultiByte(CP_ACP,
5362 0,
5363 DriverInfoDetailDataW->SectionName,
5364 LINE_LEN,
5365 DriverInfoDetailData->SectionName,
5366 LINE_LEN,
5367 NULL,
5368 NULL) &&
5369 WideCharToMultiByte(CP_ACP,
5370 0,
5371 DriverInfoDetailDataW->InfFileName,
5372 MAX_PATH,
5373 DriverInfoDetailData->InfFileName,
5374 MAX_PATH,
5375 NULL,
5376 NULL) &&
5377 WideCharToMultiByte(CP_ACP,
5378 0,
5379 DriverInfoDetailDataW->DrvDescription,
5380 LINE_LEN,
5381 DriverInfoDetailData->DrvDescription,
5382 LINE_LEN,
5383 NULL,
5384 NULL) &&
5385 WideCharToMultiByte(CP_ACP,
5386 0,
5387 DriverInfoDetailDataW->HardwareID,
5388 HardwareIDLen,
5389 DriverInfoDetailData->HardwareID,
5390 HardwareIDLen,
5391 NULL,
5392 NULL))
5393 {
5394 DWORD len, cnt = 0;
5395 DWORD hwidlen = HardwareIDLen;
5396 CHAR *s = DriverInfoDetailData->HardwareID;
5397
5398 /* count the strings in the list */
5399 while (*s != '\0')
5400 {
5401 len = lstrlenA(s) + 1;
5402 if (hwidlen > len)
5403 {
5404 cnt++;
5405 s += len;
5406 hwidlen -= len;
5407 }
5408 else
5409 {
5410 /* looks like the string list wasn't terminated... */
5411 SetLastError(ERROR_INVALID_USER_BUFFER);
5412 ret = FALSE;
5413 break;
5414 }
5415 }
5416
5417 /* make sure CompatIDsOffset points to the second string in the
5418 list, if present */
5419 if (cnt > 1)
5420 {
5421 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
5422 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
5423 DriverInfoDetailData->CompatIDsOffset + 1;
5424 }
5425 else
5426 {
5427 DriverInfoDetailData->CompatIDsOffset = 0;
5428 DriverInfoDetailData->CompatIDsLength = 0;
5429 }
5430 }
5431 else
5432 {
5433 ret = FALSE;
5434 }
5435 }
5436
5437 if (RequiredSize != NULL)
5438 {
5439 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
5440 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
5441 }
5442 }
5443 }
5444
5445 Cleanup:
5446 if (DriverInfoDetailDataW != NULL)
5447 {
5448 MyFree(DriverInfoDetailDataW);
5449 }
5450
5451 return ret;
5452 }
5453
5454 /***********************************************************************
5455 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5456 */
5457 BOOL WINAPI
5458 SetupDiGetDriverInfoDetailW(
5459 IN HDEVINFO DeviceInfoSet,
5460 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5461 IN PSP_DRVINFO_DATA_W DriverInfoData,
5462 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
5463 IN DWORD DriverInfoDetailDataSize,
5464 OUT PDWORD RequiredSize OPTIONAL)
5465 {
5466 BOOL ret = FALSE;
5467
5468 if (!DeviceInfoSet)
5469 SetLastError(ERROR_INVALID_PARAMETER);
5470 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5471 SetLastError(ERROR_INVALID_HANDLE);
5472 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5473 SetLastError(ERROR_INVALID_HANDLE);
5474 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5475 SetLastError(ERROR_INVALID_USER_BUFFER);
5476 else if (!DriverInfoData)
5477 SetLastError(ERROR_INVALID_PARAMETER);
5478 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
5479 SetLastError(ERROR_INVALID_PARAMETER);
5480 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
5481 SetLastError(ERROR_INVALID_PARAMETER);
5482 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
5483 SetLastError(ERROR_INVALID_USER_BUFFER);
5484 else if (DriverInfoDetailData && DriverInfoDetailData->Reserved == 0)
5485 SetLastError(ERROR_INVALID_PARAMETER);
5486 else
5487 {
5488 struct DriverInfoElement *driverInfoElement;
5489 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
5490
5491 memcpy(
5492 DriverInfoDetailData,
5493 &driverInfoElement->Details,
5494 driverInfoElement->Details.cbSize);
5495 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5496 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5497 */
5498 ret = TRUE;
5499 }
5500
5501 TRACE("Returning %d\n", ret);
5502 return ret;
5503 }
5504
5505 /***********************************************************************
5506 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5507 */
5508 BOOL WINAPI
5509 SetupDiSelectBestCompatDrv(
5510 IN HDEVINFO DeviceInfoSet,
5511 IN PSP_DEVINFO_DATA DeviceInfoData)
5512 {
5513 SP_DRVINFO_DATA_W drvInfoData;
5514 BOOL ret;
5515
5516 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5517
5518 /* Drivers are sorted by rank in the driver list, so
5519 * the first driver in the list is the best one.
5520 */
5521 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
5522 ret = SetupDiEnumDriverInfoW(
5523 DeviceInfoSet,
5524 DeviceInfoData,
5525 SPDIT_COMPATDRIVER,
5526 0, /* Member index */
5527 &drvInfoData);
5528
5529 if (ret)
5530 {
5531 ret = SetupDiSetSelectedDriverW(
5532 DeviceInfoSet,
5533 DeviceInfoData,
5534 &drvInfoData);
5535 }
5536
5537 TRACE("Returning %d\n", ret);
5538 return ret;
5539 }
5540
5541 /***********************************************************************
5542 * SetupDiInstallDriverFiles (SETUPAPI.@)
5543 */
5544 BOOL WINAPI
5545 SetupDiInstallDriverFiles(
5546 IN HDEVINFO DeviceInfoSet,
5547 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5548 {
5549 BOOL ret = FALSE;
5550
5551 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5552
5553 if (!DeviceInfoSet)
5554 SetLastError(ERROR_INVALID_PARAMETER);
5555 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5556 SetLastError(ERROR_INVALID_HANDLE);
5557 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5558 SetLastError(ERROR_INVALID_HANDLE);
5559 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5560 SetLastError(ERROR_INVALID_USER_BUFFER);
5561 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
5562 SetLastError(ERROR_NO_DRIVER_SELECTED);
5563 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
5564 SetLastError(ERROR_NO_DRIVER_SELECTED);
5565 else
5566 {
5567 SP_DEVINSTALL_PARAMS_W InstallParams;
5568 struct DriverInfoElement *SelectedDriver;
5569 WCHAR SectionName[MAX_PATH];
5570 DWORD SectionNameLength = 0;
5571
5572 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5573 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5574 if (!ret)
5575 goto done;
5576
5577 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5578 if (!SelectedDriver)
5579 {
5580 SetLastError(ERROR_NO_DRIVER_SELECTED);
5581 goto done;
5582 }
5583
5584 ret = SetupDiGetActualSectionToInstallW(
5585 SelectedDriver->InfFileDetails->hInf,
5586 SelectedDriver->Details.SectionName,
5587 SectionName, MAX_PATH, &SectionNameLength, NULL);
5588 if (!ret)
5589 goto done;
5590
5591 if (!InstallParams.InstallMsgHandler)
5592 {
5593 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
5594 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5595 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5596 }
5597 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5598 SelectedDriver->InfFileDetails->hInf, SectionName,
5599 SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
5600 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5601 DeviceInfoSet, DeviceInfoData);
5602 }
5603
5604 done:
5605 TRACE("Returning %d\n", ret);
5606 return ret;
5607 }
5608
5609 /***********************************************************************
5610 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5611 */
5612 BOOL WINAPI
5613 SetupDiRegisterCoDeviceInstallers(
5614 IN HDEVINFO DeviceInfoSet,
5615 IN PSP_DEVINFO_DATA DeviceInfoData)
5616 {
5617 BOOL ret = FALSE; /* Return value */
5618
5619 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5620
5621 if (!DeviceInfoSet)
5622 SetLastError(ERROR_INVALID_PARAMETER);
5623 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5624 SetLastError(ERROR_INVALID_HANDLE);
5625 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5626 SetLastError(ERROR_INVALID_HANDLE);
5627 else if (!DeviceInfoData)
5628 SetLastError(ERROR_INVALID_PARAMETER);
5629 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5630 SetLastError(ERROR_INVALID_USER_BUFFER);
5631 else
5632 {
5633 SP_DEVINSTALL_PARAMS_W InstallParams;
5634 struct DriverInfoElement *SelectedDriver;
5635 BOOL Result;
5636 DWORD DoAction;
5637 WCHAR SectionName[MAX_PATH];
5638 DWORD SectionNameLength = 0;
5639 HKEY hKey = INVALID_HANDLE_VALUE;;
5640
5641 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5642 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5643 if (!Result)
5644 goto cleanup;
5645
5646 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5647 if (SelectedDriver == NULL)
5648 {
5649 SetLastError(ERROR_NO_DRIVER_SELECTED);
5650 goto cleanup;
5651 }
5652
5653 /* Get .CoInstallers section name */
5654 Result = SetupDiGetActualSectionToInstallW(
5655 SelectedDriver->InfFileDetails->hInf,
5656 SelectedDriver->Details.SectionName,
5657 SectionName, MAX_PATH, &SectionNameLength, NULL);
5658 if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
5659 goto cleanup;
5660 wcscat(SectionName, L".CoInstallers");
5661
5662 /* Open/Create driver key information */
5663 #if _WIN32_WINNT >= 0x502
5664 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5665 #else
5666 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5667 #endif
5668 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5669 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5670 if (hKey == INVALID_HANDLE_VALUE)
5671 goto cleanup;
5672
5673 /* Install .CoInstallers section */
5674 DoAction = SPINST_REGISTRY;
5675 if (!(InstallParams.Flags & DI_NOFILECOPY))
5676 {
5677 DoAction |= SPINST_FILES;
5678 if (!InstallParams.InstallMsgHandler)
5679 {
5680 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
5681 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5682 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5683 }
5684 }
5685 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5686 SelectedDriver->InfFileDetails->hInf, SectionName,
5687 DoAction, hKey, NULL, SP_COPY_NEWER,
5688 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5689 DeviceInfoSet, DeviceInfoData);
5690 if (!Result)
5691 goto cleanup;
5692
5693 ret = TRUE;
5694
5695 cleanup:
5696 if (hKey != INVALID_HANDLE_VALUE)
5697 RegCloseKey(hKey);
5698 }
5699
5700 TRACE("Returning %d\n", ret);
5701 return ret;
5702 }
5703
5704 /***********************************************************************
5705 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5706 */
5707 BOOL WINAPI
5708 SetupDiInstallDeviceInterfaces(
5709 IN HDEVINFO DeviceInfoSet,
5710 IN PSP_DEVINFO_DATA DeviceInfoData)
5711 {
5712 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5713
5714 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5715 //SetLastError(ERROR_GEN_FAILURE);
5716 //return FALSE;
5717 return TRUE;
5718 }
5719
5720 /***********************************************************************
5721 * SetupDiInstallDevice (SETUPAPI.@)
5722 */
5723 BOOL WINAPI
5724 SetupDiInstallDevice(
5725 IN HDEVINFO DeviceInfoSet,
5726 IN PSP_DEVINFO_DATA DeviceInfoData)
5727 {
5728 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5729 SP_DEVINSTALL_PARAMS_W InstallParams;
5730 struct DriverInfoElement *SelectedDriver;
5731 SYSTEMTIME DriverDate;
5732 WCHAR SectionName[MAX_PATH];
5733 WCHAR Buffer[32];
5734 DWORD SectionNameLength = 0;
5735 BOOL Result = FALSE;
5736 INFCONTEXT ContextService;
5737 INT Flags;
5738 ULONG DoAction;
5739 DWORD RequiredSize;
5740 LPCWSTR AssociatedService = NULL;
5741 LPWSTR pSectionName = NULL;
5742 WCHAR ClassName[MAX_CLASS_NAME_LEN];
5743 GUID ClassGuid;
5744 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
5745 BOOL RebootRequired = FALSE;
5746 HKEY hKey = INVALID_HANDLE_VALUE;
5747 HKEY hClassKey = INVALID_HANDLE_VALUE;
5748 LONG rc;
5749 BOOL ret = FALSE; /* Return value */
5750
5751 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5752
5753 if (!DeviceInfoSet)
5754 SetLastError(ERROR_INVALID_PARAMETER);
5755 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5756 SetLastError(ERROR_INVALID_HANDLE);
5757 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5758 SetLastError(ERROR_INVALID_HANDLE);
5759 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5760 SetLastError(ERROR_INVALID_USER_BUFFER);
5761 else
5762 Result = TRUE;
5763
5764 if (!Result)
5765 {
5766 /* One parameter is bad */
5767 goto cleanup;
5768 }
5769
5770 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5771 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5772 if (!Result)
5773 goto cleanup;
5774
5775 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
5776 {
5777 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5778 goto cleanup;
5779 }
5780
5781 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5782 if (SelectedDriver == NULL)
5783 {
5784 SetLastError(ERROR_NO_DRIVER_SELECTED);
5785 goto cleanup;
5786 }
5787
5788 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
5789
5790 Result = SetupDiGetActualSectionToInstallW(
5791 SelectedDriver->InfFileDetails->hInf,
5792 SelectedDriver->Details.SectionName,
5793 SectionName, MAX_PATH, &SectionNameLength, NULL);
5794 if (!Result || SectionNameLength > MAX_PATH - 9)
5795 goto cleanup;
5796 pSectionName = &SectionName[wcslen(SectionName)];
5797
5798 /* Get information from [Version] section */
5799 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
5800 goto cleanup;
5801 /* Format ClassGuid to a string */
5802 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
5803 goto cleanup;
5804 RequiredSize = lstrlenW(lpGuidString);
5805 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
5806 if (!lpFullGuidString)
5807 {
5808 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5809 goto cleanup;
5810 }
5811 lpFullGuidString[0] = '{';
5812 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
5813 lpFullGuidString[RequiredSize + 1] = '}';
5814 lpFullGuidString[RequiredSize + 2] = '\0';
5815
5816 /* Open/Create driver key information */
5817 #if _WIN32_WINNT >= 0x502
5818 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5819 #else
5820 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5821 #endif
5822 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5823 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5824 if (hKey == INVALID_HANDLE_VALUE)
5825 goto cleanup;
5826
5827 /* Install main section */
5828 DoAction = SPINST_REGISTRY;
5829 if (!(InstallParams.Flags & DI_NOFILECOPY))
5830 {
5831 DoAction |= SPINST_FILES;
5832 if (!InstallParams.InstallMsgHandler)
5833 {
5834 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
5835 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5836 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5837 }
5838 }
5839 *pSectionName = '\0';
5840 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5841 SelectedDriver->InfFileDetails->hInf, SectionName,
5842 DoAction, hKey, NULL, SP_COPY_NEWER,
5843 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5844 DeviceInfoSet, DeviceInfoData);
5845 if (!Result)
5846 goto cleanup;
5847 if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
5848 {
5849 if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
5850 {
5851 /* Delete resources allocated by SetupInitDefaultQueueCallback */
5852 SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
5853 }
5854 }
5855 InstallParams.Flags |= DI_NOFILECOPY;
5856 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5857
5858 /* Write information to driver key */
5859 *pSectionName = UNICODE_NULL;
5860 TRACE("Write information to driver key\n");
5861 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5862 TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
5863 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);
5864 TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
5865 TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
5866 TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
5867 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
5868 TRACE("ProviderName : '%S'\n", SelectedDriver->Info.ProviderName);
5869 swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5870 rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
5871 if (rc == ERROR_SUCCESS)
5872 rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
5873 if (rc == ERROR_SUCCESS)
5874 rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5875 if (rc == ERROR_SUCCESS)
5876 {
5877 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);
5878 rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
5879 }
5880 if (rc == ERROR_SUCCESS)
5881 rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
5882 if (rc == ERROR_SUCCESS)
5883 rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5884 if (rc == ERROR_SUCCESS)
5885 rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5886 if (rc == ERROR_SUCCESS)
5887 rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
5888 if (rc == ERROR_SUCCESS)
5889 rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
5890 if (rc != ERROR_SUCCESS)
5891 {
5892 SetLastError(rc);
5893 goto cleanup;
5894 }
5895 RegCloseKey(hKey);
5896 hKey = INVALID_HANDLE_VALUE;
5897
5898 /* FIXME: Process .LogConfigOverride section */
5899
5900 /* Install .Services section */
5901 wcscpy(pSectionName, L".Services");
5902 Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf, SectionName, NULL, &ContextService);
5903 while (Result)
5904 {
5905 LPWSTR ServiceName = NULL;
5906 LPWSTR ServiceSection = NULL;
5907
5908 Result = SetupGetStringFieldW(
5909 &ContextService,
5910 1, /* Field index */
5911 NULL, 0,
5912 &RequiredSize);
5913 if (!Result)
5914 goto nextfile;
5915 if (RequiredSize > 0)
5916 {
5917 /* We got the needed size for the buffer */
5918 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5919 if (!ServiceName)
5920 {
5921 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5922 goto nextfile;
5923 }
5924 Result = SetupGetStringFieldW(
5925 &ContextService,
5926 1, /* Field index */
5927 ServiceName, RequiredSize,
5928 &RequiredSize);
5929 if (!Result)
5930 goto nextfile;
5931 }
5932 Result = SetupGetIntField(
5933 &ContextService,
5934 2, /* Field index */
5935 &Flags);
5936 if (!Result)
5937 {
5938 /* The field may be empty. Ignore the error */
5939 Flags = 0;
5940 }
5941 Result = SetupGetStringFieldW(
5942 &ContextService,
5943 3, /* Field index */
5944 NULL, 0,
5945 &RequiredSize);
5946 if (!Result)
5947 goto nextfile;
5948 if (RequiredSize > 0)
5949 {
5950 /* We got the needed size for the buffer */
5951 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5952 if (!ServiceSection)
5953 {
5954 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5955 goto nextfile;
5956 }
5957 Result = SetupGetStringFieldW(
5958 &ContextService,
5959 3, /* Field index */
5960 ServiceSection, RequiredSize,
5961 &RequiredSize);
5962 if (!Result)
5963 goto nextfile;
5964 }
5965 SetLastError(ERROR_SUCCESS);
5966 Result = SetupInstallServicesFromInfSectionExW(
5967 SelectedDriver->InfFileDetails->hInf,
5968 ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
5969 if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
5970 {
5971 AssociatedService = ServiceName;
5972 ServiceName = NULL;
5973 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
5974 RebootRequired = TRUE;
5975 }
5976 nextfile:
5977 HeapFree(GetProcessHeap(), 0, ServiceName);
5978 HeapFree(GetProcessHeap(), 0, ServiceSection);
5979 if (!Result)
5980 goto cleanup;
5981 Result = SetupFindNextLine(&ContextService, &ContextService);
5982 }
5983
5984 /* Copy .inf file to Inf\ directory */
5985 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
5986
5987 /* Open device registry key */
5988 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
5989 if (hKey == INVALID_HANDLE_VALUE)
5990 goto cleanup;
5991
5992 /* Install .HW section */
5993 wcscpy(pSectionName, L".HW");
5994 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5995 SelectedDriver->InfFileDetails->hInf, SectionName,
5996 SPINST_REGISTRY, hKey, NULL, 0,
5997 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5998 DeviceInfoSet, DeviceInfoData);
5999 if (!Result)
6000 goto cleanup;
6001
6002 /* Write information to enum key */
6003 TRACE("Write information to enum key\n");
6004 TRACE("Service : '%S'\n", AssociatedService);
6005 TRACE("Class : '%S'\n", ClassName);
6006 TRACE("ClassGUID : '%S'\n", lpFullGuidString);
6007 TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
6008 TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
6009 rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
6010 if (rc == ERROR_SUCCESS)
6011 rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
6012 if (rc == ERROR_SUCCESS)
6013 rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
6014 if (rc == ERROR_SUCCESS)
6015 rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
6016 if (rc == ERROR_SUCCESS)
6017 rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
6018 if (rc != ERROR_SUCCESS)
6019 {
6020 SetLastError(rc);
6021 goto cleanup;
6022 }
6023
6024 /* Start the device */
6025 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
6026 {
6027 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
6028 NTSTATUS Status;
6029 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
6030 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
6031 ret = NT_SUCCESS(Status);
6032 }
6033 else
6034 ret = TRUE;
6035
6036 cleanup:
6037 /* End of installation */
6038 if (hClassKey != INVALID_HANDLE_VALUE)
6039 RegCloseKey(hClassKey);
6040 if (hKey != INVALID_HANDLE_VALUE)
6041 RegCloseKey(hKey);
6042 if (lpGuidString)
6043 RpcStringFreeW(&lpGuidString);
6044 HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
6045 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
6046
6047 TRACE("Returning %d\n", ret);
6048 return ret;
6049 }