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