2faf7ae5261b66d092a41b54122203002a146734
[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,
1190 FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
1191 if (!deviceInterface)
1192 {
1193 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1194 return FALSE;
1195 }
1196 deviceInterface->DeviceInfo = deviceInfo;
1197 wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
1198 deviceInterface->Flags = 0; /* FIXME */
1199 memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
1200
1201 *pDeviceInterface = deviceInterface;
1202 return TRUE;
1203 }
1204
1205 static LONG SETUP_CreateDevListFromEnumerator(
1206 struct DeviceInfoSet *list,
1207 LPCGUID pClassGuid OPTIONAL,
1208 LPCWSTR Enumerator,
1209 HKEY hEnumeratorKey) /* handle to Enumerator registry key */
1210 {
1211 HKEY hDeviceIdKey, hInstanceIdKey;
1212 WCHAR KeyBuffer[MAX_PATH];
1213 WCHAR InstancePath[MAX_PATH];
1214 LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
1215 struct DeviceInfoElement *deviceInfo;
1216 DWORD i = 0, j;
1217 DWORD dwLength, dwRegType;
1218 DWORD rc;
1219
1220 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1221 while (TRUE)
1222 {
1223 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1224 rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1225 if (rc == ERROR_NO_MORE_ITEMS)
1226 break;
1227 if (rc != ERROR_SUCCESS)
1228 return rc;
1229 i++;
1230
1231 /* Open device id sub key */
1232 rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
1233 if (rc != ERROR_SUCCESS)
1234 return rc;
1235 wcscpy(InstancePath, Enumerator);
1236 wcscat(InstancePath, L"\\");
1237 wcscat(InstancePath, KeyBuffer);
1238 wcscat(InstancePath, L"\\");
1239 pEndOfInstancePath = &InstancePath[wcslen(InstancePath)];
1240
1241 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1242 j = 0;
1243 while (TRUE)
1244 {
1245 GUID KeyGuid;
1246
1247 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1248 rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1249 if (rc == ERROR_NO_MORE_ITEMS)
1250 break;
1251 if (rc != ERROR_SUCCESS)
1252 {
1253 RegCloseKey(hDeviceIdKey);
1254 return rc;
1255 }
1256 j++;
1257
1258 /* Open instance id sub key */
1259 rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
1260 if (rc != ERROR_SUCCESS)
1261 {
1262 RegCloseKey(hDeviceIdKey);
1263 return rc;
1264 }
1265 *pEndOfInstancePath = '\0';
1266 wcscat(InstancePath, KeyBuffer);
1267
1268 /* Read ClassGUID value */
1269 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1270 rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength);
1271 RegCloseKey(hInstanceIdKey);
1272 if (rc == ERROR_FILE_NOT_FOUND)
1273 {
1274 if (pClassGuid)
1275 /* Skip this bad entry as we can't verify it */
1276 continue;
1277 /* Set a default GUID for this device */
1278 memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
1279 }
1280 else if (rc != ERROR_SUCCESS)
1281 {
1282 RegCloseKey(hDeviceIdKey);
1283 return rc;
1284 }
1285 else if (dwRegType != REG_SZ)
1286 {
1287 RegCloseKey(hDeviceIdKey);
1288 return ERROR_GEN_FAILURE;
1289 }
1290 else
1291 {
1292 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1293 if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
1294 /* Bad GUID, skip the entry */
1295 continue;
1296 }
1297
1298 if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
1299 {
1300 /* Skip this entry as it is not the right device class */
1301 continue;
1302 }
1303
1304 /* Add the entry to the list */
1305 if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo))
1306 {
1307 RegCloseKey(hDeviceIdKey);
1308 return GetLastError();
1309 }
1310 TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
1311 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1312 }
1313 RegCloseKey(hDeviceIdKey);
1314 }
1315
1316 return ERROR_SUCCESS;
1317 }
1318
1319 static LONG SETUP_CreateDevList(
1320 struct DeviceInfoSet *list,
1321 PCWSTR MachineName OPTIONAL,
1322 LPGUID class OPTIONAL,
1323 PCWSTR Enumerator OPTIONAL)
1324 {
1325 HKEY HKLM, hEnumKey, hEnumeratorKey;
1326 WCHAR KeyBuffer[MAX_PATH];
1327 DWORD i;
1328 DWORD dwLength;
1329 DWORD rc;
1330
1331 if (class && IsEqualIID(class, &GUID_NULL))
1332 class = NULL;
1333
1334 /* Open Enum key */
1335 if (MachineName != NULL)
1336 {
1337 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
1338 if (rc != ERROR_SUCCESS)
1339 return rc;
1340 }
1341 else
1342 HKLM = HKEY_LOCAL_MACHINE;
1343
1344 rc = RegOpenKeyExW(HKLM,
1345 EnumKeyName,
1346 0,
1347 KEY_ENUMERATE_SUB_KEYS,
1348 &hEnumKey);
1349 if (MachineName != NULL) RegCloseKey(HKLM);
1350 if (rc != ERROR_SUCCESS)
1351 return rc;
1352
1353 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1354 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1355 * for each one.
1356 */
1357 if (Enumerator)
1358 {
1359 rc = RegOpenKeyExW(
1360 hEnumKey,
1361 Enumerator,
1362 0,
1363 KEY_ENUMERATE_SUB_KEYS,
1364 &hEnumeratorKey);
1365 RegCloseKey(hEnumKey);
1366 if (rc != ERROR_SUCCESS)
1367 return rc;
1368 rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey);
1369 RegCloseKey(hEnumeratorKey);
1370 return rc;
1371 }
1372 else
1373 {
1374 /* Enumerate enumerators */
1375 i = 0;
1376 while (TRUE)
1377 {
1378 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1379 rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1380 if (rc == ERROR_NO_MORE_ITEMS)
1381 break;
1382 if (rc != ERROR_SUCCESS)
1383 {
1384 RegCloseKey(hEnumKey);
1385 return rc;
1386 }
1387 i++;
1388
1389 /* Open sub key */
1390 rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
1391 if (rc != ERROR_SUCCESS)
1392 {
1393 RegCloseKey(hEnumKey);
1394 return rc;
1395 }
1396
1397 /* Call SETUP_CreateDevListFromEnumerator */
1398 rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey);
1399 RegCloseKey(hEnumeratorKey);
1400 if (rc != ERROR_SUCCESS)
1401 {
1402 RegCloseKey(hEnumKey);
1403 return rc;
1404 }
1405 }
1406 RegCloseKey(hEnumKey);
1407 return ERROR_SUCCESS;
1408 }
1409 }
1410
1411 #ifndef __REACTOS__
1412 static LONG SETUP_CreateSerialDeviceList(
1413 struct DeviceInfoSet *list,
1414 PCWSTR MachineName,
1415 LPGUID InterfaceGuid,
1416 PCWSTR DeviceInstanceW)
1417 {
1418 static const size_t initialSize = 100;
1419 size_t size;
1420 WCHAR buf[initialSize];
1421 LPWSTR devices;
1422 static const WCHAR devicePrefixW[] = { 'C','O','M',0 };
1423 LPWSTR ptr;
1424 struct DeviceInfoElement *deviceInfo;
1425
1426 if (MachineName)
1427 WARN("'MachineName' is ignored on Wine!\n");
1428 if (DeviceInstanceW)
1429 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1430
1431 devices = buf;
1432 size = initialSize;
1433 while (TRUE)
1434 {
1435 if (QueryDosDeviceW(NULL, devices, size) != 0)
1436 break;
1437 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1438 {
1439 size *= 2;
1440 if (devices != buf)
1441 HeapFree(GetProcessHeap(), 0, devices);
1442 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1443 if (!devices)
1444 return ERROR_NOT_ENOUGH_MEMORY;
1445 *devices = '\0';
1446 }
1447 else
1448 {
1449 if (devices != buf)
1450 HeapFree(GetProcessHeap(), 0, devices);
1451 return GetLastError();
1452 }
1453 }
1454
1455 /* 'devices' is a MULTI_SZ string */
1456 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
1457 {
1458 if (strncmpW(devicePrefixW, ptr, sizeof(devicePrefixW) / sizeof(devicePrefixW[0]) - 1) == 0)
1459 {
1460 /* We have found a device */
1461 struct DeviceInterface *interfaceInfo;
1462 TRACE("Adding %s to list\n", debugstr_w(ptr));
1463 /* Step 1. Create a device info element */
1464 if (!CreateDeviceInfoElement(list, ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
1465 {
1466 if (devices != buf)
1467 HeapFree(GetProcessHeap(), 0, devices);
1468 return GetLastError();
1469 }
1470 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1471
1472 /* Step 2. Create an interface list for this element */
1473 if (!CreateDeviceInterface(deviceInfo, ptr, InterfaceGuid, &interfaceInfo))
1474 {
1475 if (devices != buf)
1476 HeapFree(GetProcessHeap(), 0, devices);
1477 return GetLastError();
1478 }
1479 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1480 }
1481 }
1482 if (devices != buf)
1483 HeapFree(GetProcessHeap(), 0, devices);
1484 return ERROR_SUCCESS;
1485 }
1486
1487 #else /* __REACTOS__ */
1488
1489 static LONG SETUP_CreateInterfaceList(
1490 struct DeviceInfoSet *list,
1491 PCWSTR MachineName,
1492 LPGUID InterfaceGuid,
1493 PCWSTR DeviceInstanceW /* OPTIONAL */)
1494 {
1495 HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1496 HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1497 HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1498 HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1499 HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1500 LONG rc;
1501 WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
1502 PWSTR InstancePath;
1503 DWORD i, j;
1504 DWORD dwLength, dwInstancePathLength;
1505 DWORD dwRegType;
1506 GUID ClassGuid;
1507 struct DeviceInfoElement *deviceInfo;
1508
1509 /* Open registry key related to this interface */
1510 hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
1511 if (hInterfaceKey == INVALID_HANDLE_VALUE)
1512 return GetLastError();
1513
1514 /* Enumerate sub keys of hInterfaceKey */
1515 i = 0;
1516 while (TRUE)
1517 {
1518 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1519 rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1520 if (rc == ERROR_NO_MORE_ITEMS)
1521 break;
1522 if (rc != ERROR_SUCCESS)
1523 {
1524 RegCloseKey(hInterfaceKey);
1525 return rc;
1526 }
1527 i++;
1528
1529 /* Open sub key */
1530 rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
1531 if (rc != ERROR_SUCCESS)
1532 {
1533 RegCloseKey(hInterfaceKey);
1534 return rc;
1535 }
1536
1537 /* Read DeviceInstance */
1538 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
1539 if (rc != ERROR_SUCCESS )
1540 {
1541 RegCloseKey(hDeviceInstanceKey);
1542 RegCloseKey(hInterfaceKey);
1543 return rc;
1544 }
1545 if (dwRegType != REG_SZ)
1546 {
1547 RegCloseKey(hDeviceInstanceKey);
1548 RegCloseKey(hInterfaceKey);
1549 return ERROR_GEN_FAILURE;
1550 }
1551 InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
1552 if (!InstancePath)
1553 {
1554 RegCloseKey(hDeviceInstanceKey);
1555 RegCloseKey(hInterfaceKey);
1556 return ERROR_NOT_ENOUGH_MEMORY;
1557 }
1558 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
1559 if (rc != ERROR_SUCCESS)
1560 {
1561 HeapFree(GetProcessHeap(), 0, InstancePath);
1562 RegCloseKey(hDeviceInstanceKey);
1563 RegCloseKey(hInterfaceKey);
1564 return rc;
1565 }
1566 InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
1567 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
1568
1569 if (DeviceInstanceW)
1570 {
1571 /* Check if device enumerator is not the right one */
1572 if (wcscmp(DeviceInstanceW, InstancePath) != 0)
1573 {
1574 HeapFree(GetProcessHeap(), 0, InstancePath);
1575 RegCloseKey(hDeviceInstanceKey);
1576 continue;
1577 }
1578 }
1579
1580 /* Find class GUID associated to the device instance */
1581 rc = RegOpenKeyExW(
1582 HKEY_LOCAL_MACHINE,
1583 EnumKeyName,
1584 0, /* Options */
1585 KEY_ENUMERATE_SUB_KEYS,
1586 &hEnumKey);
1587 if (rc != ERROR_SUCCESS)
1588 {
1589 HeapFree(GetProcessHeap(), 0, InstancePath);
1590 RegCloseKey(hDeviceInstanceKey);
1591 RegCloseKey(hInterfaceKey);
1592 return rc;
1593 }
1594 rc = RegOpenKeyExW(
1595 hEnumKey,
1596 InstancePath,
1597 0, /* Options */
1598 KEY_QUERY_VALUE,
1599 &hKey);
1600 RegCloseKey(hEnumKey);
1601 if (rc != ERROR_SUCCESS)
1602 {
1603 HeapFree(GetProcessHeap(), 0, InstancePath);
1604 RegCloseKey(hDeviceInstanceKey);
1605 RegCloseKey(hInterfaceKey);
1606 return rc;
1607 }
1608 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1609 rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1610 RegCloseKey(hKey);
1611 if (rc != ERROR_SUCCESS)
1612 {
1613 HeapFree(GetProcessHeap(), 0, InstancePath);
1614 RegCloseKey(hDeviceInstanceKey);
1615 RegCloseKey(hInterfaceKey);
1616 return rc;
1617 }
1618 KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
1619 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1620 if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
1621 {
1622 HeapFree(GetProcessHeap(), 0, InstancePath);
1623 RegCloseKey(hDeviceInstanceKey);
1624 RegCloseKey(hInterfaceKey);
1625 return ERROR_GEN_FAILURE;
1626 }
1627 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
1628
1629 /* If current device doesn't match the list GUID (if any), skip this entry */
1630 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
1631 {
1632 HeapFree(GetProcessHeap(), 0, InstancePath);
1633 RegCloseKey(hDeviceInstanceKey);
1634 continue;
1635 }
1636
1637 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1638 j = 0;
1639 while (TRUE)
1640 {
1641 LPWSTR pSymbolicLink;
1642 struct DeviceInterface *interfaceInfo;
1643
1644 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1645 rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1646 if (rc == ERROR_NO_MORE_ITEMS)
1647 break;
1648 if (rc != ERROR_SUCCESS)
1649 {
1650 HeapFree(GetProcessHeap(), 0, InstancePath);
1651 RegCloseKey(hDeviceInstanceKey);
1652 RegCloseKey(hInterfaceKey);
1653 return rc;
1654 }
1655 j++;
1656 if (KeyBuffer[0] != '#')
1657 /* This entry doesn't represent an interesting entry */
1658 continue;
1659
1660 /* Open sub key */
1661 rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
1662 if (rc != ERROR_SUCCESS)
1663 {
1664 RegCloseKey(hDeviceInstanceKey);
1665 RegCloseKey(hInterfaceKey);
1666 return rc;
1667 }
1668
1669 /* Read SymbolicLink value */
1670 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
1671 if (rc != ERROR_SUCCESS )
1672 {
1673 RegCloseKey(hReferenceKey);
1674 RegCloseKey(hDeviceInstanceKey);
1675 RegCloseKey(hInterfaceKey);
1676 return rc;
1677 }
1678 if (dwRegType != REG_SZ)
1679 {
1680 RegCloseKey(hReferenceKey);
1681 RegCloseKey(hDeviceInstanceKey);
1682 RegCloseKey(hInterfaceKey);
1683 return ERROR_GEN_FAILURE;
1684 }
1685
1686 /* We have found a device */
1687 /* Step 1. Create a device info element */
1688 if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
1689 {
1690 RegCloseKey(hReferenceKey);
1691 RegCloseKey(hDeviceInstanceKey);
1692 RegCloseKey(hInterfaceKey);
1693 return GetLastError();
1694 }
1695 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
1696 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1697
1698 /* Step 2. Create an interface list for this element */
1699 pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
1700 if (!pSymbolicLink)
1701 {
1702 RegCloseKey(hReferenceKey);
1703 RegCloseKey(hDeviceInstanceKey);
1704 RegCloseKey(hInterfaceKey);
1705 return ERROR_NOT_ENOUGH_MEMORY;
1706 }
1707 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
1708 pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
1709 RegCloseKey(hReferenceKey);
1710 if (rc != ERROR_SUCCESS)
1711 {
1712 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1713 RegCloseKey(hDeviceInstanceKey);
1714 RegCloseKey(hInterfaceKey);
1715 return rc;
1716 }
1717 if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
1718 {
1719 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1720 RegCloseKey(hDeviceInstanceKey);
1721 RegCloseKey(hInterfaceKey);
1722 return GetLastError();
1723 }
1724 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
1725 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1726 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1727 }
1728 RegCloseKey(hDeviceInstanceKey);
1729 }
1730 RegCloseKey(hInterfaceKey);
1731 return ERROR_SUCCESS;
1732 }
1733 #endif /* __REACTOS__ */
1734
1735 /***********************************************************************
1736 * SetupDiGetClassDevsExW (SETUPAPI.@)
1737 */
1738 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1739 CONST GUID *class,
1740 LPCWSTR enumstr,
1741 HWND parent,
1742 DWORD flags,
1743 HDEVINFO deviceset,
1744 LPCWSTR machine,
1745 PVOID reserved)
1746 {
1747 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1748 struct DeviceInfoSet *list;
1749 LPGUID pClassGuid;
1750 LONG rc;
1751
1752 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr),
1753 parent, flags, deviceset, debugstr_w(machine), reserved);
1754
1755 /* Create the deviceset if not set */
1756 if (deviceset)
1757 {
1758 list = (struct DeviceInfoSet *)deviceset;
1759 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
1760 {
1761 SetLastError(ERROR_INVALID_HANDLE);
1762 return INVALID_HANDLE_VALUE;
1763 }
1764 hDeviceInfo = deviceset;
1765 }
1766 else
1767 {
1768 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
1769 flags & DIGCF_DEVICEINTERFACE ? NULL : class,
1770 NULL, machine, NULL);
1771 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1772 return INVALID_HANDLE_VALUE;
1773 list = (struct DeviceInfoSet *)hDeviceInfo;
1774 }
1775
1776 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1777 pClassGuid = NULL;
1778 else
1779 pClassGuid = &list->ClassGuid;
1780
1781 if (flags & DIGCF_PRESENT)
1782 FIXME(": flag DIGCF_PRESENT ignored\n");
1783 if (flags & DIGCF_PROFILE)
1784 FIXME(": flag DIGCF_PROFILE ignored\n");
1785
1786 if (flags & DIGCF_ALLCLASSES)
1787 {
1788 rc = SETUP_CreateDevList(list, machine, pClassGuid, enumstr);
1789 if (rc != ERROR_SUCCESS)
1790 {
1791 SetLastError(rc);
1792 if (!deviceset)
1793 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1794 return INVALID_HANDLE_VALUE;
1795 }
1796 return hDeviceInfo;
1797 }
1798 else if (flags & DIGCF_DEVICEINTERFACE)
1799 {
1800 if (class == NULL)
1801 {
1802 SetLastError(ERROR_INVALID_PARAMETER);
1803 if (!deviceset)
1804 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1805 return INVALID_HANDLE_VALUE;
1806 }
1807
1808 #ifndef __REACTOS__
1809 /* Special case: find serial ports by calling QueryDosDevice */
1810 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
1811 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1812 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
1813 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1814 else
1815 {
1816 ERR("Wine can only enumerate serial devices at the moment!\n");
1817 rc = ERROR_INVALID_PARAMETER;
1818 }
1819 #else /* __REACTOS__ */
1820 rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
1821 #endif /* __REACTOS__ */
1822 if (rc != ERROR_SUCCESS)
1823 {
1824 SetLastError(rc);
1825 if (!deviceset)
1826 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1827 return INVALID_HANDLE_VALUE;
1828 }
1829 return hDeviceInfo;
1830 }
1831 else
1832 {
1833 rc = SETUP_CreateDevList(list, machine, (LPGUID)class, enumstr);
1834 if (rc != ERROR_SUCCESS)
1835 {
1836 SetLastError(rc);
1837 if (!deviceset)
1838 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1839 return INVALID_HANDLE_VALUE;
1840 }
1841 return hDeviceInfo;
1842 }
1843 }
1844
1845 /***********************************************************************
1846 * SetupDiGetClassImageIndex (SETUPAPI.@)
1847 */
1848
1849 static BOOL GetIconIndex(
1850 IN HKEY hClassKey,
1851 OUT PINT ImageIndex)
1852 {
1853 LPWSTR Buffer = NULL;
1854 DWORD dwRegType, dwLength;
1855 LONG rc;
1856 BOOL ret = FALSE;
1857
1858 /* Read "Icon" registry key */
1859 rc = RegQueryValueExW(hClassKey, L"Icon", NULL, &dwRegType, NULL, &dwLength);
1860 if (rc != ERROR_SUCCESS)
1861 {
1862 SetLastError(rc);
1863 goto cleanup;
1864 } else if (dwRegType != REG_SZ)
1865 {
1866 SetLastError(ERROR_INVALID_INDEX);
1867 goto cleanup;
1868 }
1869 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
1870 if (!Buffer)
1871 {
1872 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1873 goto cleanup;
1874 }
1875 Buffer[dwLength / sizeof(WCHAR)] = 0;
1876 rc = RegQueryValueExW(hClassKey, L"Icon", NULL, NULL, (LPBYTE)Buffer, &dwLength);
1877 if (rc != ERROR_SUCCESS)
1878 {
1879 SetLastError(rc);
1880 goto cleanup;
1881 }
1882
1883 /* Transform "Icon" value to a INT */
1884 *ImageIndex = atoiW(Buffer);
1885 ret = TRUE;
1886
1887 cleanup:
1888 MyFree(Buffer);
1889 return ret;
1890 }
1891
1892 BOOL WINAPI SetupDiGetClassImageIndex(
1893 IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
1894 IN CONST GUID *ClassGuid,
1895 OUT PINT ImageIndex)
1896 {
1897 struct ClassImageList *list;
1898 BOOL ret = FALSE;
1899
1900 TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
1901
1902 if (!ClassImageListData || !ClassGuid || !ImageIndex)
1903 SetLastError(ERROR_INVALID_PARAMETER);
1904 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
1905 SetLastError(ERROR_INVALID_USER_BUFFER);
1906 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
1907 SetLastError(ERROR_INVALID_USER_BUFFER);
1908 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
1909 SetLastError(ERROR_INVALID_USER_BUFFER);
1910 else if (!ImageIndex)
1911 SetLastError(ERROR_INVALID_PARAMETER);
1912 else
1913 {
1914 HKEY hKey = INVALID_HANDLE_VALUE;
1915 INT iconIndex;
1916
1917 /* Read Icon registry entry into Buffer */
1918 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL);
1919 if (hKey == INVALID_HANDLE_VALUE)
1920 goto cleanup;
1921 if (!GetIconIndex(hKey, &iconIndex))
1922 goto cleanup;
1923
1924 if (iconIndex >= 0)
1925 {
1926 SetLastError(ERROR_INVALID_INDEX);
1927 goto cleanup;
1928 }
1929
1930 *ImageIndex = -iconIndex;
1931 ret = TRUE;
1932
1933 cleanup:
1934 if (hKey != INVALID_HANDLE_VALUE)
1935 RegCloseKey(hKey);
1936 }
1937
1938 TRACE("Returning %d\n", ret);
1939 return ret;
1940 }
1941
1942 /***********************************************************************
1943 * SetupDiGetClassImageList(SETUPAPI.@)
1944 */
1945 BOOL WINAPI SetupDiGetClassImageList(
1946 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
1947 {
1948 return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
1949 }
1950
1951 /***********************************************************************
1952 * SetupDiGetClassImageListExA(SETUPAPI.@)
1953 */
1954 BOOL WINAPI SetupDiGetClassImageListExA(
1955 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
1956 IN PCSTR MachineName OPTIONAL,
1957 IN PVOID Reserved)
1958 {
1959 PWSTR MachineNameW = NULL;
1960 BOOL ret;
1961
1962 if (MachineName)
1963 {
1964 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1965 if (MachineNameW == NULL)
1966 return FALSE;
1967 }
1968
1969 ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
1970
1971 if (MachineNameW)
1972 MyFree(MachineNameW);
1973
1974 return ret;
1975 }
1976
1977 /***********************************************************************
1978 * SetupDiGetClassImageListExW(SETUPAPI.@)
1979 */
1980 BOOL WINAPI SetupDiGetClassImageListExW(
1981 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
1982 IN PCWSTR MachineName OPTIONAL,
1983 IN PVOID Reserved)
1984 {
1985 BOOL ret = FALSE;
1986
1987 TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
1988
1989 if (!ClassImageListData)
1990 SetLastError(ERROR_INVALID_PARAMETER);
1991 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
1992 SetLastError(ERROR_INVALID_USER_BUFFER);
1993 else if (Reserved)
1994 SetLastError(ERROR_INVALID_PARAMETER);
1995 else
1996 {
1997 struct ClassImageList *list = NULL;
1998 DWORD size;
1999
2000 size = FIELD_OFFSET(struct ClassImageList, szData);
2001 if (MachineName)
2002 size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
2003 list = HeapAlloc(GetProcessHeap(), 0, size);
2004 if (!list)
2005 {
2006 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2007 goto cleanup;
2008 }
2009 list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
2010 if (MachineName)
2011 {
2012 list->szData[0] = list->szData[1] = '\\';
2013 strcpyW(list->szData + 2, MachineName);
2014 list->MachineName = list->szData;
2015 }
2016 else
2017 {
2018 list->MachineName = NULL;
2019 }
2020
2021 ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
2022 ret = TRUE;
2023
2024 cleanup:
2025 if (!ret)
2026 MyFree(list);
2027 }
2028
2029 TRACE("Returning %d\n", ret);
2030 return ret;
2031 }
2032
2033 /***********************************************************************
2034 * SetupDiLoadClassIcon(SETUPAPI.@)
2035 */
2036 BOOL WINAPI SetupDiLoadClassIcon(
2037 IN CONST GUID *ClassGuid,
2038 OUT HICON *LargeIcon OPTIONAL,
2039 OUT PINT MiniIconIndex OPTIONAL)
2040 {
2041 BOOL ret = FALSE;
2042
2043 if (!ClassGuid)
2044 SetLastError(ERROR_INVALID_PARAMETER);
2045 else
2046 {
2047 LPWSTR Buffer = NULL;
2048 LPCWSTR DllName;
2049 INT iconIndex;
2050 HKEY hKey = INVALID_HANDLE_VALUE;
2051
2052 hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
2053 if (hKey == INVALID_HANDLE_VALUE)
2054 goto cleanup;
2055
2056 if (!GetIconIndex(hKey, &iconIndex))
2057 goto cleanup;
2058
2059 if (iconIndex > 0)
2060 {
2061 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2062 PWCHAR Comma;
2063 LONG rc;
2064 DWORD dwRegType, dwLength;
2065 rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
2066 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
2067 {
2068 Buffer = MyMalloc(dwLength);
2069 if (Buffer == NULL)
2070 {
2071 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2072 goto cleanup;
2073 }
2074 rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)Buffer, &dwLength);
2075 if (rc != ERROR_SUCCESS)
2076 {
2077 SetLastError(rc);
2078 goto cleanup;
2079 }
2080 }
2081 else if
2082 (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength))
2083 && dwRegType == REG_SZ)
2084 {
2085 Buffer = MyMalloc(dwLength);
2086 if (Buffer == NULL)
2087 {
2088 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2089 goto cleanup;
2090 }
2091 rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)Buffer, &dwLength);
2092 if (rc != ERROR_SUCCESS)
2093 {
2094 SetLastError(rc);
2095 goto cleanup;
2096 }
2097 }
2098 else
2099 {
2100 /* Unable to find where to load the icon */
2101 SetLastError(ERROR_FILE_NOT_FOUND);
2102 goto cleanup;
2103 }
2104 Comma = strchrW(Buffer, ',');
2105 if (!Comma)
2106 {
2107 SetLastError(ERROR_GEN_FAILURE);
2108 goto cleanup;
2109 }
2110 *Comma = '\0';
2111 }
2112 else
2113 {
2114 /* Look up icon in setupapi.dll */
2115 DllName = L"setupapi.dll";
2116 iconIndex = -iconIndex;
2117 }
2118
2119 TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
2120 if (LargeIcon)
2121 {
2122 if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1))
2123 {
2124 SetLastError(ERROR_INVALID_INDEX);
2125 goto cleanup;
2126 }
2127 }
2128 if (MiniIconIndex)
2129 *MiniIconIndex = iconIndex;
2130 ret = TRUE;
2131
2132 cleanup:
2133 if (hKey != INVALID_HANDLE_VALUE)
2134 RegCloseKey(hKey);
2135 MyFree(Buffer);
2136 }
2137
2138 TRACE("Returning %d\n", ret);
2139 return ret;
2140 }
2141
2142 /***********************************************************************
2143 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2144 */
2145 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2146 HDEVINFO DeviceInfoSet,
2147 PSP_DEVINFO_DATA DeviceInfoData,
2148 CONST GUID * InterfaceClassGuid,
2149 DWORD MemberIndex,
2150 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2151 {
2152 BOOL ret = FALSE;
2153
2154 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
2155 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2156
2157 if (!DeviceInterfaceData)
2158 SetLastError(ERROR_INVALID_PARAMETER);
2159 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2160 SetLastError(ERROR_INVALID_USER_BUFFER);
2161 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
2162 {
2163 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2164
2165 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
2166 {
2167 PLIST_ENTRY ItemList = list->ListHead.Flink;
2168 BOOL Found = FALSE;
2169 while (ItemList != &list->ListHead && !Found)
2170 {
2171 PLIST_ENTRY InterfaceListEntry;
2172 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
2173 if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
2174 {
2175 /* We are not searching for this element */
2176 ItemList = ItemList->Flink;
2177 continue;
2178 }
2179 InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
2180 while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
2181 {
2182 struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
2183 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2184 {
2185 InterfaceListEntry = InterfaceListEntry->Flink;
2186 continue;
2187 }
2188 if (MemberIndex-- == 0)
2189 {
2190 /* return this item */
2191 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2192 &DevItf->InterfaceClassGuid,
2193 sizeof(GUID));
2194 DeviceInterfaceData->Flags = 0; /* FIXME */
2195 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2196 Found = TRUE;
2197 }
2198 InterfaceListEntry = InterfaceListEntry->Flink;
2199 }
2200 ItemList = ItemList->Flink;
2201 }
2202 if (!Found)
2203 SetLastError(ERROR_NO_MORE_ITEMS);
2204 else
2205 ret = TRUE;
2206 }
2207 else
2208 SetLastError(ERROR_INVALID_HANDLE);
2209 }
2210 else
2211 SetLastError(ERROR_INVALID_HANDLE);
2212 return ret;
2213 }
2214
2215 static VOID ReferenceInfFile(struct InfFileDetails* infFile)
2216 {
2217 InterlockedIncrement(&infFile->References);
2218 }
2219
2220 static VOID DereferenceInfFile(struct InfFileDetails* infFile)
2221 {
2222 if (InterlockedDecrement(&infFile->References) == 0)
2223 {
2224 SetupCloseInfFile(infFile->hInf);
2225 HeapFree(GetProcessHeap(), 0, infFile);
2226 }
2227 }
2228
2229 static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
2230 {
2231 DereferenceInfFile(driverInfo->InfFileDetails);
2232 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
2233 HeapFree(GetProcessHeap(), 0, driverInfo);
2234 return TRUE;
2235 }
2236
2237 static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
2238 {
2239 PLIST_ENTRY ListEntry;
2240 struct DriverInfoElement *driverInfo;
2241
2242 while (!IsListEmpty(&deviceInfo->DriverListHead))
2243 {
2244 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
2245 driverInfo = (struct DriverInfoElement *)ListEntry;
2246 if (!DestroyDriverInfoElement(driverInfo))
2247 return FALSE;
2248 }
2249 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
2250 {
2251 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
2252 HeapFree(GetProcessHeap(), 0, ListEntry);
2253 }
2254 HeapFree(GetProcessHeap(), 0, deviceInfo);
2255 return TRUE;
2256 }
2257
2258 static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
2259 {
2260 PLIST_ENTRY ListEntry;
2261 struct DeviceInfoElement *deviceInfo;
2262
2263 while (!IsListEmpty(&list->ListHead))
2264 {
2265 ListEntry = RemoveHeadList(&list->ListHead);
2266 deviceInfo = (struct DeviceInfoElement *)ListEntry;
2267 if (!DestroyDeviceInfoElement(deviceInfo))
2268 return FALSE;
2269 }
2270 if (list->HKLM != HKEY_LOCAL_MACHINE)
2271 RegCloseKey(list->HKLM);
2272 CM_Disconnect_Machine(list->hMachine);
2273 HeapFree(GetProcessHeap(), 0, list);
2274 return TRUE;
2275 }
2276
2277 /***********************************************************************
2278 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2279 */
2280 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2281 {
2282 BOOL ret = FALSE;
2283
2284 TRACE("%p\n", devinfo);
2285 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2286 {
2287 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2288
2289 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
2290 ret = DestroyDeviceInfoSet(list);
2291 else
2292 SetLastError(ERROR_INVALID_HANDLE);
2293 }
2294 else
2295 SetLastError(ERROR_INVALID_HANDLE);
2296
2297 TRACE("Returning %d\n", ret);
2298 return ret;
2299 }
2300
2301 /***********************************************************************
2302 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2303 */
2304 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2305 HDEVINFO DeviceInfoSet,
2306 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2307 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2308 DWORD DeviceInterfaceDetailDataSize,
2309 PDWORD RequiredSize,
2310 PSP_DEVINFO_DATA DeviceInfoData)
2311 {
2312 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2313 DWORD sizeW = 0, sizeA;
2314 BOOL ret = FALSE;
2315
2316 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2317 DeviceInterfaceData, DeviceInterfaceDetailData,
2318 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2319
2320 if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2321 SetLastError(ERROR_INVALID_USER_BUFFER);
2322 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2323 SetLastError(ERROR_INVALID_PARAMETER);
2324 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
2325 SetLastError(ERROR_INVALID_PARAMETER);
2326 else
2327 {
2328 if (DeviceInterfaceDetailData != NULL)
2329 {
2330 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2331 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2332 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
2333 if (!DeviceInterfaceDetailDataW)
2334 {
2335 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2336 }
2337 }
2338 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2339 {
2340 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2341 ret = SetupDiGetDeviceInterfaceDetailW(
2342 DeviceInfoSet,
2343 DeviceInterfaceData,
2344 DeviceInterfaceDetailDataW,
2345 sizeW,
2346 &sizeW,
2347 DeviceInfoData);
2348 sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2349 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2350 if (RequiredSize)
2351 *RequiredSize = sizeA;
2352 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
2353 {
2354 if (!WideCharToMultiByte(
2355 CP_ACP, 0,
2356 DeviceInterfaceDetailDataW->DevicePath, -1,
2357 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2358 NULL, NULL))
2359 {
2360 ret = FALSE;
2361 }
2362 }
2363 }
2364 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
2365 }
2366
2367 TRACE("Returning %d\n", ret);
2368 return ret;
2369 }
2370
2371 /***********************************************************************
2372 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2373 */
2374 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2375 HDEVINFO DeviceInfoSet,
2376 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2377 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2378 DWORD DeviceInterfaceDetailDataSize,
2379 PDWORD RequiredSize,
2380 PSP_DEVINFO_DATA DeviceInfoData)
2381 {
2382 BOOL ret = FALSE;
2383
2384 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2385 DeviceInterfaceData, DeviceInterfaceDetailData,
2386 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2387
2388 if (!DeviceInfoSet || !DeviceInterfaceData)
2389 SetLastError(ERROR_INVALID_PARAMETER);
2390 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2391 SetLastError(ERROR_INVALID_HANDLE);
2392 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2393 SetLastError(ERROR_INVALID_HANDLE);
2394 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2395 SetLastError(ERROR_INVALID_USER_BUFFER);
2396 else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
2397 SetLastError(ERROR_INVALID_USER_BUFFER);
2398 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2399 SetLastError(ERROR_INVALID_USER_BUFFER);
2400 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2401 SetLastError(ERROR_INVALID_PARAMETER);
2402 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
2403 SetLastError(ERROR_INVALID_PARAMETER);
2404 else
2405 {
2406 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2407 LPCWSTR devName = deviceInterface->SymbolicLink;
2408 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
2409 (lstrlenW(devName) + 1) * sizeof(WCHAR);
2410
2411 if (sizeRequired > DeviceInterfaceDetailDataSize)
2412 {
2413 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2414 if (RequiredSize)
2415 *RequiredSize = sizeRequired;
2416 }
2417 else
2418 {
2419 wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
2420 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
2421 if (DeviceInfoData)
2422 {
2423 memcpy(&DeviceInfoData->ClassGuid,
2424 &deviceInterface->DeviceInfo->ClassGuid,
2425 sizeof(GUID));
2426 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
2427 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
2428 }
2429 ret = TRUE;
2430 }
2431 }
2432
2433 TRACE("Returning %d\n", ret);
2434 return ret;
2435 }
2436
2437 /***********************************************************************
2438 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2439 */
2440 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2441 HDEVINFO devinfo,
2442 PSP_DEVINFO_DATA DeviceInfoData,
2443 DWORD Property,
2444 PDWORD PropertyRegDataType,
2445 PBYTE PropertyBuffer,
2446 DWORD PropertyBufferSize,
2447 PDWORD RequiredSize)
2448 {
2449 BOOL bResult;
2450 BOOL bIsStringProperty;
2451 DWORD RegType;
2452 DWORD RequiredSizeA, RequiredSizeW;
2453 DWORD PropertyBufferSizeW;
2454 PBYTE PropertyBufferW;
2455
2456 TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
2457 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2458 RequiredSize);
2459
2460 PropertyBufferSizeW = PropertyBufferSize * 2;
2461 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
2462
2463 bResult = SetupDiGetDeviceRegistryPropertyW(
2464 devinfo,
2465 DeviceInfoData,
2466 Property,
2467 &RegType,
2468 PropertyBufferW,
2469 PropertyBufferSizeW,
2470 &RequiredSizeW);
2471
2472 if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2473 {
2474 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
2475
2476 if (bIsStringProperty)
2477 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
2478 else
2479 RequiredSizeA = RequiredSizeW;
2480 if (RequiredSize)
2481 *RequiredSize = RequiredSizeA;
2482 if (PropertyRegDataType)
2483 *PropertyRegDataType = RegType;
2484 }
2485
2486 if (!bResult)
2487 {
2488 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2489 return bResult;
2490 }
2491
2492 if (RequiredSizeA <= PropertyBufferSize)
2493 {
2494 if (bIsStringProperty && PropertyBufferSize > 0)
2495 {
2496 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
2497 {
2498 /* Last error is already set by WideCharToMultiByte */
2499 bResult = FALSE;
2500 }
2501 }
2502 else
2503 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
2504 }
2505 else
2506 {
2507 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2508 bResult = FALSE;
2509 }
2510
2511 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2512 return bResult;
2513 }
2514
2515 /***********************************************************************
2516 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2517 */
2518 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2519 HDEVINFO DeviceInfoSet,
2520 PSP_DEVINFO_DATA DeviceInfoData,
2521 DWORD Property,
2522 PDWORD PropertyRegDataType,
2523 PBYTE PropertyBuffer,
2524 DWORD PropertyBufferSize,
2525 PDWORD RequiredSize)
2526 {
2527 HKEY hEnumKey, hKey;
2528 DWORD rc;
2529 BOOL ret = FALSE;
2530
2531 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
2532 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2533 RequiredSize);
2534
2535 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2536 SetLastError(ERROR_INVALID_HANDLE);
2537 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2538 SetLastError(ERROR_INVALID_HANDLE);
2539 else if (!DeviceInfoData)
2540 SetLastError(ERROR_INVALID_PARAMETER);
2541 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2542 SetLastError(ERROR_INVALID_USER_BUFFER);
2543 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
2544 SetLastError(ERROR_INVALID_PARAMETER);
2545 else
2546 {
2547 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2548 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2549
2550 switch (Property)
2551 {
2552 case SPDRP_CAPABILITIES:
2553 case SPDRP_CLASS:
2554 case SPDRP_CLASSGUID:
2555 case SPDRP_COMPATIBLEIDS:
2556 case SPDRP_CONFIGFLAGS:
2557 case SPDRP_DEVICEDESC:
2558 case SPDRP_DRIVER:
2559 case SPDRP_FRIENDLYNAME:
2560 case SPDRP_HARDWAREID:
2561 case SPDRP_LOCATION_INFORMATION:
2562 case SPDRP_LOWERFILTERS:
2563 case SPDRP_MFG:
2564 case SPDRP_SECURITY:
2565 case SPDRP_SERVICE:
2566 case SPDRP_UI_NUMBER:
2567 case SPDRP_UI_NUMBER_DESC_FORMAT:
2568 case SPDRP_UPPERFILTERS:
2569 {
2570 LPCWSTR RegistryPropertyName;
2571 DWORD BufferSize;
2572
2573 switch (Property)
2574 {
2575 case SPDRP_CAPABILITIES:
2576 RegistryPropertyName = L"Capabilities"; break;
2577 case SPDRP_CLASS:
2578 RegistryPropertyName = L"Class"; break;
2579 case SPDRP_CLASSGUID:
2580 RegistryPropertyName = L"ClassGUID"; break;
2581 case SPDRP_COMPATIBLEIDS:
2582 RegistryPropertyName = L"CompatibleIDs"; break;
2583 case SPDRP_CONFIGFLAGS:
2584 RegistryPropertyName = L"ConfigFlags"; break;
2585 case SPDRP_DEVICEDESC:
2586 RegistryPropertyName = L"DeviceDesc"; break;
2587 case SPDRP_DRIVER:
2588 RegistryPropertyName = L"Driver"; break;
2589 case SPDRP_FRIENDLYNAME:
2590 RegistryPropertyName = L"FriendlyName"; break;
2591 case SPDRP_HARDWAREID:
2592 RegistryPropertyName = L"HardwareID"; break;
2593 case SPDRP_LOCATION_INFORMATION:
2594 RegistryPropertyName = L"LocationInformation"; break;
2595 case SPDRP_LOWERFILTERS:
2596 RegistryPropertyName = L"LowerFilters"; break;
2597 case SPDRP_MFG:
2598 RegistryPropertyName = L"Mfg"; break;
2599 case SPDRP_SECURITY:
2600 RegistryPropertyName = L"Security"; break;
2601 case SPDRP_SERVICE:
2602 RegistryPropertyName = L"Service"; break;
2603 case SPDRP_UI_NUMBER:
2604 RegistryPropertyName = L"UINumber"; break;
2605 case SPDRP_UI_NUMBER_DESC_FORMAT:
2606 RegistryPropertyName = L"UINumberDescFormat"; break;
2607 case SPDRP_UPPERFILTERS:
2608 RegistryPropertyName = L"UpperFilters"; break;
2609 default:
2610 /* Should not happen */
2611 RegistryPropertyName = NULL; break;
2612 }
2613
2614 /* Open registry key name */
2615 rc = RegOpenKeyExW(
2616 list->HKLM,
2617 EnumKeyName,
2618 0, /* Options */
2619 KEY_ENUMERATE_SUB_KEYS,
2620 &hEnumKey);
2621 if (rc != ERROR_SUCCESS)
2622 {
2623 SetLastError(rc);
2624 break;
2625 }
2626 rc = RegOpenKeyExW(
2627 hEnumKey,
2628 DevInfo->Data,
2629 0, /* Options */
2630 KEY_QUERY_VALUE,
2631 &hKey);
2632 RegCloseKey(hEnumKey);
2633 if (rc != ERROR_SUCCESS)
2634 {
2635 SetLastError(rc);
2636 break;
2637 }
2638 /* Read registry entry */
2639 BufferSize = PropertyBufferSize;
2640 rc = RegQueryValueExW(
2641 hKey,
2642 RegistryPropertyName,
2643 NULL, /* Reserved */
2644 PropertyRegDataType,
2645 PropertyBuffer,
2646 &BufferSize);
2647 if (RequiredSize)
2648 *RequiredSize = BufferSize;
2649 switch(rc) {
2650 case ERROR_SUCCESS:
2651 if (PropertyBuffer != NULL || BufferSize == 0)
2652 ret = TRUE;
2653 else
2654 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2655 break;
2656 case ERROR_MORE_DATA:
2657 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2658 break;
2659 default:
2660 SetLastError(rc);
2661 }
2662 RegCloseKey(hKey);
2663 break;
2664 }
2665
2666 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
2667 {
2668 DWORD required = (wcslen(DevInfo->Data) + 1) * sizeof(WCHAR);
2669
2670 if (PropertyRegDataType)
2671 *PropertyRegDataType = REG_SZ;
2672 if (RequiredSize)
2673 *RequiredSize = required;
2674 if (PropertyBufferSize >= required)
2675 {
2676 wcscpy((LPWSTR)PropertyBuffer, DevInfo->Data);
2677 ret = TRUE;
2678 }
2679 else
2680 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2681 break;
2682 }
2683
2684 /*case SPDRP_BUSTYPEGUID:
2685 case SPDRP_LEGACYBUSTYPE:
2686 case SPDRP_BUSNUMBER:
2687 case SPDRP_ENUMERATOR_NAME:
2688 case SPDRP_SECURITY_SDS:
2689 case SPDRP_DEVTYPE:
2690 case SPDRP_EXCLUSIVE:
2691 case SPDRP_CHARACTERISTICS:
2692 case SPDRP_ADDRESS:
2693 case SPDRP_DEVICE_POWER_DATA:*/
2694 #if (WINVER >= 0x501)
2695 /*case SPDRP_REMOVAL_POLICY:
2696 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2697 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2698 case SPDRP_INSTALL_STATE:*/
2699 #endif
2700
2701 default:
2702 {
2703 ERR("Property 0x%lx not implemented\n", Property);
2704 SetLastError(ERROR_NOT_SUPPORTED);
2705 }
2706 }
2707 }
2708
2709 TRACE("Returning %d\n", ret);
2710 return ret;
2711 }
2712
2713 /***********************************************************************
2714 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2715 */
2716 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2717 IN HDEVINFO DeviceInfoSet,
2718 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2719 IN DWORD Property,
2720 IN CONST BYTE *PropertyBuffer,
2721 IN DWORD PropertyBufferSize)
2722 {
2723 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2724 Property, PropertyBuffer, PropertyBufferSize);
2725 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2726 return FALSE;
2727 }
2728
2729 /***********************************************************************
2730 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2731 */
2732 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2733 IN HDEVINFO DeviceInfoSet,
2734 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2735 IN DWORD Property,
2736 IN const BYTE *PropertyBuffer,
2737 IN DWORD PropertyBufferSize)
2738 {
2739 struct DeviceInfoSet *list;
2740 BOOL ret = FALSE;
2741
2742 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2743 Property, PropertyBuffer, PropertyBufferSize);
2744
2745 if (!DeviceInfoSet)
2746 SetLastError(ERROR_INVALID_HANDLE);
2747 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2748 SetLastError(ERROR_INVALID_HANDLE);
2749 else if (DeviceInfoData)
2750 SetLastError(ERROR_INVALID_HANDLE);
2751 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2752 SetLastError(ERROR_INVALID_USER_BUFFER);
2753 else
2754 {
2755 switch (Property)
2756 {
2757 case SPDRP_COMPATIBLEIDS:
2758 case SPDRP_CONFIGFLAGS:
2759 case SPDRP_FRIENDLYNAME:
2760 case SPDRP_HARDWAREID:
2761 case SPDRP_LOCATION_INFORMATION:
2762 case SPDRP_LOWERFILTERS:
2763 case SPDRP_SECURITY:
2764 case SPDRP_SERVICE:
2765 case SPDRP_UI_NUMBER_DESC_FORMAT:
2766 case SPDRP_UPPERFILTERS:
2767 {
2768 LPCWSTR RegistryPropertyName;
2769 DWORD RegistryDataType;
2770 HKEY hKey;
2771 LONG rc;
2772
2773 switch (Property)
2774 {
2775 case SPDRP_COMPATIBLEIDS:
2776 RegistryPropertyName = L"CompatibleIDs";
2777 RegistryDataType = REG_MULTI_SZ;
2778 break;
2779 case SPDRP_CONFIGFLAGS:
2780 RegistryPropertyName = L"ConfigFlags";
2781 RegistryDataType = REG_DWORD;
2782 break;
2783 case SPDRP_FRIENDLYNAME:
2784 RegistryPropertyName = L"FriendlyName";
2785 RegistryDataType = REG_SZ;
2786 break;
2787 case SPDRP_HARDWAREID:
2788 RegistryPropertyName = L"HardwareID";
2789 RegistryDataType = REG_MULTI_SZ;
2790 break;
2791 case SPDRP_LOCATION_INFORMATION:
2792 RegistryPropertyName = L"LocationInformation";
2793 RegistryDataType = REG_SZ;
2794 break;
2795 case SPDRP_LOWERFILTERS:
2796 RegistryPropertyName = L"LowerFilters";
2797 RegistryDataType = REG_MULTI_SZ;
2798 break;
2799 case SPDRP_SECURITY:
2800 RegistryPropertyName = L"Security";
2801 RegistryDataType = REG_BINARY;
2802 break;
2803 case SPDRP_SERVICE:
2804 RegistryPropertyName = L"Service";
2805 RegistryDataType = REG_SZ;
2806 break;
2807 case SPDRP_UI_NUMBER_DESC_FORMAT:
2808 RegistryPropertyName = L"UINumberDescFormat";
2809 RegistryDataType = REG_SZ;
2810 break;
2811 case SPDRP_UPPERFILTERS:
2812 RegistryPropertyName = L"UpperFilters";
2813 RegistryDataType = REG_MULTI_SZ;
2814 break;
2815 default:
2816 /* Should not happen */
2817 RegistryPropertyName = NULL;
2818 RegistryDataType = REG_BINARY;
2819 break;
2820 }
2821 /* Open device registry key */
2822 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
2823 if (hKey != INVALID_HANDLE_VALUE)
2824 {
2825 /* Write new data */
2826 rc = RegSetValueExW(
2827 hKey,
2828 RegistryPropertyName,
2829 0, /* Reserved */
2830 RegistryDataType,
2831 PropertyBuffer,
2832 PropertyBufferSize);
2833 if (rc == ERROR_SUCCESS)
2834 ret = TRUE;
2835 else
2836 SetLastError(rc);
2837 RegCloseKey(hKey);
2838 }
2839 break;
2840 }
2841
2842 /*case SPDRP_CHARACTERISTICS:
2843 case SPDRP_DEVTYPE:
2844 case SPDRP_EXCLUSIVE:*/
2845 #if (WINVER >= 0x501)
2846 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2847 #endif
2848 //case SPDRP_SECURITY_SDS:
2849
2850 default:
2851 {
2852 ERR("Property 0x%lx not implemented\n", Property);
2853 SetLastError(ERROR_NOT_SUPPORTED);
2854 }
2855 }
2856 }
2857
2858 TRACE("Returning %d\n", ret);
2859 return ret;
2860 }
2861
2862 /***********************************************************************
2863 * SetupDiInstallClassA (SETUPAPI.@)
2864 */
2865 BOOL WINAPI SetupDiInstallClassA(
2866 HWND hwndParent,
2867 PCSTR InfFileName,
2868 DWORD Flags,
2869 HSPFILEQ FileQueue)
2870 {
2871 UNICODE_STRING FileNameW;
2872 BOOL Result;
2873
2874 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2875 {
2876 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2877 return FALSE;
2878 }
2879
2880 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2881
2882 RtlFreeUnicodeString(&FileNameW);
2883
2884 return Result;
2885 }
2886
2887 static HKEY CreateClassKey(HINF hInf)
2888 {
2889 WCHAR FullBuffer[MAX_PATH];
2890 WCHAR Buffer[MAX_PATH];
2891 DWORD RequiredSize;
2892 HKEY hClassKey;
2893
2894 Buffer[0] = '\\';
2895 if (!SetupGetLineTextW(NULL,
2896 hInf,
2897 Version,
2898 ClassGUID,
2899 &Buffer[1],
2900 MAX_PATH - 1,
2901 &RequiredSize))
2902 {
2903 return INVALID_HANDLE_VALUE;
2904 }
2905
2906 lstrcpyW(FullBuffer, ControlClass);
2907 lstrcatW(FullBuffer, Buffer);
2908
2909
2910 if (!SetupGetLineTextW(NULL,
2911 hInf,
2912 Version,
2913 Class,
2914 Buffer,
2915 MAX_PATH,
2916 &RequiredSize))
2917 {
2918 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2919 return INVALID_HANDLE_VALUE;
2920 }
2921
2922 if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2923 FullBuffer,
2924 0,
2925 NULL,
2926 REG_OPTION_NON_VOLATILE,
2927 KEY_SET_VALUE,
2928 NULL,
2929 &hClassKey,
2930 NULL))
2931 {
2932 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2933 return INVALID_HANDLE_VALUE;
2934 }
2935
2936 if (ERROR_SUCCESS != RegSetValueExW(hClassKey,
2937 Class,
2938 0,
2939 REG_SZ,
2940 (LPBYTE)Buffer,
2941 RequiredSize * sizeof(WCHAR)))
2942 {
2943 RegCloseKey(hClassKey);
2944 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2945 return INVALID_HANDLE_VALUE;
2946 }
2947
2948 return hClassKey;
2949 }
2950
2951 /***********************************************************************
2952 * SetupDiInstallClassW (SETUPAPI.@)
2953 */
2954 BOOL WINAPI SetupDiInstallClassW(
2955 HWND hwndParent,
2956 PCWSTR InfFileName,
2957 DWORD Flags,
2958 HSPFILEQ FileQueue)
2959 {
2960 WCHAR SectionName[MAX_PATH];
2961 DWORD SectionNameLength = 0;
2962 HINF hInf;
2963 BOOL bFileQueueCreated = FALSE;
2964 HKEY hClassKey;
2965
2966 TRACE("%p %s 0x%lx %p\n", hwndParent, debugstr_w(InfFileName),
2967 Flags, FileQueue);
2968
2969 FIXME("not fully implemented\n");
2970
2971 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2972 {
2973 SetLastError(ERROR_INVALID_PARAMETER);
2974 return FALSE;
2975 }
2976
2977 /* Open the .inf file */
2978 hInf = SetupOpenInfFileW(InfFileName,
2979 NULL,
2980 INF_STYLE_WIN4,
2981 NULL);
2982 if (hInf == INVALID_HANDLE_VALUE)
2983 {
2984
2985 return FALSE;
2986 }
2987
2988 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2989 hClassKey = CreateClassKey(hInf);
2990 if (hClassKey == INVALID_HANDLE_VALUE)
2991 {
2992 SetupCloseInfFile(hInf);
2993 return FALSE;
2994 }
2995
2996
2997
2998 /* Try to append a layout file */
2999 #if 0
3000 SetupOpenAppendInfFileW(NULL, hInf, NULL);
3001 #endif
3002
3003 /* Retrieve the actual section name */
3004 SetupDiGetActualSectionToInstallW(hInf,
3005 ClassInstall32,
3006 SectionName,
3007 MAX_PATH,
3008 &SectionNameLength,
3009 NULL);
3010
3011 #if 0
3012 if (!(Flags & DI_NOVCP))
3013 {
3014 FileQueue = SetupOpenFileQueue();
3015 if (FileQueue == INVALID_HANDLE_VALUE)
3016 {
3017 SetupCloseInfFile(hInf);
3018 RegCloseKey(hClassKey);
3019 return FALSE;
3020 }
3021
3022 bFileQueueCreated = TRUE;
3023
3024 }
3025 #endif
3026
3027 SetupInstallFromInfSectionW(NULL,
3028 hInf,
3029 SectionName,
3030 SPINST_REGISTRY,
3031 hClassKey,
3032 NULL,
3033 0,
3034 NULL,
3035 NULL,
3036 INVALID_HANDLE_VALUE,
3037 NULL);
3038
3039 /* FIXME: More code! */
3040
3041 if (bFileQueueCreated)
3042 SetupCloseFileQueue(FileQueue);
3043
3044 SetupCloseInfFile(hInf);
3045
3046 RegCloseKey(hClassKey);
3047 return TRUE;
3048 }
3049
3050
3051 /***********************************************************************
3052 * SetupDiOpenClassRegKey (SETUPAPI.@)
3053 */
3054 HKEY WINAPI SetupDiOpenClassRegKey(
3055 const GUID* ClassGuid,
3056 REGSAM samDesired)
3057 {
3058 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3059 DIOCR_INSTALLER, NULL, NULL);
3060 }
3061
3062
3063 /***********************************************************************
3064 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3065 */
3066 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3067 const GUID* ClassGuid OPTIONAL,
3068 REGSAM samDesired,
3069 DWORD Flags,
3070 PCSTR MachineName OPTIONAL,
3071 PVOID Reserved)
3072 {
3073 PWSTR MachineNameW = NULL;
3074 HKEY hKey;
3075
3076 TRACE("\n");
3077
3078 if (MachineName)
3079 {
3080 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3081 if (MachineNameW == NULL)
3082 return INVALID_HANDLE_VALUE;
3083 }
3084
3085 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3086 Flags, MachineNameW, Reserved);
3087
3088 if (MachineNameW)
3089 MyFree(MachineNameW);
3090
3091 return hKey;
3092 }
3093
3094
3095 /***********************************************************************
3096 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3097 */
3098 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3099 const GUID* ClassGuid OPTIONAL,
3100 REGSAM samDesired,
3101 DWORD Flags,
3102 PCWSTR MachineName OPTIONAL,
3103 PVOID Reserved)
3104 {
3105 LPWSTR lpGuidString;
3106 LPWSTR lpFullGuidString;
3107 DWORD dwLength;
3108 HKEY HKLM;
3109 HKEY hClassesKey;
3110 HKEY hClassKey;
3111 DWORD rc;
3112 LPCWSTR lpKeyName;
3113
3114 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3115 Flags, debugstr_w(MachineName), Reserved);
3116
3117 if (Flags == DIOCR_INSTALLER)
3118 {
3119 lpKeyName = ControlClass;
3120 }
3121 else if (Flags == DIOCR_INTERFACE)
3122 {
3123 lpKeyName = DeviceClasses;
3124 }
3125 else
3126 {
3127 ERR("Invalid Flags parameter!\n");
3128 SetLastError(ERROR_INVALID_FLAGS);
3129 return INVALID_HANDLE_VALUE;
3130 }
3131
3132 if (MachineName != NULL)
3133 {
3134 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
3135 if (rc != ERROR_SUCCESS)
3136 {
3137 SetLastError(rc);
3138 return INVALID_HANDLE_VALUE;
3139 }
3140 }
3141 else
3142 HKLM = HKEY_LOCAL_MACHINE;
3143
3144 rc = RegOpenKeyExW(HKLM,
3145 lpKeyName,
3146 0,
3147 ClassGuid ? KEY_ENUMERATE_SUB_KEYS : samDesired,
3148 &hClassesKey);
3149 if (MachineName != NULL) RegCloseKey(HKLM);
3150 if (rc != ERROR_SUCCESS)
3151 {
3152 SetLastError(rc);
3153 return INVALID_HANDLE_VALUE;
3154 }
3155
3156 if (ClassGuid == NULL)
3157 return hClassesKey;
3158
3159 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
3160 {
3161 SetLastError(ERROR_GEN_FAILURE);
3162 RegCloseKey(hClassesKey);
3163 return INVALID_HANDLE_VALUE;
3164 }
3165
3166 dwLength = lstrlenW(lpGuidString);
3167 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR));
3168 if (!lpFullGuidString)
3169 {
3170 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3171 RpcStringFreeW(&lpGuidString);
3172 return INVALID_HANDLE_VALUE;
3173 }
3174 lpFullGuidString[0] = '{';
3175 memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR));
3176 lpFullGuidString[dwLength + 1] = '}';
3177 lpFullGuidString[dwLength + 2] = '\0';
3178 RpcStringFreeW(&lpGuidString);
3179
3180 rc = RegOpenKeyExW(hClassesKey,
3181 lpFullGuidString,
3182 0,
3183 samDesired,
3184 &hClassKey);
3185 if (rc != ERROR_SUCCESS)
3186 {
3187 SetLastError(rc);
3188 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
3189 RegCloseKey(hClassesKey);
3190 return INVALID_HANDLE_VALUE;
3191 }
3192
3193 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
3194 RegCloseKey(hClassesKey);
3195
3196 return hClassKey;
3197 }
3198
3199 /***********************************************************************
3200 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3201 */
3202 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3203 HDEVINFO DeviceInfoSet,
3204 PCWSTR DevicePath,
3205 DWORD OpenFlags,
3206 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3207 {
3208 FIXME("%p %s %08lx %p\n",
3209 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3210 return FALSE;
3211 }
3212
3213 /***********************************************************************
3214 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3215 */
3216 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3217 HDEVINFO DeviceInfoSet,
3218 PCSTR DevicePath,
3219 DWORD OpenFlags,
3220 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3221 {
3222 LPWSTR DevicePathW = NULL;
3223 BOOL bResult;
3224
3225 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3226
3227 DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
3228 if (DevicePathW == NULL)
3229 return FALSE;
3230
3231 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
3232 DevicePathW, OpenFlags, DeviceInterfaceData);
3233
3234 MyFree(DevicePathW);
3235
3236 return bResult;
3237 }
3238
3239 /***********************************************************************
3240 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3241 */
3242 BOOL WINAPI SetupDiSetClassInstallParamsA(
3243 HDEVINFO DeviceInfoSet,
3244 PSP_DEVINFO_DATA DeviceInfoData,
3245 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3246 DWORD ClassInstallParamsSize)
3247 {
3248 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
3249 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3250 return FALSE;
3251 }
3252
3253 /***********************************************************************
3254 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3255 */
3256 BOOL WINAPI SetupDiSetClassInstallParamsW(
3257 HDEVINFO DeviceInfoSet,
3258 PSP_DEVINFO_DATA DeviceInfoData,
3259 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3260 DWORD ClassInstallParamsSize)
3261 {
3262 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
3263 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3264 return FALSE;
3265 }
3266
3267 static DWORD
3268 GetFunctionPointer(
3269 IN PWSTR InstallerName,
3270 OUT HMODULE* ModulePointer,
3271 OUT PVOID* FunctionPointer)
3272 {
3273 HMODULE hModule = NULL;
3274 LPSTR FunctionNameA = NULL;
3275 PWCHAR Comma;
3276 DWORD rc;
3277
3278 *ModulePointer = NULL;
3279 *FunctionPointer = NULL;
3280
3281 Comma = strchrW(InstallerName, ',');
3282 if (!Comma)
3283 {
3284 rc = ERROR_INVALID_PARAMETER;
3285 goto cleanup;
3286 }
3287
3288 /* Load library */
3289 *Comma = '\0';
3290 hModule = LoadLibraryW(InstallerName);
3291 *Comma = ',';
3292 if (!hModule)
3293 {
3294 rc = GetLastError();
3295 goto cleanup;
3296 }
3297
3298 /* Skip comma spaces */
3299 while (*Comma == ',' || isspaceW(*Comma))
3300 Comma++;
3301
3302 /* W->A conversion for function name */
3303 FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
3304 if (!FunctionNameA)
3305 {
3306 rc = GetLastError();
3307 goto cleanup;
3308 }
3309
3310 /* Search function */
3311 *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
3312 if (!*FunctionPointer)
3313 {
3314 rc = GetLastError();
3315 goto cleanup;
3316 }
3317
3318 *ModulePointer = hModule;
3319 rc = ERROR_SUCCESS;
3320
3321 cleanup:
3322 if (rc != ERROR_SUCCESS && hModule)
3323 FreeLibrary(hModule);
3324 MyFree(FunctionNameA);
3325 return rc;
3326 }
3327
3328 static DWORD
3329 FreeFunctionPointer(
3330 IN HMODULE ModulePointer,
3331 IN PVOID FunctionPointer)
3332 {
3333 if (ModulePointer == NULL)
3334 return ERROR_SUCCESS;
3335 if (FreeLibrary(ModulePointer))
3336 return ERROR_SUCCESS;
3337 else
3338 return GetLastError();
3339 }
3340
3341 /***********************************************************************
3342 * SetupDiCallClassInstaller (SETUPAPI.@)
3343 */
3344 BOOL WINAPI SetupDiCallClassInstaller(
3345 IN DI_FUNCTION InstallFunction,
3346 IN HDEVINFO DeviceInfoSet,
3347 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3348 {
3349 BOOL ret = FALSE;
3350
3351 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3352
3353 if (!DeviceInfoSet)
3354 SetLastError(ERROR_INVALID_PARAMETER);
3355 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3356 SetLastError(ERROR_INVALID_HANDLE);
3357 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3358 SetLastError(ERROR_INVALID_HANDLE);
3359 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
3360 SetLastError(ERROR_INVALID_HANDLE);
3361 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3362 SetLastError(ERROR_INVALID_USER_BUFFER);
3363 else
3364 {
3365 SP_DEVINSTALL_PARAMS_W InstallParams;
3366 #define CLASS_COINSTALLER 0x1
3367 #define DEVICE_COINSTALLER 0x2
3368 #define CLASS_INSTALLER 0x4
3369 UCHAR CanHandle = 0;
3370 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
3371
3372 switch (InstallFunction)
3373 {
3374 case DIF_ALLOW_INSTALL:
3375 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3376 break;
3377 case DIF_DESTROYPRIVATEDATA:
3378 CanHandle = CLASS_INSTALLER;
3379 break;
3380 case DIF_INSTALLDEVICE:
3381 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3382 DefaultHandler = SetupDiInstallDevice;
3383 break;
3384 case DIF_INSTALLDEVICEFILES:
3385 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3386 DefaultHandler = SetupDiInstallDriverFiles;
3387 break;
3388 case DIF_INSTALLINTERFACES:
3389 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3390 DefaultHandler = SetupDiInstallDeviceInterfaces;
3391 break;
3392 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
3393 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3394 break;
3395 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
3396 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3397 break;
3398 case DIF_NEWDEVICEWIZARD_PREANALYZE:
3399 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3400 break;
3401 case DIF_REGISTER_COINSTALLERS:
3402 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3403 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
3404 break;
3405 case DIF_SELECTBESTCOMPATDRV:
3406 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3407 DefaultHandler = SetupDiSelectBestCompatDrv;
3408 break;
3409 default:
3410 ERR("Install function %u not supported\n", InstallFunction);
3411 SetLastError(ERROR_NOT_SUPPORTED);
3412 }
3413
3414 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3415 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
3416 /* Don't process this call, as a parameter is invalid */
3417 CanHandle = 0;
3418
3419 if (CanHandle != 0)
3420 {
3421 LIST_ENTRY ClassCoInstallersListHead;
3422 LIST_ENTRY DeviceCoInstallersListHead;
3423 HMODULE ClassInstallerLibrary = NULL;
3424 CLASS_INSTALL_PROC ClassInstaller = NULL;
3425 COINSTALLER_CONTEXT_DATA Context;
3426 PLIST_ENTRY ListEntry;
3427 HKEY hKey;
3428 DWORD dwRegType, dwLength;
3429 DWORD rc = NO_ERROR;
3430
3431 InitializeListHead(&ClassCoInstallersListHead);
3432 InitializeListHead(&DeviceCoInstallersListHead);
3433
3434 if (CanHandle & DEVICE_COINSTALLER)
3435 {
3436 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
3437 if (hKey != INVALID_HANDLE_VALUE)
3438 {
3439 rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, &dwRegType, NULL, &dwLength);
3440 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3441 {
3442 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3443 if (KeyBuffer != NULL)
3444 {
3445 rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3446 if (rc == ERROR_SUCCESS)
3447 {
3448 LPWSTR ptr;
3449 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3450 {
3451 /* Add coinstaller to DeviceCoInstallersListHead list */
3452 struct CoInstallerElement *coinstaller;
3453 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
3454 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3455 if (!coinstaller)
3456 continue;
3457 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
3458 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3459 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
3460 else
3461 HeapFree(GetProcessHeap(), 0, coinstaller);
3462 }
3463 }
3464 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3465 }
3466 }
3467 RegCloseKey(hKey);
3468 }
3469 }
3470 if (CanHandle & CLASS_COINSTALLER)
3471 {
3472 rc = RegOpenKeyEx(
3473 HKEY_LOCAL_MACHINE,
3474 L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3475 0, /* Options */
3476 KEY_QUERY_VALUE,
3477 &hKey);
3478 if (rc == ERROR_SUCCESS)
3479 {
3480 LPWSTR lpGuidString;
3481 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
3482 {
3483 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
3484 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3485 {
3486 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3487 if (KeyBuffer != NULL)
3488 {
3489 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3490 if (rc == ERROR_SUCCESS)
3491 {
3492 LPWSTR ptr;
3493 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3494 {
3495 /* Add coinstaller to ClassCoInstallersListHead list */
3496 struct CoInstallerElement *coinstaller;
3497 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
3498 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3499 if (!coinstaller)
3500 continue;
3501 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
3502 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3503 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
3504 else
3505 HeapFree(GetProcessHeap(), 0, coinstaller);
3506 }
3507 }
3508 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3509 }
3510 }
3511 RpcStringFreeW(&lpGuidString);
3512 }
3513 RegCloseKey(hKey);
3514 }
3515 }
3516 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
3517 {
3518 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
3519 if (hKey != INVALID_HANDLE_VALUE)
3520 {
3521 rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
3522 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
3523 {
3524 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3525 if (KeyBuffer != NULL)
3526 {
3527 rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3528 if (rc == ERROR_SUCCESS)
3529 {
3530 /* Get ClassInstaller function pointer */
3531 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
3532 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
3533 {
3534 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
3535 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3536 }
3537 }
3538 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3539 }
3540 }
3541 RegCloseKey(hKey);
3542 }
3543 }
3544
3545 /* Call Class co-installers */
3546 Context.PostProcessing = FALSE;
3547 rc = NO_ERROR;
3548 ListEntry = ClassCoInstallersListHead.Flink;
3549 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
3550 {
3551 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3552 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3553 coinstaller->PrivateData = Context.PrivateData;
3554 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3555 {
3556 coinstaller->DoPostProcessing = TRUE;
3557 rc = NO_ERROR;
3558 }
3559 ListEntry = ListEntry->Flink;
3560 }
3561
3562 /* Call Device co-installers */
3563 ListEntry = DeviceCoInstallersListHead.Flink;
3564 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
3565 {
3566 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3567 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3568 coinstaller->PrivateData = Context.PrivateData;
3569 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3570 {
3571 coinstaller->DoPostProcessing = TRUE;
3572 rc = NO_ERROR;
3573 }
3574 ListEntry = ListEntry->Flink;
3575 }
3576
3577 /* Call Class installer */
3578 if (ClassInstaller)
3579 {
3580 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
3581 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
3582 }
3583 else
3584 rc = ERROR_DI_DO_DEFAULT;
3585
3586 /* Call default handler */
3587 if (rc == ERROR_DI_DO_DEFAULT)
3588 {
3589 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
3590 {
3591 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
3592 rc = NO_ERROR;
3593 else
3594 rc = GetLastError();
3595 }
3596 else
3597 rc = NO_ERROR;
3598 }
3599
3600 /* Call Class co-installers that required postprocessing */
3601 Context.PostProcessing = TRUE;
3602 ListEntry = ClassCoInstallersListHead.Flink;
3603 while (ListEntry != &ClassCoInstallersListHead)
3604 {
3605 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3606 if (coinstaller->DoPostProcessing)
3607 {
3608 Context.InstallResult = rc;
3609 Context.PrivateData = coinstaller->PrivateData;
3610 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3611 }
3612 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3613 ListEntry = ListEntry->Flink;
3614 }
3615
3616 /* Call Device co-installers that required postprocessing */
3617 ListEntry = DeviceCoInstallersListHead.Flink;
3618 while (ListEntry != &DeviceCoInstallersListHead)
3619 {
3620 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3621 if (coinstaller->DoPostProcessing)
3622 {
3623 Context.InstallResult = rc;
3624 Context.PrivateData = coinstaller->PrivateData;
3625 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3626 }
3627 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3628 ListEntry = ListEntry->Flink;
3629 }
3630
3631 /* Free allocated memory */
3632 while (!IsListEmpty(&ClassCoInstallersListHead))
3633 {
3634 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
3635 HeapFree(GetProcessHeap(), 0, ListEntry);
3636 }
3637 while (!IsListEmpty(&DeviceCoInstallersListHead))
3638 {
3639 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
3640 HeapFree(GetProcessHeap(), 0, ListEntry);
3641 }
3642
3643 ret = (rc == NO_ERROR);
3644 }
3645 }
3646
3647 TRACE("Returning %d\n", ret);
3648 return ret;
3649 }
3650
3651 /***********************************************************************
3652 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3653 */
3654 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
3655 IN HDEVINFO DeviceInfoSet,
3656 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
3657 {
3658 struct DeviceInfoSet *list;
3659 BOOL ret = FALSE;
3660
3661 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
3662
3663 if (!DeviceInfoSet)
3664 SetLastError(ERROR_INVALID_HANDLE);
3665 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3666 SetLastError(ERROR_INVALID_HANDLE);
3667 else if (!DeviceInfoListDetailData)
3668 SetLastError(ERROR_INVALID_PARAMETER);
3669 else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
3670 SetLastError(ERROR_INVALID_USER_BUFFER);
3671 else
3672 {
3673 memcpy(
3674 &DeviceInfoListDetailData->ClassGuid,
3675 &list->ClassGuid,
3676 sizeof(GUID));
3677 DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
3678 if (list->MachineName)
3679 strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
3680 else
3681 DeviceInfoListDetailData->RemoteMachineName[0] = 0;
3682
3683 ret = TRUE;
3684 }
3685
3686 TRACE("Returning %d\n", ret);
3687 return ret;
3688 }
3689
3690 /***********************************************************************
3691 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3692 */
3693 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3694 IN HDEVINFO DeviceInfoSet,
3695 IN PSP_DEVINFO_DATA DeviceInfoData,
3696 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3697 {
3698 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
3699 BOOL ret = FALSE;
3700
3701 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3702
3703 if (DeviceInstallParams == NULL)
3704 SetLastError(ERROR_INVALID_PARAMETER);
3705 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
3706 SetLastError(ERROR_INVALID_USER_BUFFER);
3707 else
3708 {
3709 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3710 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
3711
3712 if (ret)
3713 {
3714 /* Do W->A conversion */
3715 memcpy(
3716 DeviceInstallParams,
3717 &deviceInstallParamsW,
3718 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
3719 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
3720 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
3721 {
3722 DeviceInstallParams->DriverPath[0] = '\0';
3723 ret = FALSE;
3724 }
3725 }
3726 }
3727
3728 TRACE("Returning %d\n", ret);
3729 return ret;
3730 }
3731
3732 /***********************************************************************
3733 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3734 */
3735 BOOL WINAPI SetupDiGetDeviceInstallParamsW(
3736 IN HDEVINFO DeviceInfoSet,
3737 IN PSP_DEVINFO_DATA DeviceInfoData,
3738 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3739 {
3740 struct DeviceInfoSet *list;
3741 BOOL ret = FALSE;
3742
3743 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3744
3745 if (!DeviceInfoSet)
3746 SetLastError(ERROR_INVALID_HANDLE);
3747 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3748 SetLastError(ERROR_INVALID_HANDLE);
3749 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3750 SetLastError(ERROR_INVALID_USER_BUFFER);
3751 else if (!DeviceInstallParams)
3752 SetLastError(ERROR_INVALID_PARAMETER);
3753 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
3754 SetLastError(ERROR_INVALID_USER_BUFFER);
3755 else
3756 {
3757 PSP_DEVINSTALL_PARAMS_W Source;
3758
3759 if (DeviceInfoData)
3760 Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
3761 else
3762 Source = &list->InstallParams;
3763 memcpy(DeviceInstallParams, Source, Source->cbSize);
3764 ret = TRUE;
3765 }
3766
3767 TRACE("Returning %d\n", ret);
3768 return ret;
3769 }
3770
3771 /***********************************************************************
3772 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3773 */
3774 BOOL WINAPI SetupDiSetDeviceInstallParamsW(
3775 IN HDEVINFO DeviceInfoSet,
3776 IN PSP_DEVINFO_DATA DeviceInfoData,
3777 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3778 {
3779 struct DeviceInfoSet *list;
3780 BOOL ret = FALSE;
3781
3782 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3783
3784 if (!DeviceInfoSet)
3785 SetLastError(ERROR_INVALID_HANDLE);
3786 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3787 SetLastError(ERROR_INVALID_HANDLE);
3788 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3789 SetLastError(ERROR_INVALID_USER_BUFFER);
3790 else if (!DeviceInstallParams)
3791 SetLastError(ERROR_INVALID_PARAMETER);
3792 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
3793 SetLastError(ERROR_INVALID_USER_BUFFER);
3794 else
3795 {
3796 PSP_DEVINSTALL_PARAMS_W Destination;
3797
3798 /* FIXME: Validate parameters */
3799
3800 if (DeviceInfoData)
3801 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
3802 else
3803 Destination = &list->InstallParams;
3804 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
3805 ret = TRUE;
3806 }
3807
3808 TRACE("Returning %d\n", ret);
3809 return ret;
3810 }
3811
3812 /***********************************************************************
3813 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
3814 */
3815 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
3816 IN HDEVINFO DeviceInfoSet,
3817 IN PSP_DEVINFO_DATA DeviceInfoData,
3818 OUT PSTR DeviceInstanceId OPTIONAL,
3819 IN DWORD DeviceInstanceIdSize,
3820 OUT PDWORD RequiredSize OPTIONAL)
3821 {
3822 PWSTR DeviceInstanceIdW = NULL;
3823 BOOL ret = FALSE;
3824
3825 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
3826 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
3827
3828 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
3829 SetLastError(ERROR_INVALID_PARAMETER);
3830 else
3831 {
3832 if (DeviceInstanceIdSize != 0)
3833 {
3834 DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
3835 if (DeviceInstanceIdW == NULL)
3836 return FALSE;
3837 }
3838
3839 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
3840 DeviceInstanceIdW, DeviceInstanceIdSize,
3841 RequiredSize);
3842
3843 if (ret && DeviceInstanceIdW != NULL)
3844 {
3845 if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
3846 DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
3847 {
3848 DeviceInstanceId[0] = '\0';
3849 ret = FALSE;
3850 }
3851 }
3852 }
3853
3854 TRACE("Returning %d\n", ret);
3855 return ret;
3856 }
3857
3858 /***********************************************************************
3859 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
3860 */
3861 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
3862 IN HDEVINFO DeviceInfoSet,
3863 IN PSP_DEVINFO_DATA DeviceInfoData,
3864 OUT PWSTR DeviceInstanceId OPTIONAL,
3865 IN DWORD DeviceInstanceIdSize,
3866 OUT PDWORD RequiredSize OPTIONAL)
3867 {
3868 BOOL ret = FALSE;
3869
3870 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
3871 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
3872
3873 if (!DeviceInfoSet)
3874 SetLastError(ERROR_INVALID_HANDLE);
3875 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3876 SetLastError(ERROR_INVALID_HANDLE);
3877 else if (!DeviceInfoData)
3878 SetLastError(ERROR_INVALID_PARAMETER);
3879 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3880 SetLastError(ERROR_INVALID_USER_BUFFER);
3881 else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
3882 SetLastError(ERROR_INVALID_PARAMETER);
3883 else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
3884 SetLastError(ERROR_INVALID_PARAMETER);
3885 else
3886 {
3887 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
3888 DWORD required;
3889
3890 required = (wcslen(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
3891 if (RequiredSize)
3892 *RequiredSize = required;
3893
3894 if (required <= DeviceInstanceIdSize)
3895 {
3896 wcscpy(DeviceInstanceId, DevInfo->DeviceName);
3897 ret = TRUE;
3898 }
3899 else
3900 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3901 }
3902
3903 TRACE("Returning %d\n", ret);
3904 return ret;
3905 }
3906
3907 /***********************************************************************
3908 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
3909 */
3910 BOOL WINAPI SetupDiGetClassDevPropertySheetsA(
3911 IN HDEVINFO DeviceInfoSet,
3912 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
3913 IN LPPROPSHEETHEADERA PropertySheetHeader,
3914 IN DWORD PropertySheetHeaderPageListSize,
3915 OUT PDWORD RequiredSize OPTIONAL,
3916 IN DWORD PropertySheetType)
3917 {
3918 PROPSHEETHEADERW psh;
3919 BOOL ret = FALSE;
3920
3921 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
3922 PropertySheetHeader, PropertySheetHeaderPageListSize,
3923 RequiredSize, PropertySheetType);
3924
3925 psh.dwFlags = PropertySheetHeader->dwFlags;
3926 psh.phpage = PropertySheetHeader->phpage;
3927 psh.nPages = PropertySheetHeader->nPages;
3928
3929 ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
3930 PropertySheetHeaderPageListSize, RequiredSize,
3931 PropertySheetType);
3932 if (ret)
3933 {
3934 PropertySheetHeader->nPages = psh.nPages;
3935 }
3936
3937 TRACE("Returning %d\n", ret);
3938 return ret;
3939 }
3940
3941 struct ClassDevPropertySheetsData
3942 {
3943 HPROPSHEETPAGE *PropertySheetPages;
3944 DWORD MaximumNumberOfPages;
3945 DWORD NumberOfPages;
3946 };
3947
3948 static BOOL WINAPI GetClassDevPropertySheetsCallback(
3949 IN HPROPSHEETPAGE hPropSheetPage,
3950 IN OUT LPARAM lParam)
3951 {
3952 struct ClassDevPropertySheetsData *PropPageData;
3953
3954 PropPageData = (struct ClassDevPropertySheetsData *)lParam;
3955
3956 if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages)
3957 {
3958 *PropPageData->PropertySheetPages = hPropSheetPage;
3959 PropPageData->PropertySheetPages++;
3960 }
3961
3962 PropPageData->NumberOfPages++;
3963 return TRUE;
3964 }
3965
3966 /***********************************************************************
3967 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
3968 */
3969 BOOL WINAPI SetupDiGetClassDevPropertySheetsW(
3970 IN HDEVINFO DeviceInfoSet,
3971 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
3972 IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
3973 IN DWORD PropertySheetHeaderPageListSize,
3974 OUT PDWORD RequiredSize OPTIONAL,
3975 IN DWORD PropertySheetType)
3976 {
3977 struct DeviceInfoSet *list;
3978 BOOL ret = FALSE;
3979
3980 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
3981 PropertySheetHeader, PropertySheetHeaderPageListSize,
3982 RequiredSize, PropertySheetType);
3983
3984 if (!DeviceInfoSet)
3985 SetLastError(ERROR_INVALID_HANDLE);
3986 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3987 SetLastError(ERROR_INVALID_HANDLE);
3988 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3989 SetLastError(ERROR_INVALID_HANDLE);
3990 else if (!PropertySheetHeader)
3991 SetLastError(ERROR_INVALID_PARAMETER);
3992 else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
3993 SetLastError(ERROR_INVALID_FLAGS);
3994 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3995 SetLastError(ERROR_INVALID_USER_BUFFER);
3996 else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
3997 SetLastError(ERROR_INVALID_PARAMETER);
3998 else if (!PropertySheetHeader)
3999 SetLastError(ERROR_INVALID_PARAMETER);
4000 else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
4001 && PropertySheetType != DIGCDP_FLAG_BASIC
4002 && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
4003 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
4004 SetLastError(ERROR_INVALID_PARAMETER);
4005 else
4006 {
4007 HKEY hKey = INVALID_HANDLE_VALUE;
4008 SP_PROPSHEETPAGE_REQUEST Request;
4009 LPWSTR PropPageProvider = NULL;
4010 HMODULE hModule = NULL;
4011 PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
4012 struct ClassDevPropertySheetsData PropPageData;
4013 DWORD dwLength, dwRegType;
4014 DWORD rc;
4015
4016 if (DeviceInfoData)
4017 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
4018 else
4019 {
4020 hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
4021 DIOCR_INSTALLER, list->MachineName + 2, NULL);
4022 }
4023 if (hKey == INVALID_HANDLE_VALUE)
4024 goto cleanup;
4025
4026 rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength);
4027 if (rc == ERROR_FILE_NOT_FOUND)
4028 {
4029 /* No registry key. As it is optional, don't say it's a bad error */
4030 if (RequiredSize)
4031 *RequiredSize = 0;
4032 ret = TRUE;
4033 goto cleanup;
4034 }
4035 else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
4036 {
4037 SetLastError(rc);
4038 goto cleanup;
4039 }
4040
4041 PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
4042 if (!PropPageProvider)
4043 {
4044 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4045 goto cleanup;
4046 }
4047 rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
4048 if (rc != ERROR_SUCCESS)
4049 {
4050 SetLastError(rc);
4051 goto cleanup;
4052 }
4053 PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
4054
4055 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
4056 if (rc != ERROR_SUCCESS)
4057 {
4058 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
4059 goto cleanup;
4060 }
4061
4062 Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
4063 Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
4064 Request.DeviceInfoSet = DeviceInfoSet;
4065 Request.DeviceInfoData = DeviceInfoData;
4066 PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages];
4067 PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages;
4068 PropPageData.NumberOfPages = 0;
4069 ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
4070 if (!ret)
4071 goto cleanup;
4072
4073 if (RequiredSize)
4074 *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages;
4075 if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages)
4076 {
4077 PropertySheetHeader->nPages += PropPageData.NumberOfPages;
4078 ret = TRUE;
4079 }
4080 else
4081 {
4082 PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages;
4083 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4084 }
4085
4086 cleanup:
4087 if (hKey != INVALID_HANDLE_VALUE)
4088 RegCloseKey(hKey);
4089 HeapFree(GetProcessHeap(), 0, PropPageProvider);
4090 FreeFunctionPointer(hModule, pPropPageProvider);
4091 }
4092
4093 TRACE("Returning %d\n", ret);
4094 return ret;
4095 }
4096
4097 /***********************************************************************
4098 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4099 */
4100 HKEY WINAPI SetupDiCreateDevRegKeyA(
4101 IN HDEVINFO DeviceInfoSet,
4102 IN PSP_DEVINFO_DATA DeviceInfoData,
4103 IN DWORD Scope,
4104 IN DWORD HwProfile,
4105 IN DWORD KeyType,
4106 IN HINF InfHandle OPTIONAL,
4107 IN PCSTR InfSectionName OPTIONAL)
4108 {
4109 PCWSTR InfSectionNameW = NULL;
4110 HKEY ret = INVALID_HANDLE_VALUE;
4111
4112 if (InfSectionName)
4113 {
4114 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
4115 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
4116 }
4117
4118 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
4119 DeviceInfoData,
4120 Scope,
4121 HwProfile,
4122 KeyType,
4123 InfHandle,
4124 InfSectionNameW);
4125
4126 if (InfSectionNameW != NULL)
4127 MyFree((PVOID)InfSectionNameW);
4128
4129 return ret;
4130 }
4131
4132 /***********************************************************************
4133 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4134 */
4135 HKEY WINAPI SetupDiCreateDevRegKeyW(
4136 IN HDEVINFO DeviceInfoSet,
4137 IN PSP_DEVINFO_DATA DeviceInfoData,
4138 IN DWORD Scope,
4139 IN DWORD HwProfile,
4140 IN DWORD KeyType,
4141 IN HINF InfHandle OPTIONAL,
4142 IN PCWSTR InfSectionName OPTIONAL)
4143 {
4144 struct DeviceInfoSet *list;
4145 HKEY ret = INVALID_HANDLE_VALUE;
4146
4147 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
4148 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
4149
4150 if (!DeviceInfoSet)
4151 SetLastError(ERROR_INVALID_HANDLE);
4152 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4153 SetLastError(ERROR_INVALID_HANDLE);
4154 else if (!DeviceInfoData)
4155 SetLastError(ERROR_INVALID_PARAMETER);
4156 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4157 SetLastError(ERROR_INVALID_USER_BUFFER);
4158 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4159 SetLastError(ERROR_INVALID_PARAMETER);
4160 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4161 SetLastError(ERROR_INVALID_PARAMETER);
4162 else if (InfHandle && !InfSectionName)
4163 SetLastError(ERROR_INVALID_PARAMETER);
4164 else if (!InfHandle && InfSectionName)
4165 SetLastError(ERROR_INVALID_PARAMETER);
4166 else
4167 {
4168 LPWSTR lpGuidString = NULL;
4169 LPWSTR DriverKey = NULL; /* {GUID}\Index */
4170 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
4171 DWORD Index; /* Index used in the DriverKey name */
4172 DWORD rc;
4173 HKEY hClassKey = INVALID_HANDLE_VALUE;
4174 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
4175 HKEY hKey = INVALID_HANDLE_VALUE;
4176
4177 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
4178 {
4179 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4180 goto cleanup;
4181 }
4182
4183 if (KeyType == DIREG_DEV)
4184 {
4185 FIXME("DIREG_DEV case unimplemented\n");
4186 }
4187 else /* KeyType == DIREG_DRV */
4188 {
4189 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
4190 goto cleanup;
4191 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
4192 DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
4193 if (!DriverKey)
4194 {
4195 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4196 goto cleanup;
4197 }
4198 wcscpy(DriverKey, L"{");
4199 wcscat(DriverKey, lpGuidString);
4200 wcscat(DriverKey, L"}\\");
4201 pDeviceInstance = &DriverKey[wcslen(DriverKey)];
4202 rc = RegOpenKeyExW(list->HKLM,
4203 ControlClass,
4204 0,
4205 KEY_CREATE_SUB_KEY,
4206 &hClassKey);
4207 if (rc != ERROR_SUCCESS)
4208 {
4209 SetLastError(rc);
4210 goto cleanup;
4211 }
4212
4213 /* Try all values for Index between 0 and 9999 */
4214 Index = 0;
4215 while (Index <= 9999)
4216 {
4217 DWORD Disposition;
4218 wsprintf(pDeviceInstance, L"%04lu", Index);
4219 rc = RegCreateKeyEx(hClassKey,
4220 DriverKey,
4221 0,
4222 NULL,
4223 REG_OPTION_NON_VOLATILE,
4224 #if _WIN32_WINNT >= 0x502
4225 KEY_READ | KEY_WRITE,
4226 #else
4227 KEY_ALL_ACCESS,
4228 #endif
4229 NULL,
4230 &hKey,
4231 &Disposition);
4232 if (rc != ERROR_SUCCESS)
4233 {
4234 SetLastError(rc);
4235 goto cleanup;
4236 }
4237 if (Disposition == REG_CREATED_NEW_KEY)
4238 break;
4239 RegCloseKey(hKey);
4240 hKey = INVALID_HANDLE_VALUE;
4241 Index++;
4242 }
4243 if (Index > 9999)
4244 {
4245 /* Unable to create more than 9999 devices within the same class */
4246 SetLastError(ERROR_GEN_FAILURE);
4247 goto cleanup;
4248 }
4249
4250 /* Open device key, to write Driver value */
4251 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
4252 if (hDeviceKey == INVALID_HANDLE_VALUE)
4253 goto cleanup;
4254 rc = RegSetValueEx(hDeviceKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
4255 if (rc != ERROR_SUCCESS)
4256 {
4257 SetLastError(rc);
4258 goto cleanup;
4259 }
4260 }
4261
4262 /* Do installation of the specified section */
4263 if (InfHandle)
4264 {
4265 FIXME("Need to install section %s in file %p\n",
4266 debugstr_w(InfSectionName), InfHandle);
4267 }
4268 ret = hKey;
4269
4270 cleanup:
4271 if (lpGuidString)
4272 RpcStringFreeW(&lpGuidString);
4273 HeapFree(GetProcessHeap(), 0, DriverKey);
4274 if (hClassKey != INVALID_HANDLE_VALUE)
4275 RegCloseKey(hClassKey);
4276 if (hDeviceKey != INVALID_HANDLE_VALUE)
4277 RegCloseKey(hDeviceKey);
4278 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
4279 RegCloseKey(hKey);
4280 }
4281
4282 TRACE("Returning 0x%p\n", ret);
4283 return ret;
4284 }
4285
4286 /***********************************************************************
4287 * SetupDiOpenDevRegKey (SETUPAPI.@)
4288 */
4289 HKEY WINAPI SetupDiOpenDevRegKey(
4290 HDEVINFO DeviceInfoSet,
4291 PSP_DEVINFO_DATA DeviceInfoData,
4292 DWORD Scope,
4293 DWORD HwProfile,
4294 DWORD KeyType,
4295 REGSAM samDesired)
4296 {
4297 struct DeviceInfoSet *list;
4298 HKEY ret = INVALID_HANDLE_VALUE;
4299
4300 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4301 Scope, HwProfile, KeyType, samDesired);
4302
4303 if (!DeviceInfoSet)
4304 SetLastError(ERROR_INVALID_HANDLE);
4305 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4306 SetLastError(ERROR_INVALID_HANDLE);
4307 else if (!DeviceInfoData)
4308 SetLastError(ERROR_INVALID_PARAMETER);
4309 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4310 SetLastError(ERROR_INVALID_USER_BUFFER);
4311 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4312 SetLastError(ERROR_INVALID_PARAMETER);
4313 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4314 SetLastError(ERROR_INVALID_PARAMETER);
4315 else
4316 {
4317 HKEY hKey = INVALID_HANDLE_VALUE;
4318 HKEY hRootKey = INVALID_HANDLE_VALUE;
4319 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4320 LPWSTR DriverKey = NULL;
4321 DWORD dwLength = 0;
4322 DWORD dwRegType;
4323 DWORD rc;
4324
4325 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
4326 {
4327 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4328 }
4329 else /* Scope == DICS_FLAG_GLOBAL */
4330 {
4331 rc = RegOpenKeyExW(
4332 list->HKLM,
4333 EnumKeyName,
4334 0, /* Options */
4335 KEY_ENUMERATE_SUB_KEYS,
4336 &hRootKey);
4337 if (rc != ERROR_SUCCESS)
4338 {
4339 SetLastError(rc);
4340 goto cleanup;
4341 }
4342 rc = RegOpenKeyExW(
4343 hRootKey,
4344 deviceInfo->DeviceName,
4345 0, /* Options */
4346 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
4347 &hKey);
4348 RegCloseKey(hRootKey);
4349 hRootKey = INVALID_HANDLE_VALUE;
4350 if (rc != ERROR_SUCCESS)
4351 {
4352 SetLastError(rc);
4353 goto cleanup;
4354 }
4355 if (KeyType == DIREG_DEV)
4356 {
4357 /* We're done. Just return the hKey handle */
4358 ret = hKey;
4359 goto cleanup;
4360 }
4361 /* Read the 'Driver' key */
4362 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, NULL, &dwLength);
4363 if (rc != ERROR_SUCCESS)
4364 {
4365 SetLastError(rc);
4366 goto cleanup;
4367 }
4368 if (dwRegType != REG_SZ)
4369 {
4370 SetLastError(ERROR_GEN_FAILURE);
4371 goto cleanup;
4372 }
4373 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
4374 if (!DriverKey)
4375 {
4376 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4377 goto cleanup;
4378 }
4379 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
4380 if (rc != ERROR_SUCCESS)
4381 {
4382 SetLastError(rc);
4383 goto cleanup;
4384 }
4385 RegCloseKey(hKey);
4386 hKey = INVALID_HANDLE_VALUE;
4387 /* Need to open the driver key */
4388 rc = RegOpenKeyExW(
4389 list->HKLM,
4390 ControlClass,
4391 0, /* Options */
4392 KEY_ENUMERATE_SUB_KEYS,
4393 &hRootKey);
4394 if (rc != ERROR_SUCCESS)
4395 {
4396 SetLastError(rc);
4397 goto cleanup;
4398 }
4399 rc = RegOpenKeyExW(
4400 hRootKey,
4401 DriverKey,
4402 0, /* Options */
4403 samDesired,
4404 &hKey);
4405 if (rc != ERROR_SUCCESS)
4406 {
4407 SetLastError(rc);
4408 goto cleanup;
4409 }
4410 ret = hKey;
4411 }
4412 cleanup:
4413 if (hRootKey != INVALID_HANDLE_VALUE)
4414 RegCloseKey(hRootKey);
4415 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
4416 RegCloseKey(hKey);
4417 }
4418
4419 TRACE("Returning 0x%p\n", ret);
4420 return ret;
4421 }
4422
4423 /***********************************************************************
4424 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4425 */
4426 BOOL WINAPI SetupDiCreateDeviceInfoA(
4427 HDEVINFO DeviceInfoSet,
4428 PCSTR DeviceName,
4429 CONST GUID *ClassGuid,
4430 PCSTR DeviceDescription,
4431 HWND hwndParent,
4432 DWORD CreationFlags,
4433 PSP_DEVINFO_DATA DeviceInfoData)
4434 {
4435 LPWSTR DeviceNameW = NULL;
4436 LPWSTR DeviceDescriptionW = NULL;
4437 BOOL bResult;
4438
4439 TRACE("\n");
4440
4441 if (DeviceName)
4442 {
4443 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
4444 if (DeviceNameW == NULL) return FALSE;
4445 }
4446 if (DeviceDescription)
4447 {
4448 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
4449 if (DeviceDescriptionW == NULL)
4450 {
4451 if (DeviceNameW) MyFree(DeviceNameW);
4452 return FALSE;
4453 }
4454 }
4455
4456 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
4457 ClassGuid, DeviceDescriptionW,
4458 hwndParent, CreationFlags,
4459 DeviceInfoData);
4460
4461 if (DeviceNameW) MyFree(DeviceNameW);
4462 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
4463
4464 return bResult;
4465 }
4466
4467 /***********************************************************************
4468 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4469 */
4470 BOOL WINAPI SetupDiCreateDeviceInfoW(
4471 HDEVINFO DeviceInfoSet,
4472 PCWSTR DeviceName,
4473 CONST GUID *ClassGuid,
4474 PCWSTR DeviceDescription,
4475 HWND hwndParent,
4476 DWORD CreationFlags,
4477 PSP_DEVINFO_DATA DeviceInfoData)
4478 {
4479 struct DeviceInfoSet *list;
4480 BOOL ret = FALSE;
4481
4482 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
4483 debugstr_guid(ClassGuid), DeviceDescription,
4484 hwndParent, CreationFlags, DeviceInfoData);
4485
4486 if (!DeviceInfoSet)
4487 SetLastError(ERROR_INVALID_HANDLE);
4488 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4489 SetLastError(ERROR_INVALID_HANDLE);
4490 else if (!ClassGuid)
4491 SetLastError(ERROR_INVALID_PARAMETER);
4492 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
4493 SetLastError(ERROR_CLASS_MISMATCH);
4494 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
4495 {
4496 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
4497 SetLastError(ERROR_INVALID_FLAGS);
4498 }
4499 else
4500 {
4501 SP_DEVINFO_DATA DevInfo;
4502
4503 if (CreationFlags & DICD_GENERATE_ID)
4504 {
4505 /* Generate a new unique ID for this device */
4506 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4507 FIXME("not implemented\n");
4508 }
4509 else
4510 {
4511 /* Device name is fully qualified. Try to open it */
4512 BOOL rc;
4513
4514 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
4515 rc = SetupDiOpenDeviceInfoW(
4516 DeviceInfoSet,
4517 DeviceName,
4518 NULL, /* hwndParent */
4519 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
4520 &DevInfo);
4521
4522 if (rc)
4523 {
4524 /* SetupDiOpenDeviceInfoW has already added
4525 * the device info to the device info set
4526 */
4527 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
4528 }
4529 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
4530 {
4531 struct DeviceInfoElement *deviceInfo;
4532
4533 if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
4534 {
4535 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4536
4537 if (!DeviceInfoData)
4538 ret = TRUE;
4539 else
4540 {
4541 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
4542 {
4543 SetLastError(ERROR_INVALID_USER_BUFFER);
4544 }
4545 else
4546 {
4547 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
4548 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
4549 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4550 ret = TRUE;
4551 }
4552 }
4553 }
4554 }
4555 }
4556 }
4557
4558 TRACE("Returning %d\n", ret);
4559 return ret;
4560 }
4561
4562 /***********************************************************************
4563 * Helper functions for SetupDiBuildDriverInfoList
4564 */
4565 static BOOL
4566 AddDriverToList(
4567 IN PLIST_ENTRY DriverListHead,
4568 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4569 IN LPGUID ClassGuid,
4570 IN INFCONTEXT ContextDevice,
4571 IN struct InfFileDetails *InfFileDetails,
4572 IN LPCWSTR InfFile,
4573 IN LPCWSTR ProviderName,
4574 IN LPCWSTR ManufacturerName,
4575 IN LPCWSTR MatchingId,
4576 FILETIME DriverDate,
4577 DWORDLONG DriverVersion,
4578 IN DWORD Rank)
4579 {
4580 struct DriverInfoElement *driverInfo = NULL;
4581 HANDLE hFile = INVALID_HANDLE_VALUE;
4582 DWORD RequiredSize = 128; /* Initial buffer size */
4583 BOOL Result = FALSE;
4584 PLIST_ENTRY PreviousEntry;
4585 LPWSTR InfInstallSection = NULL;
4586 BOOL ret = FALSE;
4587
4588 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
4589 if (!driverInfo)
4590 {
4591 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4592 goto cleanup;
4593 }
4594 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
4595
4596 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
4597 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
4598
4599 /* Copy InfFileName field */
4600 wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
4601 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
4602
4603 /* Fill InfDate field */
4604 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4605 GENERIC_READ, FILE_SHARE_READ,
4606 NULL, OPEN_EXISTING, 0, NULL);
4607 if (hFile == INVALID_HANDLE_VALUE)
4608 goto cleanup;
4609 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4610 if (!Result)
4611 goto cleanup;*/
4612
4613 /* Fill SectionName field */
4614 Result = SetupGetStringFieldW(
4615 &ContextDevice,
4616 1,
4617 driverInfo->Details.SectionName, LINE_LEN,
4618 NULL);
4619 if (!Result)
4620 goto cleanup;
4621
4622 /* Fill DrvDescription field */
4623 Result = SetupGetStringFieldW(
4624 &ContextDevice,
4625 0, /* Field index */
4626 driverInfo->Details.DrvDescription, LINE_LEN,
4627 NULL);
4628
4629 /* Copy MatchingId information */
4630 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4631 if (!driverInfo->MatchingId)
4632 {
4633 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4634 goto cleanup;
4635 }
4636 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4637
4638 /* Get inf install section */
4639 Result = FALSE;
4640 RequiredSize = 128; /* Initial buffer size */
4641 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4642 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4643 {
4644 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4645 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4646 if (!InfInstallSection)
4647 goto cleanup;
4648 Result = SetupGetStringFieldW(
4649 &ContextDevice,
4650 1, /* Field index */
4651 InfInstallSection, RequiredSize,
4652 &RequiredSize);
4653 }
4654 if (!Result)
4655 goto cleanup;
4656
4657 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4658 driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
4659
4660 driverInfo->DriverRank = Rank;
4661 memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
4662 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
4663 driverInfo->Info.DriverType = DriverType;
4664 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
4665 wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
4666 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
4667 wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
4668 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
4669 if (ProviderName)
4670 {
4671 wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
4672 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
4673 }
4674 else
4675 driverInfo->Info.ProviderName[0] = '\0';
4676 driverInfo->Info.DriverDate = DriverDate;
4677 driverInfo->Info.DriverVersion = DriverVersion;
4678 ReferenceInfFile(InfFileDetails);
4679 driverInfo->InfFileDetails = InfFileDetails;
4680
4681 /* Insert current driver in driver list, according to its rank */
4682 PreviousEntry = DriverListHead->Flink;
4683 while (PreviousEntry != DriverListHead)
4684 {
4685 struct DriverInfoElement *CurrentDriver;
4686 CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
4687 if (CurrentDriver->DriverRank > Rank ||
4688 (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
4689 {
4690 /* Insert before the current item */
4691 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
4692 break;
4693 }
4694 PreviousEntry = PreviousEntry->Flink;
4695 }
4696 if (PreviousEntry == DriverListHead)
4697 {
4698 /* Insert at the end of the list */
4699 InsertTailList(DriverListHead, &driverInfo->ListEntry);
4700 }
4701
4702 ret = TRUE;
4703
4704 cleanup:
4705 if (!ret)
4706 {
4707 if (driverInfo)
4708 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
4709 HeapFree(GetProcessHeap(), 0, driverInfo);
4710 }
4711 if (hFile != INVALID_HANDLE_VALUE)
4712 CloseHandle(hFile);
4713 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4714
4715 return ret;
4716 }
4717
4718 static BOOL
4719 GetVersionInformationFromInfFile(
4720 IN HINF hInf,
4721 OUT LPGUID ClassGuid,
4722 OUT LPWSTR* pProviderName,
4723 OUT FILETIME* DriverDate,
4724 OUT DWORDLONG* DriverVersion)
4725 {
4726 DWORD RequiredSize;
4727 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
4728 LPWSTR DriverVer = NULL;
4729 LPWSTR ProviderName = NULL;
4730 LPWSTR pComma; /* Points into DriverVer */
4731 LPWSTR pVersion = NULL; /* Points into DriverVer */
4732 SYSTEMTIME SystemTime;
4733 BOOL Result;
4734 BOOL ret = FALSE; /* Final result */
4735
4736 /* Get class Guid */
4737 if (!SetupGetLineTextW(
4738 NULL, /* Context */
4739 hInf,
4740 L"Version", L"ClassGUID",
4741 guidW, sizeof(guidW),
4742 NULL /* Required size */))
4743 {
4744 goto cleanup;
4745 }
4746 guidW[37] = '\0'; /* Replace the } by a NULL character */
4747 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
4748 {
4749 SetLastError(ERROR_GEN_FAILURE);
4750 goto cleanup;
4751 }
4752
4753 /* Get provider name */
4754 Result = SetupGetLineTextW(
4755 NULL, /* Context */
4756 hInf, L"Version", L"Provider",
4757 NULL, 0,
4758 &RequiredSize);
4759 if (Result)
4760 {
4761 /* We know know the needed buffer size */
4762 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4763 if (!ProviderName)
4764 {
4765 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4766 goto cleanup;
4767 }
4768 Result = SetupGetLineTextW(
4769 NULL, /* Context */
4770 hInf, L"Version", L"Provider",
4771 ProviderName, RequiredSize,
4772 &RequiredSize);
4773 }
4774 if (!Result)
4775 goto cleanup;
4776 *pProviderName = ProviderName;
4777
4778 /* Read the "DriverVer" value */
4779 Result = SetupGetLineTextW(
4780 NULL, /* Context */
4781 hInf, L"Version", L"DriverVer",
4782 NULL, 0,
4783 &RequiredSize);
4784 if (Result)
4785 {
4786 /* We know know the needed buffer size */
4787 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4788 if (!DriverVer)
4789 {
4790 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4791 goto cleanup;
4792 }
4793 Result = SetupGetLineTextW(
4794 NULL, /* Context */
4795 hInf, L"Version", L"DriverVer",
4796 DriverVer, RequiredSize,
4797 &RequiredSize);
4798 }
4799 if (!Result)
4800 goto cleanup;
4801
4802 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4803 pComma = wcschr(DriverVer, ',');
4804 if (pComma != NULL)
4805 {
4806 *pComma = UNICODE_NULL;
4807 pVersion = pComma + 1;
4808 }
4809 /* Get driver date version. Invalid date = 00/00/00 */
4810 memset(DriverDate, 0, sizeof(FILETIME));
4811 if (wcslen(DriverVer) == 10
4812 && (DriverVer[2] == '-' || DriverVer[2] == '/')
4813 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
4814 {
4815 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
4816 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
4817 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
4818 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
4819 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
4820 SystemTimeToFileTime(&SystemTime, DriverDate);
4821 }
4822 /* Get driver version. Invalid version = 0.0.0.0 */
4823 *DriverVersion = 0;
4824 if (pVersion)
4825 {
4826 WORD Major, Minor = 0, Revision = 0, Build = 0;
4827 LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
4828 LARGE_INTEGER fullVersion;
4829
4830 pMinor = strchrW(pVersion, '.');
4831 if (pMinor)
4832 {
4833 *pMinor = 0;
4834 pRevision = strchrW(++pMinor, '.');
4835 Minor = atoiW(pMinor);
4836 }
4837 if (pRevision)
4838 {
4839 *pRevision = 0;
4840 pBuild = strchrW(++pRevision, '.');
4841 Revision = atoiW(pRevision);
4842 }
4843 if (pBuild)
4844 {
4845 *pBuild = 0;
4846 pBuild++;
4847 Build = atoiW(pBuild);
4848 }
4849 Major = atoiW(pVersion);
4850 fullVersion.u.HighPart = Major << 16 | Minor;
4851 fullVersion.u.LowPart = Revision << 16 | Build;
4852 memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
4853 }
4854
4855 ret = TRUE;
4856
4857 cleanup:
4858 if (!ret)
4859 HeapFree(GetProcessHeap(), 0, ProviderName);
4860 HeapFree(GetProcessHeap(), 0, DriverVer);
4861
4862 return ret;
4863 }
4864
4865 /***********************************************************************
4866 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4867 */
4868 BOOL WINAPI
4869 SetupDiBuildDriverInfoList(
4870 IN HDEVINFO DeviceInfoSet,
4871 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4872 IN DWORD DriverType)
4873 {
4874 struct DeviceInfoSet *list;
4875 SP_DEVINSTALL_PARAMS_W InstallParams;
4876 PVOID Buffer = NULL;
4877 struct InfFileDetails *currentInfFileDetails = NULL;
4878 LPWSTR ProviderName = NULL;
4879 LPWSTR ManufacturerName = NULL;
4880 WCHAR ManufacturerSection[LINE_LEN + 1];
4881 LPWSTR HardwareIDs = NULL;
4882 LPWSTR CompatibleIDs = NULL;
4883 LPWSTR FullInfFileName = NULL;
4884 FILETIME DriverDate;
4885 DWORDLONG DriverVersion = 0;
4886 DWORD RequiredSize;
4887 BOOL ret = FALSE;
4888
4889 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
4890
4891 if (!DeviceInfoSet)
4892 SetLastError(ERROR_INVALID_HANDLE);
4893 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4894 SetLastError(ERROR_INVALID_HANDLE);
4895 else if (list->HKLM != HKEY_LOCAL_MACHINE)
4896 SetLastError(ERROR_INVALID_HANDLE);
4897 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4898 SetLastError(ERROR_INVALID_PARAMETER);
4899 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
4900 SetLastError(ERROR_INVALID_PARAMETER);
4901 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4902 SetLastError(ERROR_INVALID_PARAMETER);
4903 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4904 SetLastError(ERROR_INVALID_USER_BUFFER);
4905 else
4906 {
4907 BOOL Result;
4908
4909 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
4910 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4911 if (!Result)
4912 goto done;
4913
4914 if (DriverType == SPDIT_COMPATDRIVER)
4915 {
4916 /* Get hardware IDs list */
4917 Result = FALSE;
4918 RequiredSize = 512; /* Initial buffer size */
4919 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4920 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4921 {
4922 HeapFree(GetProcessHeap(), 0, HardwareIDs);
4923 HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
4924 if (!HardwareIDs)
4925 {
4926 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4927 goto done;
4928 }
4929 Result = SetupDiGetDeviceRegistryPropertyW(
4930 DeviceInfoSet,
4931 DeviceInfoData,
4932 SPDRP_HARDWAREID,
4933 NULL,
4934 (PBYTE)HardwareIDs,
4935 RequiredSize,
4936 &RequiredSize);
4937 }
4938 if (!Result)
4939 goto done;
4940
4941 /* Get compatible IDs list */
4942 Result = FALSE;
4943 RequiredSize = 512; /* Initial buffer size */
4944 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4945 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4946 {
4947 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4948 CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
4949 if (!CompatibleIDs)
4950 {
4951 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4952 goto done;
4953 }
4954 Result = SetupDiGetDeviceRegistryPropertyW(
4955 DeviceInfoSet,
4956 DeviceInfoData,
4957 SPDRP_COMPATIBLEIDS,
4958 NULL,
4959 (PBYTE)CompatibleIDs,
4960 RequiredSize,
4961 &RequiredSize);
4962 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
4963 {
4964 /* No compatible ID for this device */
4965 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4966 CompatibleIDs = NULL;
4967 Result = TRUE;
4968 }
4969 }
4970 if (!Result)
4971 goto done;
4972 }
4973
4974 /* Enumerate .inf files */
4975 Result = FALSE;
4976 RequiredSize = 32768; /* Initial buffer size */
4977 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4978 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4979 {
4980 HeapFree(GetProcessHeap(), 0, Buffer);
4981 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4982 if (!Buffer)
4983 {
4984 Result = FALSE;
4985 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4986 break;
4987 }
4988 Result = SetupGetInfFileListW(
4989 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
4990 INF_STYLE_WIN4,
4991 Buffer, RequiredSize,
4992 &RequiredSize);
4993 }
4994 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
4995 {
4996 /* No .inf file in specified directory. So, we should
4997 * success as we created an empty driver info list.
4998 */
4999 ret = TRUE;
5000 goto done;
5001 }
5002 if (Result)
5003 {
5004 LPCWSTR filename;
5005 LPWSTR pFullFilename;
5006
5007 if (*InstallParams.DriverPath)
5008 {
5009 DWORD len;
5010 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
5011 if (len == 0)
5012 goto done;
5013 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
5014 if (!FullInfFileName)
5015 goto done;
5016 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
5017 if (len == 0)
5018 goto done;
5019 if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
5020 wcscat(FullInfFileName, L"\\");
5021 pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
5022 }
5023 else
5024 {
5025 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
5026 if (!FullInfFileName)
5027 goto done;
5028 pFullFilename = &FullInfFileName[0];
5029 }
5030
5031 for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
5032 {
5033 INFCONTEXT ContextManufacturer, ContextDevice;
5034 GUID ClassGuid;
5035
5036 wcscpy(pFullFilename, filename);
5037 TRACE("Opening file %S\n", FullInfFileName);
5038
5039 currentInfFileDetails = HeapAlloc(
5040 GetProcessHeap(),
5041 0,
5042 FIELD_OFFSET(struct InfFileDetails, FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) + UNICODE_NULL);
5043 if (!currentInfFileDetails)
5044 continue;
5045 memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
5046 wcscpy(currentInfFileDetails->FullInfFileName, FullInfFileName);
5047
5048 currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
5049 ReferenceInfFile(currentInfFileDetails);
5050 if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
5051 {
5052 HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
5053 currentInfFileDetails = NULL;
5054 continue;
5055 }
5056
5057 if (!GetVersionInformationFromInfFile(
5058 currentInfFileDetails->hInf,
5059 &ClassGuid,
5060 &ProviderName,
5061 &DriverDate,
5062 &DriverVersion))
5063 {
5064 SetupCloseInfFile(currentInfFileDetails->hInf);
5065 HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
5066 currentInfFileDetails = NULL;
5067 continue;
5068 }
5069
5070 if (DriverType == SPDIT_CLASSDRIVER)
5071 {
5072 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5073 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
5074 {
5075 goto next;
5076 }
5077 }
5078
5079 /* Get the manufacturers list */
5080 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
5081 while (Result)
5082 {
5083 Result = SetupGetStringFieldW(
5084 &ContextManufacturer,
5085 0, /* Field index */
5086 NULL, 0,
5087 &RequiredSize);
5088 if (Result)
5089 {
5090 /* We got the needed size for the buffer */
5091 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5092 if (!ManufacturerName)
5093 {
5094 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5095 goto done;
5096 }
5097 Result = SetupGetStringFieldW(
5098 &ContextManufacturer,
5099 0, /* Field index */
5100 ManufacturerName, RequiredSize,
5101 &RequiredSize);
5102 }
5103 /* Get manufacturer section name */
5104 Result = SetupGetStringFieldW(
5105 &ContextManufacturer,
5106 1, /* Field index */
5107 ManufacturerSection, LINE_LEN,
5108 &RequiredSize);
5109 if (Result)
5110 {
5111 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
5112 /* Add (possible) extension to manufacturer section name */
5113 Result = SetupDiGetActualSectionToInstallW(
5114 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
5115 if (Result)
5116 {
5117 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
5118 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
5119 }
5120 }
5121 while (Result)
5122 {
5123 if (DriverType == SPDIT_CLASSDRIVER)
5124 {
5125 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5126 if (!AddDriverToList(
5127 &list->DriverListHead,
5128 DriverType,
5129 &ClassGuid,
5130 ContextDevice,
5131 currentInfFileDetails,
5132 filename,
5133 ProviderName,
5134 ManufacturerName,
5135 NULL,
5136 DriverDate, DriverVersion,
5137 0))
5138 {
5139 break;
5140 }
5141 }
5142 else /* DriverType = SPDIT_COMPATDRIVER */
5143 {
5144 /* 1. Get all fields */
5145 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
5146 DWORD DriverRank;
5147 DWORD i;
5148 LPCWSTR currentId;
5149 BOOL DriverAlreadyAdded;
5150
5151 for (i = 2; i <= FieldCount; i++)
5152 {
5153 LPWSTR DeviceId = NULL;
5154 Result = FALSE;
5155 RequiredSize = 128; /* Initial buffer size */
5156 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5157 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5158 {
5159 HeapFree(GetProcessHeap(), 0, DeviceId);
5160 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5161 if (!DeviceId)
5162 {
5163 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5164 goto done;
5165 }
5166 Result = SetupGetStringFieldW(
5167 &ContextDevice,
5168 i,
5169 DeviceId, RequiredSize,
5170 &RequiredSize);
5171 }
5172 if (!Result)
5173 {
5174 HeapFree(GetProcessHeap(), 0, DeviceId);
5175 goto done;
5176 }
5177 DriverAlreadyAdded = FALSE;
5178 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
5179 {
5180 if (wcsicmp(DeviceId, currentId) == 0)
5181 {
5182 AddDriverToList(
5183 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
5184 DriverType,
5185 &ClassGuid,
5186 ContextDevice,
5187 currentInfFileDetails,
5188 filename,
5189 ProviderName,
5190 ManufacturerName,
5191 currentId,
5192 DriverDate, DriverVersion,
5193 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
5194 DriverAlreadyAdded = TRUE;
5195 }
5196 }
5197 if (CompatibleIDs)
5198 {
5199 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
5200 {
5201 if (wcsicmp(DeviceId, currentId) == 0)
5202 {
5203 AddDriverToList(
5204 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
5205 DriverType,
5206 &ClassGuid,
5207 ContextDevice,
5208 currentInfFileDetails,
5209 filename,
5210 ProviderName,
5211 ManufacturerName,
5212 currentId,
5213 DriverDate, DriverVersion,
5214 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
5215 DriverAlreadyAdded = TRUE;
5216 }
5217 }
5218 }
5219 HeapFree(GetProcessHeap(), 0, DeviceId);
5220 }
5221 }
5222 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
5223 }
5224
5225 HeapFree(GetProcessHeap(), 0, ManufacturerName);
5226 ManufacturerName = NULL;
5227 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
5228 }
5229
5230 ret = TRUE;
5231 next:
5232 HeapFree(GetProcessHeap(), 0, ProviderName);
5233 ProviderName = NULL;
5234
5235 DereferenceInfFile(currentInfFileDetails);
5236 currentInfFileDetails = NULL;
5237 }
5238 ret = TRUE;
5239 }
5240 }
5241
5242 done:
5243 if (ret)
5244 {
5245 if (DeviceInfoData)
5246 {
5247 InstallParams.Flags |= DI_DIDCOMPAT;
5248 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
5249 }
5250 else
5251 {
5252 InstallParams.Flags |= DI_DIDCLASS;
5253 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
5254 }
5255 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5256 }
5257
5258 HeapFree(GetProcessHeap(), 0, ProviderName);
5259 HeapFree(GetProcessHeap(), 0, ManufacturerName);
5260 HeapFree(GetProcessHeap(), 0, HardwareIDs);
5261 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5262 HeapFree(GetProcessHeap(), 0, FullInfFileName);
5263 if (currentInfFileDetails)
5264 DereferenceInfFile(currentInfFileDetails);
5265 HeapFree(GetProcessHeap(), 0, Buffer);
5266
5267 TRACE("Returning %d\n", ret);
5268 return ret;
5269 }
5270
5271 /***********************************************************************
5272 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5273 */
5274 BOOL WINAPI
5275 SetupDiDeleteDeviceInfo(
5276 IN HDEVINFO DeviceInfoSet,
5277 IN PSP_DEVINFO_DATA DeviceInfoData)
5278 {
5279 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5280
5281 FIXME("not implemented\n");
5282 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5283 return FALSE;
5284 }
5285
5286
5287 /***********************************************************************
5288 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5289 */
5290 BOOL WINAPI
5291 SetupDiDestroyDriverInfoList(
5292 IN HDEVINFO DeviceInfoSet,
5293 IN PSP_DEVINFO_DATA DeviceInfoData,
5294 IN DWORD DriverType)
5295 {
5296 struct DeviceInfoSet *list;
5297 BOOL ret = FALSE;
5298
5299 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
5300
5301 if (!DeviceInfoSet)
5302 SetLastError(ERROR_INVALID_HANDLE);
5303 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5304 SetLastError(ERROR_INVALID_HANDLE);
5305 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5306 SetLastError(ERROR_INVALID_PARAMETER);
5307 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5308 SetLastError(ERROR_INVALID_PARAMETER);
5309 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5310 SetLastError(ERROR_INVALID_USER_BUFFER);
5311 else
5312 {
5313 PLIST_ENTRY ListEntry;
5314 struct DriverInfoElement *driverInfo;
5315 SP_DEVINSTALL_PARAMS_W InstallParams;
5316
5317 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5318 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
5319 goto done;
5320
5321 if (!DeviceInfoData)
5322 /* Fall back to destroying class driver list */
5323 DriverType = SPDIT_CLASSDRIVER;
5324
5325 if (DriverType == SPDIT_CLASSDRIVER)
5326 {
5327 while (!IsListEmpty(&list->DriverListHead))
5328 {
5329 ListEntry = RemoveHeadList(&list->DriverListHead);
5330 driverInfo = (struct DriverInfoElement *)ListEntry;
5331 DestroyDriverInfoElement(driverInfo);
5332 }
5333 InstallParams.Reserved = 0;
5334 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
5335 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
5336 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
5337 }
5338 else
5339 {
5340 SP_DEVINSTALL_PARAMS_W InstallParamsSet;
5341 struct DeviceInfoElement *deviceInfo;
5342
5343 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5344 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
5345 goto done;
5346 deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5347 while (!IsListEmpty(&deviceInfo->DriverListHead))
5348 {
5349 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
5350 driverInfo = (struct DriverInfoElement *)ListEntry;
5351 if ((PVOID)InstallParamsSet.Reserved == driverInfo)
5352 {
5353 InstallParamsSet.Reserved = 0;
5354 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
5355 }
5356 DestroyDriverInfoElement(driverInfo);
5357 }
5358 InstallParams.Reserved = 0;
5359 InstallParams.Flags &= ~DI_DIDCOMPAT;
5360 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
5361 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5362 }
5363 }
5364
5365 done:
5366 TRACE("Returning %d\n", ret);
5367 return ret;
5368 }
5369
5370
5371 /***********************************************************************
5372 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5373 */
5374 BOOL WINAPI
5375 SetupDiOpenDeviceInfoA(
5376 IN HDEVINFO DeviceInfoSet,
5377 IN PCSTR DeviceInstanceId,
5378 IN HWND hwndParent OPTIONAL,
5379 IN DWORD OpenFlags,
5380 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5381 {
5382 LPWSTR DeviceInstanceIdW = NULL;
5383 BOOL bResult;
5384
5385 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
5386
5387 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
5388 if (DeviceInstanceIdW == NULL)
5389 return FALSE;
5390
5391 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
5392 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
5393
5394 MyFree(DeviceInstanceIdW);
5395
5396 return bResult;
5397 }
5398
5399
5400 /***********************************************************************
5401 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5402 */
5403 BOOL WINAPI
5404 SetupDiOpenDeviceInfoW(
5405 IN HDEVINFO DeviceInfoSet,
5406 IN PCWSTR DeviceInstanceId,
5407 IN HWND hwndParent OPTIONAL,
5408 IN DWORD OpenFlags,
5409 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5410 {
5411 struct DeviceInfoSet *list;
5412 HKEY hEnumKey, hKey;
5413 DWORD rc;
5414 BOOL ret = FALSE;
5415
5416 TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
5417
5418 if (OpenFlags & DIOD_CANCEL_REMOVE)
5419 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5420
5421 if (!DeviceInfoSet)
5422 SetLastError(ERROR_INVALID_HANDLE);
5423 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5424 SetLastError(ERROR_INVALID_HANDLE);
5425 else if (!DeviceInstanceId)
5426 SetLastError(ERROR_INVALID_PARAMETER);
5427 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
5428 {
5429 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
5430 SetLastError(ERROR_INVALID_FLAGS);
5431 }
5432 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5433 SetLastError(ERROR_INVALID_USER_BUFFER);
5434 else
5435 {
5436 struct DeviceInfoElement *deviceInfo = NULL;
5437 /* Search if device already exists in DeviceInfoSet.
5438 * If yes, return the existing element
5439 * If no, create a new element using informations in registry
5440 */
5441 PLIST_ENTRY ItemList = list->ListHead.Flink;
5442 while (ItemList != &list->ListHead)
5443 {
5444 // TODO
5445 //if (good one)
5446 // break;
5447 FIXME("not implemented\n");
5448 ItemList = ItemList->Flink;
5449 }
5450
5451 if (deviceInfo)
5452 {
5453 /* good one found */
5454 ret = TRUE;
5455 }
5456 else
5457 {
5458 /* Open supposed registry key */
5459 rc = RegOpenKeyExW(
5460 list->HKLM,
5461 EnumKeyName,
5462 0, /* Options */
5463 KEY_ENUMERATE_SUB_KEYS,
5464 &hEnumKey);
5465 if (rc != ERROR_SUCCESS)
5466 {
5467 SetLastError(rc);
5468 return FALSE;
5469 }
5470 rc = RegOpenKeyExW(
5471 hEnumKey,
5472 DeviceInstanceId,
5473 0, /* Options */
5474 KEY_QUERY_VALUE,
5475 &hKey);
5476 RegCloseKey(hEnumKey);
5477 if (rc != ERROR_SUCCESS)
5478 {
5479 if (rc == ERROR_FILE_NOT_FOUND)
5480 rc = ERROR_NO_SUCH_DEVINST;
5481 SetLastError(rc);
5482 return FALSE;
5483 }
5484
5485 /* FIXME: try to get ClassGUID from registry, instead of
5486 * sending GUID_NULL to CreateDeviceInfoElement
5487 */
5488 if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
5489 {
5490 RegCloseKey(hKey);
5491 return FALSE;
5492 }
5493 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
5494
5495 RegCloseKey(hKey);
5496 ret = TRUE;
5497 }
5498
5499 if (ret && deviceInfo && DeviceInfoData)
5500 {
5501 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
5502 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
5503 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
5504 }
5505 }
5506
5507 return ret;
5508 }
5509
5510
5511 /***********************************************************************
5512 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5513 */
5514 BOOL WINAPI
5515 SetupDiEnumDriverInfoA(
5516 IN HDEVINFO DeviceInfoSet,
5517 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5518 IN DWORD DriverType,
5519 IN DWORD MemberIndex,
5520 OUT PSP_DRVINFO_DATA_A DriverInfoData)
5521 {
5522 SP_DRVINFO_DATA_V2_W driverInfoData2W;
5523 BOOL ret = FALSE;
5524
5525 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
5526 DriverType, MemberIndex, DriverInfoData);
5527
5528 if (DriverInfoData == NULL)
5529 SetLastError(ERROR_INVALID_PARAMETER);
5530 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
5531 SetLastError(ERROR_INVALID_USER_BUFFER);
5532 else
5533 {
5534 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5535 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
5536 DriverType, MemberIndex, &driverInfoData2W);
5537
5538 if (ret)
5539 {
5540 /* Do W->A conversion */
5541 DriverInfoData->DriverType = driverInfoData2W.DriverType;
5542 DriverInfoData->Reserved = driverInfoData2W.Reserved;
5543 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
5544 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
5545 {
5546 DriverInfoData->Description[0] = '\0';
5547 ret = FALSE;
5548 }
5549 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
5550 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
5551 {
5552 DriverInfoData->MfgName[0] = '\0';
5553 ret = FALSE;
5554 }
5555 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
5556 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
5557 {
5558 DriverInfoData->ProviderName[0] = '\0';
5559 ret = FALSE;
5560 }
5561 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5562 {
5563 /* Copy more fields */
5564 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
5565 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
5566 }
5567 }
5568 }
5569
5570 TRACE("Returning %d\n", ret);
5571 return ret;
5572 }
5573
5574
5575 /***********************************************************************
5576 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5577 */
5578 BOOL WINAPI
5579 SetupDiEnumDriverInfoW(
5580 IN HDEVINFO DeviceInfoSet,
5581 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5582 IN DWORD DriverType,
5583 IN DWORD MemberIndex,
5584 OUT PSP_DRVINFO_DATA_W DriverInfoData)
5585 {
5586 PLIST_ENTRY ListHead;
5587 BOOL ret = FALSE;
5588
5589 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
5590 DriverType, MemberIndex, DriverInfoData);
5591
5592 if (!DeviceInfoSet || !DriverInfoData)
5593 SetLastError(ERROR_INVALID_PARAMETER);
5594 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5595 SetLastError(ERROR_INVALID_HANDLE);
5596 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5597 SetLastError(ERROR_INVALID_HANDLE);
5598 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5599 SetLastError(ERROR_INVALID_PARAMETER);
5600 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
5601 SetLastError(ERROR_INVALID_PARAMETER);
5602 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5603 SetLastError(ERROR_INVALID_PARAMETER);
5604 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5605 SetLastError(ERROR_INVALID_USER_BUFFER);
5606 else
5607 {
5608 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5609 PLIST_ENTRY ItemList;
5610 if (DriverType == SPDIT_CLASSDRIVER ||
5611 devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
5612 {
5613 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
5614 }
5615 else
5616 {
5617 ListHead = &devInfo->DriverListHead;
5618 }
5619
5620 ItemList = ListHead->Flink;
5621 while (ItemList != ListHead && MemberIndex-- > 0)
5622 ItemList = ItemList->Flink;
5623 if (ItemList == ListHead)
5624 SetLastError(ERROR_NO_MORE_ITEMS);
5625 else
5626 {
5627 struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
5628
5629 memcpy(
5630 &DriverInfoData->DriverType,
5631 &DrvInfo->Info.DriverType,
5632 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
5633 ret = TRUE;
5634 }
5635 }
5636
5637 TRACE("Returning %d\n", ret);
5638 return ret;
5639 }
5640
5641
5642 /***********************************************************************
5643 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5644 */
5645 BOOL WINAPI
5646 SetupDiGetSelectedDriverA(
5647 IN HDEVINFO DeviceInfoSet,
5648 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5649 OUT PSP_DRVINFO_DATA_A DriverInfoData)
5650 {
5651 SP_DRVINFO_DATA_V2_W driverInfoData2W;
5652 BOOL ret = FALSE;
5653
5654 if (DriverInfoData == NULL)
5655 SetLastError(ERROR_INVALID_PARAMETER);
5656 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
5657 SetLastError(ERROR_INVALID_USER_BUFFER);
5658 else
5659 {
5660 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5661
5662 ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
5663 DeviceInfoData,
5664 &driverInfoData2W);
5665
5666 if (ret)
5667 {
5668 /* Do W->A conversion */
5669 DriverInfoData->DriverType = driverInfoData2W.DriverType;
5670 DriverInfoData->Reserved = driverInfoData2W.Reserved;
5671 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
5672 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
5673 {
5674 DriverInfoData->Description[0] = '\0';
5675 ret = FALSE;
5676 }
5677 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
5678 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
5679 {
5680 DriverInfoData->MfgName[0] = '\0';
5681 ret = FALSE;
5682 }
5683 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
5684 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
5685 {
5686 DriverInfoData->ProviderName[0] = '\0';
5687 ret = FALSE;
5688 }
5689 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5690 {
5691 /* Copy more fields */
5692 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
5693 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
5694 }
5695 }
5696 }
5697
5698 return ret;
5699 }
5700
5701
5702 /***********************************************************************
5703 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5704 */
5705 BOOL WINAPI
5706 SetupDiGetSelectedDriverW(
5707 IN HDEVINFO DeviceInfoSet,
5708 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5709 OUT PSP_DRVINFO_DATA_W DriverInfoData)
5710 {
5711 BOOL ret = FALSE;
5712
5713 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5714
5715 if (!DeviceInfoSet || !DriverInfoData)
5716 SetLastError(ERROR_INVALID_PARAMETER);
5717 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5718 SetLastError(ERROR_INVALID_HANDLE);
5719 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5720 SetLastError(ERROR_INVALID_HANDLE);
5721 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5722 SetLastError(ERROR_INVALID_USER_BUFFER);
5723 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5724 SetLastError(ERROR_INVALID_USER_BUFFER);
5725 else
5726 {
5727 SP_DEVINSTALL_PARAMS InstallParams;
5728
5729 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
5730 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
5731 {
5732 struct DriverInfoElement *driverInfo;
5733 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
5734 if (driverInfo == NULL)
5735 SetLastError(ERROR_NO_DRIVER_SELECTED);
5736 else
5737 {
5738 memcpy(
5739 &DriverInfoData->DriverType,
5740 &driverInfo->Info.DriverType,
5741 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
5742 ret = TRUE;
5743 }
5744 }
5745 }
5746
5747 TRACE("Returning %d\n", ret);
5748 return ret;
5749 }
5750
5751
5752 /***********************************************************************
5753 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5754 */
5755 BOOL WINAPI
5756 SetupDiSetSelectedDriverA(
5757 IN HDEVINFO DeviceInfoSet,
5758 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5759 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
5760 {
5761 SP_DRVINFO_DATA_V1_W DriverInfoDataW;
5762 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
5763 BOOL ret = FALSE;
5764
5765 if (DriverInfoData != NULL)
5766 {
5767 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
5768 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
5769 {
5770 SetLastError(ERROR_INVALID_PARAMETER);
5771 return FALSE;
5772 }
5773
5774 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5775 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5776
5777 if (DriverInfoDataW.Reserved == 0)
5778 {
5779 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5780
5781 /* convert the strings to unicode */
5782 if (!MultiByteToWideChar(CP_ACP,
5783 0,
5784 DriverInfoData->Description,
5785 LINE_LEN,
5786 DriverInfoDataW.Description,
5787 LINE_LEN) ||
5788 !MultiByteToWideChar(CP_ACP,
5789 0,
5790 DriverInfoData->ProviderName,
5791 LINE_LEN,
5792 DriverInfoDataW.ProviderName,
5793 LINE_LEN))
5794 {
5795 return FALSE;
5796 }
5797 }
5798
5799 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
5800 }
5801
5802 ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
5803 DeviceInfoData,
5804 pDriverInfoDataW);
5805
5806 if (ret && pDriverInfoDataW != NULL)
5807 {
5808 DriverInfoData->Reserved = DriverInfoDataW.Reserved;
5809 }
5810
5811 return ret;
5812 }
5813
5814
5815 /***********************************************************************
5816 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5817 */
5818 BOOL WINAPI
5819 SetupDiSetSelectedDriverW(
5820 IN HDEVINFO DeviceInfoSet,
5821 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5822 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
5823 {
5824 BOOL ret = FALSE;
5825
5826 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5827
5828 if (!DeviceInfoSet)
5829 SetLastError(ERROR_INVALID_PARAMETER);
5830 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5831 SetLastError(ERROR_INVALID_HANDLE);
5832 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5833 SetLastError(ERROR_INVALID_HANDLE);
5834 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5835 SetLastError(ERROR_INVALID_USER_BUFFER);
5836 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5837 SetLastError(ERROR_INVALID_USER_BUFFER);
5838 else
5839 {
5840 struct DriverInfoElement **pDriverInfo;
5841 PLIST_ENTRY ListHead, ItemList;
5842
5843 if (DeviceInfoData)
5844 {
5845 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
5846 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
5847 }
5848 else
5849 {
5850 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
5851 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
5852 }
5853
5854 if (!DriverInfoData)
5855 {
5856 *pDriverInfo = NULL;
5857 ret = TRUE;
5858 }
5859 else
5860 {
5861 /* Search selected driver in list */
5862 ItemList = ListHead->Flink;
5863 while (ItemList != ListHead)
5864 {
5865 if (DriverInfoData->Reserved != 0)
5866 {
5867 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
5868 break;
5869 }
5870 else
5871 {
5872 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5873 struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
5874 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
5875 && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
5876 && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
5877 {
5878 break;
5879 }
5880 }
5881 }
5882 if (ItemList == ListHead)
5883 SetLastError(ERROR_INVALID_PARAMETER);
5884 else
5885 {
5886 *pDriverInfo = (struct DriverInfoElement *)ItemList;
5887 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
5888 ret = TRUE;
5889 TRACE("Choosing driver whose rank is 0x%lx\n",
5890 ((struct DriverInfoElement *)ItemList)->DriverRank);
5891 if (DeviceInfoData)
5892 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
5893 }
5894 }
5895 }
5896
5897 TRACE("Returning %d\n", ret);
5898 return ret;
5899 }
5900
5901 /***********************************************************************
5902 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5903 */
5904 BOOL WINAPI
5905 SetupDiGetDriverInfoDetailA(
5906 IN HDEVINFO DeviceInfoSet,
5907 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5908 IN PSP_DRVINFO_DATA_A DriverInfoData,
5909 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
5910 IN DWORD DriverInfoDetailDataSize,
5911 OUT PDWORD RequiredSize OPTIONAL)
5912 {
5913 SP_DRVINFO_DATA_V2_W DriverInfoDataW;
5914 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
5915 DWORD BufSize = 0;
5916 DWORD HardwareIDLen = 0;
5917 BOOL ret = FALSE;
5918
5919 /* do some sanity checks, the unicode version might do more thorough checks */
5920 if (DriverInfoData == NULL ||
5921 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
5922 (DriverInfoDetailData != NULL &&
5923 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
5924 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
5925 {
5926 SetLastError(ERROR_INVALID_PARAMETER);
5927 goto Cleanup;
5928 }
5929
5930 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5931 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
5932 {
5933 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5934 }
5935 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5936 {
5937 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5938 }
5939 else
5940 {
5941 SetLastError(ERROR_INVALID_PARAMETER);
5942 goto Cleanup;
5943 }
5944 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5945 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5946
5947 /* convert the strings to unicode */
5948 if (MultiByteToWideChar(CP_ACP,
5949 0,
5950 DriverInfoData->Description,
5951 LINE_LEN,
5952 DriverInfoDataW.Description,
5953 LINE_LEN) &&
5954 MultiByteToWideChar(CP_ACP,
5955 0,
5956 DriverInfoData->MfgName,
5957 LINE_LEN,
5958 DriverInfoDataW.MfgName,
5959 LINE_LEN) &&
5960 MultiByteToWideChar(CP_ACP,
5961 0,
5962 DriverInfoData->ProviderName,
5963 LINE_LEN,
5964 DriverInfoDataW.ProviderName,
5965 LINE_LEN))
5966 {
5967 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
5968 {
5969 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
5970 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
5971 }
5972
5973 if (DriverInfoDetailData != NULL)
5974 {
5975 /* calculate the unicode buffer size from the ansi buffer size */
5976 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
5977 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
5978 (HardwareIDLen * sizeof(WCHAR));
5979
5980 DriverInfoDetailDataW = MyMalloc(BufSize);
5981 if (DriverInfoDetailDataW == NULL)
5982 {
5983 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5984 goto Cleanup;
5985 }
5986
5987 /* initialize the buffer */
5988 ZeroMemory(DriverInfoDetailDataW,
5989 BufSize);
5990 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
5991 }
5992
5993 /* call the unicode version */
5994 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
5995 DeviceInfoData,
5996 &DriverInfoDataW,
5997 DriverInfoDetailDataW,
5998 BufSize,
5999 RequiredSize);
6000
6001 if (ret)
6002 {
6003 if (DriverInfoDetailDataW != NULL)
6004 {
6005 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6006 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
6007 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
6008 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
6009 if (WideCharToMultiByte(CP_ACP,
6010 0,
6011 DriverInfoDetailDataW->SectionName,
6012 LINE_LEN,
6013 DriverInfoDetailData->SectionName,
6014 LINE_LEN,
6015 NULL,
6016 NULL) &&
6017 WideCharToMultiByte(CP_ACP,
6018 0,
6019 DriverInfoDetailDataW->InfFileName,
6020 MAX_PATH,
6021 DriverInfoDetailData->InfFileName,
6022 MAX_PATH,
6023 NULL,
6024 NULL) &&
6025 WideCharToMultiByte(CP_ACP,
6026 0,
6027 DriverInfoDetailDataW->DrvDescription,
6028 LINE_LEN,
6029 DriverInfoDetailData->DrvDescription,
6030 LINE_LEN,
6031 NULL,
6032 NULL) &&
6033 WideCharToMultiByte(CP_ACP,
6034 0,
6035 DriverInfoDetailDataW->HardwareID,
6036 HardwareIDLen,
6037 DriverInfoDetailData->HardwareID,
6038 HardwareIDLen,
6039 NULL,
6040 NULL))
6041 {
6042 DWORD len, cnt = 0;
6043 DWORD hwidlen = HardwareIDLen;
6044 CHAR *s = DriverInfoDetailData->HardwareID;
6045
6046 /* count the strings in the list */
6047 while (*s != '\0')
6048 {
6049 len = lstrlenA(s) + 1;
6050 if (hwidlen > len)
6051 {
6052 cnt++;
6053 s += len;
6054 hwidlen -= len;
6055 }
6056 else
6057 {
6058 /* looks like the string list wasn't terminated... */
6059 SetLastError(ERROR_INVALID_USER_BUFFER);
6060 ret = FALSE;
6061 break;
6062 }
6063 }
6064
6065 /* make sure CompatIDsOffset points to the second string in the
6066 list, if present */
6067 if (cnt > 1)
6068 {
6069 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
6070 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
6071 DriverInfoDetailData->CompatIDsOffset + 1;
6072 }
6073 else
6074 {
6075 DriverInfoDetailData->CompatIDsOffset = 0;
6076 DriverInfoDetailData->CompatIDsLength = 0;
6077 }
6078 }
6079 else
6080 {
6081 ret = FALSE;
6082 }
6083 }
6084
6085 if (RequiredSize != NULL)
6086 {
6087 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
6088 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
6089 }
6090 }
6091 }
6092
6093 Cleanup:
6094 if (DriverInfoDetailDataW != NULL)
6095 {
6096 MyFree(DriverInfoDetailDataW);
6097 }
6098
6099 return ret;
6100 }
6101
6102 /***********************************************************************
6103 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6104 */
6105 BOOL WINAPI
6106 SetupDiGetDriverInfoDetailW(
6107 IN HDEVINFO DeviceInfoSet,
6108 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6109 IN PSP_DRVINFO_DATA_W DriverInfoData,
6110 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
6111 IN DWORD DriverInfoDetailDataSize,
6112 OUT PDWORD RequiredSize OPTIONAL)
6113 {
6114 BOOL ret = FALSE;
6115
6116 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
6117 DriverInfoData, DriverInfoDetailData,
6118 DriverInfoDetailDataSize, RequiredSize);
6119
6120 if (!DeviceInfoSet)
6121 SetLastError(ERROR_INVALID_PARAMETER);
6122 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6123 SetLastError(ERROR_INVALID_HANDLE);
6124 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6125 SetLastError(ERROR_INVALID_HANDLE);
6126 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6127 SetLastError(ERROR_INVALID_USER_BUFFER);
6128 else if (!DriverInfoData)
6129 SetLastError(ERROR_INVALID_PARAMETER);
6130 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
6131 SetLastError(ERROR_INVALID_PARAMETER);
6132 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
6133 SetLastError(ERROR_INVALID_PARAMETER);
6134 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
6135 SetLastError(ERROR_INVALID_USER_BUFFER);
6136 else if (DriverInfoData->Reserved == 0)
6137 SetLastError(ERROR_NO_DRIVER_SELECTED);
6138 else
6139 {
6140 struct DriverInfoElement *driverInfoElement;
6141 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
6142
6143 memcpy(
6144 DriverInfoDetailData,
6145 &driverInfoElement->Details,
6146 driverInfoElement->Details.cbSize);
6147 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6148 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6149 */
6150 ret = TRUE;
6151 }
6152
6153 TRACE("Returning %d\n", ret);
6154 return ret;
6155 }
6156
6157 /***********************************************************************
6158 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6159 */
6160 BOOL WINAPI
6161 SetupDiSelectBestCompatDrv(
6162 IN HDEVINFO DeviceInfoSet,
6163 IN PSP_DEVINFO_DATA DeviceInfoData)
6164 {
6165 SP_DRVINFO_DATA_W drvInfoData;
6166 BOOL ret;
6167
6168 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6169
6170 /* Drivers are sorted by rank in the driver list, so
6171 * the first driver in the list is the best one.
6172 */
6173 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
6174 ret = SetupDiEnumDriverInfoW(
6175 DeviceInfoSet,
6176 DeviceInfoData,
6177 SPDIT_COMPATDRIVER,
6178 0, /* Member index */
6179 &drvInfoData);
6180
6181 if (ret)
6182 {
6183 ret = SetupDiSetSelectedDriverW(
6184 DeviceInfoSet,
6185 DeviceInfoData,
6186 &drvInfoData);
6187 }
6188
6189 TRACE("Returning %d\n", ret);
6190 return ret;
6191 }
6192
6193 /***********************************************************************
6194 * SetupDiInstallDriverFiles (SETUPAPI.@)
6195 */
6196 BOOL WINAPI
6197 SetupDiInstallDriverFiles(
6198 IN HDEVINFO DeviceInfoSet,
6199 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6200 {
6201 BOOL ret = FALSE;
6202
6203 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6204
6205 if (!DeviceInfoSet)
6206 SetLastError(ERROR_INVALID_PARAMETER);
6207 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6208 SetLastError(ERROR_INVALID_HANDLE);
6209 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6210 SetLastError(ERROR_INVALID_HANDLE);
6211 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6212 SetLastError(ERROR_INVALID_USER_BUFFER);
6213 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
6214 SetLastError(ERROR_NO_DRIVER_SELECTED);
6215 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
6216 SetLastError(ERROR_NO_DRIVER_SELECTED);
6217 else
6218 {
6219 SP_DEVINSTALL_PARAMS_W InstallParams;
6220 struct DriverInfoElement *SelectedDriver;
6221 WCHAR SectionName[MAX_PATH];
6222 DWORD SectionNameLength = 0;
6223
6224 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6225 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6226 if (!ret)
6227 goto done;
6228
6229 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
6230 if (!SelectedDriver)
6231 {
6232 SetLastError(ERROR_NO_DRIVER_SELECTED);
6233 goto done;
6234 }
6235
6236 ret = SetupDiGetActualSectionToInstallW(
6237 SelectedDriver->InfFileDetails->hInf,
6238 SelectedDriver->Details.SectionName,
6239 SectionName, MAX_PATH, &SectionNameLength, NULL);
6240 if (!ret)
6241 goto done;
6242
6243 if (!InstallParams.InstallMsgHandler)
6244 {
6245 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
6246 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
6247 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6248 }
6249 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6250 SelectedDriver->InfFileDetails->hInf, SectionName,
6251 SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
6252 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6253 DeviceInfoSet, DeviceInfoData);
6254 }
6255
6256 done:
6257 TRACE("Returning %d\n", ret);
6258 return ret;
6259 }
6260
6261 /***********************************************************************
6262 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6263 */
6264 BOOL WINAPI
6265 SetupDiRegisterCoDeviceInstallers(
6266 IN HDEVINFO DeviceInfoSet,
6267 IN PSP_DEVINFO_DATA DeviceInfoData)
6268 {
6269 BOOL ret = FALSE; /* Return value */
6270
6271 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6272
6273 if (!DeviceInfoSet)
6274 SetLastError(ERROR_INVALID_PARAMETER);
6275 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6276 SetLastError(ERROR_INVALID_HANDLE);
6277 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6278 SetLastError(ERROR_INVALID_HANDLE);
6279 else if (!DeviceInfoData)
6280 SetLastError(ERROR_INVALID_PARAMETER);
6281 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6282 SetLastError(ERROR_INVALID_USER_BUFFER);
6283 else
6284 {
6285 SP_DEVINSTALL_PARAMS_W InstallParams;
6286 struct DriverInfoElement *SelectedDriver;
6287 BOOL Result;
6288 DWORD DoAction;
6289 WCHAR SectionName[MAX_PATH];
6290 DWORD SectionNameLength = 0;
6291 HKEY hKey = INVALID_HANDLE_VALUE;
6292
6293 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6294 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6295 if (!Result)
6296 goto cleanup;
6297
6298 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
6299 if (SelectedDriver == NULL)
6300 {
6301 SetLastError(ERROR_NO_DRIVER_SELECTED);
6302 goto cleanup;
6303 }
6304
6305 /* Get .CoInstallers section name */
6306 Result = SetupDiGetActualSectionToInstallW(
6307 SelectedDriver->InfFileDetails->hInf,
6308 SelectedDriver->Details.SectionName,
6309 SectionName, MAX_PATH, &SectionNameLength, NULL);
6310 if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
6311 goto cleanup;
6312 wcscat(SectionName, L".CoInstallers");
6313
6314 /* Open/Create driver key information */
6315 #if _WIN32_WINNT >= 0x502
6316 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
6317 #else
6318 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
6319 #endif
6320 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
6321 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
6322 if (hKey == INVALID_HANDLE_VALUE)
6323 goto cleanup;
6324
6325 /* Install .CoInstallers section */
6326 DoAction = SPINST_REGISTRY;
6327 if (!(InstallParams.Flags & DI_NOFILECOPY))
6328 {
6329 DoAction |= SPINST_FILES;
6330 if (!InstallParams.InstallMsgHandler)
6331 {
6332 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
6333 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
6334 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6335 }
6336 }
6337 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6338 SelectedDriver->InfFileDetails->hInf, SectionName,
6339 DoAction, hKey, NULL, SP_COPY_NEWER,
6340 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6341 DeviceInfoSet, DeviceInfoData);
6342 if (!Result)
6343 goto cleanup;
6344
6345 ret = TRUE;
6346
6347 cleanup:
6348 if (hKey != INVALID_HANDLE_VALUE)
6349 RegCloseKey(hKey);
6350 }
6351
6352 TRACE("Returning %d\n", ret);
6353 return ret;
6354 }
6355
6356 /***********************************************************************
6357 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
6358 */
6359 BOOL WINAPI
6360 SetupDiInstallDeviceInterfaces(
6361 IN HDEVINFO DeviceInfoSet,
6362 IN PSP_DEVINFO_DATA DeviceInfoData)
6363 {
6364 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6365
6366 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
6367 //SetLastError(ERROR_GEN_FAILURE);
6368 //return FALSE;
6369 return TRUE;
6370 }
6371
6372 BOOL
6373 InfIsFromOEMLocation(
6374 IN PCWSTR FullName,
6375 OUT LPBOOL IsOEMLocation)
6376 {
6377 PWCHAR last;
6378
6379 last = strrchrW(FullName, '\\');
6380 if (!last)
6381 {
6382 /* No directory specified */
6383 *IsOEMLocation = FALSE;
6384 }
6385 else
6386 {
6387 WCHAR Windir[MAX_PATH];
6388 UINT ret;
6389
6390 ret = GetWindowsDirectory(Windir, MAX_PATH);
6391 if (ret == 0 || ret >= MAX_PATH)
6392 {
6393 SetLastError(ERROR_GEN_FAILURE);
6394 return FALSE;
6395 }
6396
6397 if (strncmpW(FullName, Windir, last - FullName) == 0)
6398 {
6399 /* The path is %SYSTEMROOT%\Inf */
6400 *IsOEMLocation = FALSE;
6401 }
6402 else
6403 {
6404 /* The file is in another place */
6405 *IsOEMLocation = TRUE;
6406 }
6407 }
6408 return TRUE;
6409 }
6410
6411 /***********************************************************************
6412 * SetupDiInstallDevice (SETUPAPI.@)
6413 */
6414 BOOL WINAPI
6415 SetupDiInstallDevice(
6416 IN HDEVINFO DeviceInfoSet,
6417 IN PSP_DEVINFO_DATA DeviceInfoData)
6418 {
6419 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6420 SP_DEVINSTALL_PARAMS_W InstallParams;
6421 struct DriverInfoElement *SelectedDriver;
6422 SYSTEMTIME DriverDate;
6423 WCHAR SectionName[MAX_PATH];
6424 WCHAR Buffer[32];
6425 DWORD SectionNameLength = 0;
6426 BOOL Result = FALSE;
6427 INFCONTEXT ContextService;
6428 INT Flags;
6429 ULONG DoAction;
6430 DWORD RequiredSize;
6431 LPCWSTR AssociatedService = NULL;
6432 LPWSTR pSectionName = NULL;
6433 WCHAR ClassName[MAX_CLASS_NAME_LEN];
6434 GUID ClassGuid;
6435 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
6436 BOOL RebootRequired = FALSE;
6437 HKEY hKey = INVALID_HANDLE_VALUE;
6438 HKEY hClassKey = INVALID_HANDLE_VALUE;
6439 BOOL NeedtoCopyFile;
6440 LARGE_INTEGER fullVersion;
6441 LONG rc;
6442 BOOL ret = FALSE; /* Return value */
6443
6444 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6445
6446 if (!DeviceInfoSet)
6447 SetLastError(ERROR_INVALID_PARAMETER);
6448 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6449 SetLastError(ERROR_INVALID_HANDLE);
6450 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6451 SetLastError(ERROR_INVALID_HANDLE);
6452 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6453 SetLastError(ERROR_INVALID_USER_BUFFER);
6454 else
6455 Result = TRUE;
6456
6457 if (!Result)
6458 {
6459 /* One parameter is bad */
6460 goto cleanup;
6461 }
6462
6463 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6464 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6465 if (!Result)
6466 goto cleanup;
6467
6468 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
6469 {
6470 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6471 goto cleanup;
6472 }
6473
6474 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
6475 if (SelectedDriver == NULL)
6476 {
6477 SetLastError(ERROR_NO_DRIVER_SELECTED);
6478 goto cleanup;
6479 }
6480
6481 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
6482
6483 Result = SetupDiGetActualSectionToInstallW(
6484 SelectedDriver->InfFileDetails->hInf,
6485 SelectedDriver->Details.SectionName,
6486 SectionName, MAX_PATH, &SectionNameLength, NULL);
6487 if (!Result || SectionNameLength > MAX_PATH - 9)
6488 goto cleanup;
6489 pSectionName = &SectionName[wcslen(SectionName)];
6490
6491 /* Get information from [Version] section */
6492 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
6493 goto cleanup;
6494 /* Format ClassGuid to a string */
6495 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
6496 goto cleanup;
6497 RequiredSize = lstrlenW(lpGuidString);
6498 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
6499 if (!lpFullGuidString)
6500 {
6501 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6502 goto cleanup;
6503 }
6504 lpFullGuidString[0] = '{';
6505 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
6506 lpFullGuidString[RequiredSize + 1] = '}';
6507 lpFullGuidString[RequiredSize + 2] = '\0';
6508
6509 /* Open/Create driver key information */
6510 #if _WIN32_WINNT >= 0x502
6511 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
6512 #else
6513 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
6514 #endif
6515 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
6516 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
6517 if (hKey == INVALID_HANDLE_VALUE)
6518 goto cleanup;
6519
6520 /* Install main section */
6521 DoAction = SPINST_REGISTRY;
6522 if (!(InstallParams.Flags & DI_NOFILECOPY))
6523 {
6524 DoAction |= SPINST_FILES;
6525 if (!InstallParams.InstallMsgHandler)
6526 {
6527 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
6528 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
6529 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6530 }
6531 }
6532 *pSectionName = '\0';
6533 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6534 SelectedDriver->InfFileDetails->hInf, SectionName,
6535 DoAction, hKey, NULL, SP_COPY_NEWER,
6536 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6537 DeviceInfoSet, DeviceInfoData);
6538 if (!Result)
6539 goto cleanup;
6540 if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
6541 {
6542 if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
6543 {
6544 /* Delete resources allocated by SetupInitDefaultQueueCallback */
6545 SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
6546 }
6547 }
6548 InstallParams.Flags |= DI_NOFILECOPY;
6549 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6550
6551 /* Write information to driver key */
6552 *pSectionName = UNICODE_NULL;
6553 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
6554 TRACE("Write information to driver key\n");
6555 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
6556 TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
6557 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
6558 TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
6559 TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
6560 TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
6561 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
6562 TRACE("ProviderName : '%S'\n", SelectedDriver->Info.ProviderName);
6563 swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
6564 rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
6565 if (rc == ERROR_SUCCESS)
6566 rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
6567 if (rc == ERROR_SUCCESS)
6568 rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
6569 if (rc == ERROR_SUCCESS)
6570 {
6571 swprintf(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
6572 rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
6573 }
6574 if (rc == ERROR_SUCCESS)
6575 rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
6576 if (rc == ERROR_SUCCESS)
6577 rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
6578 if (rc == ERROR_SUCCESS)
6579 rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
6580 if (rc == ERROR_SUCCESS)
6581 rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
6582 if (rc == ERROR_SUCCESS)
6583 rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
6584 if (rc != ERROR_SUCCESS)
6585 {
6586 SetLastError(rc);
6587 goto cleanup;
6588 }
6589 RegCloseKey(hKey);
6590 hKey = INVALID_HANDLE_VALUE;
6591
6592 /* FIXME: Process .LogConfigOverride section */
6593
6594 /* Install .Services section */
6595 wcscpy(pSectionName, L".Services");
6596 Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf, SectionName, NULL, &ContextService);
6597 while (Result)
6598 {
6599 LPWSTR ServiceName = NULL;
6600 LPWSTR ServiceSection = NULL;
6601
6602 Result = SetupGetStringFieldW(
6603 &ContextService,
6604 1, /* Field index */
6605 NULL, 0,
6606 &RequiredSize);
6607 if (!Result)
6608 goto nextfile;
6609 if (RequiredSize > 0)
6610 {
6611 /* We got the needed size for the buffer */
6612 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
6613 if (!ServiceName)
6614 {
6615 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6616 goto nextfile;
6617 }
6618 Result = SetupGetStringFieldW(
6619 &ContextService,
6620 1, /* Field index */
6621 ServiceName, RequiredSize,
6622 &RequiredSize);
6623 if (!Result)
6624 goto nextfile;
6625 }
6626 Result = SetupGetIntField(
6627 &ContextService,
6628 2, /* Field index */
6629 &Flags);
6630 if (!Result)
6631 {
6632 /* The field may be empty. Ignore the error */
6633 Flags = 0;
6634 }
6635 Result = SetupGetStringFieldW(
6636 &ContextService,
6637 3, /* Field index */
6638 NULL, 0,
6639 &RequiredSize);
6640 if (!Result)
6641 {
6642 if (GetLastError() == ERROR_INVALID_PARAMETER)
6643 {
6644 /* This first is probably missing. It is not
6645 * required, so ignore the error */
6646 RequiredSize = 0;
6647 Result = TRUE;
6648 }
6649 else
6650 goto nextfile;
6651 }
6652 if (RequiredSize > 0)
6653 {
6654 /* We got the needed size for the buffer */
6655 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
6656 if (!ServiceSection)
6657 {
6658 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6659 goto nextfile;
6660 }
6661 Result = SetupGetStringFieldW(
6662 &ContextService,
6663 3, /* Field index */
6664 ServiceSection, RequiredSize,
6665 &RequiredSize);
6666 if (!Result)
6667 goto nextfile;
6668
6669 SetLastError(ERROR_SUCCESS);
6670 Result = SetupInstallServicesFromInfSectionExW(
6671 SelectedDriver->InfFileDetails->hInf,
6672 ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
6673 }
6674 if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
6675 {
6676 AssociatedService = ServiceName;
6677 ServiceName = NULL;
6678 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
6679 RebootRequired = TRUE;
6680 }
6681 nextfile:
6682 HeapFree(GetProcessHeap(), 0, ServiceName);
6683 HeapFree(GetProcessHeap(), 0, ServiceSection);
6684 if (!Result)
6685 goto cleanup;
6686 Result = SetupFindNextLine(&ContextService, &ContextService);
6687 }
6688
6689 /* Copy .inf file to Inf\ directory (if needed) */
6690 Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
6691 if (!Result)
6692 goto cleanup;
6693 if (NeedtoCopyFile)
6694 {
6695 Result = SetupCopyOEMInfW(
6696 SelectedDriver->InfFileDetails->FullInfFileName,
6697 NULL,
6698 SPOST_NONE,
6699 SP_COPY_NOOVERWRITE,
6700 NULL, 0,
6701 NULL,
6702 NULL);
6703 if (!Result)
6704 goto cleanup;
6705 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6706 * to release use of current InfFile */
6707 }
6708
6709 /* Open device registry key */
6710 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
6711 if (hKey == INVALID_HANDLE_VALUE)
6712 goto cleanup;
6713
6714 /* Install .HW section */
6715 wcscpy(pSectionName, L".HW");
6716 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6717 SelectedDriver->InfFileDetails->hInf, SectionName,
6718 SPINST_REGISTRY, hKey, NULL, 0,
6719 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6720 DeviceInfoSet, DeviceInfoData);
6721 if (!Result)
6722 goto cleanup;
6723
6724 /* Write information to enum key */
6725 TRACE("Write information to enum key\n");
6726 TRACE("Class : '%S'\n", ClassName);
6727 TRACE("ClassGUID : '%S'\n", lpFullGuidString);
6728 TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
6729 TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
6730 TRACE("Service : '%S'\n", AssociatedService);
6731 rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
6732 if (rc == ERROR_SUCCESS)
6733 rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
6734 if (rc == ERROR_SUCCESS)
6735 rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
6736 if (rc == ERROR_SUCCESS)
6737 rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
6738 if (rc == ERROR_SUCCESS && *AssociatedService)
6739 rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
6740 if (rc != ERROR_SUCCESS)
6741 {
6742 SetLastError(rc);
6743 goto cleanup;
6744 }
6745
6746 /* Start the device */
6747 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
6748 {
6749 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
6750 NTSTATUS Status;
6751 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
6752 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
6753 ret = NT_SUCCESS(Status);
6754 }
6755 else
6756 ret = TRUE;
6757
6758 cleanup:
6759 /* End of installation */
6760 if (hClassKey != INVALID_HANDLE_VALUE)
6761 RegCloseKey(hClassKey);
6762 if (hKey != INVALID_HANDLE_VALUE)
6763 RegCloseKey(hKey);
6764 if (lpGuidString)
6765 RpcStringFreeW(&lpGuidString);
6766 HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
6767 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
6768
6769 TRACE("Returning %d\n", ret);
6770 return ret;
6771 }