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