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