Implement SetupDiGetActualSectionToInstallExA/W
[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 DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
34 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
35 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
36
37 /* FIXME: header mess */
38 DEFINE_GUID(GUID_NULL,
39 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
40 typedef DWORD
41 (CALLBACK* CLASS_INSTALL_PROC) (
42 IN DI_FUNCTION InstallFunction,
43 IN HDEVINFO DeviceInfoSet,
44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
45 typedef BOOL
46 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
47 IN HDEVINFO DeviceInfoSet,
48 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
49 typedef DWORD
50 (CALLBACK* COINSTALLER_PROC) (
51 IN DI_FUNCTION InstallFunction,
52 IN HDEVINFO DeviceInfoSet,
53 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
54 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
55 typedef BOOL
56 (WINAPI* PROPERTY_PAGE_PROVIDER) (
57 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
58 IN LPFNADDPROPSHEETPAGE fAddFunc,
59 IN LPARAM lParam);
60 typedef BOOL
61 (*UPDATE_CLASS_PARAM_HANDLER) (
62 IN HDEVINFO DeviceInfoSet,
63 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
64 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
65 IN DWORD ClassInstallParamsSize);
66
67 struct CoInstallerElement
68 {
69 LIST_ENTRY ListEntry;
70
71 HMODULE Module;
72 COINSTALLER_PROC Function;
73 BOOL DoPostProcessing;
74 PVOID PrivateData;
75 };
76
77 static BOOL
78 PropertyChangeHandler(
79 IN HDEVINFO DeviceInfoSet,
80 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
81 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
82 IN DWORD ClassInstallParamsSize);
83
84 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
85 NULL, /* DIF_SELECTDEVICE */
86 NULL, /* DIF_INSTALLDEVICE */
87 NULL, /* DIF_ASSIGNRESOURCES */
88 NULL, /* DIF_PROPERTIES */
89 NULL, /* DIF_REMOVE */
90 NULL, /* DIF_FIRSTTIMESETUP */
91 NULL, /* DIF_FOUNDDEVICE */
92 NULL, /* DIF_SELECTCLASSDRIVERS */
93 NULL, /* DIF_VALIDATECLASSDRIVERS */
94 NULL, /* DIF_INSTALLCLASSDRIVERS */
95 NULL, /* DIF_CALCDISKSPACE */
96 NULL, /* DIF_DESTROYPRIVATEDATA */
97 NULL, /* DIF_VALIDATEDRIVER */
98 NULL, /* DIF_MOVEDEVICE */
99 NULL, /* DIF_DETECT */
100 NULL, /* DIF_INSTALLWIZARD */
101 NULL, /* DIF_DESTROYWIZARDDATA */
102 PropertyChangeHandler, /* DIF_PROPERTYCHANGE */
103 NULL, /* DIF_ENABLECLASS */
104 NULL, /* DIF_DETECTVERIFY */
105 NULL, /* DIF_INSTALLDEVICEFILES */
106 NULL, /* DIF_UNREMOVE */
107 NULL, /* DIF_SELECTBESTCOMPATDRV */
108 NULL, /* DIF_ALLOW_INSTALL */
109 NULL, /* DIF_REGISTERDEVICE */
110 NULL, /* DIF_NEWDEVICEWIZARD_PRESELECT */
111 NULL, /* DIF_NEWDEVICEWIZARD_SELECT */
112 NULL, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
113 NULL, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
114 NULL, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
115 NULL, /* DIF_UNUSED1 */
116 NULL, /* DIF_INSTALLINTERFACES */
117 NULL, /* DIF_DETECTCANCEL */
118 NULL, /* DIF_REGISTER_COINSTALLERS */
119 NULL, /* DIF_ADDPROPERTYPAGE_ADVANCED */
120 NULL, /* DIF_ADDPROPERTYPAGE_BASIC */
121 NULL, /* DIF_RESERVED1 */
122 NULL, /* DIF_TROUBLESHOOTER */
123 NULL, /* DIF_POWERMESSAGEWAKE */
124 NULL, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
125 NULL, /* DIF_UPDATEDRIVER_UI */
126 NULL /* DIF_RESERVED2 */
127 };
128
129 /***********************************************************************
130 * SetupDiBuildClassInfoList (SETUPAPI.@)
131 */
132 BOOL WINAPI SetupDiBuildClassInfoList(
133 DWORD Flags,
134 LPGUID ClassGuidList,
135 DWORD ClassGuidListSize,
136 PDWORD RequiredSize)
137 {
138 TRACE("\n");
139 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
140 ClassGuidListSize, RequiredSize,
141 NULL, NULL);
142 }
143
144 /***********************************************************************
145 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
146 */
147 BOOL WINAPI SetupDiBuildClassInfoListExA(
148 DWORD Flags,
149 LPGUID ClassGuidList,
150 DWORD ClassGuidListSize,
151 PDWORD RequiredSize,
152 LPCSTR MachineName,
153 PVOID Reserved)
154 {
155 LPWSTR MachineNameW = NULL;
156 BOOL bResult;
157
158 TRACE("\n");
159
160 if (MachineName)
161 {
162 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
163 if (MachineNameW == NULL) return FALSE;
164 }
165
166 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
167 ClassGuidListSize, RequiredSize,
168 MachineNameW, Reserved);
169
170 if (MachineNameW)
171 MyFree(MachineNameW);
172
173 return bResult;
174 }
175
176 /***********************************************************************
177 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
178 */
179 BOOL WINAPI SetupDiBuildClassInfoListExW(
180 DWORD Flags,
181 LPGUID ClassGuidList,
182 DWORD ClassGuidListSize,
183 PDWORD RequiredSize,
184 LPCWSTR MachineName,
185 PVOID Reserved)
186 {
187 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
188 HKEY hClassesKey;
189 HKEY hClassKey;
190 DWORD dwLength;
191 DWORD dwIndex;
192 LONG lError;
193 DWORD dwGuidListIndex = 0;
194
195 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
196 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
197
198 if (RequiredSize != NULL)
199 *RequiredSize = 0;
200
201 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
202 KEY_ENUMERATE_SUB_KEYS,
203 DIOCR_INSTALLER,
204 MachineName,
205 Reserved);
206 if (hClassesKey == INVALID_HANDLE_VALUE)
207 {
208 return FALSE;
209 }
210
211 for (dwIndex = 0; ; dwIndex++)
212 {
213 dwLength = MAX_GUID_STRING_LEN + 1;
214 lError = RegEnumKeyExW(hClassesKey,
215 dwIndex,
216 szKeyName,
217 &dwLength,
218 NULL,
219 NULL,
220 NULL,
221 NULL);
222 TRACE("RegEnumKeyExW() returns %ld\n", lError);
223 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
224 {
225 TRACE("Key name: %s\n", debugstr_w(szKeyName));
226
227 if (RegOpenKeyExW(hClassesKey,
228 szKeyName,
229 0,
230 KEY_QUERY_VALUE,
231 &hClassKey))
232 {
233 RegCloseKey(hClassesKey);
234 return FALSE;
235 }
236
237 if (!RegQueryValueExW(hClassKey,
238 REGSTR_VAL_NOUSECLASS,
239 NULL,
240 NULL,
241 NULL,
242 NULL))
243 {
244 TRACE("'NoUseClass' value found!\n");
245 RegCloseKey(hClassKey);
246 continue;
247 }
248
249 if ((Flags & DIBCI_NOINSTALLCLASS) &&
250 (!RegQueryValueExW(hClassKey,
251 REGSTR_VAL_NOINSTALLCLASS,
252 NULL,
253 NULL,
254 NULL,
255 NULL)))
256 {
257 TRACE("'NoInstallClass' value found!\n");
258 RegCloseKey(hClassKey);
259 continue;
260 }
261
262 if ((Flags & DIBCI_NODISPLAYCLASS) &&
263 (!RegQueryValueExW(hClassKey,
264 REGSTR_VAL_NODISPLAYCLASS,
265 NULL,
266 NULL,
267 NULL,
268 NULL)))
269 {
270 TRACE("'NoDisplayClass' value found!\n");
271 RegCloseKey(hClassKey);
272 continue;
273 }
274
275 RegCloseKey(hClassKey);
276
277 TRACE("Guid: %s\n", debugstr_w(szKeyName));
278 if (dwGuidListIndex < ClassGuidListSize)
279 {
280 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
281 {
282 szKeyName[37] = 0;
283 }
284 TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
285
286 UuidFromStringW(&szKeyName[1],
287 &ClassGuidList[dwGuidListIndex]);
288 }
289
290 dwGuidListIndex++;
291 }
292
293 if (lError != ERROR_SUCCESS)
294 break;
295 }
296
297 RegCloseKey(hClassesKey);
298
299 if (RequiredSize != NULL)
300 *RequiredSize = dwGuidListIndex;
301
302 if (ClassGuidListSize < dwGuidListIndex)
303 {
304 SetLastError(ERROR_INSUFFICIENT_BUFFER);
305 return FALSE;
306 }
307
308 return TRUE;
309 }
310
311 /***********************************************************************
312 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
313 */
314 BOOL WINAPI SetupDiClassGuidsFromNameA(
315 LPCSTR ClassName,
316 LPGUID ClassGuidList,
317 DWORD ClassGuidListSize,
318 PDWORD RequiredSize)
319 {
320 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
321 ClassGuidListSize, RequiredSize,
322 NULL, NULL);
323 }
324
325 /***********************************************************************
326 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
327 */
328 BOOL WINAPI SetupDiClassGuidsFromNameW(
329 LPCWSTR ClassName,
330 LPGUID ClassGuidList,
331 DWORD ClassGuidListSize,
332 PDWORD RequiredSize)
333 {
334 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
335 ClassGuidListSize, RequiredSize,
336 NULL, NULL);
337 }
338
339 /***********************************************************************
340 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
341 */
342 BOOL WINAPI SetupDiClassGuidsFromNameExA(
343 LPCSTR ClassName,
344 LPGUID ClassGuidList,
345 DWORD ClassGuidListSize,
346 PDWORD RequiredSize,
347 LPCSTR MachineName,
348 PVOID Reserved)
349 {
350 LPWSTR ClassNameW = NULL;
351 LPWSTR MachineNameW = NULL;
352 BOOL bResult;
353
354 TRACE("\n");
355
356 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
357 if (ClassNameW == NULL)
358 return FALSE;
359
360 if (MachineNameW)
361 {
362 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
363 if (MachineNameW == NULL)
364 {
365 MyFree(ClassNameW);
366 return FALSE;
367 }
368 }
369
370 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
371 ClassGuidListSize, RequiredSize,
372 MachineNameW, Reserved);
373
374 if (MachineNameW)
375 MyFree(MachineNameW);
376
377 MyFree(ClassNameW);
378
379 return bResult;
380 }
381
382 /***********************************************************************
383 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
384 */
385 BOOL WINAPI SetupDiClassGuidsFromNameExW(
386 LPCWSTR ClassName,
387 LPGUID ClassGuidList,
388 DWORD ClassGuidListSize,
389 PDWORD RequiredSize,
390 LPCWSTR MachineName,
391 PVOID Reserved)
392 {
393 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
394 WCHAR szClassName[256];
395 HKEY hClassesKey;
396 HKEY hClassKey;
397 DWORD dwLength;
398 DWORD dwIndex;
399 LONG lError;
400 DWORD dwGuidListIndex = 0;
401
402 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
403 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
404
405 if (RequiredSize != NULL)
406 *RequiredSize = 0;
407
408 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
409 KEY_ENUMERATE_SUB_KEYS,
410 DIOCR_INSTALLER,
411 MachineName,
412 Reserved);
413 if (hClassesKey == INVALID_HANDLE_VALUE)
414 {
415 return FALSE;
416 }
417
418 for (dwIndex = 0; ; dwIndex++)
419 {
420 dwLength = MAX_GUID_STRING_LEN + 1;
421 lError = RegEnumKeyExW(hClassesKey,
422 dwIndex,
423 szKeyName,
424 &dwLength,
425 NULL,
426 NULL,
427 NULL,
428 NULL);
429 TRACE("RegEnumKeyExW() returns %ld\n", lError);
430 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
431 {
432 TRACE("Key name: %s\n", debugstr_w(szKeyName));
433
434 if (RegOpenKeyExW(hClassesKey,
435 szKeyName,
436 0,
437 KEY_QUERY_VALUE,
438 &hClassKey))
439 {
440 RegCloseKey(hClassesKey);
441 return FALSE;
442 }
443
444 dwLength = 256 * sizeof(WCHAR);
445 if (!RegQueryValueExW(hClassKey,
446 Class,
447 NULL,
448 NULL,
449 (LPBYTE)szClassName,
450 &dwLength))
451 {
452 TRACE("Class name: %s\n", debugstr_w(szClassName));
453
454 if (strcmpiW(szClassName, ClassName) == 0)
455 {
456 TRACE("Found matching class name\n");
457
458 TRACE("Guid: %s\n", debugstr_w(szKeyName));
459 if (dwGuidListIndex < ClassGuidListSize)
460 {
461 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
462 {
463 szKeyName[37] = 0;
464 }
465 TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
466
467 UuidFromStringW(&szKeyName[1],
468 &ClassGuidList[dwGuidListIndex]);
469 }
470
471 dwGuidListIndex++;
472 }
473 }
474
475 RegCloseKey(hClassKey);
476 }
477
478 if (lError != ERROR_SUCCESS)
479 break;
480 }
481
482 RegCloseKey(hClassesKey);
483
484 if (RequiredSize != NULL)
485 *RequiredSize = dwGuidListIndex;
486
487 if (ClassGuidListSize < dwGuidListIndex)
488 {
489 SetLastError(ERROR_INSUFFICIENT_BUFFER);
490 return FALSE;
491 }
492
493 return TRUE;
494 }
495
496 /***********************************************************************
497 * SetupDiClassNameFromGuidA (SETUPAPI.@)
498 */
499 BOOL WINAPI SetupDiClassNameFromGuidA(
500 const GUID* ClassGuid,
501 PSTR ClassName,
502 DWORD ClassNameSize,
503 PDWORD RequiredSize)
504 {
505 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
506 ClassNameSize, RequiredSize,
507 NULL, NULL);
508 }
509
510 /***********************************************************************
511 * SetupDiClassNameFromGuidW (SETUPAPI.@)
512 */
513 BOOL WINAPI SetupDiClassNameFromGuidW(
514 const GUID* ClassGuid,
515 PWSTR ClassName,
516 DWORD ClassNameSize,
517 PDWORD RequiredSize)
518 {
519 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
520 ClassNameSize, RequiredSize,
521 NULL, NULL);
522 }
523
524 /***********************************************************************
525 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
526 */
527 BOOL WINAPI SetupDiClassNameFromGuidExA(
528 const GUID* ClassGuid,
529 PSTR ClassName,
530 DWORD ClassNameSize,
531 PDWORD RequiredSize,
532 PCSTR MachineName,
533 PVOID Reserved)
534 {
535 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
536 LPWSTR MachineNameW = NULL;
537 BOOL ret;
538
539 if (MachineName)
540 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
541 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
542 NULL, MachineNameW, Reserved);
543 if (ret)
544 {
545 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
546 ClassNameSize, NULL, NULL);
547
548 if (!ClassNameSize && RequiredSize)
549 *RequiredSize = len;
550 }
551 MyFree(MachineNameW);
552 return ret;
553 }
554
555 /***********************************************************************
556 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
557 */
558 BOOL WINAPI SetupDiClassNameFromGuidExW(
559 const GUID* ClassGuid,
560 PWSTR ClassName,
561 DWORD ClassNameSize,
562 PDWORD RequiredSize,
563 PCWSTR MachineName,
564 PVOID Reserved)
565 {
566 HKEY hKey;
567 DWORD dwLength;
568 LONG rc;
569
570 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
571 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
572
573 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
574 KEY_QUERY_VALUE,
575 DIOCR_INSTALLER,
576 MachineName,
577 Reserved);
578 if (hKey == INVALID_HANDLE_VALUE)
579 {
580 return FALSE;
581 }
582
583 if (RequiredSize != NULL)
584 {
585 dwLength = 0;
586 rc = RegQueryValueExW(hKey,
587 Class,
588 NULL,
589 NULL,
590 NULL,
591 &dwLength);
592 if (rc != ERROR_SUCCESS)
593 {
594 SetLastError(rc);
595 RegCloseKey(hKey);
596 return FALSE;
597 }
598
599 *RequiredSize = dwLength / sizeof(WCHAR);
600 }
601
602 dwLength = ClassNameSize * sizeof(WCHAR);
603 rc = RegQueryValueExW(hKey,
604 Class,
605 NULL,
606 NULL,
607 (LPBYTE)ClassName,
608 &dwLength);
609 if (rc != ERROR_SUCCESS)
610 {
611 SetLastError(rc);
612 RegCloseKey(hKey);
613 return FALSE;
614 }
615
616 RegCloseKey(hKey);
617
618 return TRUE;
619 }
620
621 /***********************************************************************
622 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
623 */
624 HDEVINFO WINAPI
625 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
626 HWND hwndParent)
627 {
628 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
629 }
630
631 /***********************************************************************
632 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
633 */
634 HDEVINFO WINAPI
635 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
636 HWND hwndParent,
637 PCSTR MachineName,
638 PVOID Reserved)
639 {
640 LPWSTR MachineNameW = NULL;
641 HDEVINFO hDevInfo;
642
643 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
644 debugstr_a(MachineName), Reserved);
645
646 if (MachineName)
647 {
648 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
649 if (MachineNameW == NULL)
650 return (HDEVINFO)INVALID_HANDLE_VALUE;
651 }
652
653 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
654 MachineNameW, Reserved);
655
656 if (MachineNameW)
657 MyFree(MachineNameW);
658
659 return hDevInfo;
660 }
661
662 static DWORD
663 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
664 {
665 switch (cr)
666 {
667 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
668 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
669 case CR_SUCCESS: return ERROR_SUCCESS;
670 default:
671 /* FIXME */
672 return ERROR_GEN_FAILURE;
673 }
674
675 /* Does not happen */
676 }
677
678 /***********************************************************************
679 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
680 */
681 HDEVINFO WINAPI
682 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
683 HWND hwndParent,
684 PCWSTR MachineName,
685 PVOID Reserved)
686 {
687 struct DeviceInfoSet *list;
688 LPWSTR UNCServerName = NULL;
689 DWORD size;
690 DWORD rc;
691 //CONFIGRET cr;
692 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
693
694 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
695 debugstr_w(MachineName), Reserved);
696
697 size = FIELD_OFFSET(struct DeviceInfoSet, szData);
698 if (MachineName)
699 size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
700 list = HeapAlloc(GetProcessHeap(), 0, size);
701 if (!list)
702 {
703 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
704 goto cleanup;
705 }
706 memset(list, 0, sizeof(struct DeviceInfoSet));
707
708 list->magic = SETUP_DEV_INFO_SET_MAGIC;
709 memcpy(
710 &list->ClassGuid,
711 ClassGuid ? ClassGuid : &GUID_NULL,
712 sizeof(list->ClassGuid));
713 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
714 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
715 list->InstallParams.hwndParent = hwndParent;
716 if (MachineName)
717 {
718 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
719 if (rc != ERROR_SUCCESS)
720 {
721 SetLastError(rc);
722 goto cleanup;
723 }
724 UNCServerName = HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName) + 3) * sizeof(WCHAR));
725 if (!UNCServerName)
726 {
727 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
728 goto cleanup;
729 }
730
731 strcpyW(UNCServerName + 2, MachineName);
732 list->szData[0] = list->szData[1] = '\\';
733 strcpyW(list->szData + 2, MachineName);
734 list->MachineName = list->szData;
735 }
736 else
737 {
738 DWORD Size = MAX_PATH;
739 list->HKLM = HKEY_LOCAL_MACHINE;
740 UNCServerName = HeapAlloc(GetProcessHeap(), 0, (MAX_PATH + 2) * sizeof(WCHAR));
741 if (!UNCServerName)
742 {
743 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
744 goto cleanup;
745 }
746 if (!GetComputerNameW(UNCServerName + 2, &Size))
747 goto cleanup;
748 list->MachineName = NULL;
749 }
750 #if 0
751 UNCServerName[0] = UNCServerName[1] = '\\';
752 cr = CM_Connect_MachineW(UNCServerName, &list->hMachine);
753 if (cr != CR_SUCCESS)
754 {
755 SetLastError(GetErrorCodeFromCrCode(cr));
756 goto cleanup;
757 }
758 #endif
759 InitializeListHead(&list->DriverListHead);
760 InitializeListHead(&list->ListHead);
761
762 ret = (HDEVINFO)list;
763
764 cleanup:
765 if (ret == INVALID_HANDLE_VALUE)
766 {
767 if (list && list->HKLM != 0 && list->HKLM != HKEY_LOCAL_MACHINE)
768 RegCloseKey(list->HKLM);
769 HeapFree(GetProcessHeap(), 0, list);
770 }
771 HeapFree(GetProcessHeap(), 0, UNCServerName);
772 return ret;
773 }
774
775 /***********************************************************************
776 * SetupDiEnumDeviceInfo (SETUPAPI.@)
777 */
778 BOOL WINAPI SetupDiEnumDeviceInfo(
779 HDEVINFO DeviceInfoSet,
780 DWORD MemberIndex,
781 PSP_DEVINFO_DATA DeviceInfoData)
782 {
783 BOOL ret = FALSE;
784
785 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
786 if (!DeviceInfoData)
787 SetLastError(ERROR_INVALID_PARAMETER);
788 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
789 {
790 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
791
792 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
793 SetLastError(ERROR_INVALID_HANDLE);
794 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
795 SetLastError(ERROR_INVALID_USER_BUFFER);
796 else
797 {
798 PLIST_ENTRY ItemList = list->ListHead.Flink;
799 while (ItemList != &list->ListHead && MemberIndex-- > 0)
800 ItemList = ItemList->Flink;
801 if (ItemList == &list->ListHead)
802 SetLastError(ERROR_NO_MORE_ITEMS);
803 else
804 {
805 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
806 memcpy(&DeviceInfoData->ClassGuid,
807 &DevInfo->ClassGuid,
808 sizeof(GUID));
809 DeviceInfoData->DevInst = DevInfo->dnDevInst;
810 DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
811 ret = TRUE;
812 }
813 }
814 }
815 else
816 SetLastError(ERROR_INVALID_HANDLE);
817 return ret;
818 }
819
820 /***********************************************************************
821 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
822 */
823 BOOL WINAPI
824 SetupDiGetActualSectionToInstallA(
825 IN HINF InfHandle,
826 IN PCSTR InfSectionName,
827 OUT PSTR InfSectionWithExt OPTIONAL,
828 IN DWORD InfSectionWithExtSize,
829 OUT PDWORD RequiredSize OPTIONAL,
830 OUT PSTR *Extension OPTIONAL)
831 {
832 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
833 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
834 Extension, NULL);
835 }
836
837 /***********************************************************************
838 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
839 */
840 BOOL WINAPI
841 SetupDiGetActualSectionToInstallW(
842 IN HINF InfHandle,
843 IN PCWSTR InfSectionName,
844 OUT PWSTR InfSectionWithExt OPTIONAL,
845 IN DWORD InfSectionWithExtSize,
846 OUT PDWORD RequiredSize OPTIONAL,
847 OUT PWSTR *Extension OPTIONAL)
848 {
849 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
850 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
851 Extension, NULL);
852 }
853
854 /***********************************************************************
855 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
856 */
857 BOOL WINAPI
858 SetupDiGetActualSectionToInstallExA(
859 IN HINF InfHandle,
860 IN PCSTR InfSectionName,
861 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
862 OUT PSTR InfSectionWithExt OPTIONAL,
863 IN DWORD InfSectionWithExtSize,
864 OUT PDWORD RequiredSize OPTIONAL,
865 OUT PSTR* Extension OPTIONAL,
866 IN PVOID Reserved)
867 {
868 LPWSTR InfSectionNameW = NULL;
869 LPWSTR InfSectionWithExtW = NULL;
870 PWSTR ExtensionW;
871 BOOL bResult = FALSE;
872
873 TRACE("\n");
874
875 if (InfSectionName)
876 {
877 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
878 if (InfSectionNameW == NULL)
879 goto cleanup;
880 }
881 if (InfSectionWithExt)
882 {
883 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
884 if (InfSectionWithExtW == NULL)
885 goto cleanup;
886 }
887
888 bResult = SetupDiGetActualSectionToInstallExW(
889 InfHandle, InfSectionNameW, AlternatePlatformInfo,
890 InfSectionWithExt ? InfSectionWithExtW : NULL,
891 InfSectionWithExtSize,
892 RequiredSize,
893 Extension ? &ExtensionW : NULL,
894 Reserved);
895
896 if (bResult && InfSectionWithExt)
897 {
898 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
899 InfSectionWithExtSize, NULL, NULL) != 0;
900 }
901 if (bResult && Extension)
902 {
903 if (ExtensionW == NULL)
904 *Extension = NULL;
905 else
906 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
907 }
908
909 cleanup:
910 MyFree(InfSectionNameW);
911 MyFree(InfSectionWithExtW);
912
913 return bResult;
914 }
915
916 /***********************************************************************
917 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
918 */
919 BOOL WINAPI
920 SetupDiGetActualSectionToInstallExW(
921 IN HINF InfHandle,
922 IN PCWSTR InfSectionName,
923 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
924 OUT PWSTR InfSectionWithExt OPTIONAL,
925 IN DWORD InfSectionWithExtSize,
926 OUT PDWORD RequiredSize OPTIONAL,
927 OUT PWSTR* Extension OPTIONAL,
928 IN PVOID Reserved)
929 {
930 BOOL ret = FALSE;
931
932 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
933 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
934 RequiredSize, Extension, Reserved);
935
936 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
937 SetLastError(ERROR_INVALID_HANDLE);
938 else if (!InfSectionName)
939 SetLastError(ERROR_INVALID_PARAMETER);
940 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
941 SetLastError(ERROR_INVALID_USER_BUFFER);
942 else if (Reserved != NULL)
943 SetLastError(ERROR_INVALID_PARAMETER);
944 else
945 {
946 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
947 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
948 LPCWSTR pExtensionPlatform, pExtensionArchitecture;
949 WCHAR SectionName[LINE_LEN + 1];
950 LONG lLineCount = -1;
951 DWORD dwFullLength;
952
953 /* Fill platform info if needed */
954 if (AlternatePlatformInfo)
955 pPlatformInfo = AlternatePlatformInfo;
956 else if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
957 {
958 /* That's the first time we go here. We need to fill in the structure */
959 OSVERSIONINFO VersionInfo;
960 SYSTEM_INFO SystemInfo;
961 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
962 ret = GetVersionEx(&VersionInfo);
963 if (!ret)
964 goto done;
965 GetSystemInfo(&SystemInfo);
966 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
967 CurrentPlatform.Platform = VersionInfo.dwPlatformId;
968 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
969 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
970 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
971 CurrentPlatform.Reserved = 0;
972 }
973
974 static const WCHAR ExtensionPlatformNone[] = {'.',0};
975 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
976 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
977
978 static const WCHAR ExtensionArchitectureNone[] = {0};
979 static const WCHAR ExtensionArchitectureamd64[] = {'a','m','d','6','4',0};
980 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
981 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
982
983 /* Set various extensions values */
984 switch (pPlatformInfo->Platform)
985 {
986 case VER_PLATFORM_WIN32_WINDOWS:
987 pExtensionPlatform = ExtensionPlatformWindows;
988 break;
989 case VER_PLATFORM_WIN32_NT:
990 pExtensionPlatform = ExtensionPlatformNT;
991 break;
992 default:
993 pExtensionPlatform = ExtensionPlatformNone;
994 break;
995 }
996 switch (pPlatformInfo->ProcessorArchitecture)
997 {
998 case PROCESSOR_ARCHITECTURE_AMD64:
999 pExtensionArchitecture = ExtensionArchitectureamd64;
1000 break;
1001 case PROCESSOR_ARCHITECTURE_INTEL:
1002 pExtensionArchitecture = ExtensionArchitecturex86;
1003 break;
1004 case PROCESSOR_ARCHITECTURE_PPC:
1005 pExtensionArchitecture = ExtensionArchitectureppc;
1006 break;
1007 default:
1008 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo->ProcessorArchitecture);
1009 case PROCESSOR_ARCHITECTURE_UNKNOWN:
1010 pExtensionArchitecture = ExtensionArchitectureNone;
1011 break;
1012 }
1013
1014 SectionName[LINE_LEN] = UNICODE_NULL;
1015
1016 /* Test with platform.architecture.major.minor extension */
1017 snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu.%lu", InfSectionName,
1018 pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
1019 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1020 if (lLineCount != -1) goto sectionfound;
1021
1022 /* Test with platform.major.minor extension */
1023 snprintfW(SectionName, LINE_LEN, L"%s%s.%lu.%lu", InfSectionName,
1024 pExtensionPlatform, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
1025 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1026 if (lLineCount != -1) goto sectionfound;
1027
1028 /* Test with platform.architecture.major extension */
1029 snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu", InfSectionName,
1030 pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion);
1031 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1032 if (lLineCount != -1) goto sectionfound;
1033
1034 /* Test with platform.major extension */
1035 snprintfW(SectionName, LINE_LEN, L"%s%s.%lu", InfSectionName,
1036 pExtensionPlatform, pPlatformInfo->MajorVersion);
1037 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1038 if (lLineCount != -1) goto sectionfound;
1039
1040 /* Test with platform.architecture extension */
1041 snprintfW(SectionName, LINE_LEN, L"%s%s%s", InfSectionName,
1042 pExtensionPlatform, pExtensionArchitecture);
1043 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1044 if (lLineCount != -1) goto sectionfound;
1045
1046 /* Test with platform extension */
1047 snprintfW(SectionName, LINE_LEN, L"%s%s", InfSectionName,
1048 pExtensionPlatform);
1049 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1050 if (lLineCount != -1) goto sectionfound;
1051
1052 /* Test without extension */
1053 snprintfW(SectionName, LINE_LEN, L"%s", InfSectionName);
1054 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1055 if (lLineCount != -1) goto sectionfound;
1056
1057 /* No appropriate section found */
1058 SetLastError(ERROR_INVALID_PARAMETER);
1059 goto done;
1060
1061 sectionfound:
1062 dwFullLength = lstrlenW(SectionName);
1063 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1064 {
1065 if (InfSectionWithExtSize < (dwFullLength + 1))
1066 {
1067 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1068 goto done;
1069 }
1070
1071 lstrcpyW(InfSectionWithExt, SectionName);
1072 if (Extension != NULL)
1073 {
1074 DWORD dwLength = lstrlenW(SectionName);
1075 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1076 }
1077 }
1078
1079 if (RequiredSize != NULL)
1080 *RequiredSize = dwFullLength + 1;
1081
1082 ret = TRUE;
1083 }
1084
1085 done:
1086 TRACE("Returning %d\n", ret);
1087 return ret;
1088 }
1089
1090
1091 /***********************************************************************
1092 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1093 */
1094 BOOL WINAPI SetupDiGetClassDescriptionA(
1095 const GUID* ClassGuid,
1096 PSTR ClassDescription,
1097 DWORD ClassDescriptionSize,
1098 PDWORD RequiredSize)
1099 {
1100 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1101 ClassDescriptionSize,
1102 RequiredSize, NULL, NULL);
1103 }
1104
1105 /***********************************************************************
1106 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1107 */
1108 BOOL WINAPI SetupDiGetClassDescriptionW(
1109 const GUID* ClassGuid,
1110 PWSTR ClassDescription,
1111 DWORD ClassDescriptionSize,
1112 PDWORD RequiredSize)
1113 {
1114 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1115 ClassDescriptionSize,
1116 RequiredSize, NULL, NULL);
1117 }
1118
1119 /***********************************************************************
1120 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1121 */
1122 BOOL WINAPI SetupDiGetClassDescriptionExA(
1123 const GUID* ClassGuid,
1124 PSTR ClassDescription,
1125 DWORD ClassDescriptionSize,
1126 PDWORD RequiredSize,
1127 PCSTR MachineName,
1128 PVOID Reserved)
1129 {
1130 PWCHAR ClassDescriptionW;
1131 LPWSTR MachineNameW = NULL;
1132 BOOL ret;
1133
1134 TRACE("\n");
1135 if (ClassDescriptionSize > 0)
1136 {
1137 ClassDescriptionW = HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize * sizeof(WCHAR));
1138 if (!ClassDescriptionW)
1139 {
1140 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1141 ret = FALSE;
1142 goto end;
1143 }
1144 }
1145 else
1146 ClassDescriptionW = NULL;
1147
1148 if (MachineName)
1149 {
1150 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1151 if (!MachineNameW)
1152 {
1153 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1154 ret = FALSE;
1155 goto end;
1156 }
1157 }
1158
1159 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, ClassDescriptionSize * sizeof(WCHAR),
1160 NULL, MachineNameW, Reserved);
1161 if (ret)
1162 {
1163 int len = WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
1164 ClassDescriptionSize, NULL, NULL);
1165
1166 if (!ClassDescriptionSize && RequiredSize)
1167 *RequiredSize = len;
1168 }
1169
1170 end:
1171 HeapFree(GetProcessHeap(), 0, ClassDescriptionW);
1172 MyFree(MachineNameW);
1173 return ret;
1174 }
1175
1176 /***********************************************************************
1177 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1178 */
1179 BOOL WINAPI SetupDiGetClassDescriptionExW(
1180 const GUID* ClassGuid,
1181 PWSTR ClassDescription,
1182 DWORD ClassDescriptionSize,
1183 PDWORD RequiredSize,
1184 PCWSTR MachineName,
1185 PVOID Reserved)
1186 {
1187 HKEY hKey;
1188 DWORD dwLength;
1189
1190 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
1191 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
1192
1193 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1194 KEY_QUERY_VALUE,
1195 DIOCR_INSTALLER,
1196 MachineName,
1197 Reserved);
1198 if (hKey == INVALID_HANDLE_VALUE)
1199 {
1200 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1201 return FALSE;
1202 }
1203
1204 if (RequiredSize != NULL)
1205 {
1206 dwLength = 0;
1207 if (RegQueryValueExW(hKey,
1208 NULL,
1209 NULL,
1210 NULL,
1211 NULL,
1212 &dwLength))
1213 {
1214 RegCloseKey(hKey);
1215 return FALSE;
1216 }
1217
1218 *RequiredSize = dwLength / sizeof(WCHAR);
1219 }
1220
1221 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1222 if (RegQueryValueExW(hKey,
1223 NULL,
1224 NULL,
1225 NULL,
1226 (LPBYTE)ClassDescription,
1227 &dwLength))
1228 {
1229 RegCloseKey(hKey);
1230 return FALSE;
1231 }
1232
1233 RegCloseKey(hKey);
1234
1235 return TRUE;
1236 }
1237
1238 /***********************************************************************
1239 * SetupDiGetClassDevsA (SETUPAPI.@)
1240 */
1241 HDEVINFO WINAPI SetupDiGetClassDevsA(
1242 CONST GUID *class,
1243 LPCSTR enumstr,
1244 HWND parent,
1245 DWORD flags)
1246 {
1247 return SetupDiGetClassDevsExA(class, enumstr, parent,
1248 flags, NULL, NULL, NULL);
1249 }
1250
1251 /***********************************************************************
1252 * SetupDiGetClassDevsW (SETUPAPI.@)
1253 */
1254 HDEVINFO WINAPI SetupDiGetClassDevsW(
1255 CONST GUID *class,
1256 LPCWSTR enumstr,
1257 HWND parent,
1258 DWORD flags)
1259 {
1260 return SetupDiGetClassDevsExW(class, enumstr, parent,
1261 flags, NULL, NULL, NULL);
1262 }
1263
1264 /***********************************************************************
1265 * SetupDiGetClassDevsExA (SETUPAPI.@)
1266 */
1267 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1268 CONST GUID *class,
1269 LPCSTR enumstr,
1270 HWND parent,
1271 DWORD flags,
1272 HDEVINFO deviceset,
1273 LPCSTR machine,
1274 PVOID reserved)
1275 {
1276 HDEVINFO ret;
1277 LPWSTR enumstrW = NULL;
1278 LPWSTR machineW = NULL;
1279
1280 if (enumstr)
1281 {
1282 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1283 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1284 if (!enumstrW)
1285 {
1286 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1287 goto end;
1288 }
1289 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1290 }
1291 if (machine)
1292 {
1293 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1294 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1295 if (!machineW)
1296 {
1297 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1298 goto end;
1299 }
1300 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1301 }
1302 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, machineW, reserved);
1303
1304 end:
1305 HeapFree(GetProcessHeap(), 0, enumstrW);
1306 HeapFree(GetProcessHeap(), 0, machineW);
1307 return ret;
1308 }
1309
1310 static BOOL
1311 CreateDeviceInfoElement(
1312 IN struct DeviceInfoSet *list,
1313 IN LPCWSTR InstancePath,
1314 IN LPCGUID pClassGuid,
1315 OUT struct DeviceInfoElement **pDeviceInfo)
1316 {
1317 DWORD size;
1318 CONFIGRET cr;
1319 struct DeviceInfoElement *deviceInfo;
1320
1321 *pDeviceInfo = NULL;
1322
1323 size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
1324 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
1325 if (!deviceInfo)
1326 {
1327 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1328 return FALSE;
1329 }
1330 memset(deviceInfo, 0, size);
1331
1332 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
1333 if (cr != CR_SUCCESS)
1334 {
1335 SetLastError(GetErrorCodeFromCrCode(cr));
1336 return FALSE;
1337 }
1338
1339 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1340 wcscpy(deviceInfo->Data, InstancePath);
1341 deviceInfo->DeviceName = deviceInfo->Data;
1342 deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
1343 deviceInfo->DeviceDescription = NULL;
1344 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
1345 deviceInfo->CreationFlags = 0;
1346 InitializeListHead(&deviceInfo->DriverListHead);
1347 InitializeListHead(&deviceInfo->InterfaceListHead);
1348
1349 *pDeviceInfo = deviceInfo;
1350 return TRUE;
1351 }
1352
1353 static BOOL
1354 CreateDeviceInterface(
1355 IN struct DeviceInfoElement* deviceInfo,
1356 IN LPCWSTR SymbolicLink,
1357 IN LPCGUID pInterfaceGuid,
1358 OUT struct DeviceInterface **pDeviceInterface)
1359 {
1360 struct DeviceInterface *deviceInterface;
1361
1362 *pDeviceInterface = NULL;
1363
1364 deviceInterface = HeapAlloc(GetProcessHeap(), 0,
1365 FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
1366 if (!deviceInterface)
1367 {
1368 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1369 return FALSE;
1370 }
1371 deviceInterface->DeviceInfo = deviceInfo;
1372 wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
1373 deviceInterface->Flags = 0; /* FIXME */
1374 memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
1375
1376 *pDeviceInterface = deviceInterface;
1377 return TRUE;
1378 }
1379
1380 static LONG SETUP_CreateDevListFromEnumerator(
1381 struct DeviceInfoSet *list,
1382 LPCGUID pClassGuid OPTIONAL,
1383 LPCWSTR Enumerator,
1384 HKEY hEnumeratorKey) /* handle to Enumerator registry key */
1385 {
1386 HKEY hDeviceIdKey, hInstanceIdKey;
1387 WCHAR KeyBuffer[MAX_PATH];
1388 WCHAR InstancePath[MAX_PATH];
1389 LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
1390 struct DeviceInfoElement *deviceInfo;
1391 DWORD i = 0, j;
1392 DWORD dwLength, dwRegType;
1393 DWORD rc;
1394
1395 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1396 while (TRUE)
1397 {
1398 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1399 rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1400 if (rc == ERROR_NO_MORE_ITEMS)
1401 break;
1402 if (rc != ERROR_SUCCESS)
1403 return rc;
1404 i++;
1405
1406 /* Open device id sub key */
1407 rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
1408 if (rc != ERROR_SUCCESS)
1409 return rc;
1410 wcscpy(InstancePath, Enumerator);
1411 wcscat(InstancePath, L"\\");
1412 wcscat(InstancePath, KeyBuffer);
1413 wcscat(InstancePath, L"\\");
1414 pEndOfInstancePath = &InstancePath[wcslen(InstancePath)];
1415
1416 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1417 j = 0;
1418 while (TRUE)
1419 {
1420 GUID KeyGuid;
1421
1422 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1423 rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1424 if (rc == ERROR_NO_MORE_ITEMS)
1425 break;
1426 if (rc != ERROR_SUCCESS)
1427 {
1428 RegCloseKey(hDeviceIdKey);
1429 return rc;
1430 }
1431 j++;
1432
1433 /* Open instance id sub key */
1434 rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
1435 if (rc != ERROR_SUCCESS)
1436 {
1437 RegCloseKey(hDeviceIdKey);
1438 return rc;
1439 }
1440 *pEndOfInstancePath = '\0';
1441 wcscat(InstancePath, KeyBuffer);
1442
1443 /* Read ClassGUID value */
1444 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1445 rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength);
1446 RegCloseKey(hInstanceIdKey);
1447 if (rc == ERROR_FILE_NOT_FOUND)
1448 {
1449 if (pClassGuid)
1450 /* Skip this bad entry as we can't verify it */
1451 continue;
1452 /* Set a default GUID for this device */
1453 memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
1454 }
1455 else if (rc != ERROR_SUCCESS)
1456 {
1457 RegCloseKey(hDeviceIdKey);
1458 return rc;
1459 }
1460 else if (dwRegType != REG_SZ)
1461 {
1462 RegCloseKey(hDeviceIdKey);
1463 return ERROR_GEN_FAILURE;
1464 }
1465 else
1466 {
1467 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1468 if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
1469 /* Bad GUID, skip the entry */
1470 continue;
1471 }
1472
1473 if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
1474 {
1475 /* Skip this entry as it is not the right device class */
1476 continue;
1477 }
1478
1479 /* Add the entry to the list */
1480 if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo))
1481 {
1482 RegCloseKey(hDeviceIdKey);
1483 return GetLastError();
1484 }
1485 TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
1486 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1487 }
1488 RegCloseKey(hDeviceIdKey);
1489 }
1490
1491 return ERROR_SUCCESS;
1492 }
1493
1494 static LONG SETUP_CreateDevList(
1495 struct DeviceInfoSet *list,
1496 PCWSTR MachineName OPTIONAL,
1497 LPGUID class OPTIONAL,
1498 PCWSTR Enumerator OPTIONAL)
1499 {
1500 HKEY HKLM, hEnumKey, hEnumeratorKey;
1501 WCHAR KeyBuffer[MAX_PATH];
1502 DWORD i;
1503 DWORD dwLength;
1504 DWORD rc;
1505
1506 if (class && IsEqualIID(class, &GUID_NULL))
1507 class = NULL;
1508
1509 /* Open Enum key */
1510 if (MachineName != NULL)
1511 {
1512 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
1513 if (rc != ERROR_SUCCESS)
1514 return rc;
1515 }
1516 else
1517 HKLM = HKEY_LOCAL_MACHINE;
1518
1519 rc = RegOpenKeyExW(HKLM,
1520 REGSTR_PATH_SYSTEMENUM,
1521 0,
1522 KEY_ENUMERATE_SUB_KEYS,
1523 &hEnumKey);
1524 if (MachineName != NULL) RegCloseKey(HKLM);
1525 if (rc != ERROR_SUCCESS)
1526 return rc;
1527
1528 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1529 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1530 * for each one.
1531 */
1532 if (Enumerator)
1533 {
1534 rc = RegOpenKeyExW(
1535 hEnumKey,
1536 Enumerator,
1537 0,
1538 KEY_ENUMERATE_SUB_KEYS,
1539 &hEnumeratorKey);
1540 RegCloseKey(hEnumKey);
1541 if (rc != ERROR_SUCCESS)
1542 return rc;
1543 rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey);
1544 RegCloseKey(hEnumeratorKey);
1545 return rc;
1546 }
1547 else
1548 {
1549 /* Enumerate enumerators */
1550 i = 0;
1551 while (TRUE)
1552 {
1553 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1554 rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1555 if (rc == ERROR_NO_MORE_ITEMS)
1556 break;
1557 if (rc != ERROR_SUCCESS)
1558 {
1559 RegCloseKey(hEnumKey);
1560 return rc;
1561 }
1562 i++;
1563
1564 /* Open sub key */
1565 rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
1566 if (rc != ERROR_SUCCESS)
1567 {
1568 RegCloseKey(hEnumKey);
1569 return rc;
1570 }
1571
1572 /* Call SETUP_CreateDevListFromEnumerator */
1573 rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey);
1574 RegCloseKey(hEnumeratorKey);
1575 if (rc != ERROR_SUCCESS)
1576 {
1577 RegCloseKey(hEnumKey);
1578 return rc;
1579 }
1580 }
1581 RegCloseKey(hEnumKey);
1582 return ERROR_SUCCESS;
1583 }
1584 }
1585
1586 #ifndef __REACTOS__
1587 static LONG SETUP_CreateSerialDeviceList(
1588 struct DeviceInfoSet *list,
1589 PCWSTR MachineName,
1590 LPGUID InterfaceGuid,
1591 PCWSTR DeviceInstanceW)
1592 {
1593 static const size_t initialSize = 100;
1594 size_t size;
1595 WCHAR buf[initialSize];
1596 LPWSTR devices;
1597 static const WCHAR devicePrefixW[] = { 'C','O','M',0 };
1598 LPWSTR ptr;
1599 struct DeviceInfoElement *deviceInfo;
1600
1601 if (MachineName)
1602 WARN("'MachineName' is ignored on Wine!\n");
1603 if (DeviceInstanceW)
1604 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1605
1606 devices = buf;
1607 size = initialSize;
1608 while (TRUE)
1609 {
1610 if (QueryDosDeviceW(NULL, devices, size) != 0)
1611 break;
1612 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1613 {
1614 size *= 2;
1615 if (devices != buf)
1616 HeapFree(GetProcessHeap(), 0, devices);
1617 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1618 if (!devices)
1619 return ERROR_NOT_ENOUGH_MEMORY;
1620 *devices = '\0';
1621 }
1622 else
1623 {
1624 if (devices != buf)
1625 HeapFree(GetProcessHeap(), 0, devices);
1626 return GetLastError();
1627 }
1628 }
1629
1630 /* 'devices' is a MULTI_SZ string */
1631 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
1632 {
1633 if (strncmpW(devicePrefixW, ptr, sizeof(devicePrefixW) / sizeof(devicePrefixW[0]) - 1) == 0)
1634 {
1635 /* We have found a device */
1636 struct DeviceInterface *interfaceInfo;
1637 TRACE("Adding %s to list\n", debugstr_w(ptr));
1638 /* Step 1. Create a device info element */
1639 if (!CreateDeviceInfoElement(list, ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
1640 {
1641 if (devices != buf)
1642 HeapFree(GetProcessHeap(), 0, devices);
1643 return GetLastError();
1644 }
1645 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1646
1647 /* Step 2. Create an interface list for this element */
1648 if (!CreateDeviceInterface(deviceInfo, ptr, InterfaceGuid, &interfaceInfo))
1649 {
1650 if (devices != buf)
1651 HeapFree(GetProcessHeap(), 0, devices);
1652 return GetLastError();
1653 }
1654 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1655 }
1656 }
1657 if (devices != buf)
1658 HeapFree(GetProcessHeap(), 0, devices);
1659 return ERROR_SUCCESS;
1660 }
1661
1662 #else /* __REACTOS__ */
1663
1664 static LONG SETUP_CreateInterfaceList(
1665 struct DeviceInfoSet *list,
1666 PCWSTR MachineName,
1667 LPGUID InterfaceGuid,
1668 PCWSTR DeviceInstanceW /* OPTIONAL */)
1669 {
1670 HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1671 HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1672 HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1673 HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1674 HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1675 LONG rc;
1676 WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
1677 PWSTR InstancePath;
1678 DWORD i, j;
1679 DWORD dwLength, dwInstancePathLength;
1680 DWORD dwRegType;
1681 GUID ClassGuid;
1682 struct DeviceInfoElement *deviceInfo;
1683
1684 /* Open registry key related to this interface */
1685 hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
1686 if (hInterfaceKey == INVALID_HANDLE_VALUE)
1687 return GetLastError();
1688
1689 /* Enumerate sub keys of hInterfaceKey */
1690 i = 0;
1691 while (TRUE)
1692 {
1693 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1694 rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1695 if (rc == ERROR_NO_MORE_ITEMS)
1696 break;
1697 if (rc != ERROR_SUCCESS)
1698 {
1699 RegCloseKey(hInterfaceKey);
1700 return rc;
1701 }
1702 i++;
1703
1704 /* Open sub key */
1705 rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
1706 if (rc != ERROR_SUCCESS)
1707 {
1708 RegCloseKey(hInterfaceKey);
1709 return rc;
1710 }
1711
1712 /* Read DeviceInstance */
1713 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
1714 if (rc != ERROR_SUCCESS )
1715 {
1716 RegCloseKey(hDeviceInstanceKey);
1717 RegCloseKey(hInterfaceKey);
1718 return rc;
1719 }
1720 if (dwRegType != REG_SZ)
1721 {
1722 RegCloseKey(hDeviceInstanceKey);
1723 RegCloseKey(hInterfaceKey);
1724 return ERROR_GEN_FAILURE;
1725 }
1726 InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
1727 if (!InstancePath)
1728 {
1729 RegCloseKey(hDeviceInstanceKey);
1730 RegCloseKey(hInterfaceKey);
1731 return ERROR_NOT_ENOUGH_MEMORY;
1732 }
1733 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
1734 if (rc != ERROR_SUCCESS)
1735 {
1736 HeapFree(GetProcessHeap(), 0, InstancePath);
1737 RegCloseKey(hDeviceInstanceKey);
1738 RegCloseKey(hInterfaceKey);
1739 return rc;
1740 }
1741 InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
1742 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
1743
1744 if (DeviceInstanceW)
1745 {
1746 /* Check if device enumerator is not the right one */
1747 if (wcscmp(DeviceInstanceW, InstancePath) != 0)
1748 {
1749 HeapFree(GetProcessHeap(), 0, InstancePath);
1750 RegCloseKey(hDeviceInstanceKey);
1751 continue;
1752 }
1753 }
1754
1755 /* Find class GUID associated to the device instance */
1756 rc = RegOpenKeyExW(
1757 list->HKLM,
1758 REGSTR_PATH_SYSTEMENUM,
1759 0, /* Options */
1760 0,
1761 &hEnumKey);
1762 if (rc != ERROR_SUCCESS)
1763 {
1764 HeapFree(GetProcessHeap(), 0, InstancePath);
1765 RegCloseKey(hDeviceInstanceKey);
1766 RegCloseKey(hInterfaceKey);
1767 return rc;
1768 }
1769 rc = RegOpenKeyExW(
1770 hEnumKey,
1771 InstancePath,
1772 0, /* Options */
1773 KEY_QUERY_VALUE,
1774 &hKey);
1775 RegCloseKey(hEnumKey);
1776 if (rc != ERROR_SUCCESS)
1777 {
1778 HeapFree(GetProcessHeap(), 0, InstancePath);
1779 RegCloseKey(hDeviceInstanceKey);
1780 RegCloseKey(hInterfaceKey);
1781 return rc;
1782 }
1783 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1784 rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1785 RegCloseKey(hKey);
1786 if (rc != ERROR_SUCCESS)
1787 {
1788 HeapFree(GetProcessHeap(), 0, InstancePath);
1789 RegCloseKey(hDeviceInstanceKey);
1790 RegCloseKey(hInterfaceKey);
1791 return rc;
1792 }
1793 KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
1794 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1795 if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
1796 {
1797 HeapFree(GetProcessHeap(), 0, InstancePath);
1798 RegCloseKey(hDeviceInstanceKey);
1799 RegCloseKey(hInterfaceKey);
1800 return ERROR_GEN_FAILURE;
1801 }
1802 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
1803
1804 /* If current device doesn't match the list GUID (if any), skip this entry */
1805 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
1806 {
1807 HeapFree(GetProcessHeap(), 0, InstancePath);
1808 RegCloseKey(hDeviceInstanceKey);
1809 continue;
1810 }
1811
1812 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1813 j = 0;
1814 while (TRUE)
1815 {
1816 LPWSTR pSymbolicLink;
1817 struct DeviceInterface *interfaceInfo;
1818
1819 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1820 rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1821 if (rc == ERROR_NO_MORE_ITEMS)
1822 break;
1823 if (rc != ERROR_SUCCESS)
1824 {
1825 HeapFree(GetProcessHeap(), 0, InstancePath);
1826 RegCloseKey(hDeviceInstanceKey);
1827 RegCloseKey(hInterfaceKey);
1828 return rc;
1829 }
1830 j++;
1831 if (KeyBuffer[0] != '#')
1832 /* This entry doesn't represent an interesting entry */
1833 continue;
1834
1835 /* Open sub key */
1836 rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
1837 if (rc != ERROR_SUCCESS)
1838 {
1839 RegCloseKey(hDeviceInstanceKey);
1840 RegCloseKey(hInterfaceKey);
1841 return rc;
1842 }
1843
1844 /* Read SymbolicLink value */
1845 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
1846 if (rc != ERROR_SUCCESS )
1847 {
1848 RegCloseKey(hReferenceKey);
1849 RegCloseKey(hDeviceInstanceKey);
1850 RegCloseKey(hInterfaceKey);
1851 return rc;
1852 }
1853 if (dwRegType != REG_SZ)
1854 {
1855 RegCloseKey(hReferenceKey);
1856 RegCloseKey(hDeviceInstanceKey);
1857 RegCloseKey(hInterfaceKey);
1858 return ERROR_GEN_FAILURE;
1859 }
1860
1861 /* We have found a device */
1862 /* Step 1. Create a device info element */
1863 if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
1864 {
1865 RegCloseKey(hReferenceKey);
1866 RegCloseKey(hDeviceInstanceKey);
1867 RegCloseKey(hInterfaceKey);
1868 return GetLastError();
1869 }
1870 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
1871 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1872
1873 /* Step 2. Create an interface list for this element */
1874 pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
1875 if (!pSymbolicLink)
1876 {
1877 RegCloseKey(hReferenceKey);
1878 RegCloseKey(hDeviceInstanceKey);
1879 RegCloseKey(hInterfaceKey);
1880 return ERROR_NOT_ENOUGH_MEMORY;
1881 }
1882 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
1883 pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
1884 RegCloseKey(hReferenceKey);
1885 if (rc != ERROR_SUCCESS)
1886 {
1887 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1888 RegCloseKey(hDeviceInstanceKey);
1889 RegCloseKey(hInterfaceKey);
1890 return rc;
1891 }
1892 if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
1893 {
1894 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1895 RegCloseKey(hDeviceInstanceKey);
1896 RegCloseKey(hInterfaceKey);
1897 return GetLastError();
1898 }
1899 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
1900 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1901 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1902 }
1903 RegCloseKey(hDeviceInstanceKey);
1904 }
1905 RegCloseKey(hInterfaceKey);
1906 return ERROR_SUCCESS;
1907 }
1908 #endif /* __REACTOS__ */
1909
1910 /***********************************************************************
1911 * SetupDiGetClassDevsExW (SETUPAPI.@)
1912 */
1913 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1914 CONST GUID *class,
1915 LPCWSTR enumstr,
1916 HWND parent,
1917 DWORD flags,
1918 HDEVINFO deviceset,
1919 LPCWSTR machine,
1920 PVOID reserved)
1921 {
1922 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1923 struct DeviceInfoSet *list;
1924 LPGUID pClassGuid;
1925 LONG rc;
1926
1927 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr),
1928 parent, flags, deviceset, debugstr_w(machine), reserved);
1929
1930 /* Create the deviceset if not set */
1931 if (deviceset)
1932 {
1933 list = (struct DeviceInfoSet *)deviceset;
1934 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
1935 {
1936 SetLastError(ERROR_INVALID_HANDLE);
1937 return INVALID_HANDLE_VALUE;
1938 }
1939 hDeviceInfo = deviceset;
1940 }
1941 else
1942 {
1943 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
1944 flags & DIGCF_DEVICEINTERFACE ? NULL : class,
1945 NULL, machine, NULL);
1946 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1947 return INVALID_HANDLE_VALUE;
1948 list = (struct DeviceInfoSet *)hDeviceInfo;
1949 }
1950
1951 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1952 pClassGuid = NULL;
1953 else
1954 pClassGuid = &list->ClassGuid;
1955
1956 if (flags & DIGCF_PRESENT)
1957 FIXME(": flag DIGCF_PRESENT ignored\n");
1958 if (flags & DIGCF_PROFILE)
1959 FIXME(": flag DIGCF_PROFILE ignored\n");
1960
1961 if (flags & DIGCF_ALLCLASSES)
1962 {
1963 rc = SETUP_CreateDevList(list, machine, pClassGuid, enumstr);
1964 if (rc != ERROR_SUCCESS)
1965 {
1966 SetLastError(rc);
1967 if (!deviceset)
1968 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1969 return INVALID_HANDLE_VALUE;
1970 }
1971 return hDeviceInfo;
1972 }
1973 else if (flags & DIGCF_DEVICEINTERFACE)
1974 {
1975 if (class == NULL)
1976 {
1977 SetLastError(ERROR_INVALID_PARAMETER);
1978 if (!deviceset)
1979 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1980 return INVALID_HANDLE_VALUE;
1981 }
1982
1983 #ifndef __REACTOS__
1984 /* Special case: find serial ports by calling QueryDosDevice */
1985 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
1986 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1987 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
1988 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1989 else
1990 {
1991 ERR("Wine can only enumerate serial devices at the moment!\n");
1992 rc = ERROR_INVALID_PARAMETER;
1993 }
1994 #else /* __REACTOS__ */
1995 rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
1996 #endif /* __REACTOS__ */
1997 if (rc != ERROR_SUCCESS)
1998 {
1999 SetLastError(rc);
2000 if (!deviceset)
2001 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2002 return INVALID_HANDLE_VALUE;
2003 }
2004 return hDeviceInfo;
2005 }
2006 else
2007 {
2008 rc = SETUP_CreateDevList(list, machine, (LPGUID)class, enumstr);
2009 if (rc != ERROR_SUCCESS)
2010 {
2011 SetLastError(rc);
2012 if (!deviceset)
2013 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2014 return INVALID_HANDLE_VALUE;
2015 }
2016 return hDeviceInfo;
2017 }
2018 }
2019
2020 /***********************************************************************
2021 * SetupDiGetClassImageIndex (SETUPAPI.@)
2022 */
2023
2024 static BOOL GetIconIndex(
2025 IN HKEY hClassKey,
2026 OUT PINT ImageIndex)
2027 {
2028 LPWSTR Buffer = NULL;
2029 DWORD dwRegType, dwLength;
2030 LONG rc;
2031 BOOL ret = FALSE;
2032
2033 /* Read icon registry key */
2034 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength);
2035 if (rc != ERROR_SUCCESS)
2036 {
2037 SetLastError(rc);
2038 goto cleanup;
2039 } else if (dwRegType != REG_SZ)
2040 {
2041 SetLastError(ERROR_INVALID_INDEX);
2042 goto cleanup;
2043 }
2044 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
2045 if (!Buffer)
2046 {
2047 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2048 goto cleanup;
2049 }
2050 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength);
2051 if (rc != ERROR_SUCCESS)
2052 {
2053 SetLastError(rc);
2054 goto cleanup;
2055 }
2056 /* make sure the returned buffer is NULL-terminated */
2057 Buffer[dwLength / sizeof(WCHAR)] = 0;
2058
2059 /* Transform icon value to a INT */
2060 *ImageIndex = atoiW(Buffer);
2061 ret = TRUE;
2062
2063 cleanup:
2064 MyFree(Buffer);
2065 return ret;
2066 }
2067
2068 BOOL WINAPI SetupDiGetClassImageIndex(
2069 IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
2070 IN CONST GUID *ClassGuid,
2071 OUT PINT ImageIndex)
2072 {
2073 struct ClassImageList *list;
2074 BOOL ret = FALSE;
2075
2076 TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
2077
2078 if (!ClassImageListData || !ClassGuid || !ImageIndex)
2079 SetLastError(ERROR_INVALID_PARAMETER);
2080 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
2081 SetLastError(ERROR_INVALID_USER_BUFFER);
2082 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
2083 SetLastError(ERROR_INVALID_USER_BUFFER);
2084 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
2085 SetLastError(ERROR_INVALID_USER_BUFFER);
2086 else if (!ImageIndex)
2087 SetLastError(ERROR_INVALID_PARAMETER);
2088 else
2089 {
2090 HKEY hKey = INVALID_HANDLE_VALUE;
2091 INT iconIndex;
2092
2093 /* Read Icon registry entry into Buffer */
2094 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL);
2095 if (hKey == INVALID_HANDLE_VALUE)
2096 goto cleanup;
2097 if (!GetIconIndex(hKey, &iconIndex))
2098 goto cleanup;
2099
2100 if (iconIndex >= 0)
2101 {
2102 SetLastError(ERROR_INVALID_INDEX);
2103 goto cleanup;
2104 }
2105
2106 *ImageIndex = -iconIndex;
2107 ret = TRUE;
2108
2109 cleanup:
2110 if (hKey != INVALID_HANDLE_VALUE)
2111 RegCloseKey(hKey);
2112 }
2113
2114 TRACE("Returning %d\n", ret);
2115 return ret;
2116 }
2117
2118 /***********************************************************************
2119 * SetupDiGetClassImageList(SETUPAPI.@)
2120 */
2121 BOOL WINAPI SetupDiGetClassImageList(
2122 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
2123 {
2124 return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
2125 }
2126
2127 /***********************************************************************
2128 * SetupDiGetClassImageListExA(SETUPAPI.@)
2129 */
2130 BOOL WINAPI SetupDiGetClassImageListExA(
2131 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
2132 IN PCSTR MachineName OPTIONAL,
2133 IN PVOID Reserved)
2134 {
2135 PWSTR MachineNameW = NULL;
2136 BOOL ret;
2137
2138 if (MachineName)
2139 {
2140 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2141 if (MachineNameW == NULL)
2142 return FALSE;
2143 }
2144
2145 ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
2146
2147 if (MachineNameW)
2148 MyFree(MachineNameW);
2149
2150 return ret;
2151 }
2152
2153 /***********************************************************************
2154 * SetupDiGetClassImageListExW(SETUPAPI.@)
2155 */
2156 BOOL WINAPI SetupDiGetClassImageListExW(
2157 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
2158 IN PCWSTR MachineName OPTIONAL,
2159 IN PVOID Reserved)
2160 {
2161 BOOL ret = FALSE;
2162
2163 TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
2164
2165 if (!ClassImageListData)
2166 SetLastError(ERROR_INVALID_PARAMETER);
2167 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
2168 SetLastError(ERROR_INVALID_USER_BUFFER);
2169 else if (Reserved)
2170 SetLastError(ERROR_INVALID_PARAMETER);
2171 else
2172 {
2173 struct ClassImageList *list = NULL;
2174 DWORD size;
2175
2176 size = FIELD_OFFSET(struct ClassImageList, szData);
2177 if (MachineName)
2178 size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
2179 list = HeapAlloc(GetProcessHeap(), 0, size);
2180 if (!list)
2181 {
2182 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2183 goto cleanup;
2184 }
2185 list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
2186 if (MachineName)
2187 {
2188 list->szData[0] = list->szData[1] = '\\';
2189 strcpyW(list->szData + 2, MachineName);
2190 list->MachineName = list->szData;
2191 }
2192 else
2193 {
2194 list->MachineName = NULL;
2195 }
2196
2197 ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
2198 ret = TRUE;
2199
2200 cleanup:
2201 if (!ret)
2202 MyFree(list);
2203 }
2204
2205 TRACE("Returning %d\n", ret);
2206 return ret;
2207 }
2208
2209 /***********************************************************************
2210 * SetupDiLoadClassIcon(SETUPAPI.@)
2211 */
2212 BOOL WINAPI SetupDiLoadClassIcon(
2213 IN CONST GUID *ClassGuid,
2214 OUT HICON *LargeIcon OPTIONAL,
2215 OUT PINT MiniIconIndex OPTIONAL)
2216 {
2217 BOOL ret = FALSE;
2218
2219 if (!ClassGuid)
2220 SetLastError(ERROR_INVALID_PARAMETER);
2221 else
2222 {
2223 LPWSTR Buffer = NULL;
2224 LPCWSTR DllName;
2225 INT iconIndex;
2226 HKEY hKey = INVALID_HANDLE_VALUE;
2227
2228 hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
2229 if (hKey == INVALID_HANDLE_VALUE)
2230 goto cleanup;
2231
2232 if (!GetIconIndex(hKey, &iconIndex))
2233 goto cleanup;
2234
2235 if (iconIndex > 0)
2236 {
2237 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2238 PWCHAR Comma;
2239 LONG rc;
2240 DWORD dwRegType, dwLength;
2241 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
2242 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
2243 {
2244 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
2245 if (Buffer == NULL)
2246 {
2247 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2248 goto cleanup;
2249 }
2250 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
2251 if (rc != ERROR_SUCCESS)
2252 {
2253 SetLastError(rc);
2254 goto cleanup;
2255 }
2256 /* make sure the returned buffer is NULL-terminated */
2257 Buffer[dwLength / sizeof(WCHAR)] = 0;
2258 }
2259 else if
2260 (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
2261 && dwRegType == REG_SZ)
2262 {
2263 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
2264 if (Buffer == NULL)
2265 {
2266 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2267 goto cleanup;
2268 }
2269 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
2270 if (rc != ERROR_SUCCESS)
2271 {
2272 SetLastError(rc);
2273 goto cleanup;
2274 }
2275 /* make sure the returned buffer is NULL-terminated */
2276 Buffer[dwLength / sizeof(WCHAR)] = 0;
2277 }
2278 else
2279 {
2280 /* Unable to find where to load the icon */
2281 SetLastError(ERROR_FILE_NOT_FOUND);
2282 goto cleanup;
2283 }
2284 Comma = strchrW(Buffer, ',');
2285 if (!Comma)
2286 {
2287 SetLastError(ERROR_GEN_FAILURE);
2288 goto cleanup;
2289 }
2290 *Comma = '\0';
2291 DllName = Buffer;
2292 }
2293 else
2294 {
2295 /* Look up icon in setupapi.dll */
2296 DllName = L"setupapi.dll";
2297 iconIndex = -iconIndex;
2298 }
2299
2300 TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
2301 if (LargeIcon)
2302 {
2303 if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1))
2304 {
2305 SetLastError(ERROR_INVALID_INDEX);
2306 goto cleanup;
2307 }
2308 }
2309 if (MiniIconIndex)
2310 *MiniIconIndex = iconIndex;
2311 ret = TRUE;
2312
2313 cleanup:
2314 if (hKey != INVALID_HANDLE_VALUE)
2315 RegCloseKey(hKey);
2316 MyFree(Buffer);
2317 }
2318
2319 TRACE("Returning %d\n", ret);
2320 return ret;
2321 }
2322
2323 /***********************************************************************
2324 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2325 */
2326 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2327 HDEVINFO DeviceInfoSet,
2328 PSP_DEVINFO_DATA DeviceInfoData,
2329 CONST GUID * InterfaceClassGuid,
2330 DWORD MemberIndex,
2331 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2332 {
2333 BOOL ret = FALSE;
2334
2335 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
2336 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2337
2338 if (!DeviceInterfaceData)
2339 SetLastError(ERROR_INVALID_PARAMETER);
2340 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2341 SetLastError(ERROR_INVALID_USER_BUFFER);
2342 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
2343 {
2344 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2345
2346 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
2347 {
2348 PLIST_ENTRY ItemList = list->ListHead.Flink;
2349 BOOL Found = FALSE;
2350 while (ItemList != &list->ListHead && !Found)
2351 {
2352 PLIST_ENTRY InterfaceListEntry;
2353 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
2354 if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
2355 {
2356 /* We are not searching for this element */
2357 ItemList = ItemList->Flink;
2358 continue;
2359 }
2360 InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
2361 while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
2362 {
2363 struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
2364 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2365 {
2366 InterfaceListEntry = InterfaceListEntry->Flink;
2367 continue;
2368 }
2369 if (MemberIndex-- == 0)
2370 {
2371 /* return this item */
2372 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2373 &DevItf->InterfaceClassGuid,
2374 sizeof(GUID));
2375 DeviceInterfaceData->Flags = 0; /* FIXME */
2376 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2377 Found = TRUE;
2378 }
2379 InterfaceListEntry = InterfaceListEntry->Flink;
2380 }
2381 ItemList = ItemList->Flink;
2382 }
2383 if (!Found)
2384 SetLastError(ERROR_NO_MORE_ITEMS);
2385 else
2386 ret = TRUE;
2387 }
2388 else
2389 SetLastError(ERROR_INVALID_HANDLE);
2390 }
2391 else
2392 SetLastError(ERROR_INVALID_HANDLE);
2393 return ret;
2394 }
2395
2396 static VOID ReferenceInfFile(struct InfFileDetails* infFile)
2397 {
2398 InterlockedIncrement(&infFile->References);
2399 }
2400
2401 static VOID DereferenceInfFile(struct InfFileDetails* infFile)
2402 {
2403 if (InterlockedDecrement(&infFile->References) == 0)
2404 {
2405 SetupCloseInfFile(infFile->hInf);
2406 HeapFree(GetProcessHeap(), 0, infFile);
2407 }
2408 }
2409
2410 static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
2411 {
2412 DereferenceInfFile(driverInfo->InfFileDetails);
2413 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
2414 HeapFree(GetProcessHeap(), 0, driverInfo);
2415 return TRUE;
2416 }
2417
2418 static BOOL DestroyClassInstallParams(struct ClassInstallParams* installParams)
2419 {
2420 HeapFree(GetProcessHeap(), 0, installParams->PropChange);
2421 return TRUE;
2422 }
2423
2424 static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
2425 {
2426 PLIST_ENTRY ListEntry;
2427 struct DriverInfoElement *driverInfo;
2428
2429 while (!IsListEmpty(&deviceInfo->DriverListHead))
2430 {
2431 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
2432 driverInfo = (struct DriverInfoElement *)ListEntry;
2433 if (!DestroyDriverInfoElement(driverInfo))
2434 return FALSE;
2435 }
2436 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
2437 {
2438 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
2439 HeapFree(GetProcessHeap(), 0, ListEntry);
2440 }
2441 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
2442 HeapFree(GetProcessHeap(), 0, deviceInfo);
2443 return TRUE;
2444 }
2445
2446 static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
2447 {
2448 PLIST_ENTRY ListEntry;
2449 struct DeviceInfoElement *deviceInfo;
2450
2451 while (!IsListEmpty(&list->ListHead))
2452 {
2453 ListEntry = RemoveHeadList(&list->ListHead);
2454 deviceInfo = (struct DeviceInfoElement *)ListEntry;
2455 if (!DestroyDeviceInfoElement(deviceInfo))
2456 return FALSE;
2457 }
2458 if (list->HKLM != HKEY_LOCAL_MACHINE)
2459 RegCloseKey(list->HKLM);
2460 CM_Disconnect_Machine(list->hMachine);
2461 DestroyClassInstallParams(&list->ClassInstallParams);
2462 HeapFree(GetProcessHeap(), 0, list);
2463 return TRUE;
2464 }
2465
2466 /***********************************************************************
2467 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2468 */
2469 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2470 {
2471 BOOL ret = FALSE;
2472
2473 TRACE("%p\n", devinfo);
2474 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2475 {
2476 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2477
2478 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
2479 ret = DestroyDeviceInfoSet(list);
2480 else
2481 SetLastError(ERROR_INVALID_HANDLE);
2482 }
2483 else
2484 SetLastError(ERROR_INVALID_HANDLE);
2485
2486 TRACE("Returning %d\n", ret);
2487 return ret;
2488 }
2489
2490 /***********************************************************************
2491 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2492 */
2493 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2494 HDEVINFO DeviceInfoSet,
2495 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2496 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2497 DWORD DeviceInterfaceDetailDataSize,
2498 PDWORD RequiredSize,
2499 PSP_DEVINFO_DATA DeviceInfoData)
2500 {
2501 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2502 DWORD sizeW = 0, sizeA;
2503 BOOL ret = FALSE;
2504
2505 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2506 DeviceInterfaceData, DeviceInterfaceDetailData,
2507 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2508
2509 if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2510 SetLastError(ERROR_INVALID_USER_BUFFER);
2511 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2512 SetLastError(ERROR_INVALID_PARAMETER);
2513 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
2514 SetLastError(ERROR_INVALID_PARAMETER);
2515 else
2516 {
2517 if (DeviceInterfaceDetailData != NULL)
2518 {
2519 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2520 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2521 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
2522 if (!DeviceInterfaceDetailDataW)
2523 {
2524 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2525 }
2526 }
2527 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2528 {
2529 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2530 ret = SetupDiGetDeviceInterfaceDetailW(
2531 DeviceInfoSet,
2532 DeviceInterfaceData,
2533 DeviceInterfaceDetailDataW,
2534 sizeW,
2535 &sizeW,
2536 DeviceInfoData);
2537 sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2538 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2539 if (RequiredSize)
2540 *RequiredSize = sizeA;
2541 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
2542 {
2543 if (!WideCharToMultiByte(
2544 CP_ACP, 0,
2545 DeviceInterfaceDetailDataW->DevicePath, -1,
2546 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2547 NULL, NULL))
2548 {
2549 ret = FALSE;
2550 }
2551 }
2552 }
2553 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
2554 }
2555
2556 TRACE("Returning %d\n", ret);
2557 return ret;
2558 }
2559
2560 /***********************************************************************
2561 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2562 */
2563 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2564 HDEVINFO DeviceInfoSet,
2565 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2566 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2567 DWORD DeviceInterfaceDetailDataSize,
2568 PDWORD RequiredSize,
2569 PSP_DEVINFO_DATA DeviceInfoData)
2570 {
2571 BOOL ret = FALSE;
2572
2573 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2574 DeviceInterfaceData, DeviceInterfaceDetailData,
2575 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2576
2577 if (!DeviceInfoSet || !DeviceInterfaceData)
2578 SetLastError(ERROR_INVALID_PARAMETER);
2579 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2580 SetLastError(ERROR_INVALID_HANDLE);
2581 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2582 SetLastError(ERROR_INVALID_HANDLE);
2583 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2584 SetLastError(ERROR_INVALID_USER_BUFFER);
2585 else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
2586 SetLastError(ERROR_INVALID_USER_BUFFER);
2587 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2588 SetLastError(ERROR_INVALID_USER_BUFFER);
2589 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2590 SetLastError(ERROR_INVALID_PARAMETER);
2591 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
2592 SetLastError(ERROR_INVALID_PARAMETER);
2593 else
2594 {
2595 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2596 LPCWSTR devName = deviceInterface->SymbolicLink;
2597 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
2598 (lstrlenW(devName) + 1) * sizeof(WCHAR);
2599
2600 if (sizeRequired > DeviceInterfaceDetailDataSize)
2601 {
2602 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2603 if (RequiredSize)
2604 *RequiredSize = sizeRequired;
2605 }
2606 else
2607 {
2608 wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
2609 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
2610 if (DeviceInfoData)
2611 {
2612 memcpy(&DeviceInfoData->ClassGuid,
2613 &deviceInterface->DeviceInfo->ClassGuid,
2614 sizeof(GUID));
2615 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
2616 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
2617 }
2618 ret = TRUE;
2619 }
2620 }
2621
2622 TRACE("Returning %d\n", ret);
2623 return ret;
2624 }
2625
2626 /***********************************************************************
2627 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2628 */
2629 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2630 HDEVINFO devinfo,
2631 PSP_DEVINFO_DATA DeviceInfoData,
2632 DWORD Property,
2633 PDWORD PropertyRegDataType,
2634 PBYTE PropertyBuffer,
2635 DWORD PropertyBufferSize,
2636 PDWORD RequiredSize)
2637 {
2638 BOOL bResult;
2639 BOOL bIsStringProperty;
2640 DWORD RegType;
2641 DWORD RequiredSizeA, RequiredSizeW;
2642 DWORD PropertyBufferSizeW;
2643 PBYTE PropertyBufferW;
2644
2645 TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
2646 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2647 RequiredSize);
2648
2649 PropertyBufferSizeW = PropertyBufferSize * 2;
2650 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
2651
2652 bResult = SetupDiGetDeviceRegistryPropertyW(
2653 devinfo,
2654 DeviceInfoData,
2655 Property,
2656 &RegType,
2657 PropertyBufferW,
2658 PropertyBufferSizeW,
2659 &RequiredSizeW);
2660
2661 if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2662 {
2663 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
2664
2665 if (bIsStringProperty)
2666 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
2667 else
2668 RequiredSizeA = RequiredSizeW;
2669 if (RequiredSize)
2670 *RequiredSize = RequiredSizeA;
2671 if (PropertyRegDataType)
2672 *PropertyRegDataType = RegType;
2673 }
2674
2675 if (!bResult)
2676 {
2677 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2678 return bResult;
2679 }
2680
2681 if (RequiredSizeA <= PropertyBufferSize)
2682 {
2683 if (bIsStringProperty && PropertyBufferSize > 0)
2684 {
2685 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
2686 {
2687 /* Last error is already set by WideCharToMultiByte */
2688 bResult = FALSE;
2689 }
2690 }
2691 else
2692 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
2693 }
2694 else
2695 {
2696 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2697 bResult = FALSE;
2698 }
2699
2700 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2701 return bResult;
2702 }
2703
2704 /***********************************************************************
2705 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2706 */
2707 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2708 HDEVINFO DeviceInfoSet,
2709 PSP_DEVINFO_DATA DeviceInfoData,
2710 DWORD Property,
2711 PDWORD PropertyRegDataType,
2712 PBYTE PropertyBuffer,
2713 DWORD PropertyBufferSize,
2714 PDWORD RequiredSize)
2715 {
2716 HKEY hEnumKey, hKey;
2717 DWORD rc;
2718 BOOL ret = FALSE;
2719
2720 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
2721 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2722 RequiredSize);
2723
2724 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2725 SetLastError(ERROR_INVALID_HANDLE);
2726 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2727 SetLastError(ERROR_INVALID_HANDLE);
2728 else if (!DeviceInfoData)
2729 SetLastError(ERROR_INVALID_PARAMETER);
2730 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2731 SetLastError(ERROR_INVALID_USER_BUFFER);
2732 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
2733 SetLastError(ERROR_INVALID_PARAMETER);
2734 else
2735 {
2736 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2737 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2738
2739 switch (Property)
2740 {
2741 case SPDRP_CAPABILITIES:
2742 case SPDRP_CLASS:
2743 case SPDRP_CLASSGUID:
2744 case SPDRP_COMPATIBLEIDS:
2745 case SPDRP_CONFIGFLAGS:
2746 case SPDRP_DEVICEDESC:
2747 case SPDRP_DRIVER:
2748 case SPDRP_FRIENDLYNAME:
2749 case SPDRP_HARDWAREID:
2750 case SPDRP_LOCATION_INFORMATION:
2751 case SPDRP_LOWERFILTERS:
2752 case SPDRP_MFG:
2753 case SPDRP_SECURITY:
2754 case SPDRP_SERVICE:
2755 case SPDRP_UI_NUMBER:
2756 case SPDRP_UI_NUMBER_DESC_FORMAT:
2757 case SPDRP_UPPERFILTERS:
2758 {
2759 LPCWSTR RegistryPropertyName;
2760 DWORD BufferSize;
2761
2762 switch (Property)
2763 {
2764 case SPDRP_CAPABILITIES:
2765 RegistryPropertyName = REGSTR_VAL_CAPABILITIES; break;
2766 case SPDRP_CLASS:
2767 RegistryPropertyName = REGSTR_VAL_CLASS; break;
2768 case SPDRP_CLASSGUID:
2769 RegistryPropertyName = REGSTR_VAL_CLASSGUID; break;
2770 case SPDRP_COMPATIBLEIDS:
2771 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS; break;
2772 case SPDRP_CONFIGFLAGS:
2773 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS; break;
2774 case SPDRP_DEVICEDESC:
2775 RegistryPropertyName = REGSTR_VAL_DEVDESC; break;
2776 case SPDRP_DRIVER:
2777 RegistryPropertyName = REGSTR_VAL_DRIVER; break;
2778 case SPDRP_FRIENDLYNAME:
2779 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME; break;
2780 case SPDRP_HARDWAREID:
2781 RegistryPropertyName = REGSTR_VAL_HARDWAREID; break;
2782 case SPDRP_LOCATION_INFORMATION:
2783 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION; break;
2784 case SPDRP_LOWERFILTERS:
2785 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS; break;
2786 case SPDRP_MFG:
2787 RegistryPropertyName = REGSTR_VAL_MFG; break;
2788 case SPDRP_SECURITY:
2789 RegistryPropertyName = L"Security"; break;
2790 case SPDRP_SERVICE:
2791 RegistryPropertyName = REGSTR_VAL_SERVICE; break;
2792 case SPDRP_UI_NUMBER:
2793 RegistryPropertyName = REGSTR_VAL_UI_NUMBER; break;
2794 case SPDRP_UI_NUMBER_DESC_FORMAT:
2795 RegistryPropertyName = L"UINumberDescFormat"; break;
2796 case SPDRP_UPPERFILTERS:
2797 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
2798 default:
2799 /* Should not happen */
2800 RegistryPropertyName = NULL; break;
2801 }
2802
2803 /* Open registry key name */
2804 rc = RegOpenKeyExW(
2805 list->HKLM,
2806 REGSTR_PATH_SYSTEMENUM,
2807 0, /* Options */
2808 0,
2809 &hEnumKey);
2810 if (rc != ERROR_SUCCESS)
2811 {
2812 SetLastError(rc);
2813 break;
2814 }
2815 rc = RegOpenKeyExW(
2816 hEnumKey,
2817 DevInfo->Data,
2818 0, /* Options */
2819 KEY_QUERY_VALUE,
2820 &hKey);
2821 RegCloseKey(hEnumKey);
2822 if (rc != ERROR_SUCCESS)
2823 {
2824 SetLastError(rc);
2825 break;
2826 }
2827 /* Read registry entry */
2828 BufferSize = PropertyBufferSize;
2829 rc = RegQueryValueExW(
2830 hKey,
2831 RegistryPropertyName,
2832 NULL, /* Reserved */
2833 PropertyRegDataType,
2834 PropertyBuffer,
2835 &BufferSize);
2836 if (RequiredSize)
2837 *RequiredSize = BufferSize;
2838 switch(rc) {
2839 case ERROR_SUCCESS:
2840 if (PropertyBuffer != NULL || BufferSize == 0)
2841 ret = TRUE;
2842 else
2843 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2844 break;
2845 case ERROR_MORE_DATA:
2846 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2847 break;
2848 default:
2849 SetLastError(rc);
2850 }
2851 RegCloseKey(hKey);
2852 break;
2853 }
2854
2855 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
2856 {
2857 DWORD required = (wcslen(DevInfo->Data) + 1) * sizeof(WCHAR);
2858
2859 if (PropertyRegDataType)
2860 *PropertyRegDataType = REG_SZ;
2861 if (RequiredSize)
2862 *RequiredSize = required;
2863 if (PropertyBufferSize >= required)
2864 {
2865 wcscpy((LPWSTR)PropertyBuffer, DevInfo->Data);
2866 ret = TRUE;
2867 }
2868 else
2869 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2870 break;
2871 }
2872
2873 /*case SPDRP_BUSTYPEGUID:
2874 case SPDRP_LEGACYBUSTYPE:
2875 case SPDRP_BUSNUMBER:
2876 case SPDRP_ENUMERATOR_NAME:
2877 case SPDRP_SECURITY_SDS:
2878 case SPDRP_DEVTYPE:
2879 case SPDRP_EXCLUSIVE:
2880 case SPDRP_CHARACTERISTICS:
2881 case SPDRP_ADDRESS:
2882 case SPDRP_DEVICE_POWER_DATA:*/
2883 #if (WINVER >= 0x501)
2884 /*case SPDRP_REMOVAL_POLICY:
2885 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2886 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2887 case SPDRP_INSTALL_STATE:*/
2888 #endif
2889
2890 default:
2891 {
2892 ERR("Property 0x%lx not implemented\n", Property);
2893 SetLastError(ERROR_NOT_SUPPORTED);
2894 }
2895 }
2896 }
2897
2898 TRACE("Returning %d\n", ret);
2899 return ret;
2900 }
2901
2902 /***********************************************************************
2903 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2904 */
2905 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2906 IN HDEVINFO DeviceInfoSet,
2907 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2908 IN DWORD Property,
2909 IN CONST BYTE *PropertyBuffer,
2910 IN DWORD PropertyBufferSize)
2911 {
2912 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2913 Property, PropertyBuffer, PropertyBufferSize);
2914 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2915 return FALSE;
2916 }
2917
2918 /***********************************************************************
2919 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2920 */
2921 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2922 IN HDEVINFO DeviceInfoSet,
2923 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2924 IN DWORD Property,
2925 IN const BYTE *PropertyBuffer,
2926 IN DWORD PropertyBufferSize)
2927 {
2928 struct DeviceInfoSet *list;
2929 BOOL ret = FALSE;
2930
2931 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2932 Property, PropertyBuffer, PropertyBufferSize);
2933
2934 if (!DeviceInfoSet)
2935 SetLastError(ERROR_INVALID_HANDLE);
2936 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2937 SetLastError(ERROR_INVALID_HANDLE);
2938 else if (!DeviceInfoData)
2939 SetLastError(ERROR_INVALID_HANDLE);
2940 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2941 SetLastError(ERROR_INVALID_USER_BUFFER);
2942 else
2943 {
2944 switch (Property)
2945 {
2946 case SPDRP_COMPATIBLEIDS:
2947 case SPDRP_CONFIGFLAGS:
2948 case SPDRP_FRIENDLYNAME:
2949 case SPDRP_HARDWAREID:
2950 case SPDRP_LOCATION_INFORMATION:
2951 case SPDRP_LOWERFILTERS:
2952 case SPDRP_SECURITY:
2953 case SPDRP_SERVICE:
2954 case SPDRP_UI_NUMBER_DESC_FORMAT:
2955 case SPDRP_UPPERFILTERS:
2956 {
2957 LPCWSTR RegistryPropertyName;
2958 DWORD RegistryDataType;
2959 HKEY hKey;
2960 LONG rc;
2961
2962 switch (Property)
2963 {
2964 case SPDRP_COMPATIBLEIDS:
2965 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS;
2966 RegistryDataType = REG_MULTI_SZ;
2967 break;
2968 case SPDRP_CONFIGFLAGS:
2969 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
2970 RegistryDataType = REG_DWORD;
2971 break;
2972 case SPDRP_FRIENDLYNAME:
2973 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
2974 RegistryDataType = REG_SZ;
2975 break;
2976 case SPDRP_HARDWAREID:
2977 RegistryPropertyName = REGSTR_VAL_HARDWAREID;
2978 RegistryDataType = REG_MULTI_SZ;
2979 break;
2980 case SPDRP_LOCATION_INFORMATION:
2981 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
2982 RegistryDataType = REG_SZ;
2983 break;
2984 case SPDRP_LOWERFILTERS:
2985 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
2986 RegistryDataType = REG_MULTI_SZ;
2987 break;
2988 case SPDRP_SECURITY:
2989 RegistryPropertyName = L"Security";
2990 RegistryDataType = REG_BINARY;
2991 break;
2992 case SPDRP_SERVICE:
2993 RegistryPropertyName = REGSTR_VAL_SERVICE;
2994 RegistryDataType = REG_SZ;
2995 break;
2996 case SPDRP_UI_NUMBER_DESC_FORMAT:
2997 RegistryPropertyName = L"UINumberDescFormat";
2998 RegistryDataType = REG_SZ;
2999 break;
3000 case SPDRP_UPPERFILTERS:
3001 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS;
3002 RegistryDataType = REG_MULTI_SZ;
3003 break;
3004 default:
3005 /* Should not happen */
3006 RegistryPropertyName = NULL;
3007 RegistryDataType = REG_BINARY;
3008 break;
3009 }
3010 /* Open device registry key */
3011 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
3012 if (hKey != INVALID_HANDLE_VALUE)
3013 {
3014 /* Write new data */
3015 rc = RegSetValueExW(
3016 hKey,
3017 RegistryPropertyName,
3018 0, /* Reserved */
3019 RegistryDataType,
3020 PropertyBuffer,
3021 PropertyBufferSize);
3022 if (rc == ERROR_SUCCESS)
3023 ret = TRUE;
3024 else
3025 SetLastError(rc);
3026 RegCloseKey(hKey);
3027 }
3028 break;
3029 }
3030
3031 /*case SPDRP_CHARACTERISTICS:
3032 case SPDRP_DEVTYPE:
3033 case SPDRP_EXCLUSIVE:*/
3034 #if (WINVER >= 0x501)
3035 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3036 #endif
3037 //case SPDRP_SECURITY_SDS:
3038
3039 default:
3040 {
3041 ERR("Property 0x%lx not implemented\n", Property);
3042 SetLastError(ERROR_NOT_SUPPORTED);
3043 }
3044 }
3045 }
3046
3047 TRACE("Returning %d\n", ret);
3048 return ret;
3049 }
3050
3051
3052 /***********************************************************************
3053 * SetupDiInstallClassA (SETUPAPI.@)
3054 */
3055 BOOL WINAPI SetupDiInstallClassA(
3056 IN HWND hwndParent OPTIONAL,
3057 IN PCSTR InfFileName,
3058 IN DWORD Flags,
3059 IN HSPFILEQ FileQueue OPTIONAL)
3060 {
3061 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3062 }
3063
3064
3065 /***********************************************************************
3066 * SetupDiInstallClassW (SETUPAPI.@)
3067 */
3068 BOOL WINAPI SetupDiInstallClassW(
3069 IN HWND hwndParent OPTIONAL,
3070 IN PCWSTR InfFileName,
3071 IN DWORD Flags,
3072 IN HSPFILEQ FileQueue OPTIONAL)
3073 {
3074 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3075 }
3076
3077
3078 /***********************************************************************
3079 * SetupDiInstallClassExA (SETUPAPI.@)
3080 */
3081 BOOL WINAPI SetupDiInstallClassExA(
3082 IN HWND hwndParent OPTIONAL,
3083 IN PCSTR InfFileName OPTIONAL,
3084 IN DWORD Flags,
3085 IN HSPFILEQ FileQueue OPTIONAL,
3086 IN const GUID* InterfaceClassGuid OPTIONAL,
3087 IN PVOID Reserved1,
3088 IN PVOID Reserved2)
3089 {
3090 PWSTR InfFileNameW = NULL;
3091 BOOL Result;
3092
3093 if (InfFileName)
3094 {
3095 InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
3096 if (InfFileNameW == NULL)
3097 {
3098 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3099 return FALSE;
3100 }
3101 }
3102
3103 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3104 FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3105
3106 MyFree(InfFileNameW);
3107
3108 return Result;
3109 }
3110
3111
3112 static HKEY CreateClassKey(HINF hInf)
3113 {
3114 WCHAR FullBuffer[MAX_PATH];
3115 WCHAR Buffer[MAX_PATH];
3116 DWORD RequiredSize;
3117 HKEY hClassKey;
3118
3119 Buffer[0] = '\\';
3120 if (!SetupGetLineTextW(NULL,
3121 hInf,
3122 Version,
3123 ClassGUID,
3124 &Buffer[1],
3125 MAX_PATH - 1,
3126 &RequiredSize))
3127 {
3128 return INVALID_HANDLE_VALUE;
3129 }
3130
3131 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3132 lstrcatW(FullBuffer, Buffer);
3133
3134
3135 if (!SetupGetLineTextW(NULL,
3136 hInf,
3137 Version,
3138 Class,
3139 Buffer,
3140 MAX_PATH,
3141 &RequiredSize))
3142 {
3143 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
3144 return INVALID_HANDLE_VALUE;
3145 }
3146
3147 if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3148 FullBuffer,
3149 0,
3150 NULL,
3151 REG_OPTION_NON_VOLATILE,
3152 KEY_SET_VALUE,
3153 NULL,
3154 &hClassKey,
3155 NULL))
3156 {
3157 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
3158 return INVALID_HANDLE_VALUE;
3159 }
3160
3161 if (ERROR_SUCCESS != RegSetValueExW(hClassKey,
3162 Class,
3163 0,
3164 REG_SZ,
3165 (LPBYTE)Buffer,
3166 RequiredSize * sizeof(WCHAR)))
3167 {
3168 RegCloseKey(hClassKey);
3169 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
3170 return INVALID_HANDLE_VALUE;
3171 }
3172
3173 return hClassKey;
3174 }
3175
3176
3177 static BOOL
3178 InstallServicesSection(
3179 IN HINF hInf,
3180 IN PCWSTR SectionName,
3181 IN HDEVINFO DeviceInfoSet OPTIONAL,
3182 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
3183 OUT PCWSTR* pAssociatedService OPTIONAL,
3184 OUT PBOOL pRebootRequired OPTIONAL)
3185 {
3186 INFCONTEXT ContextService;
3187 DWORD RequiredSize;
3188 INT Flags;
3189 BOOL ret = FALSE;
3190
3191 ret = SetupFindFirstLineW(hInf, SectionName, NULL, &ContextService);
3192 while (ret)
3193 {
3194 LPWSTR ServiceName = NULL;
3195 LPWSTR ServiceSection = NULL;
3196
3197 ret = SetupGetStringFieldW(
3198 &ContextService,
3199 1, /* Field index */
3200 NULL, 0,
3201 &RequiredSize);
3202 if (!ret)
3203 goto nextservice;
3204 if (RequiredSize > 0)
3205 {
3206 /* We got the needed size for the buffer */
3207 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3208 if (!ServiceName)
3209 {
3210 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3211 goto nextservice;
3212 }
3213 ret = SetupGetStringFieldW(
3214 &ContextService,
3215 1, /* Field index */
3216 ServiceName, RequiredSize,
3217 &RequiredSize);
3218 if (!ret)
3219 goto nextservice;
3220 }
3221 ret = SetupGetIntField(
3222 &ContextService,
3223 2, /* Field index */
3224 &Flags);
3225 if (!ret)
3226 {
3227 /* The field may be empty. Ignore the error */
3228 Flags = 0;
3229 }
3230 ret = SetupGetStringFieldW(
3231 &ContextService,
3232 3, /* Field index */
3233 NULL, 0,
3234 &RequiredSize);
3235 if (!ret)
3236 {
3237 if (GetLastError() == ERROR_INVALID_PARAMETER)
3238 {
3239 /* This first is probably missing. It is not
3240 * required, so ignore the error */
3241 RequiredSize = 0;
3242 ret = TRUE;
3243 }
3244 else
3245 goto nextservice;
3246 }
3247 if (RequiredSize > 0)
3248 {
3249 /* We got the needed size for the buffer */
3250 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3251 if (!ServiceSection)
3252 {
3253 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3254 goto nextservice;
3255 }
3256 ret = SetupGetStringFieldW(
3257 &ContextService,
3258 3, /* Field index */
3259 ServiceSection, RequiredSize,
3260 &RequiredSize);
3261 if (!ret)
3262 goto nextservice;