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