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