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