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