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