6515b5149ff0fe0e83dd968f68d729c479b31c35
[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 OPTIONAL,
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 (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
3408 SetLastError(ERROR_INVALID_PARAMETER);
3409 else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE
3410 && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE
3411 && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP)
3412 SetLastError(ERROR_INVALID_FLAGS);
3413 else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL
3414 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
3415 SetLastError(ERROR_INVALID_FLAGS);
3416 else if (PropChangeParams
3417 && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP)
3418 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
3419 SetLastError(ERROR_INVALID_USER_BUFFER);
3420 else
3421 {
3422 PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
3423 if (!DeviceInfoData)
3424 {
3425 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
3426 CurrentPropChangeParams = &list->ClassInstallParams.PropChange;
3427 }
3428 else
3429 {
3430 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
3431 CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChange;
3432 }
3433 if (*CurrentPropChangeParams)
3434 {
3435 MyFree(*CurrentPropChangeParams);
3436 *CurrentPropChangeParams = NULL;
3437 }
3438 if (PropChangeParams)
3439 {
3440 *CurrentPropChangeParams = MyMalloc(sizeof(SP_PROPCHANGE_PARAMS));
3441 if (!*CurrentPropChangeParams)
3442 {
3443 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3444 goto done;
3445 }
3446 memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS));
3447 }
3448 ret = TRUE;
3449 }
3450
3451 done:
3452 return ret;
3453 }
3454
3455 static DWORD
3456 GetFunctionPointer(
3457 IN PWSTR InstallerName,
3458 OUT HMODULE* ModulePointer,
3459 OUT PVOID* FunctionPointer)
3460 {
3461 HMODULE hModule = NULL;
3462 LPSTR FunctionNameA = NULL;
3463 PWCHAR Comma;
3464 DWORD rc;
3465
3466 *ModulePointer = NULL;
3467 *FunctionPointer = NULL;
3468
3469 Comma = strchrW(InstallerName, ',');
3470 if (!Comma)
3471 {
3472 rc = ERROR_INVALID_PARAMETER;
3473 goto cleanup;
3474 }
3475
3476 /* Load library */
3477 *Comma = '\0';
3478 hModule = LoadLibraryW(InstallerName);
3479 *Comma = ',';
3480 if (!hModule)
3481 {
3482 rc = GetLastError();
3483 goto cleanup;
3484 }
3485
3486 /* Skip comma spaces */
3487 while (*Comma == ',' || isspaceW(*Comma))
3488 Comma++;
3489
3490 /* W->A conversion for function name */
3491 FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
3492 if (!FunctionNameA)
3493 {
3494 rc = GetLastError();
3495 goto cleanup;
3496 }
3497
3498 /* Search function */
3499 *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
3500 if (!*FunctionPointer)
3501 {
3502 rc = GetLastError();
3503 goto cleanup;
3504 }
3505
3506 *ModulePointer = hModule;
3507 rc = ERROR_SUCCESS;
3508
3509 cleanup:
3510 if (rc != ERROR_SUCCESS && hModule)
3511 FreeLibrary(hModule);
3512 MyFree(FunctionNameA);
3513 return rc;
3514 }
3515
3516 static DWORD
3517 FreeFunctionPointer(
3518 IN HMODULE ModulePointer,
3519 IN PVOID FunctionPointer)
3520 {
3521 if (ModulePointer == NULL)
3522 return ERROR_SUCCESS;
3523 if (FreeLibrary(ModulePointer))
3524 return ERROR_SUCCESS;
3525 else
3526 return GetLastError();
3527 }
3528
3529 /***********************************************************************
3530 * SetupDiCallClassInstaller (SETUPAPI.@)
3531 */
3532 BOOL WINAPI SetupDiCallClassInstaller(
3533 IN DI_FUNCTION InstallFunction,
3534 IN HDEVINFO DeviceInfoSet,
3535 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3536 {
3537 BOOL ret = FALSE;
3538
3539 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3540
3541 if (!DeviceInfoSet)
3542 SetLastError(ERROR_INVALID_PARAMETER);
3543 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3544 SetLastError(ERROR_INVALID_HANDLE);
3545 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3546 SetLastError(ERROR_INVALID_HANDLE);
3547 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
3548 SetLastError(ERROR_INVALID_HANDLE);
3549 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3550 SetLastError(ERROR_INVALID_USER_BUFFER);
3551 else
3552 {
3553 SP_DEVINSTALL_PARAMS_W InstallParams;
3554 #define CLASS_COINSTALLER 0x1
3555 #define DEVICE_COINSTALLER 0x2
3556 #define CLASS_INSTALLER 0x4
3557 UCHAR CanHandle = 0;
3558 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
3559
3560 switch (InstallFunction)
3561 {
3562 case DIF_ALLOW_INSTALL:
3563 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3564 break;
3565 case DIF_DESTROYPRIVATEDATA:
3566 CanHandle = CLASS_INSTALLER;
3567 break;
3568 case DIF_INSTALLDEVICE:
3569 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3570 DefaultHandler = SetupDiInstallDevice;
3571 break;
3572 case DIF_INSTALLDEVICEFILES:
3573 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3574 DefaultHandler = SetupDiInstallDriverFiles;
3575 break;
3576 case DIF_INSTALLINTERFACES:
3577 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3578 DefaultHandler = SetupDiInstallDeviceInterfaces;
3579 break;
3580 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
3581 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3582 break;
3583 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
3584 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3585 break;
3586 case DIF_NEWDEVICEWIZARD_PREANALYZE:
3587 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3588 break;
3589 case DIF_PROPERTYCHANGE:
3590 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3591 DefaultHandler = SetupDiChangeState;
3592 break;
3593 case DIF_REGISTER_COINSTALLERS:
3594 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3595 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
3596 break;
3597 case DIF_SELECTBESTCOMPATDRV:
3598 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3599 DefaultHandler = SetupDiSelectBestCompatDrv;
3600 break;
3601 default:
3602 ERR("Install function %u not supported\n", InstallFunction);
3603 SetLastError(ERROR_NOT_SUPPORTED);
3604 }
3605
3606 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3607 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
3608 /* Don't process this call, as a parameter is invalid */
3609 CanHandle = 0;
3610
3611 if (CanHandle != 0)
3612 {
3613 LIST_ENTRY ClassCoInstallersListHead;
3614 LIST_ENTRY DeviceCoInstallersListHead;
3615 HMODULE ClassInstallerLibrary = NULL;
3616 CLASS_INSTALL_PROC ClassInstaller = NULL;
3617 COINSTALLER_CONTEXT_DATA Context;
3618 PLIST_ENTRY ListEntry;
3619 HKEY hKey;
3620 DWORD dwRegType, dwLength;
3621 DWORD rc = NO_ERROR;
3622
3623 InitializeListHead(&ClassCoInstallersListHead);
3624 InitializeListHead(&DeviceCoInstallersListHead);
3625
3626 if (CanHandle & DEVICE_COINSTALLER)
3627 {
3628 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
3629 if (hKey != INVALID_HANDLE_VALUE)
3630 {
3631 rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, &dwRegType, NULL, &dwLength);
3632 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3633 {
3634 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3635 if (KeyBuffer != NULL)
3636 {
3637 rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3638 if (rc == ERROR_SUCCESS)
3639 {
3640 LPWSTR ptr;
3641 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3642 {
3643 /* Add coinstaller to DeviceCoInstallersListHead list */
3644 struct CoInstallerElement *coinstaller;
3645 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
3646 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3647 if (!coinstaller)
3648 continue;
3649 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
3650 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3651 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
3652 else
3653 HeapFree(GetProcessHeap(), 0, coinstaller);
3654 }
3655 }
3656 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3657 }
3658 }
3659 RegCloseKey(hKey);
3660 }
3661 }
3662 if (CanHandle & CLASS_COINSTALLER)
3663 {
3664 rc = RegOpenKeyEx(
3665 HKEY_LOCAL_MACHINE,
3666 L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3667 0, /* Options */
3668 KEY_QUERY_VALUE,
3669 &hKey);
3670 if (rc == ERROR_SUCCESS)
3671 {
3672 LPWSTR lpGuidString;
3673 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
3674 {
3675 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
3676 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3677 {
3678 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3679 if (KeyBuffer != NULL)
3680 {
3681 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3682 if (rc == ERROR_SUCCESS)
3683 {
3684 LPWSTR ptr;
3685 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3686 {
3687 /* Add coinstaller to ClassCoInstallersListHead list */
3688 struct CoInstallerElement *coinstaller;
3689 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
3690 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3691 if (!coinstaller)
3692 continue;
3693 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
3694 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3695 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
3696 else
3697 HeapFree(GetProcessHeap(), 0, coinstaller);
3698 }
3699 }
3700 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3701 }
3702 }
3703 RpcStringFreeW(&lpGuidString);
3704 }
3705 RegCloseKey(hKey);
3706 }
3707 }
3708 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
3709 {
3710 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
3711 if (hKey != INVALID_HANDLE_VALUE)
3712 {
3713 rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
3714 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
3715 {
3716 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3717 if (KeyBuffer != NULL)
3718 {
3719 rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3720 if (rc == ERROR_SUCCESS)
3721 {
3722 /* Get ClassInstaller function pointer */
3723 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
3724 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
3725 {
3726 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
3727 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3728 }
3729 }
3730 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3731 }
3732 }
3733 RegCloseKey(hKey);
3734 }
3735 }
3736
3737 /* Call Class co-installers */
3738 Context.PostProcessing = FALSE;
3739 rc = NO_ERROR;
3740 ListEntry = ClassCoInstallersListHead.Flink;
3741 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
3742 {
3743 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3744 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3745 coinstaller->PrivateData = Context.PrivateData;
3746 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3747 {
3748 coinstaller->DoPostProcessing = TRUE;
3749 rc = NO_ERROR;
3750 }
3751 ListEntry = ListEntry->Flink;
3752 }
3753
3754 /* Call Device co-installers */
3755 ListEntry = DeviceCoInstallersListHead.Flink;
3756 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
3757 {
3758 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3759 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3760 coinstaller->PrivateData = Context.PrivateData;
3761 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3762 {
3763 coinstaller->DoPostProcessing = TRUE;
3764 rc = NO_ERROR;
3765 }
3766 ListEntry = ListEntry->Flink;
3767 }
3768
3769 /* Call Class installer */
3770 if (ClassInstaller)
3771 {
3772 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
3773 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
3774 }
3775 else
3776 rc = ERROR_DI_DO_DEFAULT;
3777
3778 /* Call default handler */
3779 if (rc == ERROR_DI_DO_DEFAULT)
3780 {
3781 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
3782 {
3783 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
3784 rc = NO_ERROR;
3785 else
3786 rc = GetLastError();
3787 }
3788 else
3789 rc = NO_ERROR;
3790 }
3791
3792 /* Call Class co-installers that required postprocessing */
3793 Context.PostProcessing = TRUE;
3794 ListEntry = ClassCoInstallersListHead.Flink;
3795 while (ListEntry != &ClassCoInstallersListHead)
3796 {
3797 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3798 if (coinstaller->DoPostProcessing)
3799 {
3800 Context.InstallResult = rc;
3801 Context.PrivateData = coinstaller->PrivateData;
3802 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3803 }
3804 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3805 ListEntry = ListEntry->Flink;
3806 }
3807
3808 /* Call Device co-installers that required postprocessing */
3809 ListEntry = DeviceCoInstallersListHead.Flink;
3810 while (ListEntry != &DeviceCoInstallersListHead)
3811 {
3812 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3813 if (coinstaller->DoPostProcessing)
3814 {
3815 Context.InstallResult = rc;
3816 Context.PrivateData = coinstaller->PrivateData;
3817 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3818 }
3819 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3820 ListEntry = ListEntry->Flink;
3821 }
3822
3823 /* Free allocated memory */
3824 while (!IsListEmpty(&ClassCoInstallersListHead))
3825 {
3826 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
3827 HeapFree(GetProcessHeap(), 0, ListEntry);
3828 }
3829 while (!IsListEmpty(&DeviceCoInstallersListHead))
3830 {
3831 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
3832 HeapFree(GetProcessHeap(), 0, ListEntry);
3833 }
3834
3835 ret = (rc == NO_ERROR);
3836 }
3837 }
3838
3839 TRACE("Returning %d\n", ret);
3840 return ret;
3841 }
3842
3843 /***********************************************************************
3844 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3845 */
3846 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
3847 IN HDEVINFO DeviceInfoSet,
3848 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
3849 {
3850 struct DeviceInfoSet *list;
3851 BOOL ret = FALSE;
3852
3853 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
3854
3855 if (!DeviceInfoSet)
3856 SetLastError(ERROR_INVALID_HANDLE);
3857 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3858 SetLastError(ERROR_INVALID_HANDLE);
3859 else if (!DeviceInfoListDetailData)
3860 SetLastError(ERROR_INVALID_PARAMETER);
3861 else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
3862 SetLastError(ERROR_INVALID_USER_BUFFER);
3863 else
3864 {
3865 memcpy(
3866 &DeviceInfoListDetailData->ClassGuid,
3867 &list->ClassGuid,
3868 sizeof(GUID));
3869 DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
3870 if (list->MachineName)
3871 strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
3872 else
3873 DeviceInfoListDetailData->RemoteMachineName[0] = 0;
3874
3875 ret = TRUE;
3876 }
3877
3878 TRACE("Returning %d\n", ret);
3879 return ret;
3880 }
3881
3882 /***********************************************************************
3883 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3884 */
3885 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3886 IN HDEVINFO DeviceInfoSet,
3887 IN PSP_DEVINFO_DATA DeviceInfoData,
3888 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3889 {
3890 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
3891 BOOL ret = FALSE;
3892
3893 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3894
3895 if (DeviceInstallParams == NULL)
3896 SetLastError(ERROR_INVALID_PARAMETER);
3897 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
3898 SetLastError(ERROR_INVALID_USER_BUFFER);
3899 else
3900 {
3901 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3902 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
3903
3904 if (ret)
3905 {
3906 /* Do W->A conversion */
3907 memcpy(
3908 DeviceInstallParams,
3909 &deviceInstallParamsW,
3910 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
3911 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
3912 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
3913 {
3914 DeviceInstallParams->DriverPath[0] = '\0';
3915 ret = FALSE;
3916 }
3917 }
3918 }
3919
3920 TRACE("Returning %d\n", ret);
3921 return ret;
3922 }
3923
3924 /***********************************************************************
3925 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3926 */
3927 BOOL WINAPI SetupDiGetDeviceInstallParamsW(
3928 IN HDEVINFO DeviceInfoSet,
3929 IN PSP_DEVINFO_DATA DeviceInfoData,
3930 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3931 {
3932 struct DeviceInfoSet *list;
3933 BOOL ret = FALSE;
3934
3935 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3936
3937 if (!DeviceInfoSet)
3938 SetLastError(ERROR_INVALID_HANDLE);
3939 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3940 SetLastError(ERROR_INVALID_HANDLE);
3941 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3942 SetLastError(ERROR_INVALID_USER_BUFFER);
3943 else if (!DeviceInstallParams)
3944 SetLastError(ERROR_INVALID_PARAMETER);
3945 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
3946 SetLastError(ERROR_INVALID_USER_BUFFER);
3947 else
3948 {
3949 PSP_DEVINSTALL_PARAMS_W Source;
3950
3951 if (DeviceInfoData)
3952 Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
3953 else
3954 Source = &list->InstallParams;
3955 memcpy(DeviceInstallParams, Source, Source->cbSize);
3956 ret = TRUE;
3957 }
3958
3959 TRACE("Returning %d\n", ret);
3960 return ret;
3961 }
3962
3963 /***********************************************************************
3964 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3965 */
3966 BOOL WINAPI SetupDiSetDeviceInstallParamsW(
3967 IN HDEVINFO DeviceInfoSet,
3968 IN PSP_DEVINFO_DATA DeviceInfoData,
3969 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3970 {
3971 struct DeviceInfoSet *list;
3972 BOOL ret = FALSE;
3973
3974 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3975
3976 if (!DeviceInfoSet)
3977 SetLastError(ERROR_INVALID_HANDLE);
3978 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3979 SetLastError(ERROR_INVALID_HANDLE);
3980 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3981 SetLastError(ERROR_INVALID_USER_BUFFER);
3982 else if (!DeviceInstallParams)
3983 SetLastError(ERROR_INVALID_PARAMETER);
3984 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
3985 SetLastError(ERROR_INVALID_USER_BUFFER);
3986 else
3987 {
3988 PSP_DEVINSTALL_PARAMS_W Destination;
3989
3990 /* FIXME: Validate parameters */
3991
3992 if (DeviceInfoData)
3993 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
3994 else
3995 Destination = &list->InstallParams;
3996 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
3997 ret = TRUE;
3998 }
3999
4000 TRACE("Returning %d\n", ret);
4001 return ret;
4002 }
4003
4004 /***********************************************************************
4005 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4006 */
4007 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
4008 IN HDEVINFO DeviceInfoSet,
4009 IN PSP_DEVINFO_DATA DeviceInfoData,
4010 OUT PSTR DeviceInstanceId OPTIONAL,
4011 IN DWORD DeviceInstanceIdSize,
4012 OUT PDWORD RequiredSize OPTIONAL)
4013 {
4014 PWSTR DeviceInstanceIdW = NULL;
4015 BOOL ret = FALSE;
4016
4017 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
4018 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
4019
4020 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
4021 SetLastError(ERROR_INVALID_PARAMETER);
4022 else
4023 {
4024 if (DeviceInstanceIdSize != 0)
4025 {
4026 DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
4027 if (DeviceInstanceIdW == NULL)
4028 return FALSE;
4029 }
4030
4031 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
4032 DeviceInstanceIdW, DeviceInstanceIdSize,
4033 RequiredSize);
4034
4035 if (ret && DeviceInstanceIdW != NULL)
4036 {
4037 if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
4038 DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
4039 {
4040 DeviceInstanceId[0] = '\0';
4041 ret = FALSE;
4042 }
4043 }
4044 }
4045
4046 TRACE("Returning %d\n", ret);
4047 return ret;
4048 }
4049
4050 /***********************************************************************
4051 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4052 */
4053 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
4054 IN HDEVINFO DeviceInfoSet,
4055 IN PSP_DEVINFO_DATA DeviceInfoData,
4056 OUT PWSTR DeviceInstanceId OPTIONAL,
4057 IN DWORD DeviceInstanceIdSize,
4058 OUT PDWORD RequiredSize OPTIONAL)
4059 {
4060 BOOL ret = FALSE;
4061
4062 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
4063 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
4064
4065 if (!DeviceInfoSet)
4066 SetLastError(ERROR_INVALID_HANDLE);
4067 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4068 SetLastError(ERROR_INVALID_HANDLE);
4069 else if (!DeviceInfoData)
4070 SetLastError(ERROR_INVALID_PARAMETER);
4071 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4072 SetLastError(ERROR_INVALID_USER_BUFFER);
4073 else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
4074 SetLastError(ERROR_INVALID_PARAMETER);
4075 else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
4076 SetLastError(ERROR_INVALID_PARAMETER);
4077 else
4078 {
4079 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4080 DWORD required;
4081
4082 required = (wcslen(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
4083 if (RequiredSize)
4084 *RequiredSize = required;
4085
4086 if (required <= DeviceInstanceIdSize)
4087 {
4088 wcscpy(DeviceInstanceId, DevInfo->DeviceName);
4089 ret = TRUE;
4090 }
4091 else
4092 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4093 }
4094
4095 TRACE("Returning %d\n", ret);
4096 return ret;
4097 }
4098
4099 /***********************************************************************
4100 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4101 */
4102 BOOL WINAPI SetupDiGetClassDevPropertySheetsA(
4103 IN HDEVINFO DeviceInfoSet,
4104 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4105 IN LPPROPSHEETHEADERA PropertySheetHeader,
4106 IN DWORD PropertySheetHeaderPageListSize,
4107 OUT PDWORD RequiredSize OPTIONAL,
4108 IN DWORD PropertySheetType)
4109 {
4110 PROPSHEETHEADERW psh;
4111 BOOL ret = FALSE;
4112
4113 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4114 PropertySheetHeader, PropertySheetHeaderPageListSize,
4115 RequiredSize, PropertySheetType);
4116
4117 psh.dwFlags = PropertySheetHeader->dwFlags;
4118 psh.phpage = PropertySheetHeader->phpage;
4119 psh.nPages = PropertySheetHeader->nPages;
4120
4121 ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
4122 PropertySheetHeaderPageListSize, RequiredSize,
4123 PropertySheetType);
4124 if (ret)
4125 {
4126 PropertySheetHeader->nPages = psh.nPages;
4127 }
4128
4129 TRACE("Returning %d\n", ret);
4130 return ret;
4131 }
4132
4133 struct ClassDevPropertySheetsData
4134 {
4135 HPROPSHEETPAGE *PropertySheetPages;
4136 DWORD MaximumNumberOfPages;
4137 DWORD NumberOfPages;
4138 };
4139
4140 static BOOL WINAPI GetClassDevPropertySheetsCallback(
4141 IN HPROPSHEETPAGE hPropSheetPage,
4142 IN OUT LPARAM lParam)
4143 {
4144 struct ClassDevPropertySheetsData *PropPageData;
4145
4146 PropPageData = (struct ClassDevPropertySheetsData *)lParam;
4147
4148 if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages)
4149 {
4150 *PropPageData->PropertySheetPages = hPropSheetPage;
4151 PropPageData->PropertySheetPages++;
4152 }
4153
4154 PropPageData->NumberOfPages++;
4155 return TRUE;
4156 }
4157
4158 /***********************************************************************
4159 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4160 */
4161 BOOL WINAPI SetupDiGetClassDevPropertySheetsW(
4162 IN HDEVINFO DeviceInfoSet,
4163 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4164 IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
4165 IN DWORD PropertySheetHeaderPageListSize,
4166 OUT PDWORD RequiredSize OPTIONAL,
4167 IN DWORD PropertySheetType)
4168 {
4169 struct DeviceInfoSet *list;
4170 BOOL ret = FALSE;
4171
4172 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4173 PropertySheetHeader, PropertySheetHeaderPageListSize,
4174 RequiredSize, PropertySheetType);
4175
4176 if (!DeviceInfoSet)
4177 SetLastError(ERROR_INVALID_HANDLE);
4178 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4179 SetLastError(ERROR_INVALID_HANDLE);
4180 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4181 SetLastError(ERROR_INVALID_HANDLE);
4182 else if (!PropertySheetHeader)
4183 SetLastError(ERROR_INVALID_PARAMETER);
4184 else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
4185 SetLastError(ERROR_INVALID_FLAGS);
4186 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4187 SetLastError(ERROR_INVALID_USER_BUFFER);
4188 else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
4189 SetLastError(ERROR_INVALID_PARAMETER);
4190 else if (!PropertySheetHeader)
4191 SetLastError(ERROR_INVALID_PARAMETER);
4192 else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
4193 && PropertySheetType != DIGCDP_FLAG_BASIC
4194 && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
4195 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
4196 SetLastError(ERROR_INVALID_PARAMETER);
4197 else
4198 {
4199 HKEY hKey = INVALID_HANDLE_VALUE;
4200 SP_PROPSHEETPAGE_REQUEST Request;
4201 LPWSTR PropPageProvider = NULL;
4202 HMODULE hModule = NULL;
4203 PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
4204 struct ClassDevPropertySheetsData PropPageData;
4205 DWORD dwLength, dwRegType;
4206 DWORD rc;
4207
4208 if (DeviceInfoData)
4209 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
4210 else
4211 {
4212 hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
4213 DIOCR_INSTALLER, list->MachineName + 2, NULL);
4214 }
4215 if (hKey == INVALID_HANDLE_VALUE)
4216 goto cleanup;
4217
4218 rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength);
4219 if (rc == ERROR_FILE_NOT_FOUND)
4220 {
4221 /* No registry key. As it is optional, don't say it's a bad error */
4222 if (RequiredSize)
4223 *RequiredSize = 0;
4224 ret = TRUE;
4225 goto cleanup;
4226 }
4227 else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
4228 {
4229 SetLastError(rc);
4230 goto cleanup;
4231 }
4232
4233 PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
4234 if (!PropPageProvider)
4235 {
4236 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4237 goto cleanup;
4238 }
4239 rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
4240 if (rc != ERROR_SUCCESS)
4241 {
4242 SetLastError(rc);
4243 goto cleanup;
4244 }
4245 PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
4246
4247 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
4248 if (rc != ERROR_SUCCESS)
4249 {
4250 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
4251 goto cleanup;
4252 }
4253
4254 Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
4255 Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
4256 Request.DeviceInfoSet = DeviceInfoSet;
4257 Request.DeviceInfoData = DeviceInfoData;
4258 PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages];
4259 PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages;
4260 PropPageData.NumberOfPages = 0;
4261 ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
4262 if (!ret)
4263 goto cleanup;
4264
4265 if (RequiredSize)
4266 *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages;
4267 if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages)
4268 {
4269 PropertySheetHeader->nPages += PropPageData.NumberOfPages;
4270 ret = TRUE;
4271 }
4272 else
4273 {
4274 PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages;
4275 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4276 }
4277
4278 cleanup:
4279 if (hKey != INVALID_HANDLE_VALUE)
4280 RegCloseKey(hKey);
4281 HeapFree(GetProcessHeap(), 0, PropPageProvider);
4282 FreeFunctionPointer(hModule, pPropPageProvider);
4283 }
4284
4285 TRACE("Returning %d\n", ret);
4286 return ret;
4287 }
4288
4289 /***********************************************************************
4290 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4291 */
4292 HKEY WINAPI SetupDiCreateDevRegKeyA(
4293 IN HDEVINFO DeviceInfoSet,
4294 IN PSP_DEVINFO_DATA DeviceInfoData,
4295 IN DWORD Scope,
4296 IN DWORD HwProfile,
4297 IN DWORD KeyType,
4298 IN HINF InfHandle OPTIONAL,
4299 IN PCSTR InfSectionName OPTIONAL)
4300 {
4301 PCWSTR InfSectionNameW = NULL;
4302 HKEY ret = INVALID_HANDLE_VALUE;
4303
4304 if (InfSectionName)
4305 {
4306 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
4307 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
4308 }
4309
4310 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
4311 DeviceInfoData,
4312 Scope,
4313 HwProfile,
4314 KeyType,
4315 InfHandle,
4316 InfSectionNameW);
4317
4318 if (InfSectionNameW != NULL)
4319 MyFree((PVOID)InfSectionNameW);
4320
4321 return ret;
4322 }
4323
4324 /***********************************************************************
4325 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4326 */
4327 HKEY WINAPI SetupDiCreateDevRegKeyW(
4328 IN HDEVINFO DeviceInfoSet,
4329 IN PSP_DEVINFO_DATA DeviceInfoData,
4330 IN DWORD Scope,
4331 IN DWORD HwProfile,
4332 IN DWORD KeyType,
4333 IN HINF InfHandle OPTIONAL,
4334 IN PCWSTR InfSectionName OPTIONAL)
4335 {
4336 struct DeviceInfoSet *list;
4337 HKEY ret = INVALID_HANDLE_VALUE;
4338
4339 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
4340 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
4341
4342 if (!DeviceInfoSet)
4343 SetLastError(ERROR_INVALID_HANDLE);
4344 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4345 SetLastError(ERROR_INVALID_HANDLE);
4346 else if (!DeviceInfoData)
4347 SetLastError(ERROR_INVALID_PARAMETER);
4348 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4349 SetLastError(ERROR_INVALID_USER_BUFFER);
4350 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4351 SetLastError(ERROR_INVALID_PARAMETER);
4352 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4353 SetLastError(ERROR_INVALID_PARAMETER);
4354 else if (InfHandle && !InfSectionName)
4355 SetLastError(ERROR_INVALID_PARAMETER);
4356 else if (!InfHandle && InfSectionName)
4357 SetLastError(ERROR_INVALID_PARAMETER);
4358 else
4359 {
4360 LPWSTR lpGuidString = NULL;
4361 LPWSTR DriverKey = NULL; /* {GUID}\Index */
4362 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
4363 DWORD Index; /* Index used in the DriverKey name */
4364 DWORD rc;
4365 HKEY hClassKey = INVALID_HANDLE_VALUE;
4366 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
4367 HKEY hKey = INVALID_HANDLE_VALUE;
4368
4369 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
4370 {
4371 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4372 goto cleanup;
4373 }
4374
4375 if (KeyType == DIREG_DEV)
4376 {
4377 FIXME("DIREG_DEV case unimplemented\n");
4378 }
4379 else /* KeyType == DIREG_DRV */
4380 {
4381 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
4382 goto cleanup;
4383 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
4384 DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
4385 if (!DriverKey)
4386 {
4387 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4388 goto cleanup;
4389 }
4390 wcscpy(DriverKey, L"{");
4391 wcscat(DriverKey, lpGuidString);
4392 wcscat(DriverKey, L"}\\");
4393 pDeviceInstance = &DriverKey[wcslen(DriverKey)];
4394 rc = RegOpenKeyExW(list->HKLM,
4395 ControlClass,
4396 0,
4397 KEY_CREATE_SUB_KEY,
4398 &hClassKey);
4399 if (rc != ERROR_SUCCESS)
4400 {
4401 SetLastError(rc);
4402 goto cleanup;
4403 }
4404
4405 /* Try all values for Index between 0 and 9999 */
4406 Index = 0;
4407 while (Index <= 9999)
4408 {
4409 DWORD Disposition;
4410 wsprintf(pDeviceInstance, L"%04lu", Index);
4411 rc = RegCreateKeyEx(hClassKey,
4412 DriverKey,
4413 0,
4414 NULL,
4415 REG_OPTION_NON_VOLATILE,
4416 #if _WIN32_WINNT >= 0x502
4417 KEY_READ | KEY_WRITE,
4418 #else
4419 KEY_ALL_ACCESS,
4420 #endif
4421 NULL,
4422 &hKey,
4423 &Disposition);
4424 if (rc != ERROR_SUCCESS)
4425 {
4426 SetLastError(rc);
4427 goto cleanup;
4428 }
4429 if (Disposition == REG_CREATED_NEW_KEY)
4430 break;
4431 RegCloseKey(hKey);
4432 hKey = INVALID_HANDLE_VALUE;
4433 Index++;
4434 }
4435 if (Index > 9999)
4436 {
4437 /* Unable to create more than 9999 devices within the same class */
4438 SetLastError(ERROR_GEN_FAILURE);
4439 goto cleanup;
4440 }
4441
4442 /* Open device key, to write Driver value */
4443 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
4444 if (hDeviceKey == INVALID_HANDLE_VALUE)
4445 goto cleanup;
4446 rc = RegSetValueEx(hDeviceKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
4447 if (rc != ERROR_SUCCESS)
4448 {
4449 SetLastError(rc);
4450 goto cleanup;
4451 }
4452 }
4453
4454 /* Do installation of the specified section */
4455 if (InfHandle)
4456 {
4457 FIXME("Need to install section %s in file %p\n",
4458 debugstr_w(InfSectionName), InfHandle);
4459 }
4460 ret = hKey;
4461
4462 cleanup:
4463 if (lpGuidString)
4464 RpcStringFreeW(&lpGuidString);
4465 HeapFree(GetProcessHeap(), 0, DriverKey);
4466 if (hClassKey != INVALID_HANDLE_VALUE)
4467 RegCloseKey(hClassKey);
4468 if (hDeviceKey != INVALID_HANDLE_VALUE)
4469 RegCloseKey(hDeviceKey);
4470 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
4471 RegCloseKey(hKey);
4472 }
4473
4474 TRACE("Returning 0x%p\n", ret);
4475 return ret;
4476 }
4477
4478 /***********************************************************************
4479 * SetupDiOpenDevRegKey (SETUPAPI.@)
4480 */
4481 HKEY WINAPI SetupDiOpenDevRegKey(
4482 HDEVINFO DeviceInfoSet,
4483 PSP_DEVINFO_DATA DeviceInfoData,
4484 DWORD Scope,
4485 DWORD HwProfile,
4486 DWORD KeyType,
4487 REGSAM samDesired)
4488 {
4489 struct DeviceInfoSet *list;
4490 HKEY ret = INVALID_HANDLE_VALUE;
4491
4492 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4493 Scope, HwProfile, KeyType, samDesired);
4494
4495 if (!DeviceInfoSet)
4496 SetLastError(ERROR_INVALID_HANDLE);
4497 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4498 SetLastError(ERROR_INVALID_HANDLE);
4499 else if (!DeviceInfoData)
4500 SetLastError(ERROR_INVALID_PARAMETER);
4501 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4502 SetLastError(ERROR_INVALID_USER_BUFFER);
4503 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4504 SetLastError(ERROR_INVALID_PARAMETER);
4505 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4506 SetLastError(ERROR_INVALID_PARAMETER);
4507 else
4508 {
4509 HKEY hKey = INVALID_HANDLE_VALUE;
4510 HKEY hRootKey = INVALID_HANDLE_VALUE;
4511 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4512 LPWSTR DriverKey = NULL;
4513 DWORD dwLength = 0;
4514 DWORD dwRegType;
4515 DWORD rc;
4516
4517 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
4518 {
4519 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4520 }
4521 else /* Scope == DICS_FLAG_GLOBAL */
4522 {
4523 rc = RegOpenKeyExW(
4524 list->HKLM,
4525 EnumKeyName,
4526 0, /* Options */
4527 KEY_ENUMERATE_SUB_KEYS,
4528 &hRootKey);
4529 if (rc != ERROR_SUCCESS)
4530 {
4531 SetLastError(rc);
4532 goto cleanup;
4533 }
4534 rc = RegOpenKeyExW(
4535 hRootKey,
4536 deviceInfo->DeviceName,
4537 0, /* Options */
4538 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
4539 &hKey);
4540 RegCloseKey(hRootKey);
4541 hRootKey = INVALID_HANDLE_VALUE;
4542 if (rc != ERROR_SUCCESS)
4543 {
4544 SetLastError(rc);
4545 goto cleanup;
4546 }
4547 if (KeyType == DIREG_DEV)
4548 {
4549 /* We're done. Just return the hKey handle */
4550 ret = hKey;
4551 goto cleanup;
4552 }
4553 /* Read the 'Driver' key */
4554 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, NULL, &dwLength);
4555 if (rc != ERROR_SUCCESS)
4556 {
4557 SetLastError(rc);
4558 goto cleanup;
4559 }
4560 if (dwRegType != REG_SZ)
4561 {
4562 SetLastError(ERROR_GEN_FAILURE);
4563 goto cleanup;
4564 }
4565 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
4566 if (!DriverKey)
4567 {
4568 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4569 goto cleanup;
4570 }
4571 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
4572 if (rc != ERROR_SUCCESS)
4573 {
4574 SetLastError(rc);
4575 goto cleanup;
4576 }
4577 RegCloseKey(hKey);
4578 hKey = INVALID_HANDLE_VALUE;
4579 /* Need to open the driver key */
4580 rc = RegOpenKeyExW(
4581 list->HKLM,
4582 ControlClass,
4583 0, /* Options */
4584 KEY_ENUMERATE_SUB_KEYS,
4585 &hRootKey);
4586 if (rc != ERROR_SUCCESS)
4587 {
4588 SetLastError(rc);
4589 goto cleanup;
4590 }
4591 rc = RegOpenKeyExW(
4592 hRootKey,
4593 DriverKey,
4594 0, /* Options */
4595 samDesired,
4596 &hKey);
4597 if (rc != ERROR_SUCCESS)
4598 {
4599 SetLastError(rc);
4600 goto cleanup;
4601 }
4602 ret = hKey;
4603 }
4604 cleanup:
4605 if (hRootKey != INVALID_HANDLE_VALUE)
4606 RegCloseKey(hRootKey);
4607 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
4608 RegCloseKey(hKey);
4609 }
4610
4611 TRACE("Returning 0x%p\n", ret);
4612 return ret;
4613 }
4614
4615 /***********************************************************************
4616 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4617 */
4618 BOOL WINAPI SetupDiCreateDeviceInfoA(
4619 HDEVINFO DeviceInfoSet,
4620 PCSTR DeviceName,
4621 CONST GUID *ClassGuid,
4622 PCSTR DeviceDescription,
4623 HWND hwndParent,
4624 DWORD CreationFlags,
4625 PSP_DEVINFO_DATA DeviceInfoData)
4626 {
4627 LPWSTR DeviceNameW = NULL;
4628 LPWSTR DeviceDescriptionW = NULL;
4629 BOOL bResult;
4630
4631 TRACE("\n");
4632
4633 if (DeviceName)
4634 {
4635 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
4636 if (DeviceNameW == NULL) return FALSE;
4637 }
4638 if (DeviceDescription)
4639 {
4640 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
4641 if (DeviceDescriptionW == NULL)
4642 {
4643 if (DeviceNameW) MyFree(DeviceNameW);
4644 return FALSE;
4645 }
4646 }
4647
4648 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
4649 ClassGuid, DeviceDescriptionW,
4650 hwndParent, CreationFlags,
4651 DeviceInfoData);
4652
4653 if (DeviceNameW) MyFree(DeviceNameW);
4654 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
4655
4656 return bResult;
4657 }
4658
4659 /***********************************************************************
4660 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4661 */
4662 BOOL WINAPI SetupDiCreateDeviceInfoW(
4663 HDEVINFO DeviceInfoSet,
4664 PCWSTR DeviceName,
4665 CONST GUID *ClassGuid,
4666 PCWSTR DeviceDescription,
4667 HWND hwndParent,
4668 DWORD CreationFlags,
4669 PSP_DEVINFO_DATA DeviceInfoData)
4670 {
4671 struct DeviceInfoSet *list;
4672 BOOL ret = FALSE;
4673
4674 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
4675 debugstr_guid(ClassGuid), DeviceDescription,
4676 hwndParent, CreationFlags, DeviceInfoData);
4677
4678 if (!DeviceInfoSet)
4679 SetLastError(ERROR_INVALID_HANDLE);
4680 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4681 SetLastError(ERROR_INVALID_HANDLE);
4682 else if (!ClassGuid)
4683 SetLastError(ERROR_INVALID_PARAMETER);
4684 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
4685 SetLastError(ERROR_CLASS_MISMATCH);
4686 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
4687 {
4688 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
4689 SetLastError(ERROR_INVALID_FLAGS);
4690 }
4691 else
4692 {
4693 SP_DEVINFO_DATA DevInfo;
4694
4695 if (CreationFlags & DICD_GENERATE_ID)
4696 {
4697 /* Generate a new unique ID for this device */
4698 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4699 FIXME("not implemented\n");
4700 }
4701 else
4702 {
4703 /* Device name is fully qualified. Try to open it */
4704 BOOL rc;
4705
4706 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
4707 rc = SetupDiOpenDeviceInfoW(
4708 DeviceInfoSet,
4709 DeviceName,
4710 NULL, /* hwndParent */
4711 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
4712 &DevInfo);
4713
4714 if (rc)
4715 {
4716 /* SetupDiOpenDeviceInfoW has already added
4717 * the device info to the device info set
4718 */
4719 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
4720 }
4721 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
4722 {
4723 struct DeviceInfoElement *deviceInfo;
4724
4725 if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
4726 {
4727 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4728
4729 if (!DeviceInfoData)
4730 ret = TRUE;
4731 else
4732 {
4733 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
4734 {
4735 SetLastError(ERROR_INVALID_USER_BUFFER);
4736 }
4737 else
4738 {
4739 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
4740 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
4741 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4742 ret = TRUE;
4743 }
4744 }
4745 }
4746 }
4747 }
4748 }
4749
4750 TRACE("Returning %d\n", ret);
4751 return ret;
4752 }
4753
4754 /***********************************************************************
4755 * Helper functions for SetupDiBuildDriverInfoList
4756 */
4757 static BOOL
4758 AddDriverToList(
4759 IN PLIST_ENTRY DriverListHead,
4760 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4761 IN LPGUID ClassGuid,
4762 IN INFCONTEXT ContextDevice,
4763 IN struct InfFileDetails *InfFileDetails,
4764 IN LPCWSTR InfFile,
4765 IN LPCWSTR ProviderName,
4766 IN LPCWSTR ManufacturerName,
4767 IN LPCWSTR MatchingId,
4768 FILETIME DriverDate,
4769 DWORDLONG DriverVersion,
4770 IN DWORD Rank)
4771 {
4772 struct DriverInfoElement *driverInfo = NULL;
4773 HANDLE hFile = INVALID_HANDLE_VALUE;
4774 DWORD RequiredSize = 128; /* Initial buffer size */
4775 BOOL Result = FALSE;
4776 PLIST_ENTRY PreviousEntry;
4777 LPWSTR InfInstallSection = NULL;
4778 BOOL ret = FALSE;
4779
4780 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
4781 if (!driverInfo)
4782 {
4783 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4784 goto cleanup;
4785 }
4786 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
4787
4788 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
4789 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
4790
4791 /* Copy InfFileName field */
4792 wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
4793 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
4794
4795 /* Fill InfDate field */
4796 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4797 GENERIC_READ, FILE_SHARE_READ,
4798 NULL, OPEN_EXISTING, 0, NULL);
4799 if (hFile == INVALID_HANDLE_VALUE)
4800 goto cleanup;
4801 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4802 if (!Result)
4803 goto cleanup;*/
4804
4805 /* Fill SectionName field */
4806 Result = SetupGetStringFieldW(
4807 &ContextDevice,
4808 1,
4809 driverInfo->Details.SectionName, LINE_LEN,
4810 NULL);
4811 if (!Result)
4812 goto cleanup;
4813
4814 /* Fill DrvDescription field */
4815 Result = SetupGetStringFieldW(
4816 &ContextDevice,
4817 0, /* Field index */
4818 driverInfo->Details.DrvDescription, LINE_LEN,
4819 NULL);
4820
4821 /* Copy MatchingId information */
4822 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4823 if (!driverInfo->MatchingId)
4824 {
4825 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4826 goto cleanup;
4827 }
4828 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4829
4830 /* Get inf install section */
4831 Result = FALSE;
4832 RequiredSize = 128; /* Initial buffer size */
4833 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4834 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4835 {
4836 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4837 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4838 if (!InfInstallSection)
4839 goto cleanup;
4840 Result = SetupGetStringFieldW(
4841 &ContextDevice,
4842 1, /* Field index */
4843 InfInstallSection, RequiredSize,
4844 &RequiredSize);
4845 }
4846 if (!Result)
4847 goto cleanup;
4848
4849 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4850 driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
4851
4852 driverInfo->DriverRank = Rank;
4853 memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
4854 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
4855 driverInfo->Info.DriverType = DriverType;
4856 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
4857 wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
4858 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
4859 wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
4860 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
4861 if (ProviderName)
4862 {
4863 wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
4864 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
4865 }
4866 else
4867 driverInfo->Info.ProviderName[0] = '\0';
4868 driverInfo->Info.DriverDate = DriverDate;
4869 driverInfo->Info.DriverVersion = DriverVersion;
4870 ReferenceInfFile(InfFileDetails);
4871 driverInfo->InfFileDetails = InfFileDetails;
4872
4873 /* Insert current driver in driver list, according to its rank */
4874 PreviousEntry = DriverListHead->Flink;
4875 while (PreviousEntry != DriverListHead)
4876 {
4877 struct DriverInfoElement *CurrentDriver;
4878 CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
4879 if (CurrentDriver->DriverRank > Rank ||
4880 (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
4881 {
4882 /* Insert before the current item */
4883 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
4884 break;
4885 }
4886 PreviousEntry = PreviousEntry->Flink;
4887 }
4888 if (PreviousEntry == DriverListHead)
4889 {
4890 /* Insert at the end of the list */
4891 InsertTailList(DriverListHead, &driverInfo->ListEntry);
4892 }
4893
4894 ret = TRUE;
4895
4896 cleanup:
4897 if (!ret)
4898 {
4899 if (driverInfo)
4900 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
4901 HeapFree(GetProcessHeap(), 0, driverInfo);
4902 }
4903 if (hFile != INVALID_HANDLE_VALUE)
4904 CloseHandle(hFile);
4905 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4906
4907 return ret;
4908 }
4909
4910 static BOOL
4911 GetVersionInformationFromInfFile(
4912 IN HINF hInf,
4913 OUT LPGUID ClassGuid,
4914 OUT LPWSTR* pProviderName,
4915 OUT FILETIME* DriverDate,
4916 OUT DWORDLONG* DriverVersion)
4917 {
4918 DWORD RequiredSize;
4919 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
4920 LPWSTR DriverVer = NULL;
4921 LPWSTR ProviderName = NULL;
4922 LPWSTR pComma; /* Points into DriverVer */
4923 LPWSTR pVersion = NULL; /* Points into DriverVer */
4924 SYSTEMTIME SystemTime;
4925 BOOL Result;
4926 BOOL ret = FALSE; /* Final result */
4927
4928 /* Get class Guid */
4929 if (!SetupGetLineTextW(
4930 NULL, /* Context */
4931 hInf,
4932 L"Version", L"ClassGUID",
4933 guidW, sizeof(guidW),
4934 NULL /* Required size */))
4935 {
4936 goto cleanup;
4937 }
4938 guidW[37] = '\0'; /* Replace the } by a NULL character */
4939 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
4940 {
4941 SetLastError(ERROR_GEN_FAILURE);
4942 goto cleanup;
4943 }
4944
4945 /* Get provider name */
4946 Result = SetupGetLineTextW(
4947 NULL, /* Context */
4948 hInf, L"Version", L"Provider",
4949 NULL, 0,
4950 &RequiredSize);
4951 if (Result)
4952 {
4953 /* We know know the needed buffer size */
4954 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4955 if (!ProviderName)
4956 {
4957 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4958 goto cleanup;
4959 }
4960 Result = SetupGetLineTextW(
4961 NULL, /* Context */
4962 hInf, L"Version", L"Provider",
4963 ProviderName, RequiredSize,
4964 &RequiredSize);
4965 }
4966 if (!Result)
4967 goto cleanup;
4968 *pProviderName = ProviderName;
4969
4970 /* Read the "DriverVer" value */
4971 Result = SetupGetLineTextW(
4972 NULL, /* Context */
4973 hInf, L"Version", L"DriverVer",
4974 NULL, 0,
4975 &RequiredSize);
4976 if (Result)
4977 {
4978 /* We know know the needed buffer size */
4979 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4980 if (!DriverVer)
4981 {
4982 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4983 goto cleanup;
4984 }
4985 Result = SetupGetLineTextW(
4986 NULL, /* Context */
4987 hInf, L"Version", L"DriverVer",
4988 DriverVer, RequiredSize,
4989 &RequiredSize);
4990 }
4991 if (!Result)
4992 goto cleanup;
4993
4994 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4995 pComma = wcschr(DriverVer, ',');
4996 if (pComma != NULL)
4997 {
4998 *pComma = UNICODE_NULL;
4999 pVersion = pComma + 1;
5000 }
5001 /* Get driver date version. Invalid date = 00/00/00 */
5002 memset(DriverDate, 0, sizeof(FILETIME));
5003 if (wcslen(DriverVer) == 10
5004 && (DriverVer[2] == '-' || DriverVer[2] == '/')
5005 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
5006 {
5007 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
5008 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
5009 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
5010 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
5011 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
5012 SystemTimeToFileTime(&SystemTime, DriverDate);
5013 }
5014 /* Get driver version. Invalid version = 0.0.0.0 */
5015 *DriverVersion = 0;
5016 if (pVersion)
5017 {
5018 WORD Major, Minor = 0, Revision = 0, Build = 0;
5019 LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
5020 LARGE_INTEGER fullVersion;
5021
5022 pMinor = strchrW(pVersion, '.');
5023 if (pMinor)
5024 {
5025 *pMinor = 0;
5026 pRevision = strchrW(++pMinor, '.');
5027 Minor = atoiW(pMinor);
5028 }
5029 if (pRevision)
5030 {
5031 *pRevision = 0;
5032 pBuild = strchrW(++pRevision, '.');
5033 Revision = atoiW(pRevision);
5034 }
5035 if (pBuild)
5036 {
5037 *pBuild = 0;
5038 pBuild++;
5039 Build = atoiW(pBuild);
5040 }
5041 Major = atoiW(pVersion);
5042 fullVersion.u.HighPart = Major << 16 | Minor;
5043 fullVersion.u.LowPart = Revision << 16 | Build;
5044 memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
5045 }
5046
5047 ret = TRUE;
5048
5049 cleanup:
5050 if (!ret)
5051 HeapFree(GetProcessHeap(), 0, ProviderName);
5052 HeapFree(GetProcessHeap(), 0, DriverVer);
5053
5054 return ret;
5055 }
5056
5057 /***********************************************************************
5058 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5059 */
5060 BOOL WINAPI
5061 SetupDiBuildDriverInfoList(
5062 IN HDEVINFO DeviceInfoSet,
5063 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5064 IN DWORD DriverType)
5065 {
5066 struct DeviceInfoSet *list;
5067 SP_DEVINSTALL_PARAMS_W InstallParams;
5068 PVOID Buffer = NULL;
5069 struct InfFileDetails *currentInfFileDetails = NULL;
5070 LPWSTR ProviderName = NULL;
5071 LPWSTR ManufacturerName = NULL;
5072 WCHAR ManufacturerSection[LINE_LEN + 1];
5073 LPWSTR HardwareIDs = NULL;
5074 LPWSTR CompatibleIDs = NULL;
5075 LPWSTR FullInfFileName = NULL;
5076 FILETIME DriverDate;
5077 DWORDLONG DriverVersion = 0;
5078 DWORD RequiredSize;
5079 BOOL ret = FALSE;
5080
5081 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
5082
5083 if (!DeviceInfoSet)
5084 SetLastError(ERROR_INVALID_HANDLE);
5085 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5086 SetLastError(ERROR_INVALID_HANDLE);
5087 else if (list->HKLM != HKEY_LOCAL_MACHINE)
5088 SetLastError(ERROR_INVALID_HANDLE);
5089 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5090 SetLastError(ERROR_INVALID_PARAMETER);
5091 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
5092 SetLastError(ERROR_INVALID_PARAMETER);
5093 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5094 SetLastError(ERROR_INVALID_PARAMETER);
5095 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5096 SetLastError(ERROR_INVALID_USER_BUFFER);
5097 else
5098 {
5099 BOOL Result;
5100
5101 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
5102 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5103 if (!Result)
5104 goto done;
5105
5106 if (DriverType == SPDIT_COMPATDRIVER)
5107 {
5108 /* Get hardware IDs list */
5109 Result = FALSE;
5110 RequiredSize = 512; /* Initial buffer size */
5111 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5112 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5113 {
5114 HeapFree(GetProcessHeap(), 0, HardwareIDs);
5115 HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
5116 if (!HardwareIDs)
5117 {
5118 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5119 goto done;
5120 }
5121 Result = SetupDiGetDeviceRegistryPropertyW(
5122 DeviceInfoSet,
5123 DeviceInfoData,
5124 SPDRP_HARDWAREID,
5125 NULL,
5126 (PBYTE)HardwareIDs,
5127 RequiredSize,
5128 &RequiredSize);
5129 }
5130 if (!Result)
5131 goto done;
5132
5133 /* Get compatible IDs list */
5134 Result = FALSE;
5135 RequiredSize = 512; /* Initial buffer size */
5136 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5137 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5138 {
5139 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5140 CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
5141 if (!CompatibleIDs)
5142 {
5143 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5144 goto done;
5145 }
5146 Result = SetupDiGetDeviceRegistryPropertyW(
5147 DeviceInfoSet,
5148 DeviceInfoData,
5149 SPDRP_COMPATIBLEIDS,
5150 NULL,
5151 (PBYTE)CompatibleIDs,
5152 RequiredSize,
5153 &RequiredSize);
5154 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
5155 {
5156 /* No compatible ID for this device */
5157 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5158 CompatibleIDs = NULL;
5159 Result = TRUE;
5160 }
5161 }
5162 if (!Result)
5163 goto done;
5164 }
5165
5166 /* Enumerate .inf files */
5167 Result = FALSE;
5168 RequiredSize = 32768; /* Initial buffer size */
5169 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5170 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5171 {
5172 HeapFree(GetProcessHeap(), 0, Buffer);
5173 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5174 if (!Buffer)
5175 {
5176 Result = FALSE;
5177 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5178 break;
5179 }
5180 Result = SetupGetInfFileListW(
5181 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
5182 INF_STYLE_WIN4,
5183 Buffer, RequiredSize,
5184 &RequiredSize);
5185 }
5186 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
5187 {
5188 /* No .inf file in specified directory. So, we should
5189 * success as we created an empty driver info list.
5190 */
5191 ret = TRUE;
5192 goto done;
5193 }
5194 if (Result)
5195 {
5196 LPCWSTR filename;
5197 LPWSTR pFullFilename;
5198
5199 if (*InstallParams.DriverPath)
5200 {
5201 DWORD len;
5202 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
5203 if (len == 0)
5204 goto done;
5205 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
5206 if (!FullInfFileName)
5207 goto done;
5208 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
5209 if (len == 0)
5210 goto done;
5211 if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
5212 wcscat(FullInfFileName, L"\\");
5213 pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
5214 }
5215 else
5216 {
5217 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
5218 if (!FullInfFileName)
5219 goto done;
5220 pFullFilename = &FullInfFileName[0];
5221 }
5222
5223 for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
5224 {
5225 INFCONTEXT ContextManufacturer, ContextDevice;
5226 GUID ClassGuid;
5227
5228 wcscpy(pFullFilename, filename);
5229 TRACE("Opening file %S\n", FullInfFileName);
5230
5231 currentInfFileDetails = HeapAlloc(
5232 GetProcessHeap(),
5233 0,
5234 FIELD_OFFSET(struct InfFileDetails, FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) + UNICODE_NULL);
5235 if (!currentInfFileDetails)
5236 continue;
5237 memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
5238 wcscpy(currentInfFileDetails->FullInfFileName, FullInfFileName);
5239
5240 currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
5241 ReferenceInfFile(currentInfFileDetails);
5242 if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
5243 {
5244 HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
5245 currentInfFileDetails = NULL;
5246 continue;
5247 }
5248
5249 if (!GetVersionInformationFromInfFile(
5250 currentInfFileDetails->hInf,
5251 &ClassGuid,
5252 &ProviderName,
5253 &DriverDate,
5254 &DriverVersion))
5255 {
5256 SetupCloseInfFile(currentInfFileDetails->hInf);
5257 HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
5258 currentInfFileDetails = NULL;
5259 continue;
5260 }
5261
5262 if (DriverType == SPDIT_CLASSDRIVER)
5263 {
5264 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5265 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
5266 {
5267 goto next;
5268 }
5269 }
5270
5271 /* Get the manufacturers list */
5272 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
5273 while (Result)
5274 {
5275 Result = SetupGetStringFieldW(
5276 &ContextManufacturer,
5277 0, /* Field index */
5278 NULL, 0,
5279 &RequiredSize);
5280 if (Result)
5281 {
5282 /* We got the needed size for the buffer */
5283 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5284 if (!ManufacturerName)
5285 {
5286 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5287 goto done;
5288 }
5289 Result = SetupGetStringFieldW(
5290 &ContextManufacturer,
5291 0, /* Field index */
5292 ManufacturerName, RequiredSize,
5293 &RequiredSize);
5294 }
5295 /* Get manufacturer section name */
5296 Result = SetupGetStringFieldW(
5297 &ContextManufacturer,
5298 1, /* Field index */
5299 ManufacturerSection, LINE_LEN,
5300 &RequiredSize);
5301 if (Result)
5302 {
5303 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
5304 /* Add (possible) extension to manufacturer section name */
5305 Result = SetupDiGetActualSectionToInstallW(
5306 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
5307 if (Result)
5308 {
5309 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
5310 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
5311 }
5312 }
5313 while (Result)
5314 {
5315 if (DriverType == SPDIT_CLASSDRIVER)
5316 {
5317 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5318 if (!AddDriverToList(
5319 &list->DriverListHead,
5320 DriverType,
5321 &ClassGuid,
5322 ContextDevice,
5323 currentInfFileDetails,
5324 filename,
5325 ProviderName,
5326 ManufacturerName,
5327 NULL,
5328 DriverDate, DriverVersion,
5329 0))
5330 {
5331 break;
5332 }
5333 }
5334 else /* DriverType = SPDIT_COMPATDRIVER */
5335 {
5336 /* 1. Get all fields */
5337 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
5338 DWORD DriverRank;
5339 DWORD i;
5340 LPCWSTR currentId;
5341 BOOL DriverAlreadyAdded;
5342
5343 for (i = 2; i <= FieldCount; i++)
5344 {
5345 LPWSTR DeviceId = NULL;
5346 Result = FALSE;
5347 RequiredSize = 128; /* Initial buffer size */
5348 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5349 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5350 {
5351 HeapFree(GetProcessHeap(), 0, DeviceId);
5352 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5353 if (!DeviceId)
5354 {
5355 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5356 goto done;
5357 }
5358 Result = SetupGetStringFieldW(
5359 &ContextDevice,
5360 i,
5361 DeviceId, RequiredSize,
5362 &RequiredSize);
5363 }
5364 if (!Result)
5365 {
5366 HeapFree(GetProcessHeap(), 0, DeviceId);
5367 goto done;
5368 }
5369 DriverAlreadyAdded = FALSE;
5370 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
5371 {
5372 if (wcsicmp(DeviceId, currentId) == 0)
5373 {
5374 AddDriverToList(
5375 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
5376 DriverType,
5377 &ClassGuid,
5378 ContextDevice,
5379 currentInfFileDetails,
5380 filename,
5381 ProviderName,
5382 ManufacturerName,
5383 currentId,
5384 DriverDate, DriverVersion,
5385 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
5386 DriverAlreadyAdded = TRUE;
5387 }
5388 }
5389 if (CompatibleIDs)
5390 {
5391 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
5392 {
5393 if (wcsicmp(DeviceId, currentId) == 0)
5394 {
5395 AddDriverToList(
5396 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
5397 DriverType,
5398 &ClassGuid,
5399 ContextDevice,
5400 currentInfFileDetails,
5401 filename,
5402 ProviderName,
5403 ManufacturerName,
5404 currentId,
5405 DriverDate, DriverVersion,
5406 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
5407 DriverAlreadyAdded = TRUE;
5408 }
5409 }
5410 }
5411 HeapFree(GetProcessHeap(), 0, DeviceId);
5412 }
5413 }
5414 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
5415 }
5416
5417 HeapFree(GetProcessHeap(), 0, ManufacturerName);
5418 ManufacturerName = NULL;
5419 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
5420 }
5421
5422 ret = TRUE;
5423 next:
5424 HeapFree(GetProcessHeap(), 0, ProviderName);
5425 ProviderName = NULL;
5426
5427 DereferenceInfFile(currentInfFileDetails);
5428 currentInfFileDetails = NULL;
5429 }
5430 ret = TRUE;
5431 }
5432 }
5433
5434 done:
5435 if (ret)
5436 {
5437 if (DeviceInfoData)
5438 {
5439 InstallParams.Flags |= DI_DIDCOMPAT;
5440 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
5441 }
5442 else
5443 {
5444 InstallParams.Flags |= DI_DIDCLASS;
5445 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
5446 }
5447 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5448 }
5449
5450 HeapFree(GetProcessHeap(), 0, ProviderName);
5451 HeapFree(GetProcessHeap(), 0, ManufacturerName);
5452 HeapFree(GetProcessHeap(), 0, HardwareIDs);
5453 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5454 HeapFree(GetProcessHeap(), 0, FullInfFileName);
5455 if (currentInfFileDetails)
5456 DereferenceInfFile(currentInfFileDetails);
5457 HeapFree(GetProcessHeap(), 0, Buffer);
5458
5459 TRACE("Returning %d\n", ret);
5460 return ret;
5461 }
5462
5463 /***********************************************************************
5464 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5465 */
5466 BOOL WINAPI
5467 SetupDiDeleteDeviceInfo(
5468 IN HDEVINFO DeviceInfoSet,
5469 IN PSP_DEVINFO_DATA DeviceInfoData)
5470 {
5471 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5472
5473 FIXME("not implemented\n");
5474 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5475 return FALSE;
5476 }
5477
5478
5479 /***********************************************************************
5480 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5481 */
5482 BOOL WINAPI
5483 SetupDiDestroyDriverInfoList(
5484 IN HDEVINFO DeviceInfoSet,
5485 IN PSP_DEVINFO_DATA DeviceInfoData,
5486 IN DWORD DriverType)
5487 {
5488 struct DeviceInfoSet *list;
5489 BOOL ret = FALSE;
5490
5491 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
5492
5493 if (!DeviceInfoSet)
5494 SetLastError(ERROR_INVALID_HANDLE);
5495 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5496 SetLastError(ERROR_INVALID_HANDLE);
5497 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5498 SetLastError(ERROR_INVALID_PARAMETER);
5499 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5500 SetLastError(ERROR_INVALID_PARAMETER);
5501 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5502 SetLastError(ERROR_INVALID_USER_BUFFER);
5503 else
5504 {
5505 PLIST_ENTRY ListEntry;
5506 struct DriverInfoElement *driverInfo;
5507 SP_DEVINSTALL_PARAMS_W InstallParams;
5508
5509 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5510 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
5511 goto done;
5512
5513 if (!DeviceInfoData)
5514 /* Fall back to destroying class driver list */
5515 DriverType = SPDIT_CLASSDRIVER;
5516
5517 if (DriverType == SPDIT_CLASSDRIVER)
5518 {
5519 while (!IsListEmpty(&list->DriverListHead))
5520 {
5521 ListEntry = RemoveHeadList(&list->DriverListHead);
5522 driverInfo = (struct DriverInfoElement *)ListEntry;
5523 DestroyDriverInfoElement(driverInfo);
5524 }
5525 InstallParams.Reserved = 0;
5526 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
5527 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
5528 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
5529 }
5530 else
5531 {
5532 SP_DEVINSTALL_PARAMS_W InstallParamsSet;
5533 struct DeviceInfoElement *deviceInfo;
5534
5535 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5536 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
5537 goto done;
5538 deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5539 while (!IsListEmpty(&deviceInfo->DriverListHead))
5540 {
5541 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
5542 driverInfo = (struct DriverInfoElement *)ListEntry;
5543 if ((PVOID)InstallParamsSet.Reserved == driverInfo)
5544 {
5545 InstallParamsSet.Reserved = 0;
5546 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
5547 }
5548 DestroyDriverInfoElement(driverInfo);
5549 }
5550 InstallParams.Reserved = 0;
5551 InstallParams.Flags &= ~DI_DIDCOMPAT;
5552 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
5553 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5554 }
5555 }
5556
5557 done:
5558 TRACE("Returning %d\n", ret);
5559 return ret;
5560 }
5561
5562
5563 /***********************************************************************
5564 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5565 */
5566 BOOL WINAPI
5567 SetupDiOpenDeviceInfoA(
5568 IN HDEVINFO DeviceInfoSet,
5569 IN PCSTR DeviceInstanceId,
5570 IN HWND hwndParent OPTIONAL,
5571 IN DWORD OpenFlags,
5572 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5573 {
5574 LPWSTR DeviceInstanceIdW = NULL;
5575 BOOL bResult;
5576
5577 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
5578
5579 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
5580 if (DeviceInstanceIdW == NULL)
5581 return FALSE;
5582
5583 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
5584 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
5585
5586 MyFree(DeviceInstanceIdW);
5587
5588 return bResult;
5589 }
5590
5591
5592 /***********************************************************************
5593 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5594 */
5595 BOOL WINAPI
5596 SetupDiOpenDeviceInfoW(
5597 IN HDEVINFO DeviceInfoSet,
5598 IN PCWSTR DeviceInstanceId,
5599 IN HWND hwndParent OPTIONAL,
5600 IN DWORD OpenFlags,
5601 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5602 {
5603 struct DeviceInfoSet *list;
5604 HKEY hEnumKey, hKey;
5605 DWORD rc;
5606 BOOL ret = FALSE;
5607
5608 TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
5609
5610 if (OpenFlags & DIOD_CANCEL_REMOVE)
5611 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5612
5613 if (!DeviceInfoSet)
5614 SetLastError(ERROR_INVALID_HANDLE);
5615 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5616 SetLastError(ERROR_INVALID_HANDLE);
5617 else if (!DeviceInstanceId)
5618 SetLastError(ERROR_INVALID_PARAMETER);
5619 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
5620 {
5621 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
5622 SetLastError(ERROR_INVALID_FLAGS);
5623 }
5624 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5625 SetLastError(ERROR_INVALID_USER_BUFFER);
5626 else
5627 {
5628 struct DeviceInfoElement *deviceInfo = NULL;
5629 /* Search if device already exists in DeviceInfoSet.
5630 * If yes, return the existing element
5631 * If no, create a new element using informations in registry
5632 */
5633 PLIST_ENTRY ItemList = list->ListHead.Flink;
5634 while (ItemList != &list->ListHead)
5635 {
5636 // TODO
5637 //if (good one)
5638 // break;
5639 FIXME("not implemented\n");
5640 ItemList = ItemList->Flink;
5641 }
5642
5643 if (deviceInfo)
5644 {
5645 /* good one found */
5646 ret = TRUE;
5647 }
5648 else
5649 {
5650 /* Open supposed registry key */
5651 rc = RegOpenKeyExW(
5652 list->HKLM,
5653 EnumKeyName,
5654 0, /* Options */
5655 KEY_ENUMERATE_SUB_KEYS,
5656 &hEnumKey);
5657 if (rc != ERROR_SUCCESS)
5658 {
5659 SetLastError(rc);
5660 return FALSE;
5661 }
5662 rc = RegOpenKeyExW(
5663 hEnumKey,
5664 DeviceInstanceId,
5665 0, /* Options */
5666 KEY_QUERY_VALUE,
5667 &hKey);
5668 RegCloseKey(hEnumKey);
5669 if (rc != ERROR_SUCCESS)
5670 {
5671 if (rc == ERROR_FILE_NOT_FOUND)
5672 rc = ERROR_NO_SUCH_DEVINST;
5673 SetLastError(rc);
5674 return FALSE;
5675 }
5676
5677 /* FIXME: try to get ClassGUID from registry, instead of
5678 * sending GUID_NULL to CreateDeviceInfoElement
5679 */
5680 if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
5681 {
5682 RegCloseKey(hKey);
5683 return FALSE;
5684 }
5685 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
5686
5687 RegCloseKey(hKey);
5688 ret = TRUE;
5689 }
5690
5691 if (ret && deviceInfo && DeviceInfoData)
5692 {
5693 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
5694 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
5695 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
5696 }
5697 }
5698
5699 return ret;
5700 }
5701
5702
5703 /***********************************************************************
5704 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5705 */
5706 BOOL WINAPI
5707 SetupDiEnumDriverInfoA(
5708 IN HDEVINFO DeviceInfoSet,
5709 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5710 IN DWORD DriverType,
5711 IN DWORD MemberIndex,
5712 OUT PSP_DRVINFO_DATA_A DriverInfoData)
5713 {
5714 SP_DRVINFO_DATA_V2_W driverInfoData2W;
5715 BOOL ret = FALSE;
5716
5717 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
5718 DriverType, MemberIndex, DriverInfoData);
5719
5720 if (DriverInfoData == NULL)
5721 SetLastError(ERROR_INVALID_PARAMETER);
5722 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
5723 SetLastError(ERROR_INVALID_USER_BUFFER);
5724 else
5725 {
5726 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5727 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
5728 DriverType, MemberIndex, &driverInfoData2W);
5729
5730 if (ret)
5731 {
5732 /* Do W->A conversion */
5733 DriverInfoData->DriverType = driverInfoData2W.DriverType;
5734 DriverInfoData->Reserved = driverInfoData2W.Reserved;
5735 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
5736 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
5737 {
5738 DriverInfoData->Description[0] = '\0';
5739 ret = FALSE;
5740 }
5741 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
5742 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
5743 {
5744 DriverInfoData->MfgName[0] = '\0';
5745 ret = FALSE;
5746 }
5747 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
5748 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
5749 {
5750 DriverInfoData->ProviderName[0] = '\0';
5751 ret = FALSE;
5752 }
5753 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5754 {
5755 /* Copy more fields */
5756 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
5757 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
5758 }
5759 }
5760 }
5761
5762 TRACE("Returning %d\n", ret);
5763 return ret;
5764 }
5765
5766
5767 /***********************************************************************
5768 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5769 */
5770 BOOL WINAPI
5771 SetupDiEnumDriverInfoW(
5772 IN HDEVINFO DeviceInfoSet,
5773 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5774 IN DWORD DriverType,
5775 IN DWORD MemberIndex,
5776 OUT PSP_DRVINFO_DATA_W DriverInfoData)
5777 {
5778 PLIST_ENTRY ListHead;
5779 BOOL ret = FALSE;
5780
5781 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
5782 DriverType, MemberIndex, DriverInfoData);
5783
5784 if (!DeviceInfoSet || !DriverInfoData)
5785 SetLastError(ERROR_INVALID_PARAMETER);
5786 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5787 SetLastError(ERROR_INVALID_HANDLE);
5788 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5789 SetLastError(ERROR_INVALID_HANDLE);
5790 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5791 SetLastError(ERROR_INVALID_PARAMETER);
5792 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
5793 SetLastError(ERROR_INVALID_PARAMETER);
5794 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5795 SetLastError(ERROR_INVALID_PARAMETER);
5796 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5797 SetLastError(ERROR_INVALID_USER_BUFFER);
5798 else
5799 {
5800 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5801 PLIST_ENTRY ItemList;
5802 if (DriverType == SPDIT_CLASSDRIVER ||
5803 devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
5804 {
5805 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
5806 }
5807 else
5808 {
5809 ListHead = &devInfo->DriverListHead;
5810 }
5811
5812 ItemList = ListHead->Flink;
5813 while (ItemList != ListHead && MemberIndex-- > 0)
5814 ItemList = ItemList->Flink;
5815 if (ItemList == ListHead)
5816 SetLastError(ERROR_NO_MORE_ITEMS);
5817 else
5818 {
5819 struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
5820
5821 memcpy(
5822 &DriverInfoData->DriverType,
5823 &DrvInfo->Info.DriverType,
5824 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
5825 ret = TRUE;
5826 }
5827 }
5828
5829 TRACE("Returning %d\n", ret);
5830 return ret;
5831 }
5832
5833
5834 /***********************************************************************
5835 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5836 */
5837 BOOL WINAPI
5838 SetupDiGetSelectedDriverA(
5839 IN HDEVINFO DeviceInfoSet,
5840 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5841 OUT PSP_DRVINFO_DATA_A DriverInfoData)
5842 {
5843 SP_DRVINFO_DATA_V2_W driverInfoData2W;
5844 BOOL ret = FALSE;
5845
5846 if (DriverInfoData == NULL)
5847 SetLastError(ERROR_INVALID_PARAMETER);
5848 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
5849 SetLastError(ERROR_INVALID_USER_BUFFER);
5850 else
5851 {
5852 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5853
5854 ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
5855 DeviceInfoData,
5856 &driverInfoData2W);
5857
5858 if (ret)
5859 {
5860 /* Do W->A conversion */
5861 DriverInfoData->DriverType = driverInfoData2W.DriverType;
5862 DriverInfoData->Reserved = driverInfoData2W.Reserved;
5863 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
5864 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
5865 {
5866 DriverInfoData->Description[0] = '\0';
5867 ret = FALSE;
5868 }
5869 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
5870 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
5871 {
5872 DriverInfoData->MfgName[0] = '\0';
5873 ret = FALSE;
5874 }
5875 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
5876 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
5877 {
5878 DriverInfoData->ProviderName[0] = '\0';
5879 ret = FALSE;
5880 }
5881 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5882 {
5883 /* Copy more fields */
5884 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
5885 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
5886 }
5887 }
5888 }
5889
5890 return ret;
5891 }
5892
5893
5894 /***********************************************************************
5895 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5896 */
5897 BOOL WINAPI
5898 SetupDiGetSelectedDriverW(
5899 IN HDEVINFO DeviceInfoSet,
5900 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5901 OUT PSP_DRVINFO_DATA_W DriverInfoData)
5902 {
5903 BOOL ret = FALSE;
5904
5905 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5906
5907 if (!DeviceInfoSet || !DriverInfoData)
5908 SetLastError(ERROR_INVALID_PARAMETER);
5909 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5910 SetLastError(ERROR_INVALID_HANDLE);
5911 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5912 SetLastError(ERROR_INVALID_HANDLE);
5913 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5914 SetLastError(ERROR_INVALID_USER_BUFFER);
5915 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5916 SetLastError(ERROR_INVALID_USER_BUFFER);
5917 else
5918 {
5919 SP_DEVINSTALL_PARAMS InstallParams;
5920
5921 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
5922 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
5923 {
5924 struct DriverInfoElement *driverInfo;
5925 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
5926 if (driverInfo == NULL)
5927 SetLastError(ERROR_NO_DRIVER_SELECTED);
5928 else
5929 {
5930 memcpy(
5931 &DriverInfoData->DriverType,
5932 &driverInfo->Info.DriverType,
5933 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
5934 ret = TRUE;
5935 }
5936 }
5937 }
5938
5939 TRACE("Returning %d\n", ret);
5940 return ret;
5941 }
5942
5943
5944 /***********************************************************************
5945 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5946 */
5947 BOOL WINAPI
5948 SetupDiSetSelectedDriverA(
5949 IN HDEVINFO DeviceInfoSet,
5950 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5951 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
5952 {
5953 SP_DRVINFO_DATA_V1_W DriverInfoDataW;
5954 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
5955 BOOL ret = FALSE;
5956
5957 if (DriverInfoData != NULL)
5958 {
5959 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
5960 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
5961 {
5962 SetLastError(ERROR_INVALID_PARAMETER);
5963 return FALSE;
5964 }
5965
5966 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5967 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5968
5969 if (DriverInfoDataW.Reserved == 0)
5970 {
5971 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5972
5973 /* convert the strings to unicode */
5974 if (!MultiByteToWideChar(CP_ACP,
5975 0,
5976 DriverInfoData->Description,
5977 LINE_LEN,
5978 DriverInfoDataW.Description,
5979 LINE_LEN) ||
5980 !MultiByteToWideChar(CP_ACP,
5981 0,
5982 DriverInfoData->ProviderName,
5983 LINE_LEN,
5984 DriverInfoDataW.ProviderName,
5985 LINE_LEN))
5986 {
5987 return FALSE;
5988 }
5989 }
5990
5991 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
5992 }
5993
5994 ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
5995 DeviceInfoData,
5996 pDriverInfoDataW);
5997
5998 if (ret && pDriverInfoDataW != NULL)
5999 {
6000 DriverInfoData->Reserved = DriverInfoDataW.Reserved;
6001 }
6002
6003 return ret;
6004 }
6005
6006
6007 /***********************************************************************
6008 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6009 */
6010 BOOL WINAPI
6011 SetupDiSetSelectedDriverW(
6012 IN HDEVINFO DeviceInfoSet,
6013 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6014 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
6015 {
6016 BOOL ret = FALSE;
6017
6018 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
6019
6020 if (!DeviceInfoSet)
6021 SetLastError(ERROR_INVALID_PARAMETER);
6022 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6023 SetLastError(ERROR_INVALID_HANDLE);
6024 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6025 SetLastError(ERROR_INVALID_HANDLE);
6026 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6027 SetLastError(ERROR_INVALID_USER_BUFFER);
6028 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6029 SetLastError(ERROR_INVALID_USER_BUFFER);
6030 else
6031 {
6032 struct DriverInfoElement **pDriverInfo;
6033 PLIST_ENTRY ListHead, ItemList;
6034
6035 if (DeviceInfoData)
6036 {
6037 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
6038 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
6039 }
6040 else
6041 {
6042 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
6043 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
6044 }
6045
6046 if (!DriverInfoData)
6047 {
6048 *pDriverInfo = NULL;
6049 ret = TRUE;
6050 }
6051 else
6052 {
6053 /* Search selected driver in list */
6054 ItemList = ListHead->Flink;
6055 while (ItemList != ListHead)
6056 {
6057 if (DriverInfoData->Reserved != 0)
6058 {
6059 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
6060 break;
6061 }
6062 else
6063 {
6064 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6065 struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
6066 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
6067 && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
6068 && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
6069 {
6070 break;
6071 }
6072 }
6073 }
6074 if (ItemList == ListHead)
6075 SetLastError(ERROR_INVALID_PARAMETER);
6076 else
6077 {
6078 *pDriverInfo = (struct DriverInfoElement *)ItemList;
6079 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
6080 ret = TRUE;
6081 TRACE("Choosing driver whose rank is 0x%lx\n",
6082 ((struct DriverInfoElement *)ItemList)->DriverRank);
6083 if (DeviceInfoData)
6084 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
6085 }
6086 }
6087 }
6088
6089 TRACE("Returning %d\n", ret);
6090 return ret;
6091 }
6092
6093 /***********************************************************************
6094 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6095 */
6096 BOOL WINAPI
6097 SetupDiGetDriverInfoDetailA(
6098 IN HDEVINFO DeviceInfoSet,
6099 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6100 IN PSP_DRVINFO_DATA_A DriverInfoData,
6101 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
6102 IN DWORD DriverInfoDetailDataSize,
6103 OUT PDWORD RequiredSize OPTIONAL)
6104 {
6105 SP_DRVINFO_DATA_V2_W DriverInfoDataW;
6106 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
6107 DWORD BufSize = 0;
6108 DWORD HardwareIDLen = 0;
6109 BOOL ret = FALSE;
6110
6111 /* do some sanity checks, the unicode version might do more thorough checks */
6112 if (DriverInfoData == NULL ||
6113 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
6114 (DriverInfoDetailData != NULL &&
6115 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
6116 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
6117 {
6118 SetLastError(ERROR_INVALID_PARAMETER);
6119 goto Cleanup;
6120 }
6121
6122 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6123 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
6124 {
6125 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
6126 }
6127 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
6128 {
6129 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
6130 }
6131 else
6132 {
6133 SetLastError(ERROR_INVALID_PARAMETER);
6134 goto Cleanup;
6135 }
6136 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
6137 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
6138
6139 /* convert the strings to unicode */
6140 if (MultiByteToWideChar(CP_ACP,
6141 0,
6142 DriverInfoData->Description,
6143 LINE_LEN,
6144 DriverInfoDataW.Description,
6145 LINE_LEN) &&
6146 MultiByteToWideChar(CP_ACP,
6147 0,
6148 DriverInfoData->MfgName,
6149 LINE_LEN,
6150 DriverInfoDataW.MfgName,
6151 LINE_LEN) &&
6152 MultiByteToWideChar(CP_ACP,
6153 0,
6154 DriverInfoData->ProviderName,
6155 LINE_LEN,
6156 DriverInfoDataW.ProviderName,
6157 LINE_LEN))
6158 {
6159 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
6160 {
6161 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
6162 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
6163 }
6164
6165 if (DriverInfoDetailData != NULL)
6166 {
6167 /* calculate the unicode buffer size from the ansi buffer size */
6168 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
6169 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
6170 (HardwareIDLen * sizeof(WCHAR));
6171
6172 DriverInfoDetailDataW = MyMalloc(BufSize);
6173 if (DriverInfoDetailDataW == NULL)
6174 {
6175 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6176 goto Cleanup;
6177 }
6178
6179 /* initialize the buffer */
6180 ZeroMemory(DriverInfoDetailDataW,
6181 BufSize);
6182 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
6183 }
6184
6185 /* call the unicode version */
6186 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
6187 DeviceInfoData,
6188 &DriverInfoDataW,
6189 DriverInfoDetailDataW,
6190 BufSize,
6191 RequiredSize);
6192
6193 if (ret)
6194 {
6195 if (DriverInfoDetailDataW != NULL)
6196 {
6197 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6198 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
6199 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
6200 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
6201 if (WideCharToMultiByte(CP_ACP,
6202 0,
6203 DriverInfoDetailDataW->SectionName,
6204 LINE_LEN,
6205 DriverInfoDetailData->SectionName,
6206 LINE_LEN,
6207 NULL,
6208 NULL) &&
6209 WideCharToMultiByte(CP_ACP,
6210 0,
6211 DriverInfoDetailDataW->InfFileName,
6212 MAX_PATH,
6213 DriverInfoDetailData->InfFileName,
6214 MAX_PATH,
6215 NULL,
6216 NULL) &&
6217 WideCharToMultiByte(CP_ACP,
6218 0,
6219 DriverInfoDetailDataW->DrvDescription,
6220 LINE_LEN,
6221 DriverInfoDetailData->DrvDescription,
6222 LINE_LEN,
6223 NULL,
6224 NULL) &&
6225 WideCharToMultiByte(CP_ACP,
6226 0,
6227 DriverInfoDetailDataW->HardwareID,
6228 HardwareIDLen,
6229 DriverInfoDetailData->HardwareID,
6230 HardwareIDLen,
6231 NULL,
6232 NULL))
6233 {
6234 DWORD len, cnt = 0;
6235 DWORD hwidlen = HardwareIDLen;
6236 CHAR *s = DriverInfoDetailData->HardwareID;
6237
6238 /* count the strings in the list */
6239 while (*s != '\0')
6240 {
6241 len = lstrlenA(s) + 1;
6242 if (hwidlen > len)
6243 {
6244 cnt++;
6245 s += len;
6246 hwidlen -= len;
6247 }
6248 else
6249 {
6250 /* looks like the string list wasn't terminated... */
6251 SetLastError(ERROR_INVALID_USER_BUFFER);
6252 ret = FALSE;
6253 break;
6254 }
6255 }
6256
6257 /* make sure CompatIDsOffset points to the second string in the
6258 list, if present */
6259 if (cnt > 1)
6260 {
6261 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
6262 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
6263 DriverInfoDetailData->CompatIDsOffset + 1;
6264 }
6265 else
6266 {
6267 DriverInfoDetailData->CompatIDsOffset = 0;
6268 DriverInfoDetailData->CompatIDsLength = 0;
6269 }
6270 }
6271 else
6272 {
6273 ret = FALSE;
6274 }
6275 }
6276
6277 if (RequiredSize != NULL)
6278 {
6279 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
6280 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
6281 }
6282 }
6283 }
6284
6285 Cleanup:
6286 if (DriverInfoDetailDataW != NULL)
6287 {
6288 MyFree(DriverInfoDetailDataW);
6289 }
6290
6291 return ret;
6292 }
6293
6294 /***********************************************************************
6295 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6296 */
6297 BOOL WINAPI
6298 SetupDiGetDriverInfoDetailW(
6299 IN HDEVINFO DeviceInfoSet,
6300 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6301 IN PSP_DRVINFO_DATA_W DriverInfoData,
6302 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
6303 IN DWORD DriverInfoDetailDataSize,
6304 OUT PDWORD RequiredSize OPTIONAL)
6305 {
6306 BOOL ret = FALSE;
6307
6308 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
6309 DriverInfoData, DriverInfoDetailData,
6310 DriverInfoDetailDataSize, RequiredSize);
6311
6312 if (!DeviceInfoSet)
6313 SetLastError(ERROR_INVALID_PARAMETER);
6314 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6315 SetLastError(ERROR_INVALID_HANDLE);
6316 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6317 SetLastError(ERROR_INVALID_HANDLE);
6318 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6319 SetLastError(ERROR_INVALID_USER_BUFFER);
6320 else if (!DriverInfoData)
6321 SetLastError(ERROR_INVALID_PARAMETER);
6322 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
6323 SetLastError(ERROR_INVALID_PARAMETER);
6324 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
6325 SetLastError(ERROR_INVALID_PARAMETER);
6326 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
6327 SetLastError(ERROR_INVALID_USER_BUFFER);
6328 else if (DriverInfoData->Reserved == 0)
6329 SetLastError(ERROR_NO_DRIVER_SELECTED);
6330 else
6331 {
6332 struct DriverInfoElement *driverInfoElement;
6333 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
6334
6335 memcpy(
6336 DriverInfoDetailData,
6337 &driverInfoElement->Details,
6338 driverInfoElement->Details.cbSize);
6339 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6340 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6341 */
6342 ret = TRUE;
6343 }
6344
6345 TRACE("Returning %d\n", ret);
6346 return ret;
6347 }
6348
6349 /***********************************************************************
6350 * SetupDiChangeState (SETUPAPI.@)
6351 */
6352 BOOL WINAPI
6353 SetupDiChangeState(
6354 IN HDEVINFO DeviceInfoSet,
6355 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6356 {
6357 PSP_PROPCHANGE_PARAMS PropChange;
6358 BOOL ret = FALSE;
6359
6360 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6361
6362 if (!DeviceInfoData)
6363 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChange;
6364 else
6365 PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChange;
6366 if (!PropChange)
6367 {
6368 SetLastError(ERROR_INVALID_PARAMETER);
6369 goto done;
6370 }
6371
6372 FIXME("Stub %p %p\n", DeviceInfoSet, DeviceInfoData);
6373 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
6374
6375 done:
6376 TRACE("Returning %d\n", ret);
6377 return ret;
6378 }
6379
6380 /***********************************************************************
6381 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6382 */
6383 BOOL WINAPI
6384 SetupDiSelectBestCompatDrv(
6385 IN HDEVINFO DeviceInfoSet,
6386 IN PSP_DEVINFO_DATA DeviceInfoData)
6387 {
6388 SP_DRVINFO_DATA_W drvInfoData;
6389 BOOL ret;
6390
6391 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6392
6393 /* Drivers are sorted by rank in the driver list, so
6394 * the first driver in the list is the best one.
6395 */
6396 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
6397 ret = SetupDiEnumDriverInfoW(
6398 DeviceInfoSet,
6399 DeviceInfoData,
6400 SPDIT_COMPATDRIVER,
6401 0, /* Member index */
6402 &drvInfoData);
6403
6404 if (ret)
6405 {
6406 ret = SetupDiSetSelectedDriverW(
6407 DeviceInfoSet,
6408 DeviceInfoData,
6409 &drvInfoData);
6410 }
6411
6412 TRACE("Returning %d\n", ret);
6413 return ret;
6414 }
6415
6416 /***********************************************************************
6417 * SetupDiInstallDriverFiles (SETUPAPI.@)
6418 */
6419 BOOL WINAPI
6420 SetupDiInstallDriverFiles(
6421 IN HDEVINFO DeviceInfoSet,
6422 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6423 {
6424 BOOL ret = FALSE;
6425
6426 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6427
6428 if (!DeviceInfoSet)
6429 SetLastError(ERROR_INVALID_PARAMETER);
6430 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6431 SetLastError(ERROR_INVALID_HANDLE);
6432 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6433 SetLastError(ERROR_INVALID_HANDLE);
6434 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6435 SetLastError(ERROR_INVALID_USER_BUFFER);
6436 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
6437 SetLastError(ERROR_NO_DRIVER_SELECTED);
6438 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
6439 SetLastError(ERROR_NO_DRIVER_SELECTED);
6440 else
6441 {
6442 SP_DEVINSTALL_PARAMS_W InstallParams;
6443 struct DriverInfoElement *SelectedDriver;
6444 WCHAR SectionName[MAX_PATH];
6445 DWORD SectionNameLength = 0;
6446
6447 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6448 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6449 if (!ret)
6450 goto done;
6451
6452 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
6453 if (!SelectedDriver)
6454 {
6455 SetLastError(ERROR_NO_DRIVER_SELECTED);
6456 goto done;
6457 }
6458
6459 ret = SetupDiGetActualSectionToInstallW(
6460 SelectedDriver->InfFileDetails->hInf,
6461 SelectedDriver->Details.SectionName,
6462 SectionName, MAX_PATH, &SectionNameLength, NULL);
6463 if (!ret)
6464 goto done;
6465
6466 if (!InstallParams.InstallMsgHandler)
6467 {
6468 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
6469 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
6470 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6471 }
6472 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6473 SelectedDriver->InfFileDetails->hInf, SectionName,
6474 SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
6475 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6476 DeviceInfoSet, DeviceInfoData);
6477 }
6478
6479 done:
6480 TRACE("Returning %d\n", ret);
6481 return ret;
6482 }
6483
6484 /***********************************************************************
6485 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6486 */
6487 BOOL WINAPI
6488 SetupDiRegisterCoDeviceInstallers(
6489 IN HDEVINFO DeviceInfoSet,
6490 IN PSP_DEVINFO_DATA DeviceInfoData)
6491 {
6492 BOOL ret = FALSE; /* Return value */
6493
6494 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6495
6496 if (!DeviceInfoSet)
6497 SetLastError(ERROR_INVALID_PARAMETER);
6498 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6499 SetLastError(ERROR_INVALID_HANDLE);
6500 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6501 SetLastError(ERROR_INVALID_HANDLE);
6502 else if (!DeviceInfoData)
6503 SetLastError(ERROR_INVALID_PARAMETER);
6504 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6505 SetLastError(ERROR_INVALID_USER_BUFFER);
6506 else
6507 {
6508 SP_DEVINSTALL_PARAMS_W InstallParams;
6509 struct DriverInfoElement *SelectedDriver;
6510 BOOL Result;
6511 DWORD DoAction;
6512 WCHAR SectionName[MAX_PATH];
6513 DWORD SectionNameLength = 0;
6514 HKEY hKey = INVALID_HANDLE_VALUE;
6515
6516 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6517 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6518 if (!Result)
6519 goto cleanup;
6520
6521 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
6522 if (SelectedDriver == NULL)
6523 {
6524 SetLastError(ERROR_NO_DRIVER_SELECTED);
6525 goto cleanup;
6526 }
6527
6528 /* Get .CoInstallers section name */
6529 Result = SetupDiGetActualSectionToInstallW(
6530 SelectedDriver->InfFileDetails->hInf,
6531 SelectedDriver->Details.SectionName,
6532 SectionName, MAX_PATH, &SectionNameLength, NULL);
6533 if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
6534 goto cleanup;
6535 wcscat(SectionName, L".CoInstallers");
6536
6537 /* Open/Create driver key information */
6538 #if _WIN32_WINNT >= 0x502
6539 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
6540 #else
6541 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
6542 #endif
6543 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
6544 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
6545 if (hKey == INVALID_HANDLE_VALUE)
6546 goto cleanup;
6547
6548 /* Install .CoInstallers section */
6549 DoAction = SPINST_REGISTRY;
6550 if (!(InstallParams.Flags & DI_NOFILECOPY))
6551 {
6552 DoAction |= SPINST_FILES;
6553 if (!InstallParams.InstallMsgHandler)
6554 {
6555 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
6556 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
6557 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6558 }
6559 }
6560 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6561 SelectedDriver->InfFileDetails->hInf, SectionName,
6562 DoAction, hKey, NULL, SP_COPY_NEWER,
6563 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6564 DeviceInfoSet, DeviceInfoData);
6565 if (!Result)
6566 goto cleanup;
6567
6568 ret = TRUE;
6569
6570 cleanup:
6571 if (hKey != INVALID_HANDLE_VALUE)
6572 RegCloseKey(hKey);
6573 }
6574
6575 TRACE("Returning %d\n", ret);
6576 return ret;
6577 }
6578
6579 /***********************************************************************
6580 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
6581 */
6582 BOOL WINAPI
6583 SetupDiInstallDeviceInterfaces(
6584 IN HDEVINFO DeviceInfoSet,
6585 IN PSP_DEVINFO_DATA DeviceInfoData)
6586 {
6587 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6588
6589 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
6590 //SetLastError(ERROR_GEN_FAILURE);
6591 //return FALSE;
6592 return TRUE;
6593 }
6594
6595 BOOL
6596 InfIsFromOEMLocation(
6597 IN PCWSTR FullName,
6598 OUT LPBOOL IsOEMLocation)
6599 {
6600 PWCHAR last;
6601
6602 last = strrchrW(FullName, '\\');
6603 if (!last)
6604 {
6605 /* No directory specified */
6606 *IsOEMLocation = FALSE;
6607 }
6608 else
6609 {
6610 WCHAR Windir[MAX_PATH];
6611 UINT ret;
6612
6613 ret = GetWindowsDirectory(Windir, MAX_PATH);
6614 if (ret == 0 || ret >= MAX_PATH)
6615 {
6616 SetLastError(ERROR_GEN_FAILURE);
6617 return FALSE;
6618 }
6619
6620 if (strncmpW(FullName, Windir, last - FullName) == 0)
6621 {
6622 /* The path is %SYSTEMROOT%\Inf */
6623 *IsOEMLocation = FALSE;
6624 }
6625 else
6626 {
6627 /* The file is in another place */
6628 *IsOEMLocation = TRUE;
6629 }
6630 }
6631 return TRUE;
6632 }
6633
6634 /***********************************************************************
6635 * SetupDiInstallDevice (SETUPAPI.@)
6636 */
6637 BOOL WINAPI
6638 SetupDiInstallDevice(
6639 IN HDEVINFO DeviceInfoSet,
6640 IN PSP_DEVINFO_DATA DeviceInfoData)
6641 {
6642 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6643 SP_DEVINSTALL_PARAMS_W InstallParams;
6644 struct DriverInfoElement *SelectedDriver;
6645 SYSTEMTIME DriverDate;
6646 WCHAR SectionName[MAX_PATH];
6647 WCHAR Buffer[32];
6648 DWORD SectionNameLength = 0;
6649 BOOL Result = FALSE;
6650 INFCONTEXT ContextService;
6651 INT Flags;
6652 ULONG DoAction;
6653 DWORD RequiredSize;
6654 LPCWSTR AssociatedService = NULL;
6655 LPWSTR pSectionName = NULL;
6656 WCHAR ClassName[MAX_CLASS_NAME_LEN];
6657 GUID ClassGuid;
6658 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
6659 BOOL RebootRequired = FALSE;
6660 HKEY hKey = INVALID_HANDLE_VALUE;
6661 HKEY hClassKey = INVALID_HANDLE_VALUE;
6662 BOOL NeedtoCopyFile;
6663 LARGE_INTEGER fullVersion;
6664 LONG rc;
6665 BOOL ret = FALSE; /* Return value */
6666
6667 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6668
6669 if (!DeviceInfoSet)
6670 SetLastError(ERROR_INVALID_PARAMETER);
6671 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6672 SetLastError(ERROR_INVALID_HANDLE);
6673 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6674 SetLastError(ERROR_INVALID_HANDLE);
6675 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6676 SetLastError(ERROR_INVALID_USER_BUFFER);
6677 else
6678 Result = TRUE;
6679
6680 if (!Result)
6681 {
6682 /* One parameter is bad */
6683 goto cleanup;
6684 }
6685
6686 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6687 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6688 if (!Result)
6689 goto cleanup;
6690
6691 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
6692 {
6693 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6694 goto cleanup;
6695 }
6696
6697 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
6698 if (SelectedDriver == NULL)
6699 {
6700 SetLastError(ERROR_NO_DRIVER_SELECTED);
6701 goto cleanup;
6702 }
6703
6704 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
6705
6706 Result = SetupDiGetActualSectionToInstallW(
6707 SelectedDriver->InfFileDetails->hInf,
6708 SelectedDriver->Details.SectionName,
6709 SectionName, MAX_PATH, &SectionNameLength, NULL);
6710 if (!Result || SectionNameLength > MAX_PATH - 9)
6711 goto cleanup;
6712 pSectionName = &SectionName[wcslen(SectionName)];
6713
6714 /* Get information from [Version] section */
6715 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
6716 goto cleanup;
6717 /* Format ClassGuid to a string */
6718 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
6719 goto cleanup;
6720 RequiredSize = lstrlenW(lpGuidString);
6721 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
6722 if (!lpFullGuidString)
6723 {
6724 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6725 goto cleanup;
6726 }
6727 lpFullGuidString[0] = '{';
6728 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
6729 lpFullGuidString[RequiredSize + 1] = '}';
6730 lpFullGuidString[RequiredSize + 2] = '\0';
6731
6732 /* Open/Create driver key information */
6733 #if _WIN32_WINNT >= 0x502
6734 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
6735 #else
6736 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
6737 #endif
6738 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
6739 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
6740 if (hKey == INVALID_HANDLE_VALUE)
6741 goto cleanup;
6742
6743 /* Install main section */
6744 DoAction = SPINST_REGISTRY;
6745 if (!(InstallParams.Flags & DI_NOFILECOPY))
6746 {
6747 DoAction |= SPINST_FILES;
6748 if (!InstallParams.InstallMsgHandler)
6749 {
6750 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
6751 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
6752 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6753 }
6754 }
6755 *pSectionName = '\0';
6756 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6757 SelectedDriver->InfFileDetails->hInf, SectionName,
6758 DoAction, hKey, NULL, SP_COPY_NEWER,
6759 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6760 DeviceInfoSet, DeviceInfoData);
6761 if (!Result)
6762 goto cleanup;
6763 if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
6764 {
6765 if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
6766 {
6767 /* Delete resources allocated by SetupInitDefaultQueueCallback */
6768 SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
6769 }
6770 }
6771 InstallParams.Flags |= DI_NOFILECOPY;
6772 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6773
6774 /* Write information to driver key */
6775 *pSectionName = UNICODE_NULL;
6776 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
6777 TRACE("Write information to driver key\n");
6778 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
6779 TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
6780 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
6781 TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
6782 TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
6783 TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
6784 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
6785 TRACE("ProviderName : '%S'\n", SelectedDriver->Info.ProviderName);
6786 swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
6787 rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
6788 if (rc == ERROR_SUCCESS)
6789 rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
6790 if (rc == ERROR_SUCCESS)
6791 rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
6792 if (rc == ERROR_SUCCESS)
6793 {
6794 swprintf(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
6795 rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
6796 }
6797 if (rc == ERROR_SUCCESS)
6798 rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
6799 if (rc == ERROR_SUCCESS)
6800 rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
6801 if (rc == ERROR_SUCCESS)
6802 rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
6803 if (rc == ERROR_SUCCESS)
6804 rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
6805 if (rc == ERROR_SUCCESS)
6806 rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
6807 if (rc != ERROR_SUCCESS)
6808 {
6809 SetLastError(rc);
6810 goto cleanup;
6811 }
6812 RegCloseKey(hKey);
6813 hKey = INVALID_HANDLE_VALUE;
6814
6815 /* FIXME: Process .LogConfigOverride section */
6816
6817 /* Install .Services section */
6818 wcscpy(pSectionName, L".Services");
6819 Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf, SectionName, NULL, &ContextService);
6820 while (Result)
6821 {
6822 LPWSTR ServiceName = NULL;
6823 LPWSTR ServiceSection = NULL;
6824
6825 Result = SetupGetStringFieldW(
6826 &ContextService,
6827 1, /* Field index */
6828 NULL, 0,
6829 &RequiredSize);
6830 if (!Result)
6831 goto nextservice;
6832 if (RequiredSize > 0)
6833 {
6834 /* We got the needed size for the buffer */
6835 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
6836 if (!ServiceName)
6837 {
6838 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6839 goto nextservice;
6840 }
6841 Result = SetupGetStringFieldW(
6842 &ContextService,
6843 1, /* Field index */
6844 ServiceName, RequiredSize,
6845 &RequiredSize);
6846 if (!Result)
6847 goto nextservice;
6848 }
6849 Result = SetupGetIntField(
6850 &ContextService,
6851 2, /* Field index */
6852 &Flags);
6853 if (!Result)
6854 {
6855 /* The field may be empty. Ignore the error */
6856 Flags = 0;
6857 }
6858 Result = SetupGetStringFieldW(
6859 &ContextService,
6860 3, /* Field index */
6861 NULL, 0,
6862 &RequiredSize);
6863 if (!Result)
6864 {
6865 if (GetLastError() == ERROR_INVALID_PARAMETER)
6866 {
6867 /* This first is probably missing. It is not
6868 * required, so ignore the error */
6869 RequiredSize = 0;
6870 Result = TRUE;
6871 }
6872 else
6873 goto nextservice;
6874 }
6875 if (RequiredSize > 0)
6876 {
6877 /* We got the needed size for the buffer */
6878 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
6879 if (!ServiceSection)
6880 {
6881 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6882 goto nextservice;
6883 }
6884 Result = SetupGetStringFieldW(
6885 &ContextService,
6886 3, /* Field index */
6887 ServiceSection, RequiredSize,
6888 &RequiredSize);
6889 if (!Result)
6890 goto nextservice;
6891
6892 SetLastError(ERROR_SUCCESS);
6893 Result = SetupInstallServicesFromInfSectionExW(
6894 SelectedDriver->InfFileDetails->hInf,
6895 ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
6896 }
6897 if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
6898 {
6899 AssociatedService = ServiceName;
6900 ServiceName = NULL;
6901 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
6902 RebootRequired = TRUE;
6903 }
6904 nextservice:
6905 HeapFree(GetProcessHeap(), 0, ServiceName);
6906 HeapFree(GetProcessHeap(), 0, ServiceSection);
6907 if (!Result)
6908 goto cleanup;
6909 Result = SetupFindNextLine(&ContextService, &ContextService);
6910 }
6911
6912 /* Copy .inf file to Inf\ directory (if needed) */
6913 Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
6914 if (!Result)
6915 goto cleanup;
6916 if (NeedtoCopyFile)
6917 {
6918 Result = SetupCopyOEMInfW(
6919 SelectedDriver->InfFileDetails->FullInfFileName,
6920 NULL,
6921 SPOST_NONE,
6922 SP_COPY_NOOVERWRITE,
6923 NULL, 0,
6924 NULL,
6925 NULL);
6926 if (!Result)
6927 goto cleanup;
6928 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6929 * to release use of current InfFile */
6930 }
6931
6932 /* Open device registry key */
6933 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
6934 if (hKey == INVALID_HANDLE_VALUE)
6935 goto cleanup;
6936
6937 /* Install .HW section */
6938 wcscpy(pSectionName, L".HW");
6939 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6940 SelectedDriver->InfFileDetails->hInf, SectionName,
6941 SPINST_REGISTRY, hKey, NULL, 0,
6942 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6943 DeviceInfoSet, DeviceInfoData);
6944 if (!Result)
6945 goto cleanup;
6946
6947 /* Write information to enum key */
6948 TRACE("Write information to enum key\n");
6949 TRACE("Class : '%S'\n", ClassName);
6950 TRACE("ClassGUID : '%S'\n", lpFullGuidString);
6951 TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
6952 TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
6953 TRACE("Service : '%S'\n", AssociatedService);
6954 rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
6955 if (rc == ERROR_SUCCESS)
6956 rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
6957 if (rc == ERROR_SUCCESS)
6958 rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
6959 if (rc == ERROR_SUCCESS)
6960 rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
6961 if (rc == ERROR_SUCCESS && *AssociatedService)
6962 rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
6963 if (rc != ERROR_SUCCESS)
6964 {
6965 SetLastError(rc);
6966 goto cleanup;
6967 }
6968
6969 /* Start the device */
6970 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
6971 {
6972 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
6973 NTSTATUS Status;
6974 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
6975 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
6976 ret = NT_SUCCESS(Status);
6977 }
6978 else
6979 ret = TRUE;
6980
6981 cleanup:
6982 /* End of installation */
6983 if (hClassKey != INVALID_HANDLE_VALUE)
6984 RegCloseKey(hClassKey);
6985 if (hKey != INVALID_HANDLE_VALUE)
6986 RegCloseKey(hKey);
6987 if (lpGuidString)
6988 RpcStringFreeW(&lpGuidString);
6989 HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
6990 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
6991
6992 TRACE("Returning %d\n", ret);
6993 return ret;
6994 }