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