Fix access rights when opening registry keys
[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
76 struct CoInstallerElement
77 {
78 LIST_ENTRY ListEntry;
79
80 HMODULE Module;
81 COINSTALLER_PROC Function;
82 BOOL DoPostProcessing;
83 PVOID PrivateData;
84 };
85
86 /***********************************************************************
87 * SetupDiBuildClassInfoList (SETUPAPI.@)
88 */
89 BOOL WINAPI SetupDiBuildClassInfoList(
90 DWORD Flags,
91 LPGUID ClassGuidList,
92 DWORD ClassGuidListSize,
93 PDWORD RequiredSize)
94 {
95 TRACE("\n");
96 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
97 ClassGuidListSize, RequiredSize,
98 NULL, NULL);
99 }
100
101 /***********************************************************************
102 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
103 */
104 BOOL WINAPI SetupDiBuildClassInfoListExA(
105 DWORD Flags,
106 LPGUID ClassGuidList,
107 DWORD ClassGuidListSize,
108 PDWORD RequiredSize,
109 LPCSTR MachineName,
110 PVOID Reserved)
111 {
112 LPWSTR MachineNameW = NULL;
113 BOOL bResult;
114
115 TRACE("\n");
116
117 if (MachineName)
118 {
119 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
120 if (MachineNameW == NULL) return FALSE;
121 }
122
123 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
124 ClassGuidListSize, RequiredSize,
125 MachineNameW, Reserved);
126
127 if (MachineNameW)
128 MyFree(MachineNameW);
129
130 return bResult;
131 }
132
133 /***********************************************************************
134 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
135 */
136 BOOL WINAPI SetupDiBuildClassInfoListExW(
137 DWORD Flags,
138 LPGUID ClassGuidList,
139 DWORD ClassGuidListSize,
140 PDWORD RequiredSize,
141 LPCWSTR MachineName,
142 PVOID Reserved)
143 {
144 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
145 HKEY hClassesKey;
146 HKEY hClassKey;
147 DWORD dwLength;
148 DWORD dwIndex;
149 LONG lError;
150 DWORD dwGuidListIndex = 0;
151
152 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
153 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
154
155 if (RequiredSize != NULL)
156 *RequiredSize = 0;
157
158 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
159 KEY_ENUMERATE_SUB_KEYS,
160 DIOCR_INSTALLER,
161 MachineName,
162 Reserved);
163 if (hClassesKey == INVALID_HANDLE_VALUE)
164 {
165 return FALSE;
166 }
167
168 for (dwIndex = 0; ; dwIndex++)
169 {
170 dwLength = MAX_GUID_STRING_LEN + 1;
171 lError = RegEnumKeyExW(hClassesKey,
172 dwIndex,
173 szKeyName,
174 &dwLength,
175 NULL,
176 NULL,
177 NULL,
178 NULL);
179 TRACE("RegEnumKeyExW() returns %ld\n", lError);
180 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
181 {
182 TRACE("Key name: %s\n", debugstr_w(szKeyName));
183
184 if (RegOpenKeyExW(hClassesKey,
185 szKeyName,
186 0,
187 KEY_QUERY_VALUE,
188 &hClassKey))
189 {
190 RegCloseKey(hClassesKey);
191 return FALSE;
192 }
193
194 if (!RegQueryValueExW(hClassKey,
195 NoUseClass,
196 NULL,
197 NULL,
198 NULL,
199 NULL))
200 {
201 TRACE("'NoUseClass' value found!\n");
202 RegCloseKey(hClassKey);
203 continue;
204 }
205
206 if ((Flags & DIBCI_NOINSTALLCLASS) &&
207 (!RegQueryValueExW(hClassKey,
208 NoInstallClass,
209 NULL,
210 NULL,
211 NULL,
212 NULL)))
213 {
214 TRACE("'NoInstallClass' value found!\n");
215 RegCloseKey(hClassKey);
216 continue;
217 }
218
219 if ((Flags & DIBCI_NODISPLAYCLASS) &&
220 (!RegQueryValueExW(hClassKey,
221 NoDisplayClass,
222 NULL,
223 NULL,
224 NULL,
225 NULL)))
226 {
227 TRACE("'NoDisplayClass' value found!\n");
228 RegCloseKey(hClassKey);
229 continue;
230 }
231
232 RegCloseKey(hClassKey);
233
234 TRACE("Guid: %s\n", debugstr_w(szKeyName));
235 if (dwGuidListIndex < ClassGuidListSize)
236 {
237 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
238 {
239 szKeyName[37] = 0;
240 }
241 TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
242
243 UuidFromStringW(&szKeyName[1],
244 &ClassGuidList[dwGuidListIndex]);
245 }
246
247 dwGuidListIndex++;
248 }
249
250 if (lError != ERROR_SUCCESS)
251 break;
252 }
253
254 RegCloseKey(hClassesKey);
255
256 if (RequiredSize != NULL)
257 *RequiredSize = dwGuidListIndex;
258
259 if (ClassGuidListSize < dwGuidListIndex)
260 {
261 SetLastError(ERROR_INSUFFICIENT_BUFFER);
262 return FALSE;
263 }
264
265 return TRUE;
266 }
267
268 /***********************************************************************
269 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
270 */
271 BOOL WINAPI SetupDiClassGuidsFromNameA(
272 LPCSTR ClassName,
273 LPGUID ClassGuidList,
274 DWORD ClassGuidListSize,
275 PDWORD RequiredSize)
276 {
277 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
278 ClassGuidListSize, RequiredSize,
279 NULL, NULL);
280 }
281
282 /***********************************************************************
283 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
284 */
285 BOOL WINAPI SetupDiClassGuidsFromNameW(
286 LPCWSTR ClassName,
287 LPGUID ClassGuidList,
288 DWORD ClassGuidListSize,
289 PDWORD RequiredSize)
290 {
291 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
292 ClassGuidListSize, RequiredSize,
293 NULL, NULL);
294 }
295
296 /***********************************************************************
297 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
298 */
299 BOOL WINAPI SetupDiClassGuidsFromNameExA(
300 LPCSTR ClassName,
301 LPGUID ClassGuidList,
302 DWORD ClassGuidListSize,
303 PDWORD RequiredSize,
304 LPCSTR MachineName,
305 PVOID Reserved)
306 {
307 LPWSTR ClassNameW = NULL;
308 LPWSTR MachineNameW = NULL;
309 BOOL bResult;
310
311 TRACE("\n");
312
313 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
314 if (ClassNameW == NULL)
315 return FALSE;
316
317 if (MachineNameW)
318 {
319 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
320 if (MachineNameW == NULL)
321 {
322 MyFree(ClassNameW);
323 return FALSE;
324 }
325 }
326
327 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
328 ClassGuidListSize, RequiredSize,
329 MachineNameW, Reserved);
330
331 if (MachineNameW)
332 MyFree(MachineNameW);
333
334 MyFree(ClassNameW);
335
336 return bResult;
337 }
338
339 /***********************************************************************
340 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
341 */
342 BOOL WINAPI SetupDiClassGuidsFromNameExW(
343 LPCWSTR ClassName,
344 LPGUID ClassGuidList,
345 DWORD ClassGuidListSize,
346 PDWORD RequiredSize,
347 LPCWSTR MachineName,
348 PVOID Reserved)
349 {
350 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
351 WCHAR szClassName[256];
352 HKEY hClassesKey;
353 HKEY hClassKey;
354 DWORD dwLength;
355 DWORD dwIndex;
356 LONG lError;
357 DWORD dwGuidListIndex = 0;
358
359 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
360 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
361
362 if (RequiredSize != NULL)
363 *RequiredSize = 0;
364
365 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
366 KEY_ENUMERATE_SUB_KEYS,
367 DIOCR_INSTALLER,
368 MachineName,
369 Reserved);
370 if (hClassesKey == INVALID_HANDLE_VALUE)
371 {
372 return FALSE;
373 }
374
375 for (dwIndex = 0; ; dwIndex++)
376 {
377 dwLength = MAX_GUID_STRING_LEN + 1;
378 lError = RegEnumKeyExW(hClassesKey,
379 dwIndex,
380 szKeyName,
381 &dwLength,
382 NULL,
383 NULL,
384 NULL,
385 NULL);
386 TRACE("RegEnumKeyExW() returns %ld\n", lError);
387 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
388 {
389 TRACE("Key name: %s\n", debugstr_w(szKeyName));
390
391 if (RegOpenKeyExW(hClassesKey,
392 szKeyName,
393 0,
394 KEY_QUERY_VALUE,
395 &hClassKey))
396 {
397 RegCloseKey(hClassesKey);
398 return FALSE;
399 }
400
401 dwLength = 256 * sizeof(WCHAR);
402 if (!RegQueryValueExW(hClassKey,
403 Class,
404 NULL,
405 NULL,
406 (LPBYTE)szClassName,
407 &dwLength))
408 {
409 TRACE("Class name: %s\n", debugstr_w(szClassName));
410
411 if (strcmpiW(szClassName, ClassName) == 0)
412 {
413 TRACE("Found matching class name\n");
414
415 TRACE("Guid: %s\n", debugstr_w(szKeyName));
416 if (dwGuidListIndex < ClassGuidListSize)
417 {
418 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
419 {
420 szKeyName[37] = 0;
421 }
422 TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
423
424 UuidFromStringW(&szKeyName[1],
425 &ClassGuidList[dwGuidListIndex]);
426 }
427
428 dwGuidListIndex++;
429 }
430 }
431
432 RegCloseKey(hClassKey);
433 }
434
435 if (lError != ERROR_SUCCESS)
436 break;
437 }
438
439 RegCloseKey(hClassesKey);
440
441 if (RequiredSize != NULL)
442 *RequiredSize = dwGuidListIndex;
443
444 if (ClassGuidListSize < dwGuidListIndex)
445 {
446 SetLastError(ERROR_INSUFFICIENT_BUFFER);
447 return FALSE;
448 }
449
450 return TRUE;
451 }
452
453 /***********************************************************************
454 * SetupDiClassNameFromGuidA (SETUPAPI.@)
455 */
456 BOOL WINAPI SetupDiClassNameFromGuidA(
457 const GUID* ClassGuid,
458 PSTR ClassName,
459 DWORD ClassNameSize,
460 PDWORD RequiredSize)
461 {
462 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
463 ClassNameSize, RequiredSize,
464 NULL, NULL);
465 }
466
467 /***********************************************************************
468 * SetupDiClassNameFromGuidW (SETUPAPI.@)
469 */
470 BOOL WINAPI SetupDiClassNameFromGuidW(
471 const GUID* ClassGuid,
472 PWSTR ClassName,
473 DWORD ClassNameSize,
474 PDWORD RequiredSize)
475 {
476 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
477 ClassNameSize, RequiredSize,
478 NULL, NULL);
479 }
480
481 /***********************************************************************
482 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
483 */
484 BOOL WINAPI SetupDiClassNameFromGuidExA(
485 const GUID* ClassGuid,
486 PSTR ClassName,
487 DWORD ClassNameSize,
488 PDWORD RequiredSize,
489 PCSTR MachineName,
490 PVOID Reserved)
491 {
492 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
493 LPWSTR MachineNameW = NULL;
494 BOOL ret;
495
496 if (MachineName)
497 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
498 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
499 NULL, MachineNameW, Reserved);
500 if (ret)
501 {
502 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
503 ClassNameSize, NULL, NULL);
504
505 if (!ClassNameSize && RequiredSize)
506 *RequiredSize = len;
507 }
508 MyFree(MachineNameW);
509 return ret;
510 }
511
512 /***********************************************************************
513 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
514 */
515 BOOL WINAPI SetupDiClassNameFromGuidExW(
516 const GUID* ClassGuid,
517 PWSTR ClassName,
518 DWORD ClassNameSize,
519 PDWORD RequiredSize,
520 PCWSTR MachineName,
521 PVOID Reserved)
522 {
523 HKEY hKey;
524 DWORD dwLength;
525 LONG rc;
526
527 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
528 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
529
530 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
531 KEY_QUERY_VALUE,
532 DIOCR_INSTALLER,
533 MachineName,
534 Reserved);
535 if (hKey == INVALID_HANDLE_VALUE)
536 {
537 return FALSE;
538 }
539
540 if (RequiredSize != NULL)
541 {
542 dwLength = 0;
543 rc = RegQueryValueExW(hKey,
544 Class,
545 NULL,
546 NULL,
547 NULL,
548 &dwLength);
549 if (rc != ERROR_SUCCESS)
550 {
551 SetLastError(rc);
552 RegCloseKey(hKey);
553 return FALSE;
554 }
555
556 *RequiredSize = dwLength / sizeof(WCHAR);
557 }
558
559 dwLength = ClassNameSize * sizeof(WCHAR);
560 rc = RegQueryValueExW(hKey,
561 Class,
562 NULL,
563 NULL,
564 (LPBYTE)ClassName,
565 &dwLength);
566 if (rc != ERROR_SUCCESS)
567 {
568 SetLastError(rc);
569 RegCloseKey(hKey);
570 return FALSE;
571 }
572
573 RegCloseKey(hKey);
574
575 return TRUE;
576 }
577
578 /***********************************************************************
579 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
580 */
581 HDEVINFO WINAPI
582 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
583 HWND hwndParent)
584 {
585 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
586 }
587
588 /***********************************************************************
589 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
590 */
591 HDEVINFO WINAPI
592 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
593 HWND hwndParent,
594 PCSTR MachineName,
595 PVOID Reserved)
596 {
597 LPWSTR MachineNameW = NULL;
598 HDEVINFO hDevInfo;
599
600 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
601 debugstr_a(MachineName), Reserved);
602
603 if (MachineName)
604 {
605 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
606 if (MachineNameW == NULL)
607 return (HDEVINFO)INVALID_HANDLE_VALUE;
608 }
609
610 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
611 MachineNameW, Reserved);
612
613 if (MachineNameW)
614 MyFree(MachineNameW);
615
616 return hDevInfo;
617 }
618
619 /***********************************************************************
620 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
621 */
622 HDEVINFO WINAPI
623 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
624 HWND hwndParent,
625 PCWSTR MachineName,
626 PVOID Reserved)
627 {
628 struct DeviceInfoSet *list;
629 LPWSTR UNCServerName = NULL;
630 DWORD rc;
631 //CONFIGRET cr;
632 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
633
634 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
635 debugstr_w(MachineName), Reserved);
636
637 list = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet));
638 if (!list)
639 {
640 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
641 goto cleanup;
642 }
643 memset(list, 0, sizeof(struct DeviceInfoSet));
644
645 list->magic = SETUP_DEV_INFO_SET_MAGIC;
646 memcpy(
647 &list->ClassGuid,
648 ClassGuid ? ClassGuid : &GUID_NULL,
649 sizeof(list->ClassGuid));
650 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
651 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
652 list->InstallParams.hwndParent = hwndParent;
653 if (MachineName)
654 {
655 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
656 if (rc != ERROR_SUCCESS)
657 {
658 SetLastError(rc);
659 goto cleanup;
660 }
661 UNCServerName = HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName) + 3) * sizeof(WCHAR));
662 if (!UNCServerName)
663 {
664 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
665 goto cleanup;
666 }
667
668 strcpyW(UNCServerName + 2, MachineName);
669 }
670 else
671 {
672 DWORD Size = MAX_PATH;
673 list->HKLM = HKEY_LOCAL_MACHINE;
674 UNCServerName = HeapAlloc(GetProcessHeap(), 0, (MAX_PATH + 2) * sizeof(WCHAR));
675 if (!UNCServerName)
676 {
677 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
678 goto cleanup;
679 }
680 if (!GetComputerNameW(UNCServerName + 2, &Size))
681 goto cleanup;
682 }
683 #if 0
684 UNCServerName[0] = UNCServerName[1] = '\\';
685 cr = CM_Connect_MachineW(UNCServerName, &list->hMachine);
686 if (cr != CR_SUCCESS)
687 {
688 switch (cr)
689 {
690 case CR_OUT_OF_MEMORY: rc = ERROR_NOT_ENOUGH_MEMORY; break;
691 case CR_INVALID_MACHINENAME: rc = ERROR_INVALID_COMPUTERNAME; break;
692 default: rc = ERROR_GEN_FAILURE; break;
693 }
694 SetLastError(rc);
695 goto cleanup;
696 }
697 #endif
698 InitializeListHead(&list->DriverListHead);
699 InitializeListHead(&list->ListHead);
700
701 ret = (HDEVINFO)list;
702
703 cleanup:
704 if (ret == INVALID_HANDLE_VALUE)
705 {
706 if (list && list->HKLM != 0 && list->HKLM != HKEY_LOCAL_MACHINE)
707 RegCloseKey(list->HKLM);
708 HeapFree(GetProcessHeap(), 0, list);
709 }
710 HeapFree(GetProcessHeap(), 0, UNCServerName);
711 return ret;
712 }
713
714 /***********************************************************************
715 * SetupDiEnumDeviceInfo (SETUPAPI.@)
716 */
717 BOOL WINAPI SetupDiEnumDeviceInfo(
718 HDEVINFO DeviceInfoSet,
719 DWORD MemberIndex,
720 PSP_DEVINFO_DATA DeviceInfoData)
721 {
722 BOOL ret = FALSE;
723
724 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
725 if (!DeviceInfoData)
726 SetLastError(ERROR_INVALID_PARAMETER);
727 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
728 {
729 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
730
731 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
732 SetLastError(ERROR_INVALID_HANDLE);
733 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
734 SetLastError(ERROR_INVALID_USER_BUFFER);
735 else
736 {
737 PLIST_ENTRY ItemList = list->ListHead.Flink;
738 while (ItemList != &list->ListHead && MemberIndex-- > 0)
739 ItemList = ItemList->Flink;
740 if (ItemList == &list->ListHead)
741 SetLastError(ERROR_NO_MORE_ITEMS);
742 else
743 {
744 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
745 memcpy(&DeviceInfoData->ClassGuid,
746 &DevInfo->ClassGuid,
747 sizeof(GUID));
748 DeviceInfoData->DevInst = (DWORD)list->hMachine;
749 DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
750 ret = TRUE;
751 }
752 }
753 }
754 else
755 SetLastError(ERROR_INVALID_HANDLE);
756 return ret;
757 }
758
759 /***********************************************************************
760 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
761 */
762 BOOL WINAPI SetupDiGetActualSectionToInstallA(
763 HINF InfHandle,
764 PCSTR InfSectionName,
765 PSTR InfSectionWithExt,
766 DWORD InfSectionWithExtSize,
767 PDWORD RequiredSize,
768 PSTR *Extension)
769 {
770 LPWSTR InfSectionNameW = NULL;
771 PWSTR InfSectionWithExtW = NULL;
772 PWSTR ExtensionW;
773 BOOL bResult = FALSE;
774
775 TRACE("\n");
776
777 if (InfSectionName)
778 {
779 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
780 if (InfSectionNameW == NULL) goto end;
781 }
782 if (InfSectionWithExt)
783 {
784 InfSectionWithExtW = HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize * sizeof(WCHAR));
785 if (InfSectionWithExtW == NULL) goto end;
786 }
787
788 bResult = SetupDiGetActualSectionToInstallW(InfHandle, InfSectionNameW,
789 InfSectionWithExt ? InfSectionNameW : NULL,
790 InfSectionWithExtSize, RequiredSize,
791 Extension ? &ExtensionW : NULL);
792
793 if (bResult && InfSectionWithExt)
794 {
795 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
796 InfSectionWithExtSize, NULL, NULL) != 0;
797 }
798 if (bResult && Extension)
799 {
800 if (ExtensionW == NULL)
801 *Extension = NULL;
802 else
803 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
804 }
805
806 end:
807 if (InfSectionNameW) MyFree(InfSectionNameW);
808 if (InfSectionWithExtW) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW);
809
810 return bResult;
811 }
812
813 /***********************************************************************
814 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
815 */
816 BOOL WINAPI SetupDiGetActualSectionToInstallW(
817 HINF InfHandle,
818 PCWSTR InfSectionName,
819 PWSTR InfSectionWithExt,
820 DWORD InfSectionWithExtSize,
821 PDWORD RequiredSize,
822 PWSTR *Extension)
823 {
824 WCHAR szBuffer[MAX_PATH];
825 DWORD dwLength;
826 DWORD dwFullLength;
827 LONG lLineCount = -1;
828
829 TRACE("%p %s %p %lu %p %p\n", InfHandle, debugstr_w(InfSectionName),
830 InfSectionWithExt, InfSectionWithExtSize, RequiredSize, Extension);
831
832 lstrcpyW(szBuffer, InfSectionName);
833 dwLength = lstrlenW(szBuffer);
834
835 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
836 {
837 /* Test section name with '.NTx86' extension */
838 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
839 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
840
841 if (lLineCount == -1)
842 {
843 /* Test section name with '.NT' extension */
844 lstrcpyW(&szBuffer[dwLength], NtExtension);
845 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
846 }
847 }
848 else
849 {
850 /* Test section name with '.Win' extension */
851 lstrcpyW(&szBuffer[dwLength], WinExtension);
852 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
853 }
854
855 if (lLineCount == -1)
856 {
857 /* Test section name without extension */
858 szBuffer[dwLength] = 0;
859 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
860 }
861
862 if (lLineCount == -1)
863 {
864 SetLastError(ERROR_INVALID_PARAMETER);
865 return FALSE;
866 }
867
868 dwFullLength = lstrlenW(szBuffer);
869
870 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
871 {
872 if (InfSectionWithExtSize < (dwFullLength + 1))
873 {
874 SetLastError(ERROR_INSUFFICIENT_BUFFER);
875 return FALSE;
876 }
877
878 lstrcpyW(InfSectionWithExt, szBuffer);
879 if (Extension != NULL)
880 {
881 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
882 }
883 }
884
885 if (RequiredSize != NULL)
886 {
887 *RequiredSize = dwFullLength + 1;
888 }
889
890 return TRUE;
891 }
892
893 /***********************************************************************
894 * SetupDiGetClassDescriptionA (SETUPAPI.@)
895 */
896 BOOL WINAPI SetupDiGetClassDescriptionA(
897 const GUID* ClassGuid,
898 PSTR ClassDescription,
899 DWORD ClassDescriptionSize,
900 PDWORD RequiredSize)
901 {
902 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
903 ClassDescriptionSize,
904 RequiredSize, NULL, NULL);
905 }
906
907 /***********************************************************************
908 * SetupDiGetClassDescriptionW (SETUPAPI.@)
909 */
910 BOOL WINAPI SetupDiGetClassDescriptionW(
911 const GUID* ClassGuid,
912 PWSTR ClassDescription,
913 DWORD ClassDescriptionSize,
914 PDWORD RequiredSize)
915 {
916 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
917 ClassDescriptionSize,
918 RequiredSize, NULL, NULL);
919 }
920
921 /***********************************************************************
922 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
923 */
924 BOOL WINAPI SetupDiGetClassDescriptionExA(
925 const GUID* ClassGuid,
926 PSTR ClassDescription,
927 DWORD ClassDescriptionSize,
928 PDWORD RequiredSize,
929 PCSTR MachineName,
930 PVOID Reserved)
931 {
932 PWCHAR ClassDescriptionW;
933 LPWSTR MachineNameW = NULL;
934 BOOL ret;
935
936 TRACE("\n");
937 if (ClassDescriptionSize > 0)
938 {
939 ClassDescriptionW = HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize * sizeof(WCHAR));
940 if (!ClassDescriptionW)
941 {
942 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
943 ret = FALSE;
944 goto end;
945 }
946 }
947 else
948 ClassDescriptionW = NULL;
949
950 if (MachineName)
951 {
952 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
953 if (!MachineNameW)
954 {
955 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
956 ret = FALSE;
957 goto end;
958 }
959 }
960
961 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, ClassDescriptionSize * sizeof(WCHAR),
962 NULL, MachineNameW, Reserved);
963 if (ret)
964 {
965 int len = WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
966 ClassDescriptionSize, NULL, NULL);
967
968 if (!ClassDescriptionSize && RequiredSize)
969 *RequiredSize = len;
970 }
971
972 end:
973 HeapFree(GetProcessHeap(), 0, ClassDescriptionW);
974 MyFree(MachineNameW);
975 return ret;
976 }
977
978 /***********************************************************************
979 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
980 */
981 BOOL WINAPI SetupDiGetClassDescriptionExW(
982 const GUID* ClassGuid,
983 PWSTR ClassDescription,
984 DWORD ClassDescriptionSize,
985 PDWORD RequiredSize,
986 PCWSTR MachineName,
987 PVOID Reserved)
988 {
989 HKEY hKey;
990 DWORD dwLength;
991
992 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
993 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
994
995 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
996 KEY_QUERY_VALUE,
997 DIOCR_INSTALLER,
998 MachineName,
999 Reserved);
1000 if (hKey == INVALID_HANDLE_VALUE)
1001 {
1002 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1003 return FALSE;
1004 }
1005
1006 if (RequiredSize != NULL)
1007 {
1008 dwLength = 0;
1009 if (RegQueryValueExW(hKey,
1010 NULL,
1011 NULL,
1012 NULL,
1013 NULL,
1014 &dwLength))
1015 {
1016 RegCloseKey(hKey);
1017 return FALSE;
1018 }
1019
1020 *RequiredSize = dwLength / sizeof(WCHAR);
1021 }
1022
1023 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1024 if (RegQueryValueExW(hKey,
1025 NULL,
1026 NULL,
1027 NULL,
1028 (LPBYTE)ClassDescription,
1029 &dwLength))
1030 {
1031 RegCloseKey(hKey);
1032 return FALSE;
1033 }
1034
1035 RegCloseKey(hKey);
1036
1037 return TRUE;
1038 }
1039
1040 /***********************************************************************
1041 * SetupDiGetClassDevsA (SETUPAPI.@)
1042 */
1043 HDEVINFO WINAPI SetupDiGetClassDevsA(
1044 CONST GUID *class,
1045 LPCSTR enumstr,
1046 HWND parent,
1047 DWORD flags)
1048 {
1049 return SetupDiGetClassDevsExA(class, enumstr, parent,
1050 flags, NULL, NULL, NULL);
1051 }
1052
1053 /***********************************************************************
1054 * SetupDiGetClassDevsW (SETUPAPI.@)
1055 */
1056 HDEVINFO WINAPI SetupDiGetClassDevsW(
1057 CONST GUID *class,
1058 LPCWSTR enumstr,
1059 HWND parent,
1060 DWORD flags)
1061 {
1062 return SetupDiGetClassDevsExW(class, enumstr, parent,
1063 flags, NULL, NULL, NULL);
1064 }
1065
1066 /***********************************************************************
1067 * SetupDiGetClassDevsExA (SETUPAPI.@)
1068 */
1069 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1070 CONST GUID *class,
1071 LPCSTR enumstr,
1072 HWND parent,
1073 DWORD flags,
1074 HDEVINFO deviceset,
1075 LPCSTR machine,
1076 PVOID reserved)
1077 {
1078 HDEVINFO ret;
1079 LPWSTR enumstrW = NULL;
1080 LPWSTR machineW = NULL;
1081
1082 if (enumstr)
1083 {
1084 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1085 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1086 if (!enumstrW)
1087 {
1088 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1089 goto end;
1090 }
1091 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1092 }
1093 if (machine)
1094 {
1095 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1096 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1097 if (!machineW)
1098 {
1099 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1100 goto end;
1101 }
1102 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1103 }
1104 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, machineW, reserved);
1105
1106 end:
1107 HeapFree(GetProcessHeap(), 0, enumstrW);
1108 HeapFree(GetProcessHeap(), 0, machineW);
1109 return ret;
1110 }
1111
1112 static BOOL
1113 CreateDeviceInfoElement(
1114 IN LPCWSTR InstancePath,
1115 IN LPCGUID pClassGuid,
1116 OUT struct DeviceInfoElement **pDeviceInfo)
1117 {
1118 DWORD size;
1119 struct DeviceInfoElement *deviceInfo;
1120
1121 *pDeviceInfo = NULL;
1122
1123 size = sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
1124 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
1125 if (!deviceInfo)
1126 {
1127 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1128 return FALSE;
1129 }
1130 memset(deviceInfo, 0, size);
1131 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1132 wcscpy(deviceInfo->Data, InstancePath);
1133 deviceInfo->DeviceName = deviceInfo->Data;
1134 deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
1135 deviceInfo->DeviceDescription = NULL;
1136 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
1137 deviceInfo->CreationFlags = 0;
1138 InitializeListHead(&deviceInfo->DriverListHead);
1139 InitializeListHead(&deviceInfo->InterfaceListHead);
1140
1141 *pDeviceInfo = deviceInfo;
1142 return TRUE;
1143 }
1144
1145 static BOOL
1146 CreateDeviceInterface(
1147 IN struct DeviceInfoElement* deviceInfo,
1148 IN LPCWSTR SymbolicLink,
1149 IN LPCGUID pInterfaceGuid,
1150 OUT struct DeviceInterface **pDeviceInterface)
1151 {
1152 struct DeviceInterface *deviceInterface;
1153
1154 *pDeviceInterface = NULL;
1155
1156 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
1157 if (!deviceInterface)
1158 {
1159 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1160 return FALSE;
1161 }
1162 deviceInterface->DeviceInfo = deviceInfo;
1163 wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
1164 deviceInterface->Flags = 0; /* FIXME */
1165 memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
1166
1167 *pDeviceInterface = deviceInterface;
1168 return TRUE;
1169 }
1170
1171 static LONG SETUP_CreateDevListFromEnumerator(
1172 struct DeviceInfoSet *list,
1173 LPCGUID pClassGuid OPTIONAL,
1174 LPCWSTR Enumerator,
1175 HKEY hEnumeratorKey) /* handle to Enumerator registry key */
1176 {
1177 HKEY hDeviceIdKey, hInstanceIdKey;
1178 WCHAR KeyBuffer[MAX_PATH];
1179 WCHAR InstancePath[MAX_PATH];
1180 LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
1181 struct DeviceInfoElement *deviceInfo;
1182 DWORD i = 0, j;
1183 DWORD dwLength, dwRegType;
1184 DWORD rc;
1185
1186 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1187 while (TRUE)
1188 {
1189 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1190 rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1191 if (rc == ERROR_NO_MORE_ITEMS)
1192 break;
1193 if (rc != ERROR_SUCCESS)
1194 return rc;
1195 i++;
1196
1197 /* Open device id sub key */
1198 rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
1199 if (rc != ERROR_SUCCESS)
1200 return rc;
1201 wcscpy(InstancePath, Enumerator);
1202 wcscat(InstancePath, L"\\");
1203 wcscat(InstancePath, KeyBuffer);
1204 wcscat(InstancePath, L"\\");
1205 pEndOfInstancePath = &InstancePath[wcslen(InstancePath)];
1206
1207 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1208 j = 0;
1209 while (TRUE)
1210 {
1211 GUID KeyGuid;
1212
1213 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1214 rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1215 if (rc == ERROR_NO_MORE_ITEMS)
1216 break;
1217 if (rc != ERROR_SUCCESS)
1218 {
1219 RegCloseKey(hDeviceIdKey);
1220 return rc;
1221 }
1222 j++;
1223
1224 /* Open instance id sub key */
1225 rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
1226 if (rc != ERROR_SUCCESS)
1227 {
1228 RegCloseKey(hDeviceIdKey);
1229 return rc;
1230 }
1231 *pEndOfInstancePath = '\0';
1232 wcscat(InstancePath, KeyBuffer);
1233
1234 /* Read ClassGUID value */
1235 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1236 rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength);
1237 RegCloseKey(hInstanceIdKey);
1238 if (rc == ERROR_FILE_NOT_FOUND)
1239 {
1240 if (pClassGuid)
1241 /* Skip this bad entry as we can't verify it */
1242 continue;
1243 /* Set a default GUID for this device */
1244 memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
1245 }
1246 else if (rc != ERROR_SUCCESS)
1247 {
1248 RegCloseKey(hDeviceIdKey);
1249 return rc;
1250 }
1251 else if (dwRegType != REG_SZ)
1252 {
1253 RegCloseKey(hDeviceIdKey);
1254 return ERROR_GEN_FAILURE;
1255 }
1256 else
1257 {
1258 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1259 if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
1260 /* Bad GUID, skip the entry */
1261 continue;
1262 }
1263
1264 if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
1265 {
1266 /* Skip this entry as it is not the right device class */
1267 continue;
1268 }
1269
1270 /* Add the entry to the list */
1271 if (!CreateDeviceInfoElement(InstancePath, &KeyGuid, &deviceInfo))
1272 {
1273 RegCloseKey(hDeviceIdKey);
1274 return GetLastError();
1275 }
1276 TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
1277 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1278 }
1279 RegCloseKey(hDeviceIdKey);
1280 }
1281
1282 return ERROR_SUCCESS;
1283 }
1284
1285 static LONG SETUP_CreateDevList(
1286 struct DeviceInfoSet *list,
1287 PCWSTR MachineName OPTIONAL,
1288 LPGUID class OPTIONAL,
1289 PCWSTR Enumerator OPTIONAL)
1290 {
1291 HKEY HKLM, hEnumKey, hEnumeratorKey;
1292 WCHAR KeyBuffer[MAX_PATH];
1293 DWORD i;
1294 DWORD dwLength;
1295 DWORD rc;
1296
1297 if (class && IsEqualIID(class, &GUID_NULL))
1298 class = NULL;
1299
1300 /* Open Enum key */
1301 if (MachineName != NULL)
1302 {
1303 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
1304 if (rc != ERROR_SUCCESS)
1305 return rc;
1306 }
1307 else
1308 HKLM = HKEY_LOCAL_MACHINE;
1309
1310 rc = RegOpenKeyExW(HKLM,
1311 EnumKeyName,
1312 0,
1313 KEY_ENUMERATE_SUB_KEYS,
1314 &hEnumKey);
1315 if (MachineName != NULL) RegCloseKey(HKLM);
1316 if (rc != ERROR_SUCCESS)
1317 return rc;
1318
1319 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1320 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1321 * for each one.
1322 */
1323 if (Enumerator)
1324 {
1325 rc = RegOpenKeyExW(
1326 hEnumKey,
1327 Enumerator,
1328 0,
1329 KEY_ENUMERATE_SUB_KEYS,
1330 &hEnumeratorKey);
1331 RegCloseKey(hEnumKey);
1332 if (rc != ERROR_SUCCESS)
1333 return rc;
1334 rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey);
1335 RegCloseKey(hEnumeratorKey);
1336 return rc;
1337 }
1338 else
1339 {
1340 /* Enumerate enumerators */
1341 i = 0;
1342 while (TRUE)
1343 {
1344 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1345 rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1346 if (rc == ERROR_NO_MORE_ITEMS)
1347 break;
1348 if (rc != ERROR_SUCCESS)
1349 {
1350 RegCloseKey(hEnumKey);
1351 return rc;
1352 }
1353 i++;
1354
1355 /* Open sub key */
1356 rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
1357 if (rc != ERROR_SUCCESS)
1358 {
1359 RegCloseKey(hEnumKey);
1360 return rc;
1361 }
1362
1363 /* Call SETUP_CreateDevListFromEnumerator */
1364 rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey);
1365 RegCloseKey(hEnumeratorKey);
1366 if (rc != ERROR_SUCCESS)
1367 {
1368 RegCloseKey(hEnumKey);
1369 return rc;
1370 }
1371 }
1372 RegCloseKey(hEnumKey);
1373 return ERROR_SUCCESS;
1374 }
1375 }
1376
1377 #ifndef __REACTOS__
1378 static LONG SETUP_CreateSerialDeviceList(
1379 struct DeviceInfoSet *list,
1380 PCWSTR MachineName,
1381 LPGUID InterfaceGuid,
1382 PCWSTR DeviceInstanceW)
1383 {
1384 static const size_t initialSize = 100;
1385 size_t size;
1386 WCHAR buf[initialSize];
1387 LPWSTR devices;
1388 static const WCHAR devicePrefixW[] = { 'C','O','M',0 };
1389 LPWSTR ptr;
1390 struct DeviceInfoElement *deviceInfo;
1391
1392 if (MachineName)
1393 WARN("'MachineName' is ignored on Wine!\n");
1394 if (DeviceInstanceW)
1395 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1396
1397 devices = buf;
1398 size = initialSize;
1399 while (TRUE)
1400 {
1401 if (QueryDosDeviceW(NULL, devices, size) != 0)
1402 break;
1403 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1404 {
1405 size *= 2;
1406 if (devices != buf)
1407 HeapFree(GetProcessHeap(), 0, devices);
1408 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1409 if (!devices)
1410 return ERROR_NOT_ENOUGH_MEMORY;
1411 *devices = '\0';
1412 }
1413 else
1414 {
1415 if (devices != buf)
1416 HeapFree(GetProcessHeap(), 0, devices);
1417 return GetLastError();
1418 }
1419 }
1420
1421 /* 'devices' is a MULTI_SZ string */
1422 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
1423 {
1424 if (strncmpW(devicePrefixW, ptr, sizeof(devicePrefixW) / sizeof(devicePrefixW[0]) - 1) == 0)
1425 {
1426 /* We have found a device */
1427 struct DeviceInterface *interfaceInfo;
1428 TRACE("Adding %s to list\n", debugstr_w(ptr));
1429 /* Step 1. Create a device info element */
1430 if (!CreateDeviceInfoElement(ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
1431 {
1432 if (devices != buf)
1433 HeapFree(GetProcessHeap(), 0, devices);
1434 return GetLastError();
1435 }
1436 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1437
1438 /* Step 2. Create an interface list for this element */
1439 if (!CreateDeviceInterface(deviceInfo, ptr, InterfaceGuid, &interfaceInfo))
1440 {
1441 if (devices != buf)
1442 HeapFree(GetProcessHeap(), 0, devices);
1443 return GetLastError();
1444 }
1445 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1446 }
1447 }
1448 if (devices != buf)
1449 HeapFree(GetProcessHeap(), 0, devices);
1450 return ERROR_SUCCESS;
1451 }
1452
1453 #else /* __REACTOS__ */
1454
1455 static LONG SETUP_CreateInterfaceList(
1456 struct DeviceInfoSet *list,
1457 PCWSTR MachineName,
1458 LPGUID InterfaceGuid,
1459 PCWSTR DeviceInstanceW /* OPTIONAL */)
1460 {
1461 HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1462 HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1463 HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1464 HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1465 HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1466 LONG rc;
1467 WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
1468 PWSTR InstancePath;
1469 DWORD i, j;
1470 DWORD dwLength, dwInstancePathLength;
1471 DWORD dwRegType;
1472 GUID ClassGuid;
1473 struct DeviceInfoElement *deviceInfo;
1474
1475 /* Open registry key related to this interface */
1476 hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
1477 if (hInterfaceKey == INVALID_HANDLE_VALUE)
1478 return GetLastError();
1479
1480 /* Enumerate sub keys of hInterfaceKey */
1481 i = 0;
1482 while (TRUE)
1483 {
1484 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1485 rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1486 if (rc == ERROR_NO_MORE_ITEMS)
1487 break;
1488 if (rc != ERROR_SUCCESS)
1489 {
1490 RegCloseKey(hInterfaceKey);
1491 return rc;
1492 }
1493 i++;
1494
1495 /* Open sub key */
1496 rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
1497 if (rc != ERROR_SUCCESS)
1498 {
1499 RegCloseKey(hInterfaceKey);
1500 return rc;
1501 }
1502
1503 /* Read DeviceInstance */
1504 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
1505 if (rc != ERROR_SUCCESS )
1506 {
1507 RegCloseKey(hDeviceInstanceKey);
1508 RegCloseKey(hInterfaceKey);
1509 return rc;
1510 }
1511 if (dwRegType != REG_SZ)
1512 {
1513 RegCloseKey(hDeviceInstanceKey);
1514 RegCloseKey(hInterfaceKey);
1515 return ERROR_GEN_FAILURE;
1516 }
1517 InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
1518 if (!InstancePath)
1519 {
1520 RegCloseKey(hDeviceInstanceKey);
1521 RegCloseKey(hInterfaceKey);
1522 return ERROR_NOT_ENOUGH_MEMORY;
1523 }
1524 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
1525 if (rc != ERROR_SUCCESS)
1526 {
1527 HeapFree(GetProcessHeap(), 0, InstancePath);
1528 RegCloseKey(hDeviceInstanceKey);
1529 RegCloseKey(hInterfaceKey);
1530 return rc;
1531 }
1532 InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
1533 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
1534
1535 if (DeviceInstanceW)
1536 {
1537 /* Check if device enumerator is not the right one */
1538 if (wcscmp(DeviceInstanceW, InstancePath) != 0)
1539 {
1540 HeapFree(GetProcessHeap(), 0, InstancePath);
1541 RegCloseKey(hDeviceInstanceKey);
1542 continue;
1543 }
1544 }
1545
1546 /* Find class GUID associated to the device instance */
1547 rc = RegOpenKeyExW(
1548 HKEY_LOCAL_MACHINE,
1549 EnumKeyName,
1550 0, /* Options */
1551 KEY_ENUMERATE_SUB_KEYS,
1552 &hEnumKey);
1553 if (rc != ERROR_SUCCESS)
1554 {
1555 HeapFree(GetProcessHeap(), 0, InstancePath);
1556 RegCloseKey(hDeviceInstanceKey);
1557 RegCloseKey(hInterfaceKey);
1558 return rc;
1559 }
1560 rc = RegOpenKeyExW(
1561 hEnumKey,
1562 InstancePath,
1563 0, /* Options */
1564 KEY_QUERY_VALUE,
1565 &hKey);
1566 RegCloseKey(hEnumKey);
1567 if (rc != ERROR_SUCCESS)
1568 {
1569 HeapFree(GetProcessHeap(), 0, InstancePath);
1570 RegCloseKey(hDeviceInstanceKey);
1571 RegCloseKey(hInterfaceKey);
1572 return rc;
1573 }
1574 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1575 rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1576 RegCloseKey(hKey);
1577 if (rc != ERROR_SUCCESS)
1578 {
1579 HeapFree(GetProcessHeap(), 0, InstancePath);
1580 RegCloseKey(hDeviceInstanceKey);
1581 RegCloseKey(hInterfaceKey);
1582 return rc;
1583 }
1584 KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
1585 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1586 if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
1587 {
1588 HeapFree(GetProcessHeap(), 0, InstancePath);
1589 RegCloseKey(hDeviceInstanceKey);
1590 RegCloseKey(hInterfaceKey);
1591 return ERROR_GEN_FAILURE;
1592 }
1593 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
1594
1595 /* If current device doesn't match the list GUID (if any), skip this entry */
1596 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
1597 {
1598 HeapFree(GetProcessHeap(), 0, InstancePath);
1599 RegCloseKey(hDeviceInstanceKey);
1600 continue;
1601 }
1602
1603 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1604 j = 0;
1605 while (TRUE)
1606 {
1607 LPWSTR pSymbolicLink;
1608 struct DeviceInterface *interfaceInfo;
1609
1610 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1611 rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1612 if (rc == ERROR_NO_MORE_ITEMS)
1613 break;
1614 if (rc != ERROR_SUCCESS)
1615 {
1616 HeapFree(GetProcessHeap(), 0, InstancePath);
1617 RegCloseKey(hDeviceInstanceKey);
1618 RegCloseKey(hInterfaceKey);
1619 return rc;
1620 }
1621 j++;
1622 if (KeyBuffer[0] != '#')
1623 /* This entry doesn't represent an interesting entry */
1624 continue;
1625
1626 /* Open sub key */
1627 rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
1628 if (rc != ERROR_SUCCESS)
1629 {
1630 RegCloseKey(hDeviceInstanceKey);
1631 RegCloseKey(hInterfaceKey);
1632 return rc;
1633 }
1634
1635 /* Read SymbolicLink value */
1636 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
1637 if (rc != ERROR_SUCCESS )
1638 {
1639 RegCloseKey(hReferenceKey);
1640 RegCloseKey(hDeviceInstanceKey);
1641 RegCloseKey(hInterfaceKey);
1642 return rc;
1643 }
1644 if (dwRegType != REG_SZ)
1645 {
1646 RegCloseKey(hReferenceKey);
1647 RegCloseKey(hDeviceInstanceKey);
1648 RegCloseKey(hInterfaceKey);
1649 return ERROR_GEN_FAILURE;
1650 }
1651
1652 /* We have found a device */
1653 /* Step 1. Create a device info element */
1654 if (!CreateDeviceInfoElement(InstancePath, &ClassGuid, &deviceInfo))
1655 {
1656 RegCloseKey(hReferenceKey);
1657 RegCloseKey(hDeviceInstanceKey);
1658 RegCloseKey(hInterfaceKey);
1659 return GetLastError();
1660 }
1661 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
1662 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1663
1664 /* Step 2. Create an interface list for this element */
1665 pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
1666 if (!pSymbolicLink)
1667 {
1668 RegCloseKey(hReferenceKey);
1669 RegCloseKey(hDeviceInstanceKey);
1670 RegCloseKey(hInterfaceKey);
1671 return ERROR_NOT_ENOUGH_MEMORY;
1672 }
1673 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
1674 pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
1675 RegCloseKey(hReferenceKey);
1676 if (rc != ERROR_SUCCESS)
1677 {
1678 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1679 RegCloseKey(hDeviceInstanceKey);
1680 RegCloseKey(hInterfaceKey);
1681 return rc;
1682 }
1683 if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
1684 {
1685 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1686 RegCloseKey(hDeviceInstanceKey);
1687 RegCloseKey(hInterfaceKey);
1688 return GetLastError();
1689 }
1690 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
1691 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1692 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1693 }
1694 RegCloseKey(hDeviceInstanceKey);
1695 }
1696 RegCloseKey(hInterfaceKey);
1697 return ERROR_SUCCESS;
1698 }
1699 #endif /* __REACTOS__ */
1700
1701 /***********************************************************************
1702 * SetupDiGetClassDevsExW (SETUPAPI.@)
1703 */
1704 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1705 CONST GUID *class,
1706 LPCWSTR enumstr,
1707 HWND parent,
1708 DWORD flags,
1709 HDEVINFO deviceset,
1710 LPCWSTR machine,
1711 PVOID reserved)
1712 {
1713 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1714 struct DeviceInfoSet *list;
1715 LPGUID pClassGuid;
1716 LONG rc;
1717
1718 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr),
1719 parent, flags, deviceset, debugstr_w(machine), reserved);
1720
1721 /* Create the deviceset if not set */
1722 if (deviceset)
1723 {
1724 list = (struct DeviceInfoSet *)deviceset;
1725 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
1726 {
1727 SetLastError(ERROR_INVALID_HANDLE);
1728 return INVALID_HANDLE_VALUE;
1729 }
1730 hDeviceInfo = deviceset;
1731 }
1732 else
1733 {
1734 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
1735 flags & DIGCF_DEVICEINTERFACE ? NULL : class,
1736 NULL, machine, NULL);
1737 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1738 return INVALID_HANDLE_VALUE;
1739 list = (struct DeviceInfoSet *)hDeviceInfo;
1740 }
1741
1742 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1743 pClassGuid = NULL;
1744 else
1745 pClassGuid = &list->ClassGuid;
1746
1747 if (flags & DIGCF_PRESENT)
1748 FIXME(": flag DIGCF_PRESENT ignored\n");
1749 if (flags & DIGCF_PROFILE)
1750 FIXME(": flag DIGCF_PROFILE ignored\n");
1751
1752 if (flags & DIGCF_ALLCLASSES)
1753 {
1754 rc = SETUP_CreateDevList(list, machine, pClassGuid, enumstr);
1755 if (rc != ERROR_SUCCESS)
1756 {
1757 SetLastError(rc);
1758 if (!deviceset)
1759 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1760 return INVALID_HANDLE_VALUE;
1761 }
1762 return hDeviceInfo;
1763 }
1764 else if (flags & DIGCF_DEVICEINTERFACE)
1765 {
1766 if (class == NULL)
1767 {
1768 SetLastError(ERROR_INVALID_PARAMETER);
1769 if (!deviceset)
1770 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1771 return INVALID_HANDLE_VALUE;
1772 }
1773
1774 #ifndef __REACTOS__
1775 /* Special case: find serial ports by calling QueryDosDevice */
1776 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
1777 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1778 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
1779 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1780 else
1781 {
1782 ERR("Wine can only enumerate serial devices at the moment!\n");
1783 rc = ERROR_INVALID_PARAMETER;
1784 }
1785 #else /* __REACTOS__ */
1786 rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
1787 #endif /* __REACTOS__ */
1788 if (rc != ERROR_SUCCESS)
1789 {
1790 SetLastError(rc);
1791 if (!deviceset)
1792 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1793 return INVALID_HANDLE_VALUE;
1794 }
1795 return hDeviceInfo;
1796 }
1797 else
1798 {
1799 rc = SETUP_CreateDevList(list, machine, (LPGUID)class, enumstr);
1800 if (rc != ERROR_SUCCESS)
1801 {
1802 SetLastError(rc);
1803 if (!deviceset)
1804 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1805 return INVALID_HANDLE_VALUE;
1806 }
1807 return hDeviceInfo;
1808 }
1809 }
1810
1811 /***********************************************************************
1812 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1813 */
1814 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1815 HDEVINFO DeviceInfoSet,
1816 PSP_DEVINFO_DATA DeviceInfoData,
1817 CONST GUID * InterfaceClassGuid,
1818 DWORD MemberIndex,
1819 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1820 {
1821 BOOL ret = FALSE;
1822
1823 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
1824 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1825
1826 if (!DeviceInterfaceData)
1827 SetLastError(ERROR_INVALID_PARAMETER);
1828 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
1829 SetLastError(ERROR_INVALID_USER_BUFFER);
1830 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
1831 {
1832 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
1833
1834 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
1835 {
1836 PLIST_ENTRY ItemList = list->ListHead.Flink;
1837 BOOL Found = FALSE;
1838 while (ItemList != &list->ListHead && !Found)
1839 {
1840 PLIST_ENTRY InterfaceListEntry;
1841 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
1842 if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
1843 {
1844 /* We are not searching for this element */
1845 ItemList = ItemList->Flink;
1846 continue;
1847 }
1848 InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
1849 while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
1850 {
1851 struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
1852 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
1853 {
1854 InterfaceListEntry = InterfaceListEntry->Flink;
1855 continue;
1856 }
1857 if (MemberIndex-- == 0)
1858 {
1859 /* return this item */
1860 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
1861 &DevItf->InterfaceClassGuid,
1862 sizeof(GUID));
1863 DeviceInterfaceData->Flags = 0; /* FIXME */
1864 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
1865 Found = TRUE;
1866 }
1867 InterfaceListEntry = InterfaceListEntry->Flink;
1868 }
1869 ItemList = ItemList->Flink;
1870 }
1871 if (!Found)
1872 SetLastError(ERROR_NO_MORE_ITEMS);
1873 else
1874 ret = TRUE;
1875 }
1876 else
1877 SetLastError(ERROR_INVALID_HANDLE);
1878 }
1879 else
1880 SetLastError(ERROR_INVALID_HANDLE);
1881 return ret;
1882 }
1883
1884 static VOID ReferenceInfFile(struct InfFileDetails* infFile)
1885 {
1886 InterlockedIncrement(&infFile->References);
1887 }
1888
1889 static VOID DereferenceInfFile(struct InfFileDetails* infFile)
1890 {
1891 if (InterlockedDecrement(&infFile->References) == 0)
1892 {
1893 SetupCloseInfFile(infFile->hInf);
1894 HeapFree(GetProcessHeap(), 0, infFile);
1895 }
1896 }
1897
1898 static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
1899 {
1900 DereferenceInfFile(driverInfo->InfFileDetails);
1901 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
1902 HeapFree(GetProcessHeap(), 0, driverInfo);
1903 return TRUE;
1904 }
1905
1906 static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
1907 {
1908 PLIST_ENTRY ListEntry;
1909 struct DriverInfoElement *driverInfo;
1910
1911 while (!IsListEmpty(&deviceInfo->DriverListHead))
1912 {
1913 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
1914 driverInfo = (struct DriverInfoElement *)ListEntry;
1915 if (!DestroyDriverInfoElement(driverInfo))
1916 return FALSE;
1917 }
1918 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
1919 {
1920 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
1921 HeapFree(GetProcessHeap(), 0, ListEntry);
1922 }
1923 HeapFree(GetProcessHeap(), 0, deviceInfo);
1924 return TRUE;
1925 }
1926
1927 static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
1928 {
1929 PLIST_ENTRY ListEntry;
1930 struct DeviceInfoElement *deviceInfo;
1931
1932 while (!IsListEmpty(&list->ListHead))
1933 {
1934 ListEntry = RemoveHeadList(&list->ListHead);
1935 deviceInfo = (struct DeviceInfoElement *)ListEntry;
1936 if (!DestroyDeviceInfoElement(deviceInfo))
1937 return FALSE;
1938 }
1939 if (list->HKLM != HKEY_LOCAL_MACHINE)
1940 RegCloseKey(list->HKLM);
1941 CM_Disconnect_Machine(list->hMachine);
1942 HeapFree(GetProcessHeap(), 0, list);
1943 return TRUE;
1944 }
1945
1946 /***********************************************************************
1947 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1948 */
1949 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1950 {
1951 BOOL ret = FALSE;
1952
1953 TRACE("%p\n", devinfo);
1954 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1955 {
1956 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1957
1958 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
1959 ret = DestroyDeviceInfoSet(list);
1960 else
1961 SetLastError(ERROR_INVALID_HANDLE);
1962 }
1963 else
1964 SetLastError(ERROR_INVALID_HANDLE);
1965
1966 TRACE("Returning %d\n", ret);
1967 return ret;
1968 }
1969
1970 /***********************************************************************
1971 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1972 */
1973 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1974 HDEVINFO DeviceInfoSet,
1975 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1976 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1977 DWORD DeviceInterfaceDetailDataSize,
1978 PDWORD RequiredSize,
1979 PSP_DEVINFO_DATA DeviceInfoData)
1980 {
1981 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
1982 DWORD sizeW = 0, sizeA;
1983 BOOL ret = FALSE;
1984
1985 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
1986 DeviceInterfaceData, DeviceInterfaceDetailData,
1987 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1988
1989 if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
1990 SetLastError(ERROR_INVALID_USER_BUFFER);
1991 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
1992 SetLastError(ERROR_INVALID_PARAMETER);
1993 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
1994 SetLastError(ERROR_INVALID_PARAMETER);
1995 else
1996 {
1997 if (DeviceInterfaceDetailData != NULL)
1998 {
1999 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2000 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2001 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
2002 if (!DeviceInterfaceDetailDataW)
2003 {
2004 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2005 }
2006 }
2007 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2008 {
2009 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2010 ret = SetupDiGetDeviceInterfaceDetailW(
2011 DeviceInfoSet,
2012 DeviceInterfaceData,
2013 DeviceInterfaceDetailDataW,
2014 sizeW,
2015 &sizeW,
2016 DeviceInfoData);
2017 sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2018 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2019 if (RequiredSize)
2020 *RequiredSize = sizeA;
2021 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
2022 {
2023 if (!WideCharToMultiByte(
2024 CP_ACP, 0,
2025 DeviceInterfaceDetailDataW->DevicePath, -1,
2026 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2027 NULL, NULL))
2028 {
2029 ret = FALSE;
2030 }
2031 }
2032 }
2033 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
2034 }
2035
2036 TRACE("Returning %d\n", ret);
2037 return ret;
2038 }
2039
2040 /***********************************************************************
2041 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2042 */
2043 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2044 HDEVINFO DeviceInfoSet,
2045 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2046 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2047 DWORD DeviceInterfaceDetailDataSize,
2048 PDWORD RequiredSize,
2049 PSP_DEVINFO_DATA DeviceInfoData)
2050 {
2051 struct DeviceInfoSet *list;
2052 BOOL ret = FALSE;
2053
2054 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2055 DeviceInterfaceData, DeviceInterfaceDetailData,
2056 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2057
2058 if (!DeviceInfoSet || !DeviceInterfaceData)
2059 SetLastError(ERROR_INVALID_PARAMETER);
2060 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2061 SetLastError(ERROR_INVALID_HANDLE);
2062 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2063 SetLastError(ERROR_INVALID_HANDLE);
2064 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2065 SetLastError(ERROR_INVALID_USER_BUFFER);
2066 else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
2067 SetLastError(ERROR_INVALID_USER_BUFFER);
2068 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2069 SetLastError(ERROR_INVALID_USER_BUFFER);
2070 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2071 SetLastError(ERROR_INVALID_PARAMETER);
2072 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
2073 SetLastError(ERROR_INVALID_PARAMETER);
2074 else
2075 {
2076 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2077 LPCWSTR devName = deviceInterface->SymbolicLink;
2078 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
2079 (lstrlenW(devName) + 1) * sizeof(WCHAR);
2080
2081 if (sizeRequired > DeviceInterfaceDetailDataSize)
2082 {
2083 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2084 if (RequiredSize)
2085 *RequiredSize = sizeRequired;
2086 }
2087 else
2088 {
2089 wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
2090 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
2091 if (DeviceInfoData)
2092 {
2093 memcpy(&DeviceInfoData->ClassGuid,
2094 &deviceInterface->DeviceInfo->ClassGuid,
2095 sizeof(GUID));
2096 DeviceInfoData->DevInst = (DWORD)list->hMachine;
2097 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
2098 }
2099 ret = TRUE;
2100 }
2101 }
2102
2103 TRACE("Returning %d\n", ret);
2104 return ret;
2105 }
2106
2107 /***********************************************************************
2108 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2109 */
2110 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2111 HDEVINFO devinfo,
2112 PSP_DEVINFO_DATA DeviceInfoData,
2113 DWORD Property,
2114 PDWORD PropertyRegDataType,
2115 PBYTE PropertyBuffer,
2116 DWORD PropertyBufferSize,
2117 PDWORD RequiredSize)
2118 {
2119 BOOL bResult;
2120 BOOL bIsStringProperty;
2121 DWORD RegType;
2122 DWORD RequiredSizeA, RequiredSizeW;
2123 DWORD PropertyBufferSizeW;
2124 PBYTE PropertyBufferW;
2125
2126 TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
2127 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2128 RequiredSize);
2129
2130 PropertyBufferSizeW = PropertyBufferSize * 2;
2131 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
2132
2133 bResult = SetupDiGetDeviceRegistryPropertyW(
2134 devinfo,
2135 DeviceInfoData,
2136 Property,
2137 &RegType,
2138 PropertyBufferW,
2139 PropertyBufferSizeW,
2140 &RequiredSizeW);
2141
2142 if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2143 {
2144 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
2145
2146 if (bIsStringProperty)
2147 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
2148 else
2149 RequiredSizeA = RequiredSizeW;
2150 if (RequiredSize)
2151 *RequiredSize = RequiredSizeA;
2152 if (PropertyRegDataType)
2153 *PropertyRegDataType = RegType;
2154 }
2155
2156 if (!bResult)
2157 {
2158 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2159 return bResult;
2160 }
2161
2162 if (RequiredSizeA <= PropertyBufferSize)
2163 {
2164 if (bIsStringProperty && PropertyBufferSize > 0)
2165 {
2166 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
2167 {
2168 /* Last error is already set by WideCharToMultiByte */
2169 bResult = FALSE;
2170 }
2171 }
2172 else
2173 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
2174 }
2175 else
2176 {
2177 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2178 bResult = FALSE;
2179 }
2180
2181 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2182 return bResult;
2183 }
2184
2185 /***********************************************************************
2186 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2187 */
2188 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2189 HDEVINFO DeviceInfoSet,
2190 PSP_DEVINFO_DATA DeviceInfoData,
2191 DWORD Property,
2192 PDWORD PropertyRegDataType,
2193 PBYTE PropertyBuffer,
2194 DWORD PropertyBufferSize,
2195 PDWORD RequiredSize)
2196 {
2197 HKEY hEnumKey, hKey;
2198 DWORD rc;
2199 BOOL ret = FALSE;
2200
2201 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
2202 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2203 RequiredSize);
2204
2205 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2206 SetLastError(ERROR_INVALID_HANDLE);
2207 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2208 SetLastError(ERROR_INVALID_HANDLE);
2209 else if (!DeviceInfoData)
2210 SetLastError(ERROR_INVALID_PARAMETER);
2211 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2212 SetLastError(ERROR_INVALID_USER_BUFFER);
2213 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
2214 SetLastError(ERROR_INVALID_PARAMETER);
2215 else
2216 {
2217 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2218 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2219
2220 switch (Property)
2221 {
2222 case SPDRP_CAPABILITIES:
2223 case SPDRP_CLASS:
2224 case SPDRP_CLASSGUID:
2225 case SPDRP_COMPATIBLEIDS:
2226 case SPDRP_CONFIGFLAGS:
2227 case SPDRP_DEVICEDESC:
2228 case SPDRP_DRIVER:
2229 case SPDRP_FRIENDLYNAME:
2230 case SPDRP_HARDWAREID:
2231 case SPDRP_LOCATION_INFORMATION:
2232 case SPDRP_LOWERFILTERS:
2233 case SPDRP_MFG:
2234 case SPDRP_SECURITY:
2235 case SPDRP_SERVICE:
2236 case SPDRP_UI_NUMBER:
2237 case SPDRP_UI_NUMBER_DESC_FORMAT:
2238 case SPDRP_UPPERFILTERS:
2239 {
2240 LPCWSTR RegistryPropertyName;
2241 DWORD BufferSize;
2242
2243 switch (Property)
2244 {
2245 case SPDRP_CAPABILITIES:
2246 RegistryPropertyName = L"Capabilities"; break;
2247 case SPDRP_CLASS:
2248 RegistryPropertyName = L"Class"; break;
2249 case SPDRP_CLASSGUID:
2250 RegistryPropertyName = L"ClassGUID"; break;
2251 case SPDRP_COMPATIBLEIDS:
2252 RegistryPropertyName = L"CompatibleIDs"; break;
2253 case SPDRP_CONFIGFLAGS:
2254 RegistryPropertyName = L"ConfigFlags"; break;
2255 case SPDRP_DEVICEDESC:
2256 RegistryPropertyName = L"DeviceDesc"; break;
2257 case SPDRP_DRIVER:
2258 RegistryPropertyName = L"Driver"; break;
2259 case SPDRP_FRIENDLYNAME:
2260 RegistryPropertyName = L"FriendlyName"; break;
2261 case SPDRP_HARDWAREID:
2262 RegistryPropertyName = L"HardwareID"; break;
2263 case SPDRP_LOCATION_INFORMATION:
2264 RegistryPropertyName = L"LocationInformation"; break;
2265 case SPDRP_LOWERFILTERS:
2266 RegistryPropertyName = L"LowerFilters"; break;
2267 case SPDRP_MFG:
2268 RegistryPropertyName = L"Mfg"; break;
2269 case SPDRP_SECURITY:
2270 RegistryPropertyName = L"Security"; break;
2271 case SPDRP_SERVICE:
2272 RegistryPropertyName = L"Service"; break;
2273 case SPDRP_UI_NUMBER:
2274 RegistryPropertyName = L"UINumber"; break;
2275 case SPDRP_UI_NUMBER_DESC_FORMAT:
2276 RegistryPropertyName = L"UINumberDescFormat"; break;
2277 case SPDRP_UPPERFILTERS:
2278 RegistryPropertyName = L"UpperFilters"; break;
2279 default:
2280 /* Should not happen */
2281 RegistryPropertyName = NULL; break;
2282 }
2283
2284 /* Open registry key name */
2285 rc = RegOpenKeyExW(
2286 list->HKLM,
2287 EnumKeyName,
2288 0, /* Options */
2289 KEY_ENUMERATE_SUB_KEYS,
2290 &hEnumKey);
2291 if (rc != ERROR_SUCCESS)
2292 {
2293 SetLastError(rc);
2294 break;
2295 }
2296 rc = RegOpenKeyExW(
2297 hEnumKey,
2298 DevInfo->Data,
2299 0, /* Options */
2300 KEY_QUERY_VALUE,
2301 &hKey);
2302 RegCloseKey(hEnumKey);
2303 if (rc != ERROR_SUCCESS)
2304 {
2305 SetLastError(rc);
2306 break;
2307 }
2308 /* Read registry entry */
2309 BufferSize = PropertyBufferSize;
2310 rc = RegQueryValueExW(
2311 hKey,
2312 RegistryPropertyName,
2313 NULL, /* Reserved */
2314 PropertyRegDataType,
2315 PropertyBuffer,
2316 &BufferSize);
2317 if (RequiredSize)
2318 *RequiredSize = BufferSize;
2319 switch(rc) {
2320 case ERROR_SUCCESS:
2321 if (PropertyBuffer != NULL || BufferSize == 0)
2322 ret = TRUE;
2323 else
2324 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2325 break;
2326 case ERROR_MORE_DATA:
2327 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2328 break;
2329 default:
2330 SetLastError(rc);
2331 }
2332 RegCloseKey(hKey);
2333 break;
2334 }
2335
2336 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
2337 {
2338 DWORD required = (wcslen(DevInfo->Data) + 1) * sizeof(WCHAR);
2339
2340 if (PropertyRegDataType)
2341 *PropertyRegDataType = REG_SZ;
2342 if (RequiredSize)
2343 *RequiredSize = required;
2344 if (PropertyBufferSize >= required)
2345 {
2346 wcscpy((LPWSTR)PropertyBuffer, DevInfo->Data);
2347 ret = TRUE;
2348 }
2349 else
2350 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2351 break;
2352 }
2353
2354 /*case SPDRP_BUSTYPEGUID:
2355 case SPDRP_LEGACYBUSTYPE:
2356 case SPDRP_BUSNUMBER:
2357 case SPDRP_ENUMERATOR_NAME:
2358 case SPDRP_SECURITY_SDS:
2359 case SPDRP_DEVTYPE:
2360 case SPDRP_EXCLUSIVE:
2361 case SPDRP_CHARACTERISTICS:
2362 case SPDRP_ADDRESS:
2363 case SPDRP_DEVICE_POWER_DATA:*/
2364 #if (WINVER >= 0x501)
2365 /*case SPDRP_REMOVAL_POLICY:
2366 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2367 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2368 case SPDRP_INSTALL_STATE:*/
2369 #endif
2370
2371 default:
2372 {
2373 ERR("Property 0x%lx not implemented\n", Property);
2374 SetLastError(ERROR_NOT_SUPPORTED);
2375 }
2376 }
2377 }
2378
2379 TRACE("Returning %d\n", ret);
2380 return ret;
2381 }
2382
2383 /***********************************************************************
2384 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2385 */
2386 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2387 IN HDEVINFO DeviceInfoSet,
2388 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2389 IN DWORD Property,
2390 IN CONST BYTE *PropertyBuffer,
2391 IN DWORD PropertyBufferSize)
2392 {
2393 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2394 Property, PropertyBuffer, PropertyBufferSize);
2395 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2396 return FALSE;
2397 }
2398
2399 /***********************************************************************
2400 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2401 */
2402 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2403 IN HDEVINFO DeviceInfoSet,
2404 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2405 IN DWORD Property,
2406 IN const BYTE *PropertyBuffer,
2407 IN DWORD PropertyBufferSize)
2408 {
2409 struct DeviceInfoSet *list;
2410 BOOL ret = FALSE;
2411
2412 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2413 Property, PropertyBuffer, PropertyBufferSize);
2414
2415 if (!DeviceInfoSet)
2416 SetLastError(ERROR_INVALID_HANDLE);
2417 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2418 SetLastError(ERROR_INVALID_HANDLE);
2419 else if (DeviceInfoData)
2420 SetLastError(ERROR_INVALID_HANDLE);
2421 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2422 SetLastError(ERROR_INVALID_USER_BUFFER);
2423 else
2424 {
2425 switch (Property)
2426 {
2427 case SPDRP_COMPATIBLEIDS:
2428 case SPDRP_CONFIGFLAGS:
2429 case SPDRP_FRIENDLYNAME:
2430 case SPDRP_HARDWAREID:
2431 case SPDRP_LOCATION_INFORMATION:
2432 case SPDRP_LOWERFILTERS:
2433 case SPDRP_SECURITY:
2434 case SPDRP_SERVICE:
2435 case SPDRP_UI_NUMBER_DESC_FORMAT:
2436 case SPDRP_UPPERFILTERS:
2437 {
2438 LPCWSTR RegistryPropertyName;
2439 DWORD RegistryDataType;
2440 HKEY hKey;
2441 LONG rc;
2442
2443 switch (Property)
2444 {
2445 case SPDRP_COMPATIBLEIDS:
2446 RegistryPropertyName = L"CompatibleIDs";
2447 RegistryDataType = REG_MULTI_SZ;
2448 break;
2449 case SPDRP_CONFIGFLAGS:
2450 RegistryPropertyName = L"ConfigFlags";
2451 RegistryDataType = REG_DWORD;
2452 break;
2453 case SPDRP_FRIENDLYNAME:
2454 RegistryPropertyName = L"FriendlyName";
2455 RegistryDataType = REG_SZ;
2456 break;
2457 case SPDRP_HARDWAREID:
2458 RegistryPropertyName = L"HardwareID";
2459 RegistryDataType = REG_MULTI_SZ;
2460 break;
2461 case SPDRP_LOCATION_INFORMATION:
2462 RegistryPropertyName = L"LocationInformation";
2463 RegistryDataType = REG_SZ;
2464 break;
2465 case SPDRP_LOWERFILTERS:
2466 RegistryPropertyName = L"LowerFilters";
2467 RegistryDataType = REG_MULTI_SZ;
2468 break;
2469 case SPDRP_SECURITY:
2470 RegistryPropertyName = L"Security";
2471 RegistryDataType = REG_BINARY;
2472 break;
2473 case SPDRP_SERVICE:
2474 RegistryPropertyName = L"Service";
2475 RegistryDataType = REG_SZ;
2476 break;
2477 case SPDRP_UI_NUMBER_DESC_FORMAT:
2478 RegistryPropertyName = L"UINumberDescFormat";
2479 RegistryDataType = REG_SZ;
2480 break;
2481 case SPDRP_UPPERFILTERS:
2482 RegistryPropertyName = L"UpperFilters";
2483 RegistryDataType = REG_MULTI_SZ;
2484 break;
2485 default:
2486 /* Should not happen */
2487 RegistryPropertyName = NULL;
2488 RegistryDataType = REG_BINARY;
2489 break;
2490 }
2491 /* Open device registry key */
2492 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
2493 if (hKey != INVALID_HANDLE_VALUE)
2494 {
2495 /* Write new data */
2496 rc = RegSetValueExW(
2497 hKey,
2498 RegistryPropertyName,
2499 0, /* Reserved */
2500 RegistryDataType,
2501 PropertyBuffer,
2502 PropertyBufferSize);
2503 if (rc == ERROR_SUCCESS)
2504 ret = TRUE;
2505 else
2506 SetLastError(rc);
2507 RegCloseKey(hKey);
2508 }
2509 break;
2510 }
2511
2512 /*case SPDRP_CHARACTERISTICS:
2513 case SPDRP_DEVTYPE:
2514 case SPDRP_EXCLUSIVE:*/
2515 #if (WINVER >= 0x501)
2516 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2517 #endif
2518 //case SPDRP_SECURITY_SDS:
2519
2520 default:
2521 {
2522 ERR("Property 0x%lx not implemented\n", Property);
2523 SetLastError(ERROR_NOT_SUPPORTED);
2524 }
2525 }
2526 }
2527
2528 TRACE("Returning %d\n", ret);
2529 return ret;
2530 }
2531
2532 /***********************************************************************
2533 * SetupDiInstallClassA (SETUPAPI.@)
2534 */
2535 BOOL WINAPI SetupDiInstallClassA(
2536 HWND hwndParent,
2537 PCSTR InfFileName,
2538 DWORD Flags,
2539 HSPFILEQ FileQueue)
2540 {
2541 UNICODE_STRING FileNameW;
2542 BOOL Result;
2543
2544 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2545 {
2546 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2547 return FALSE;
2548 }
2549
2550 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2551
2552 RtlFreeUnicodeString(&FileNameW);
2553
2554 return Result;
2555 }
2556
2557 static HKEY CreateClassKey(HINF hInf)
2558 {
2559 WCHAR FullBuffer[MAX_PATH];
2560 WCHAR Buffer[MAX_PATH];
2561 DWORD RequiredSize;
2562 HKEY hClassKey;
2563
2564 Buffer[0] = '\\';
2565 if (!SetupGetLineTextW(NULL,
2566 hInf,
2567 Version,
2568 ClassGUID,
2569 &Buffer[1],
2570 MAX_PATH - 1,
2571 &RequiredSize))
2572 {
2573 return INVALID_HANDLE_VALUE;
2574 }
2575
2576 lstrcpyW(FullBuffer, ControlClass);
2577 lstrcatW(FullBuffer, Buffer);
2578
2579
2580 if (!SetupGetLineTextW(NULL,
2581 hInf,
2582 Version,
2583 Class,
2584 Buffer,
2585 MAX_PATH,
2586 &RequiredSize))
2587 {
2588 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2589 return INVALID_HANDLE_VALUE;
2590 }
2591
2592 if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2593 FullBuffer,
2594 0,
2595 NULL,
2596 REG_OPTION_NON_VOLATILE,
2597 KEY_SET_VALUE,
2598 NULL,
2599 &hClassKey,
2600 NULL))
2601 {
2602 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2603 return INVALID_HANDLE_VALUE;
2604 }
2605
2606 if (ERROR_SUCCESS != RegSetValueExW(hClassKey,
2607 Class,
2608 0,
2609 REG_SZ,
2610 (LPBYTE)Buffer,
2611 RequiredSize * sizeof(WCHAR)))
2612 {
2613 RegCloseKey(hClassKey);
2614 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
2615 return INVALID_HANDLE_VALUE;
2616 }
2617
2618 return hClassKey;
2619 }
2620
2621 /***********************************************************************
2622 * SetupDiInstallClassW (SETUPAPI.@)
2623 */
2624 BOOL WINAPI SetupDiInstallClassW(
2625 HWND hwndParent,
2626 PCWSTR InfFileName,
2627 DWORD Flags,
2628 HSPFILEQ FileQueue)
2629 {
2630 WCHAR SectionName[MAX_PATH];
2631 DWORD SectionNameLength = 0;
2632 HINF hInf;
2633 BOOL bFileQueueCreated = FALSE;
2634 HKEY hClassKey;
2635
2636 TRACE("%p %s 0x%lx %p\n", hwndParent, debugstr_w(InfFileName),
2637 Flags, FileQueue);
2638
2639 FIXME("not fully implemented\n");
2640
2641 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2642 {
2643 SetLastError(ERROR_INVALID_PARAMETER);
2644 return FALSE;
2645 }
2646
2647 /* Open the .inf file */
2648 hInf = SetupOpenInfFileW(InfFileName,
2649 NULL,
2650 INF_STYLE_WIN4,
2651 NULL);
2652 if (hInf == INVALID_HANDLE_VALUE)
2653 {
2654
2655 return FALSE;
2656 }
2657
2658 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2659 hClassKey = CreateClassKey(hInf);
2660 if (hClassKey == INVALID_HANDLE_VALUE)
2661 {
2662 SetupCloseInfFile(hInf);
2663 return FALSE;
2664 }
2665
2666
2667
2668 /* Try to append a layout file */
2669 #if 0
2670 SetupOpenAppendInfFileW(NULL, hInf, NULL);
2671 #endif
2672
2673 /* Retrieve the actual section name */
2674 SetupDiGetActualSectionToInstallW(hInf,
2675 ClassInstall32,
2676 SectionName,
2677 MAX_PATH,
2678 &SectionNameLength,
2679 NULL);
2680
2681 #if 0
2682 if (!(Flags & DI_NOVCP))
2683 {
2684 FileQueue = SetupOpenFileQueue();
2685 if (FileQueue == INVALID_HANDLE_VALUE)
2686 {
2687 SetupCloseInfFile(hInf);
2688 RegCloseKey(hClassKey);
2689 return FALSE;
2690 }
2691
2692 bFileQueueCreated = TRUE;
2693
2694 }
2695 #endif
2696
2697 SetupInstallFromInfSectionW(NULL,
2698 hInf,
2699 SectionName,
2700 SPINST_REGISTRY,
2701 hClassKey,
2702 NULL,
2703 0,
2704 NULL,
2705 NULL,
2706 INVALID_HANDLE_VALUE,
2707 NULL);
2708
2709 /* FIXME: More code! */
2710
2711 if (bFileQueueCreated)
2712 SetupCloseFileQueue(FileQueue);
2713
2714 SetupCloseInfFile(hInf);
2715
2716 RegCloseKey(hClassKey);
2717 return TRUE;
2718 }
2719
2720
2721 /***********************************************************************
2722 * SetupDiOpenClassRegKey (SETUPAPI.@)
2723 */
2724 HKEY WINAPI SetupDiOpenClassRegKey(
2725 const GUID* ClassGuid,
2726 REGSAM samDesired)
2727 {
2728 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2729 DIOCR_INSTALLER, NULL, NULL);
2730 }
2731
2732
2733 /***********************************************************************
2734 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2735 */
2736 HKEY WINAPI SetupDiOpenClassRegKeyExA(
2737 const GUID* ClassGuid,
2738 REGSAM samDesired,
2739 DWORD Flags,
2740 PCSTR MachineName,
2741 PVOID Reserved)
2742 {
2743 PWSTR MachineNameW = NULL;
2744 HKEY hKey;
2745
2746 TRACE("\n");
2747
2748 if (MachineName)
2749 {
2750 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2751 if (MachineNameW == NULL)
2752 return INVALID_HANDLE_VALUE;
2753 }
2754
2755 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2756 Flags, MachineNameW, Reserved);
2757
2758 if (MachineNameW)
2759 MyFree(MachineNameW);
2760
2761 return hKey;
2762 }
2763
2764
2765 /***********************************************************************
2766 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2767 */
2768 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2769 const GUID* ClassGuid,
2770 REGSAM samDesired,
2771 DWORD Flags,
2772 PCWSTR MachineName,
2773 PVOID Reserved)
2774 {
2775 LPWSTR lpGuidString;
2776 LPWSTR lpFullGuidString;
2777 DWORD dwLength;
2778 HKEY HKLM;
2779 HKEY hClassesKey;
2780 HKEY hClassKey;
2781 DWORD rc;
2782 LPCWSTR lpKeyName;
2783
2784 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
2785 Flags, debugstr_w(MachineName), Reserved);
2786
2787 if (Flags == DIOCR_INSTALLER)
2788 {
2789 lpKeyName = ControlClass;
2790 }
2791 else if (Flags == DIOCR_INTERFACE)
2792 {
2793 lpKeyName = DeviceClasses;
2794 }
2795 else
2796 {
2797 ERR("Invalid Flags parameter!\n");
2798 SetLastError(ERROR_INVALID_FLAGS);
2799 return INVALID_HANDLE_VALUE;
2800 }
2801
2802 if (MachineName != NULL)
2803 {
2804 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
2805 if (rc != ERROR_SUCCESS)
2806 {
2807 SetLastError(rc);
2808 return INVALID_HANDLE_VALUE;
2809 }
2810 }
2811 else
2812 HKLM = HKEY_LOCAL_MACHINE;
2813
2814 rc = RegOpenKeyExW(HKLM,
2815 lpKeyName,
2816 0,
2817 ClassGuid ? KEY_ENUMERATE_SUB_KEYS : samDesired,
2818 &hClassesKey);
2819 if (MachineName != NULL) RegCloseKey(HKLM);
2820 if (rc != ERROR_SUCCESS)
2821 {
2822 SetLastError(rc);
2823 return INVALID_HANDLE_VALUE;
2824 }
2825
2826 if (ClassGuid == NULL)
2827 return hClassesKey;
2828
2829 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
2830 {
2831 SetLastError(ERROR_GEN_FAILURE);
2832 RegCloseKey(hClassesKey);
2833 return INVALID_HANDLE_VALUE;
2834 }
2835
2836 dwLength = lstrlenW(lpGuidString);
2837 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR));
2838 if (!lpFullGuidString)
2839 {
2840 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2841 RpcStringFreeW(&lpGuidString);
2842 return INVALID_HANDLE_VALUE;
2843 }
2844 lpFullGuidString[0] = '{';
2845 memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR));
2846 lpFullGuidString[dwLength + 1] = '}';
2847 lpFullGuidString[dwLength + 2] = '\0';
2848 RpcStringFreeW(&lpGuidString);
2849
2850 rc = RegOpenKeyExW(hClassesKey,
2851 lpFullGuidString,
2852 0,
2853 samDesired,
2854 &hClassKey);
2855 if (rc != ERROR_SUCCESS)
2856 {
2857 SetLastError(rc);
2858 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
2859 RegCloseKey(hClassesKey);
2860 return INVALID_HANDLE_VALUE;
2861 }
2862
2863 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
2864 RegCloseKey(hClassesKey);
2865
2866 return hClassKey;
2867 }
2868
2869 /***********************************************************************
2870 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2871 */
2872 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2873 HDEVINFO DeviceInfoSet,
2874 PCWSTR DevicePath,
2875 DWORD OpenFlags,
2876 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2877 {
2878 FIXME("%p %s %08lx %p\n",
2879 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2880 return FALSE;
2881 }
2882
2883 /***********************************************************************
2884 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2885 */
2886 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
2887 HDEVINFO DeviceInfoSet,
2888 PCSTR DevicePath,
2889 DWORD OpenFlags,
2890 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2891 {
2892 LPWSTR DevicePathW = NULL;
2893 BOOL bResult;
2894
2895 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
2896
2897 DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
2898 if (DevicePathW == NULL)
2899 return FALSE;
2900
2901 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
2902 DevicePathW, OpenFlags, DeviceInterfaceData);
2903
2904 MyFree(DevicePathW);
2905
2906 return bResult;
2907 }
2908
2909 /***********************************************************************
2910 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2911 */
2912 BOOL WINAPI SetupDiSetClassInstallParamsA(
2913 HDEVINFO DeviceInfoSet,
2914 PSP_DEVINFO_DATA DeviceInfoData,
2915 PSP_CLASSINSTALL_HEADER ClassInstallParams,
2916 DWORD ClassInstallParamsSize)
2917 {
2918 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
2919 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
2920 return FALSE;
2921 }
2922
2923 static DWORD
2924 GetFunctionPointer(
2925 IN PWSTR InstallerName,
2926 OUT HMODULE* ModulePointer,
2927 OUT PVOID* FunctionPointer)
2928 {
2929 HMODULE hModule = NULL;
2930 LPSTR FunctionNameA = NULL;
2931 PWCHAR Comma;
2932 DWORD rc;
2933
2934 *ModulePointer = NULL;
2935 *FunctionPointer = NULL;
2936
2937 Comma = strchrW(InstallerName, ',');
2938 if (!Comma)
2939 {
2940 rc = ERROR_INVALID_PARAMETER;
2941 goto cleanup;
2942 }
2943
2944 /* Load library */
2945 *Comma = '\0';
2946 hModule = LoadLibraryW(InstallerName);
2947 *Comma = ',';
2948 if (!hModule)
2949 {
2950 rc = GetLastError();
2951 goto cleanup;
2952 }
2953
2954 /* Skip comma spaces */
2955 while (*Comma == ',' || isspaceW(*Comma))
2956 Comma++;
2957
2958 /* W->A conversion for function name */
2959 FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
2960 if (!FunctionNameA)
2961 {
2962 rc = GetLastError();
2963 goto cleanup;
2964 }
2965
2966 /* Search function */
2967 *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
2968 if (!*FunctionPointer)
2969 {
2970 rc = GetLastError();
2971 goto cleanup;
2972 }
2973
2974 *ModulePointer = hModule;
2975 rc = ERROR_SUCCESS;
2976
2977 cleanup:
2978 if (rc != ERROR_SUCCESS && hModule)
2979 FreeLibrary(hModule);
2980 MyFree(FunctionNameA);
2981 return rc;
2982 }
2983
2984 static DWORD
2985 FreeFunctionPointer(
2986 IN HMODULE ModulePointer,
2987 IN PVOID FunctionPointer)
2988 {
2989 if (ModulePointer == NULL)
2990 return ERROR_SUCCESS;
2991 if (FreeLibrary(ModulePointer))
2992 return ERROR_SUCCESS;
2993 else
2994 return GetLastError();
2995 }
2996
2997 /***********************************************************************
2998 * SetupDiCallClassInstaller (SETUPAPI.@)
2999 */
3000 BOOL WINAPI SetupDiCallClassInstaller(
3001 IN DI_FUNCTION InstallFunction,
3002 IN HDEVINFO DeviceInfoSet,
3003 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3004 {
3005 BOOL ret = FALSE;
3006
3007 TRACE("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3008
3009 if (!DeviceInfoSet)
3010 SetLastError(ERROR_INVALID_PARAMETER);
3011 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3012 SetLastError(ERROR_INVALID_HANDLE);
3013 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3014 SetLastError(ERROR_INVALID_HANDLE);
3015 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
3016 SetLastError(ERROR_INVALID_HANDLE);
3017 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3018 SetLastError(ERROR_INVALID_USER_BUFFER);
3019 else
3020 {
3021 SP_DEVINSTALL_PARAMS_W InstallParams;
3022 #define CLASS_COINSTALLER 0x1
3023 #define DEVICE_COINSTALLER 0x2
3024 #define CLASS_INSTALLER 0x4
3025 UCHAR CanHandle = 0;
3026 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
3027
3028 switch (InstallFunction)
3029 {
3030 case DIF_ALLOW_INSTALL:
3031 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3032 break;
3033 case DIF_DESTROYPRIVATEDATA:
3034 CanHandle = CLASS_INSTALLER;
3035 break;
3036 case DIF_INSTALLDEVICE:
3037 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3038 DefaultHandler = SetupDiInstallDevice;
3039 break;
3040 case DIF_INSTALLDEVICEFILES:
3041 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3042 DefaultHandler = SetupDiInstallDriverFiles;
3043 break;
3044 case DIF_INSTALLINTERFACES:
3045 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3046 DefaultHandler = SetupDiInstallDeviceInterfaces;
3047 break;
3048 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
3049 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3050 break;
3051 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
3052 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3053 break;
3054 case DIF_NEWDEVICEWIZARD_PREANALYZE:
3055 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3056 break;
3057 case DIF_REGISTER_COINSTALLERS:
3058 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3059 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
3060 break;
3061 case DIF_SELECTBESTCOMPATDRV:
3062 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3063 DefaultHandler = SetupDiSelectBestCompatDrv;
3064 break;
3065 default:
3066 ERR("Install function %lu not supported\n", InstallFunction);
3067 SetLastError(ERROR_NOT_SUPPORTED);
3068 }
3069
3070 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3071 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
3072 /* Don't process this call, as a parameter is invalid */
3073 CanHandle = 0;
3074
3075 if (CanHandle != 0)
3076 {
3077 LIST_ENTRY ClassCoInstallersListHead;
3078 LIST_ENTRY DeviceCoInstallersListHead;
3079 HMODULE ClassInstallerLibrary = NULL;
3080 CLASS_INSTALL_PROC ClassInstaller = NULL;
3081 COINSTALLER_CONTEXT_DATA Context;
3082 PLIST_ENTRY ListEntry;
3083 HKEY hKey;
3084 DWORD dwRegType, dwLength;
3085 DWORD rc = NO_ERROR;
3086
3087 InitializeListHead(&ClassCoInstallersListHead);
3088 InitializeListHead(&DeviceCoInstallersListHead);
3089
3090 if (CanHandle & DEVICE_COINSTALLER)
3091 {
3092 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
3093 if (hKey != INVALID_HANDLE_VALUE)
3094 {
3095 rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, &dwRegType, NULL, &dwLength);
3096 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3097 {
3098 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3099 if (KeyBuffer != NULL)
3100 {
3101 rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3102 if (rc == ERROR_SUCCESS)
3103 {
3104 LPWSTR ptr;
3105 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3106 {
3107 /* Add coinstaller to DeviceCoInstallersListHead list */
3108 struct CoInstallerElement *coinstaller;
3109 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
3110 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3111 if (!coinstaller)
3112 continue;
3113 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
3114 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3115 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
3116 else
3117 HeapFree(GetProcessHeap(), 0, coinstaller);
3118 }
3119 }
3120 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3121 }
3122 }
3123 RegCloseKey(hKey);
3124 }
3125 }
3126 if (CanHandle & CLASS_COINSTALLER)
3127 {
3128 rc = RegOpenKeyEx(
3129 HKEY_LOCAL_MACHINE,
3130 L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3131 0, /* Options */
3132 KEY_QUERY_VALUE,
3133 &hKey);
3134 if (rc == ERROR_SUCCESS)
3135 {
3136 LPWSTR lpGuidString;
3137 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
3138 {
3139 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
3140 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3141 {
3142 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3143 if (KeyBuffer != NULL)
3144 {
3145 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3146 if (rc == ERROR_SUCCESS)
3147 {
3148 LPWSTR ptr;
3149 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3150 {
3151 /* Add coinstaller to ClassCoInstallersListHead list */
3152 struct CoInstallerElement *coinstaller;
3153 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
3154 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3155 if (!coinstaller)
3156 continue;
3157 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
3158 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3159 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
3160 else
3161 HeapFree(GetProcessHeap(), 0, coinstaller);
3162 }
3163 }
3164 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3165 }
3166 }
3167 RpcStringFreeW(&lpGuidString);
3168 }
3169 RegCloseKey(hKey);
3170 }
3171 }
3172 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
3173 {
3174 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
3175 if (hKey != INVALID_HANDLE_VALUE)
3176 {
3177 rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
3178 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
3179 {
3180 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3181 if (KeyBuffer != NULL)
3182 {
3183 rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3184 if (rc == ERROR_SUCCESS)
3185 {
3186 /* Get ClassInstaller function pointer */
3187 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
3188 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
3189 {
3190 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
3191 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3192 }
3193 }
3194 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3195 }
3196 }
3197 RegCloseKey(hKey);
3198 }
3199 }
3200
3201 /* Call Class co-installers */
3202 Context.PostProcessing = FALSE;
3203 rc = NO_ERROR;
3204 ListEntry = ClassCoInstallersListHead.Flink;
3205 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
3206 {
3207 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3208 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3209 coinstaller->PrivateData = Context.PrivateData;
3210 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3211 {
3212 coinstaller->DoPostProcessing = TRUE;
3213 rc = NO_ERROR;
3214 }
3215 ListEntry = ListEntry->Flink;
3216 }
3217
3218 /* Call Device co-installers */
3219 ListEntry = DeviceCoInstallersListHead.Flink;
3220 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
3221 {
3222 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3223 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3224 coinstaller->PrivateData = Context.PrivateData;
3225 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3226 {
3227 coinstaller->DoPostProcessing = TRUE;
3228 rc = NO_ERROR;
3229 }
3230 ListEntry = ListEntry->Flink;
3231 }
3232
3233 /* Call Class installer */
3234 if (ClassInstaller)
3235 {
3236 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
3237 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
3238 }
3239 else
3240 rc = ERROR_DI_DO_DEFAULT;
3241
3242 /* Call default handler */
3243 if (rc == ERROR_DI_DO_DEFAULT)
3244 {
3245 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
3246 {
3247 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
3248 rc = NO_ERROR;
3249 else
3250 rc = GetLastError();
3251 }
3252 else
3253 rc = NO_ERROR;
3254 }
3255
3256 /* Call Class co-installers that required postprocessing */
3257 Context.PostProcessing = TRUE;
3258 ListEntry = ClassCoInstallersListHead.Flink;
3259 while (ListEntry != &ClassCoInstallersListHead)
3260 {
3261 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3262 if (coinstaller->DoPostProcessing)
3263 {
3264 Context.InstallResult = rc;
3265 Context.PrivateData = coinstaller->PrivateData;
3266 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3267 }
3268 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3269 ListEntry = ListEntry->Flink;
3270 }
3271
3272 /* Call Device co-installers that required postprocessing */
3273 ListEntry = DeviceCoInstallersListHead.Flink;
3274 while (ListEntry != &DeviceCoInstallersListHead)
3275 {
3276 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
3277 if (coinstaller->DoPostProcessing)
3278 {
3279 Context.InstallResult = rc;
3280 Context.PrivateData = coinstaller->PrivateData;
3281 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3282 }
3283 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3284 ListEntry = ListEntry->Flink;
3285 }
3286
3287 /* Free allocated memory */
3288 while (!IsListEmpty(&ClassCoInstallersListHead))
3289 {
3290 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
3291 HeapFree(GetProcessHeap(), 0, ListEntry);
3292 }
3293 while (!IsListEmpty(&DeviceCoInstallersListHead))
3294 {
3295 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
3296 HeapFree(GetProcessHeap(), 0, ListEntry);
3297 }
3298
3299 ret = (rc == NO_ERROR);
3300 }
3301 }
3302
3303 TRACE("Returning %d\n", ret);
3304 return ret;
3305 }
3306
3307 /***********************************************************************
3308 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3309 */
3310 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
3311 IN HDEVINFO DeviceInfoSet,
3312 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
3313 {
3314 struct DeviceInfoSet *list;
3315 BOOL ret = FALSE;
3316
3317 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
3318
3319 if (!DeviceInfoSet)
3320 SetLastError(ERROR_INVALID_HANDLE);
3321 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3322 SetLastError(ERROR_INVALID_HANDLE);
3323 else if (!DeviceInfoListDetailData)
3324 SetLastError(ERROR_INVALID_PARAMETER);
3325 else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
3326 SetLastError(ERROR_INVALID_USER_BUFFER);
3327 else
3328 {
3329 memcpy(
3330 &DeviceInfoListDetailData->ClassGuid,
3331 &list->ClassGuid,
3332 sizeof(GUID));
3333 DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
3334 DeviceInfoListDetailData->RemoteMachineName[0] = 0; /* FIXME */
3335
3336 ret = TRUE;
3337 }
3338
3339 TRACE("Returning %d\n", ret);
3340 return ret;
3341 }
3342
3343 /***********************************************************************
3344 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3345 */
3346 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
3347 IN HDEVINFO DeviceInfoSet,
3348 IN PSP_DEVINFO_DATA DeviceInfoData,
3349 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
3350 {
3351 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
3352 BOOL ret = FALSE;
3353
3354 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3355
3356 if (DeviceInstallParams == NULL)
3357 SetLastError(ERROR_INVALID_PARAMETER);
3358 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
3359 SetLastError(ERROR_INVALID_USER_BUFFER);
3360 else
3361 {
3362 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3363 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
3364
3365 if (ret)
3366 {
3367 /* Do W->A conversion */
3368 memcpy(
3369 DeviceInstallParams,
3370 &deviceInstallParamsW,
3371 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
3372 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
3373 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
3374 {
3375 DeviceInstallParams->DriverPath[0] = '\0';
3376 ret = FALSE;
3377 }
3378 }
3379 }
3380
3381 TRACE("Returning %d\n", ret);
3382 return ret;
3383 }
3384
3385 /***********************************************************************
3386 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3387 */
3388 BOOL WINAPI SetupDiGetDeviceInstallParamsW(
3389 IN HDEVINFO DeviceInfoSet,
3390 IN PSP_DEVINFO_DATA DeviceInfoData,
3391 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3392 {
3393 struct DeviceInfoSet *list;
3394 BOOL ret = FALSE;
3395
3396 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3397
3398 if (!DeviceInfoSet)
3399 SetLastError(ERROR_INVALID_HANDLE);
3400 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3401 SetLastError(ERROR_INVALID_HANDLE);
3402 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3403 SetLastError(ERROR_INVALID_USER_BUFFER);
3404 else if (!DeviceInstallParams)
3405 SetLastError(ERROR_INVALID_PARAMETER);
3406 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
3407 SetLastError(ERROR_INVALID_USER_BUFFER);
3408 else
3409 {
3410 PSP_DEVINSTALL_PARAMS_W Source;
3411
3412 if (DeviceInfoData)
3413 Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
3414 else
3415 Source = &list->InstallParams;
3416 memcpy(DeviceInstallParams, Source, Source->cbSize);
3417 ret = TRUE;
3418 }
3419
3420 TRACE("Returning %d\n", ret);
3421 return ret;
3422 }
3423
3424 /***********************************************************************
3425 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3426 */
3427 BOOL WINAPI SetupDiSetDeviceInstallParamsW(
3428 IN HDEVINFO DeviceInfoSet,
3429 IN PSP_DEVINFO_DATA DeviceInfoData,
3430 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
3431 {
3432 struct DeviceInfoSet *list;
3433 BOOL ret = FALSE;
3434
3435 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
3436
3437 if (!DeviceInfoSet)
3438 SetLastError(ERROR_INVALID_HANDLE);
3439 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3440 SetLastError(ERROR_INVALID_HANDLE);
3441 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3442 SetLastError(ERROR_INVALID_USER_BUFFER);
3443 else if (!DeviceInstallParams)
3444 SetLastError(ERROR_INVALID_PARAMETER);
3445 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
3446 SetLastError(ERROR_INVALID_USER_BUFFER);
3447 else
3448 {
3449 PSP_DEVINSTALL_PARAMS_W Destination;
3450
3451 /* FIXME: Validate parameters */
3452
3453 if (DeviceInfoData)
3454 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
3455 else
3456 Destination = &list->InstallParams;
3457 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
3458 ret = TRUE;
3459 }
3460
3461 TRACE("Returning %d\n", ret);
3462 return ret;
3463 }
3464
3465 /***********************************************************************
3466 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3467 */
3468 HKEY WINAPI SetupDiCreateDevRegKeyA(
3469 IN HDEVINFO DeviceInfoSet,
3470 IN PSP_DEVINFO_DATA DeviceInfoData,
3471 IN DWORD Scope,
3472 IN DWORD HwProfile,
3473 IN DWORD KeyType,
3474 IN HINF InfHandle OPTIONAL,
3475 IN PCSTR InfSectionName OPTIONAL)
3476 {
3477 PCWSTR InfSectionNameW = NULL;
3478 HKEY ret = INVALID_HANDLE_VALUE;
3479
3480 if (InfSectionName)
3481 {
3482 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
3483 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
3484 }
3485
3486 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
3487 DeviceInfoData,
3488 Scope,
3489 HwProfile,
3490 KeyType,
3491 InfHandle,
3492 InfSectionNameW);
3493
3494 if (InfSectionNameW != NULL)
3495 MyFree((PVOID)InfSectionNameW);
3496
3497 return ret;
3498 }
3499
3500 /***********************************************************************
3501 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3502 */
3503 HKEY WINAPI SetupDiCreateDevRegKeyW(
3504 IN HDEVINFO DeviceInfoSet,
3505 IN PSP_DEVINFO_DATA DeviceInfoData,
3506 IN DWORD Scope,
3507 IN DWORD HwProfile,
3508 IN DWORD KeyType,
3509 IN HINF InfHandle OPTIONAL,
3510 IN PCWSTR InfSectionName OPTIONAL)
3511 {
3512 struct DeviceInfoSet *list;
3513 HKEY ret = INVALID_HANDLE_VALUE;
3514
3515 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
3516 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
3517
3518 if (!DeviceInfoSet)
3519 SetLastError(ERROR_INVALID_HANDLE);
3520 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3521 SetLastError(ERROR_INVALID_HANDLE);
3522 else if (!DeviceInfoData)
3523 SetLastError(ERROR_INVALID_PARAMETER);
3524 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3525 SetLastError(ERROR_INVALID_USER_BUFFER);
3526 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3527 SetLastError(ERROR_INVALID_PARAMETER);
3528 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3529 SetLastError(ERROR_INVALID_PARAMETER);
3530 else if (InfHandle && !InfSectionName)
3531 SetLastError(ERROR_INVALID_PARAMETER);
3532 else if (!InfHandle && InfSectionName)
3533 SetLastError(ERROR_INVALID_PARAMETER);
3534 else
3535 {
3536 LPWSTR lpGuidString = NULL;
3537 LPWSTR DriverKey = NULL; /* {GUID}\Index */
3538 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
3539 DWORD Index; /* Index used in the DriverKey name */
3540 DWORD rc;
3541 HKEY hClassKey = INVALID_HANDLE_VALUE;
3542 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
3543 HKEY hKey = INVALID_HANDLE_VALUE;
3544
3545 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
3546 {
3547 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3548 goto cleanup;
3549 }
3550
3551 if (KeyType == DIREG_DEV)
3552 {
3553 FIXME("DIREG_DEV case unimplemented\n");
3554 }
3555 else /* KeyType == DIREG_DRV */
3556 {
3557 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
3558 goto cleanup;
3559 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3560 DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
3561 if (!DriverKey)
3562 {
3563 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3564 goto cleanup;
3565 }
3566 wcscpy(DriverKey, L"{");
3567 wcscat(DriverKey, lpGuidString);
3568 wcscat(DriverKey, L"}\\");
3569 pDeviceInstance = &DriverKey[wcslen(DriverKey)];
3570 rc = RegOpenKeyExW(list->HKLM,
3571 ControlClass,
3572 0,
3573 KEY_CREATE_SUB_KEY,
3574 &hClassKey);
3575 if (rc != ERROR_SUCCESS)
3576 {
3577 SetLastError(rc);
3578 goto cleanup;
3579 }
3580
3581 /* Try all values for Index between 0 and 9999 */
3582 Index = 0;
3583 while (Index <= 9999)
3584 {
3585 DWORD Disposition;
3586 wsprintf(pDeviceInstance, L"%04lu", Index);
3587 rc = RegCreateKeyEx(hClassKey,
3588 DriverKey,
3589 0,
3590 NULL,
3591 REG_OPTION_NON_VOLATILE,
3592 #if _WIN32_WINNT >= 0x502
3593 KEY_READ | KEY_WRITE,
3594 #else
3595 KEY_ALL_ACCESS,
3596 #endif
3597 NULL,
3598 &hKey,
3599 &Disposition);
3600 if (rc != ERROR_SUCCESS)
3601 {
3602 SetLastError(rc);
3603 goto cleanup;
3604 }
3605 if (Disposition == REG_CREATED_NEW_KEY)
3606 break;
3607 RegCloseKey(hKey);
3608 hKey = INVALID_HANDLE_VALUE;
3609 Index++;
3610 }
3611 if (Index > 9999)
3612 {
3613 /* Unable to create more than 9999 devices within the same class */
3614 SetLastError(ERROR_GEN_FAILURE);
3615 goto cleanup;
3616 }
3617
3618 /* Open device key, to write Driver value */
3619 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
3620 if (hDeviceKey == INVALID_HANDLE_VALUE)
3621 goto cleanup;
3622 rc = RegSetValueEx(hDeviceKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
3623 if (rc != ERROR_SUCCESS)
3624 {
3625 SetLastError(rc);
3626 goto cleanup;
3627 }
3628 }
3629
3630 /* Do installation of the specified section */
3631 if (InfHandle)
3632 {
3633 FIXME("Need to install section %s in file %p\n",
3634 debugstr_w(InfSectionName), InfHandle);
3635 }
3636 ret = hKey;
3637
3638 cleanup:
3639 if (lpGuidString)
3640 RpcStringFreeW(&lpGuidString);
3641 HeapFree(GetProcessHeap(), 0, DriverKey);
3642 if (hClassKey != INVALID_HANDLE_VALUE)
3643 RegCloseKey(hClassKey);
3644 if (hDeviceKey != INVALID_HANDLE_VALUE)
3645 RegCloseKey(hDeviceKey);
3646 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
3647 RegCloseKey(hKey);
3648 }
3649
3650 TRACE("Returning 0x%p\n", ret);
3651 return ret;
3652 }
3653
3654 /***********************************************************************
3655 * SetupDiOpenDevRegKey (SETUPAPI.@)
3656 */
3657 HKEY WINAPI SetupDiOpenDevRegKey(
3658 HDEVINFO DeviceInfoSet,
3659 PSP_DEVINFO_DATA DeviceInfoData,
3660 DWORD Scope,
3661 DWORD HwProfile,
3662 DWORD KeyType,
3663 REGSAM samDesired)
3664 {
3665 struct DeviceInfoSet *list;
3666 HKEY ret = INVALID_HANDLE_VALUE;
3667
3668 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
3669 Scope, HwProfile, KeyType, samDesired);
3670
3671 if (!DeviceInfoSet)
3672 SetLastError(ERROR_INVALID_HANDLE);
3673 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3674 SetLastError(ERROR_INVALID_HANDLE);
3675 else if (!DeviceInfoData)
3676 SetLastError(ERROR_INVALID_PARAMETER);
3677 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3678 SetLastError(ERROR_INVALID_USER_BUFFER);
3679 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
3680 SetLastError(ERROR_INVALID_PARAMETER);
3681 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
3682 SetLastError(ERROR_INVALID_PARAMETER);
3683 else
3684 {
3685 HKEY hKey = INVALID_HANDLE_VALUE;
3686 HKEY hRootKey = INVALID_HANDLE_VALUE;
3687 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
3688 LPWSTR DriverKey = NULL;
3689 DWORD dwLength = 0;
3690 DWORD dwRegType;
3691 DWORD rc;
3692
3693 if (Scope == DICS_FLAG_CONFIGSPECIFIC)
3694 {
3695 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3696 }
3697 else /* Scope == DICS_FLAG_GLOBAL */
3698 {
3699 rc = RegOpenKeyExW(
3700 list->HKLM,
3701 EnumKeyName,
3702 0, /* Options */
3703 KEY_ENUMERATE_SUB_KEYS,
3704 &hRootKey);
3705 if (rc != ERROR_SUCCESS)
3706 {
3707 SetLastError(rc);
3708 goto cleanup;
3709 }
3710 rc = RegOpenKeyExW(
3711 hRootKey,
3712 deviceInfo->DeviceName,
3713 0, /* Options */
3714 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
3715 &hKey);
3716 RegCloseKey(hRootKey);
3717 hRootKey = INVALID_HANDLE_VALUE;
3718 if (rc != ERROR_SUCCESS)
3719 {
3720 SetLastError(rc);
3721 goto cleanup;
3722 }
3723 if (KeyType == DIREG_DEV)
3724 {
3725 /* We're done. Just return the hKey handle */
3726 ret = hKey;
3727 goto cleanup;
3728 }
3729 /* Read the 'Driver' key */
3730 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, NULL, &dwLength);
3731 if (rc != ERROR_SUCCESS)
3732 {
3733 SetLastError(rc);
3734 goto cleanup;
3735 }
3736 if (dwRegType != REG_SZ)
3737 {
3738 SetLastError(ERROR_GEN_FAILURE);
3739 goto cleanup;
3740 }
3741 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
3742 if (!DriverKey)
3743 {
3744 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3745 goto cleanup;
3746 }
3747 rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
3748 if (rc != ERROR_SUCCESS)
3749 {
3750 SetLastError(rc);
3751 goto cleanup;
3752 }
3753 RegCloseKey(hKey);
3754 hKey = INVALID_HANDLE_VALUE;
3755 /* Need to open the driver key */
3756 rc = RegOpenKeyExW(
3757 list->HKLM,
3758 ControlClass,
3759 0, /* Options */
3760 KEY_ENUMERATE_SUB_KEYS,
3761 &hRootKey);
3762 if (rc != ERROR_SUCCESS)
3763 {
3764 SetLastError(rc);
3765 goto cleanup;
3766 }
3767 rc = RegOpenKeyExW(
3768 hRootKey,
3769 DriverKey,
3770 0, /* Options */
3771 samDesired,
3772 &hKey);
3773 if (rc != ERROR_SUCCESS)
3774 {
3775 SetLastError(rc);
3776 goto cleanup;
3777 }
3778 ret = hKey;
3779 }
3780 cleanup:
3781 if (hRootKey != INVALID_HANDLE_VALUE)
3782 RegCloseKey(hRootKey);
3783 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
3784 RegCloseKey(hKey);
3785 }
3786
3787 TRACE("Returning 0x%p\n", ret);
3788 return ret;
3789 }
3790
3791 /***********************************************************************
3792 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3793 */
3794 BOOL WINAPI SetupDiCreateDeviceInfoA(
3795 HDEVINFO DeviceInfoSet,
3796 PCSTR DeviceName,
3797 CONST GUID *ClassGuid,
3798 PCSTR DeviceDescription,
3799 HWND hwndParent,
3800 DWORD CreationFlags,
3801 PSP_DEVINFO_DATA DeviceInfoData)
3802 {
3803 LPWSTR DeviceNameW = NULL;
3804 LPWSTR DeviceDescriptionW = NULL;
3805 BOOL bResult;
3806
3807 TRACE("\n");
3808
3809 if (DeviceName)
3810 {
3811 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
3812 if (DeviceNameW == NULL) return FALSE;
3813 }
3814 if (DeviceDescription)
3815 {
3816 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
3817 if (DeviceDescriptionW == NULL)
3818 {
3819 if (DeviceNameW) MyFree(DeviceNameW);
3820 return FALSE;
3821 }
3822 }
3823
3824 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
3825 ClassGuid, DeviceDescriptionW,
3826 hwndParent, CreationFlags,
3827 DeviceInfoData);
3828
3829 if (DeviceNameW) MyFree(DeviceNameW);
3830 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
3831
3832 return bResult;
3833 }
3834
3835 /***********************************************************************
3836 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3837 */
3838 BOOL WINAPI SetupDiCreateDeviceInfoW(
3839 HDEVINFO DeviceInfoSet,
3840 PCWSTR DeviceName,
3841 CONST GUID *ClassGuid,
3842 PCWSTR DeviceDescription,
3843 HWND hwndParent,
3844 DWORD CreationFlags,
3845 PSP_DEVINFO_DATA DeviceInfoData)
3846 {
3847 struct DeviceInfoSet *list;
3848 BOOL ret = FALSE;
3849
3850 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
3851 debugstr_guid(ClassGuid), DeviceDescription,
3852 hwndParent, CreationFlags, DeviceInfoData);
3853
3854 if (!DeviceInfoSet)
3855 SetLastError(ERROR_INVALID_HANDLE);
3856 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3857 SetLastError(ERROR_INVALID_HANDLE);
3858 else if (!ClassGuid)
3859 SetLastError(ERROR_INVALID_PARAMETER);
3860 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
3861 SetLastError(ERROR_CLASS_MISMATCH);
3862 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
3863 {
3864 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
3865 SetLastError(ERROR_INVALID_FLAGS);
3866 }
3867 else
3868 {
3869 SP_DEVINFO_DATA DevInfo;
3870
3871 if (CreationFlags & DICD_GENERATE_ID)
3872 {
3873 /* Generate a new unique ID for this device */
3874 SetLastError(ERROR_GEN_FAILURE);
3875 FIXME("not implemented\n");
3876 }
3877 else
3878 {
3879 /* Device name is fully qualified. Try to open it */
3880 BOOL rc;
3881
3882 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
3883 rc = SetupDiOpenDeviceInfoW(
3884 DeviceInfoSet,
3885 DeviceName,
3886 NULL, /* hwndParent */
3887 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
3888 &DevInfo);
3889
3890 if (rc)
3891 {
3892 /* SetupDiOpenDeviceInfoW has already added
3893 * the device info to the device info set
3894 */
3895 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
3896 }
3897 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
3898 {
3899 struct DeviceInfoElement *deviceInfo;
3900
3901 if (CreateDeviceInfoElement(DeviceName, ClassGuid, &deviceInfo))
3902 {
3903 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
3904
3905 if (!DeviceInfoData)
3906 ret = TRUE;
3907 else
3908 {
3909 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
3910 {
3911 SetLastError(ERROR_INVALID_USER_BUFFER);
3912 }
3913 else
3914 {
3915 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
3916 DeviceInfoData->DevInst = (DWORD)list->hMachine;
3917 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
3918 ret = TRUE;
3919 }
3920 }
3921 }
3922 }
3923 }
3924 }
3925
3926 TRACE("Returning %d\n", ret);
3927 return ret;
3928 }
3929
3930 /***********************************************************************
3931 * Helper functions for SetupDiBuildDriverInfoList
3932 */
3933 static BOOL
3934 AddDriverToList(
3935 IN PLIST_ENTRY DriverListHead,
3936 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3937 IN LPGUID ClassGuid,
3938 IN INFCONTEXT ContextDevice,
3939 IN struct InfFileDetails *InfFileDetails,
3940 IN LPCWSTR InfFile,
3941 IN LPCWSTR ProviderName,
3942 IN LPCWSTR ManufacturerName,
3943 IN LPCWSTR MatchingId,
3944 FILETIME DriverDate,
3945 DWORDLONG DriverVersion,
3946 IN DWORD Rank)
3947 {
3948 struct DriverInfoElement *driverInfo = NULL;
3949 HANDLE hFile = INVALID_HANDLE_VALUE;
3950 DWORD RequiredSize = 128; /* Initial buffer size */
3951 BOOL Result = FALSE;
3952 PLIST_ENTRY PreviousEntry;
3953 LPWSTR InfInstallSection = NULL;
3954 BOOL ret = FALSE;
3955
3956 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
3957 if (!driverInfo)
3958 {
3959 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3960 goto cleanup;
3961 }
3962 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
3963
3964 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
3965 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
3966
3967 /* Copy InfFileName field */
3968 wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
3969 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
3970
3971 /* Fill InfDate field */
3972 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3973 GENERIC_READ, FILE_SHARE_READ,
3974 NULL, OPEN_EXISTING, 0, NULL);
3975 if (hFile == INVALID_HANDLE_VALUE)
3976 goto cleanup;
3977 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
3978 if (!Result)
3979 goto cleanup;*/
3980
3981 /* Fill SectionName field */
3982 Result = SetupGetStringFieldW(
3983 &ContextDevice,
3984 1,
3985 driverInfo->Details.SectionName, LINE_LEN,
3986 NULL);
3987 if (!Result)
3988 goto cleanup;
3989
3990 /* Fill DrvDescription field */
3991 Result = SetupGetStringFieldW(
3992 &ContextDevice,
3993 0, /* Field index */
3994 driverInfo->Details.DrvDescription, LINE_LEN,
3995 NULL);
3996
3997 /* Copy MatchingId information */
3998 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
3999 if (!driverInfo->MatchingId)
4000 {
4001 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4002 goto cleanup;
4003 }
4004 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
4005
4006 /* Get inf install section */
4007 Result = FALSE;
4008 RequiredSize = 128; /* Initial buffer size */
4009 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4010 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4011 {
4012 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4013 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4014 if (!InfInstallSection)
4015 goto cleanup;
4016 Result = SetupGetStringFieldW(
4017 &ContextDevice,
4018 1, /* Field index */
4019 InfInstallSection, RequiredSize,
4020 &RequiredSize);
4021 }
4022 if (!Result)
4023 goto cleanup;
4024
4025 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4026 driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
4027
4028 driverInfo->DriverRank = Rank;
4029 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
4030 driverInfo->Info.DriverType = DriverType;
4031 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
4032 wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
4033 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
4034 wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
4035 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
4036 if (ProviderName)
4037 {
4038 wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
4039 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
4040 }
4041 else
4042 driverInfo->Info.ProviderName[0] = '\0';
4043 driverInfo->Info.DriverDate = DriverDate;
4044 driverInfo->Info.DriverVersion = DriverVersion;
4045 ReferenceInfFile(InfFileDetails);
4046 driverInfo->InfFileDetails = InfFileDetails;
4047
4048 /* Insert current driver in driver list, according to its rank */
4049 PreviousEntry = DriverListHead->Flink;
4050 while (PreviousEntry != DriverListHead)
4051 {
4052 if (((struct DriverInfoElement *)PreviousEntry)->DriverRank >= Rank)
4053 {
4054 /* Insert before the current item */
4055 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
4056 break;
4057 }
4058 PreviousEntry = PreviousEntry->Flink;
4059 }
4060 if (PreviousEntry == DriverListHead)
4061 {
4062 /* Insert at the end of the list */
4063 InsertTailList(DriverListHead, &driverInfo->ListEntry);
4064 }
4065
4066 ret = TRUE;
4067
4068 cleanup:
4069 if (!ret)
4070 {
4071 if (driverInfo)
4072 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
4073 HeapFree(GetProcessHeap(), 0, driverInfo);
4074 }
4075 if (hFile != INVALID_HANDLE_VALUE)
4076 CloseHandle(hFile);
4077 HeapFree(GetProcessHeap(), 0, InfInstallSection);
4078
4079 return ret;
4080 }
4081
4082 static BOOL
4083 GetVersionInformationFromInfFile(
4084 IN HINF hInf,
4085 OUT LPGUID ClassGuid,
4086 OUT LPWSTR* pProviderName,
4087 OUT FILETIME* DriverDate,
4088 OUT DWORDLONG* DriverVersion)
4089 {
4090 DWORD RequiredSize;
4091 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
4092 LPWSTR DriverVer = NULL;
4093 LPWSTR ProviderName = NULL;
4094 LPWSTR pComma; /* Points into DriverVer */
4095 LPWSTR pVersion = NULL; /* Points into DriverVer */
4096 SYSTEMTIME SystemTime;
4097 BOOL Result;
4098 BOOL ret = FALSE; /* Final result */
4099
4100 /* Get class Guid */
4101 if (!SetupGetLineTextW(
4102 NULL, /* Context */
4103 hInf,
4104 L"Version", L"ClassGUID",
4105 guidW, sizeof(guidW),
4106 NULL /* Required size */))
4107 {
4108 goto cleanup;
4109 }
4110 guidW[37] = '\0'; /* Replace the } by a NULL character */
4111 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
4112 {
4113 SetLastError(ERROR_GEN_FAILURE);
4114 goto cleanup;
4115 }
4116
4117 /* Get provider name */
4118 Result = SetupGetLineTextW(
4119 NULL, /* Context */
4120 hInf, L"Version", L"Provider",
4121 NULL, 0,
4122 &RequiredSize);
4123 if (Result)
4124 {
4125 /* We know know the needed buffer size */
4126 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4127 if (!ProviderName)
4128 {
4129 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4130 goto cleanup;
4131 }
4132 Result = SetupGetLineTextW(
4133 NULL, /* Context */
4134 hInf, L"Version", L"Provider",
4135 ProviderName, RequiredSize,
4136 &RequiredSize);
4137 }
4138 if (!Result)
4139 goto cleanup;
4140 *pProviderName = ProviderName;
4141
4142 /* Read the "DriverVer" value */
4143 Result = SetupGetLineTextW(
4144 NULL, /* Context */
4145 hInf, L"Version", L"DriverVer",
4146 NULL, 0,
4147 &RequiredSize);
4148 if (Result)
4149 {
4150 /* We know know the needed buffer size */
4151 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4152 if (!DriverVer)
4153 {
4154 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4155 goto cleanup;
4156 }
4157 Result = SetupGetLineTextW(
4158 NULL, /* Context */
4159 hInf, L"Version", L"DriverVer",
4160 DriverVer, RequiredSize,
4161 &RequiredSize);
4162 }
4163 if (!Result)
4164 goto cleanup;
4165
4166 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4167 pComma = wcschr(DriverVer, ',');
4168 if (pComma != NULL)
4169 {
4170 *pComma = UNICODE_NULL;
4171 pVersion = pComma + 1;
4172 }
4173 /* Get driver date version. Invalid date = 00/00/00 */
4174 memset(DriverDate, 0, sizeof(FILETIME));
4175 if (wcslen(DriverVer) == 10
4176 && (DriverVer[2] == '-' || DriverVer[2] == '/')
4177 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
4178 {
4179 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
4180 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
4181 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
4182 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
4183 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
4184 SystemTimeToFileTime(&SystemTime, DriverDate);
4185 }
4186 /* Get driver version. Invalid version = 0.0.0.0 */
4187 *DriverVersion = 0;
4188 /* FIXME: use pVersion to fill DriverVersion variable */
4189
4190 ret = TRUE;
4191
4192 cleanup:
4193 if (!ret)
4194 HeapFree(GetProcessHeap(), 0, ProviderName);
4195 HeapFree(GetProcessHeap(), 0, DriverVer);
4196
4197 TRACE("Returning %d\n", ret);
4198 return ret;
4199 }
4200
4201 /***********************************************************************
4202 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4203 */
4204 BOOL WINAPI
4205 SetupDiBuildDriverInfoList(
4206 IN HDEVINFO DeviceInfoSet,
4207 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4208 IN DWORD DriverType)
4209 {
4210 struct DeviceInfoSet *list;
4211 SP_DEVINSTALL_PARAMS_W InstallParams;
4212 PVOID Buffer = NULL;
4213 struct InfFileDetails *currentInfFileDetails = NULL;
4214 LPWSTR ProviderName = NULL;
4215 LPWSTR ManufacturerName = NULL;
4216 WCHAR ManufacturerSection[LINE_LEN + 1];
4217 LPWSTR HardwareIDs = NULL;
4218 LPWSTR CompatibleIDs = NULL;
4219 LPWSTR FullInfFileName = NULL;
4220 FILETIME DriverDate;
4221 DWORDLONG DriverVersion = 0;
4222 DWORD RequiredSize;
4223 BOOL ret = FALSE;
4224
4225 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
4226
4227 if (!DeviceInfoSet)
4228 SetLastError(ERROR_INVALID_HANDLE);
4229 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4230 SetLastError(ERROR_INVALID_HANDLE);
4231 else if (list->HKLM != HKEY_LOCAL_MACHINE)
4232 SetLastError(ERROR_INVALID_HANDLE);
4233 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4234 SetLastError(ERROR_INVALID_PARAMETER);
4235 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
4236 SetLastError(ERROR_INVALID_PARAMETER);
4237 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4238 SetLastError(ERROR_INVALID_PARAMETER);
4239 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4240 SetLastError(ERROR_INVALID_USER_BUFFER);
4241 else
4242 {
4243 BOOL Result;
4244
4245 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
4246 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4247 if (!Result)
4248 goto done;
4249
4250 if (DriverType == SPDIT_COMPATDRIVER)
4251 {
4252 /* Get hardware IDs list */
4253 Result = FALSE;
4254 RequiredSize = 512; /* Initial buffer size */
4255 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4256 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4257 {
4258 HeapFree(GetProcessHeap(), 0, HardwareIDs);
4259 HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
4260 if (!HardwareIDs)
4261 {
4262 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4263 goto done;
4264 }
4265 Result = SetupDiGetDeviceRegistryPropertyW(
4266 DeviceInfoSet,
4267 DeviceInfoData,
4268 SPDRP_HARDWAREID,
4269 NULL,
4270 (PBYTE)HardwareIDs,
4271 RequiredSize,
4272 &RequiredSize);
4273 }
4274 if (!Result)
4275 goto done;
4276
4277 /* Get compatible IDs list */
4278 Result = FALSE;
4279 RequiredSize = 512; /* Initial buffer size */
4280 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4281 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4282 {
4283 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4284 CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
4285 if (!CompatibleIDs)
4286 {
4287 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4288 goto done;
4289 }
4290 Result = SetupDiGetDeviceRegistryPropertyW(
4291 DeviceInfoSet,
4292 DeviceInfoData,
4293 SPDRP_COMPATIBLEIDS,
4294 NULL,
4295 (PBYTE)CompatibleIDs,
4296 RequiredSize,
4297 &RequiredSize);
4298 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
4299 {
4300 /* No compatible ID for this device */
4301 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4302 CompatibleIDs = NULL;
4303 Result = TRUE;
4304 }
4305 }
4306 if (!Result)
4307 goto done;
4308 }
4309
4310 /* Enumerate .inf files */
4311 Result = FALSE;
4312 RequiredSize = 32768; /* Initial buffer size */
4313 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4314 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4315 {
4316 HeapFree(GetProcessHeap(), 0, Buffer);
4317 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4318 if (!Buffer)
4319 {
4320 Result = FALSE;
4321 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4322 break;
4323 }
4324 Result = SetupGetInfFileListW(
4325 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
4326 INF_STYLE_WIN4,
4327 Buffer, RequiredSize,
4328 &RequiredSize);
4329 }
4330 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
4331 {
4332 /* No .inf file in specified directory. So, we should
4333 * success as we created an empty driver info list.
4334 */
4335 ret = TRUE;
4336 goto done;
4337 }
4338 if (Result)
4339 {
4340 LPCWSTR filename;
4341 LPWSTR pFullFilename;
4342
4343 if (*InstallParams.DriverPath)
4344 {
4345 DWORD len;
4346 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
4347 if (len == 0)
4348 goto done;
4349 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
4350 if (!FullInfFileName)
4351 goto done;
4352 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
4353 if (len == 0)
4354 goto done;
4355 if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
4356 wcscat(FullInfFileName, L"\\");
4357 pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
4358 }
4359 else
4360 {
4361 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4362 if (!FullInfFileName)
4363 goto done;
4364 pFullFilename = &FullInfFileName[0];
4365 }
4366
4367 for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
4368 {
4369 INFCONTEXT ContextManufacturer, ContextDevice;
4370 GUID ClassGuid;
4371
4372 wcscpy(pFullFilename, filename);
4373 TRACE("Opening file %S\n", FullInfFileName);
4374
4375 currentInfFileDetails = HeapAlloc(
4376 GetProcessHeap(),
4377 0,
4378 FIELD_OFFSET(struct InfFileDetails, FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) + UNICODE_NULL);
4379 if (!currentInfFileDetails)
4380 continue;
4381 memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
4382 wcscpy(currentInfFileDetails->FullInfFileName, FullInfFileName);
4383
4384 currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
4385 ReferenceInfFile(currentInfFileDetails);
4386 if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
4387 {
4388 HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
4389 currentInfFileDetails = NULL;
4390 continue;
4391 }
4392
4393 if (!GetVersionInformationFromInfFile(
4394 currentInfFileDetails->hInf,
4395 &ClassGuid,
4396 &ProviderName,
4397 &DriverDate,
4398 &DriverVersion))
4399 {
4400 SetupCloseInfFile(currentInfFileDetails->hInf);
4401 HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
4402 currentInfFileDetails = NULL;
4403 continue;
4404 }
4405
4406 if (DriverType == SPDIT_CLASSDRIVER)
4407 {
4408 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4409 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
4410 {
4411 goto next;
4412 }
4413 }
4414
4415 /* Get the manufacturers list */
4416 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
4417 while (Result)
4418 {
4419 Result = SetupGetStringFieldW(
4420 &ContextManufacturer,
4421 0, /* Field index */
4422 NULL, 0,
4423 &RequiredSize);
4424 if (Result)
4425 {
4426 /* We got the needed size for the buffer */
4427 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4428 if (!ManufacturerName)
4429 {
4430 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4431 goto done;
4432 }
4433 Result = SetupGetStringFieldW(
4434 &ContextManufacturer,
4435 0, /* Field index */
4436 ManufacturerName, RequiredSize,
4437 &RequiredSize);
4438 }
4439 /* Get manufacturer section name */
4440 Result = SetupGetStringFieldW(
4441 &ContextManufacturer,
4442 1, /* Field index */
4443 ManufacturerSection, LINE_LEN,
4444 &RequiredSize);
4445 if (Result)
4446 {
4447 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
4448 /* Add (possible) extension to manufacturer section name */
4449 Result = SetupDiGetActualSectionToInstallW(
4450 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
4451 if (Result)
4452 {
4453 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
4454 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
4455 }
4456 }
4457 while (Result)
4458 {
4459 if (DriverType == SPDIT_CLASSDRIVER)
4460 {
4461 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4462 if (!AddDriverToList(
4463 &list->DriverListHead,
4464 DriverType,
4465 &ClassGuid,
4466 ContextDevice,
4467 currentInfFileDetails,
4468 filename,
4469 ProviderName,
4470 ManufacturerName,
4471 NULL,
4472 DriverDate, DriverVersion,
4473 0))
4474 {
4475 break;
4476 }
4477 }
4478 else /* DriverType = SPDIT_COMPATDRIVER */
4479 {
4480 /* 1. Get all fields */
4481 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
4482 DWORD DriverRank;
4483 DWORD i;
4484 LPCWSTR currentId;
4485 BOOL DriverAlreadyAdded;
4486
4487 for (i = 2; i <= FieldCount; i++)
4488 {
4489 LPWSTR DeviceId = NULL;
4490 Result = FALSE;
4491 RequiredSize = 128; /* Initial buffer size */
4492 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4493 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
4494 {
4495 HeapFree(GetProcessHeap(), 0, DeviceId);
4496 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
4497 if (!DeviceId)
4498 {
4499 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4500 goto done;
4501 }
4502 Result = SetupGetStringFieldW(
4503 &ContextDevice,
4504 i,
4505 DeviceId, RequiredSize,
4506 &RequiredSize);
4507 }
4508 if (!Result)
4509 {
4510 HeapFree(GetProcessHeap(), 0, DeviceId);
4511 goto done;
4512 }
4513 DriverAlreadyAdded = FALSE;
4514 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
4515 {
4516 if (wcsicmp(DeviceId, currentId) == 0)
4517 {
4518 AddDriverToList(
4519 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
4520 DriverType,
4521 &ClassGuid,
4522 ContextDevice,
4523 currentInfFileDetails,
4524 filename,
4525 ProviderName,
4526 ManufacturerName,
4527 currentId,
4528 DriverDate, DriverVersion,
4529 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
4530 DriverAlreadyAdded = TRUE;
4531 }
4532 }
4533 if (CompatibleIDs)
4534 {
4535 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
4536 {
4537 if (wcsicmp(DeviceId, currentId) == 0)
4538 {
4539 AddDriverToList(
4540 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
4541 DriverType,
4542 &ClassGuid,
4543 ContextDevice,
4544 currentInfFileDetails,
4545 filename,
4546 ProviderName,
4547 ManufacturerName,
4548 currentId,
4549 DriverDate, DriverVersion,
4550 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
4551 DriverAlreadyAdded = TRUE;
4552 }
4553 }
4554 }
4555 HeapFree(GetProcessHeap(), 0, DeviceId);
4556 }
4557 }
4558 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
4559 }
4560
4561 HeapFree(GetProcessHeap(), 0, ManufacturerName);
4562 ManufacturerName = NULL;
4563 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
4564 }
4565
4566 ret = TRUE;
4567 next:
4568 HeapFree(GetProcessHeap(), 0, ProviderName);
4569 ProviderName = NULL;
4570
4571 DereferenceInfFile(currentInfFileDetails);
4572 currentInfFileDetails = NULL;
4573 }
4574 ret = TRUE;
4575 }
4576 }
4577
4578 done:
4579 if (ret)
4580 {
4581 if (DeviceInfoData)
4582 {
4583 InstallParams.Flags |= DI_DIDCOMPAT;
4584 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
4585 }
4586 else
4587 {
4588 InstallParams.Flags |= DI_DIDCLASS;
4589 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
4590 }
4591 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4592 }
4593
4594 HeapFree(GetProcessHeap(), 0, ProviderName);
4595 HeapFree(GetProcessHeap(), 0, ManufacturerName);
4596 HeapFree(GetProcessHeap(), 0, HardwareIDs);
4597 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
4598 HeapFree(GetProcessHeap(), 0, FullInfFileName);
4599 if (currentInfFileDetails)
4600 DereferenceInfFile(currentInfFileDetails);
4601 HeapFree(GetProcessHeap(), 0, Buffer);
4602
4603 TRACE("Returning %d\n", ret);
4604 return ret;
4605 }
4606
4607 /***********************************************************************
4608 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4609 */
4610 BOOL WINAPI
4611 SetupDiDeleteDeviceInfo(
4612 IN HDEVINFO DeviceInfoSet,
4613 IN PSP_DEVINFO_DATA DeviceInfoData)
4614 {
4615 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4616
4617 FIXME("not implemented\n");
4618 SetLastError(ERROR_GEN_FAILURE);
4619 return FALSE;
4620 }
4621
4622
4623 /***********************************************************************
4624 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4625 */
4626 BOOL WINAPI
4627 SetupDiDestroyDriverInfoList(
4628 IN HDEVINFO DeviceInfoSet,
4629 IN PSP_DEVINFO_DATA DeviceInfoData,
4630 IN DWORD DriverType)
4631 {
4632 struct DeviceInfoSet *list;
4633 BOOL ret = FALSE;
4634
4635 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
4636
4637 if (!DeviceInfoSet)
4638 SetLastError(ERROR_INVALID_HANDLE);
4639 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4640 SetLastError(ERROR_INVALID_HANDLE);
4641 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4642 SetLastError(ERROR_INVALID_PARAMETER);
4643 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4644 SetLastError(ERROR_INVALID_PARAMETER);
4645 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4646 SetLastError(ERROR_INVALID_USER_BUFFER);
4647 else
4648 {
4649 PLIST_ENTRY ListEntry;
4650 struct DriverInfoElement *driverInfo;
4651 SP_DEVINSTALL_PARAMS_W InstallParams;
4652
4653 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4654 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
4655 goto done;
4656
4657 if (!DeviceInfoData)
4658 /* Fall back to destroying class driver list */
4659 DriverType = SPDIT_CLASSDRIVER;
4660
4661 if (DriverType == SPDIT_CLASSDRIVER)
4662 {
4663 while (!IsListEmpty(&list->DriverListHead))
4664 {
4665 ListEntry = RemoveHeadList(&list->DriverListHead);
4666 driverInfo = (struct DriverInfoElement *)ListEntry;
4667 DestroyDriverInfoElement(driverInfo);
4668 }
4669 InstallParams.Reserved = 0;
4670 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
4671 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
4672 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
4673 }
4674 else
4675 {
4676 SP_DEVINSTALL_PARAMS_W InstallParamsSet;
4677 struct DeviceInfoElement *deviceInfo;
4678
4679 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4680 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
4681 goto done;
4682 deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4683 while (!IsListEmpty(&deviceInfo->DriverListHead))
4684 {
4685 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
4686 driverInfo = (struct DriverInfoElement *)ListEntry;
4687 if ((PVOID)InstallParamsSet.Reserved == driverInfo)
4688 {
4689 InstallParamsSet.Reserved = 0;
4690 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
4691 }
4692 DestroyDriverInfoElement(driverInfo);
4693 }
4694 InstallParams.Reserved = 0;
4695 InstallParams.Flags &= ~DI_DIDCOMPAT;
4696 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
4697 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4698 }
4699 }
4700
4701 done:
4702 TRACE("Returning %d\n", ret);
4703 return ret;
4704 }
4705
4706
4707 /***********************************************************************
4708 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4709 */
4710 BOOL WINAPI
4711 SetupDiOpenDeviceInfoA(
4712 IN HDEVINFO DeviceInfoSet,
4713 IN PCSTR DeviceInstanceId,
4714 IN HWND hwndParent OPTIONAL,
4715 IN DWORD OpenFlags,
4716 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4717 {
4718 LPWSTR DeviceInstanceIdW = NULL;
4719 BOOL bResult;
4720
4721 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4722
4723 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
4724 if (DeviceInstanceIdW == NULL)
4725 return FALSE;
4726
4727 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
4728 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
4729
4730 MyFree(DeviceInstanceIdW);
4731
4732 return bResult;
4733 }
4734
4735
4736 /***********************************************************************
4737 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4738 */
4739 BOOL WINAPI
4740 SetupDiOpenDeviceInfoW(
4741 IN HDEVINFO DeviceInfoSet,
4742 IN PCWSTR DeviceInstanceId,
4743 IN HWND hwndParent OPTIONAL,
4744 IN DWORD OpenFlags,
4745 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4746 {
4747 struct DeviceInfoSet *list;
4748 HKEY hEnumKey, hKey;
4749 DWORD rc;
4750 BOOL ret = FALSE;
4751
4752 TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4753
4754 if (OpenFlags & DIOD_CANCEL_REMOVE)
4755 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4756
4757 if (!DeviceInfoSet)
4758 SetLastError(ERROR_INVALID_HANDLE);
4759 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4760 SetLastError(ERROR_INVALID_HANDLE);
4761 else if (!DeviceInstanceId)
4762 SetLastError(ERROR_INVALID_PARAMETER);
4763 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
4764 {
4765 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
4766 SetLastError(ERROR_INVALID_FLAGS);
4767 }
4768 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4769 SetLastError(ERROR_INVALID_USER_BUFFER);
4770 else
4771 {
4772 struct DeviceInfoElement *deviceInfo = NULL;
4773 /* Search if device already exists in DeviceInfoSet.
4774 * If yes, return the existing element
4775 * If no, create a new element using informations in registry
4776 */
4777 PLIST_ENTRY ItemList = list->ListHead.Flink;
4778 while (ItemList != &list->ListHead)
4779 {
4780 // TODO
4781 //if (good one)
4782 // break;
4783 FIXME("not implemented\n");
4784 ItemList = ItemList->Flink;
4785 }
4786
4787 if (deviceInfo)
4788 {
4789 /* good one found */
4790 ret = TRUE;
4791 }
4792 else
4793 {
4794 /* Open supposed registry key */
4795 rc = RegOpenKeyExW(
4796 list->HKLM,
4797 EnumKeyName,
4798 0, /* Options */
4799 KEY_ENUMERATE_SUB_KEYS,
4800 &hEnumKey);
4801 if (rc != ERROR_SUCCESS)
4802 {
4803 SetLastError(rc);
4804 return FALSE;
4805 }
4806 rc = RegOpenKeyExW(
4807 hEnumKey,
4808 DeviceInstanceId,
4809 0, /* Options */
4810 KEY_QUERY_VALUE,
4811 &hKey);
4812 RegCloseKey(hEnumKey);
4813 if (rc != ERROR_SUCCESS)
4814 {
4815 if (rc == ERROR_FILE_NOT_FOUND)
4816 rc = ERROR_NO_SUCH_DEVINST;
4817 SetLastError(rc);
4818 return FALSE;
4819 }
4820
4821 /* FIXME: try to get ClassGUID from registry, instead of
4822 * sending GUID_NULL to CreateDeviceInfoElement
4823 */
4824 if (!CreateDeviceInfoElement(DeviceInstanceId, &GUID_NULL, &deviceInfo))
4825 {
4826 RegCloseKey(hKey);
4827 return FALSE;
4828 }
4829 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4830
4831 RegCloseKey(hKey);
4832 ret = TRUE;
4833 }
4834
4835 if (ret && deviceInfo && DeviceInfoData)
4836 {
4837 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
4838 DeviceInfoData->DevInst = (DWORD)list->hMachine;
4839 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4840 }
4841 }
4842
4843 return ret;
4844 }
4845
4846
4847 /***********************************************************************
4848 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4849 */
4850 BOOL WINAPI
4851 SetupDiEnumDriverInfoA(
4852 IN HDEVINFO DeviceInfoSet,
4853 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4854 IN DWORD DriverType,
4855 IN DWORD MemberIndex,
4856 OUT PSP_DRVINFO_DATA_A DriverInfoData)
4857 {
4858 SP_DRVINFO_DATA_V2_W driverInfoData2W;
4859 BOOL ret = FALSE;
4860
4861 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
4862 DriverType, MemberIndex, DriverInfoData);
4863
4864 if (DriverInfoData == NULL)
4865 SetLastError(ERROR_INVALID_PARAMETER);
4866 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
4867 SetLastError(ERROR_INVALID_USER_BUFFER);
4868 else
4869 {
4870 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
4871 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
4872 DriverType, MemberIndex, &driverInfoData2W);
4873
4874 if (ret)
4875 {
4876 /* Do W->A conversion */
4877 DriverInfoData->DriverType = driverInfoData2W.DriverType;
4878 DriverInfoData->Reserved = driverInfoData2W.Reserved;
4879 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
4880 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
4881 {
4882 DriverInfoData->Description[0] = '\0';
4883 ret = FALSE;
4884 }
4885 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
4886 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
4887 {
4888 DriverInfoData->MfgName[0] = '\0';
4889 ret = FALSE;
4890 }
4891 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
4892 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
4893 {
4894 DriverInfoData->ProviderName[0] = '\0';
4895 ret = FALSE;
4896 }
4897 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
4898 {
4899 /* Copy more fields */
4900 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
4901 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
4902 }
4903 }
4904 }
4905
4906 TRACE("Returning %d\n", ret);
4907 return ret;
4908 }
4909
4910
4911 /***********************************************************************
4912 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4913 */
4914 BOOL WINAPI
4915 SetupDiEnumDriverInfoW(
4916 IN HDEVINFO DeviceInfoSet,
4917 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4918 IN DWORD DriverType,
4919 IN DWORD MemberIndex,
4920 OUT PSP_DRVINFO_DATA_W DriverInfoData)
4921 {
4922 PLIST_ENTRY ListHead;
4923 BOOL ret = FALSE;
4924
4925 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
4926 DriverType, MemberIndex, DriverInfoData);
4927
4928 if (!DeviceInfoSet || !DriverInfoData)
4929 SetLastError(ERROR_INVALID_PARAMETER);
4930 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4931 SetLastError(ERROR_INVALID_HANDLE);
4932 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4933 SetLastError(ERROR_INVALID_HANDLE);
4934 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
4935 SetLastError(ERROR_INVALID_PARAMETER);
4936 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
4937 SetLastError(ERROR_INVALID_PARAMETER);
4938 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
4939 SetLastError(ERROR_INVALID_PARAMETER);
4940 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
4941 SetLastError(ERROR_INVALID_USER_BUFFER);
4942 else
4943 {
4944 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4945 PLIST_ENTRY ItemList;
4946 if (DriverType == SPDIT_CLASSDRIVER ||
4947 devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
4948 {
4949 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
4950 }
4951 else
4952 {
4953 ListHead = &devInfo->DriverListHead;
4954 }
4955
4956 ItemList = ListHead->Flink;
4957 while (ItemList != ListHead && MemberIndex-- > 0)
4958 ItemList = ItemList->Flink;
4959 if (ItemList == ListHead)
4960 SetLastError(ERROR_NO_MORE_ITEMS);
4961 else
4962 {
4963 struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
4964
4965 memcpy(
4966 &DriverInfoData->DriverType,
4967 &DrvInfo->Info.DriverType,
4968 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
4969 ret = TRUE;
4970 }
4971 }
4972
4973 TRACE("Returning %d\n", ret);
4974 return ret;
4975 }
4976
4977
4978 /***********************************************************************
4979 * SetupDiGetSelectedDriverA (SETUPAPI.@)
4980 */
4981 BOOL WINAPI
4982 SetupDiGetSelectedDriverA(
4983 IN HDEVINFO DeviceInfoSet,
4984 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4985 OUT PSP_DRVINFO_DATA_A DriverInfoData)
4986 {
4987 SP_DRVINFO_DATA_V2_W driverInfoData2W;
4988 BOOL ret = FALSE;
4989
4990 if (DriverInfoData == NULL)
4991 SetLastError(ERROR_INVALID_PARAMETER);
4992 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
4993 SetLastError(ERROR_INVALID_USER_BUFFER);
4994 else
4995 {
4996 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
4997
4998 ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
4999 DeviceInfoData,
5000 &driverInfoData2W);
5001
5002 if (ret)
5003 {
5004 /* Do W->A conversion */
5005 DriverInfoData->DriverType = driverInfoData2W.DriverType;
5006 DriverInfoData->Reserved = driverInfoData2W.Reserved;
5007 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
5008 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
5009 {
5010 DriverInfoData->Description[0] = '\0';
5011 ret = FALSE;
5012 }
5013 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
5014 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
5015 {
5016 DriverInfoData->MfgName[0] = '\0';
5017 ret = FALSE;
5018 }
5019 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
5020 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
5021 {
5022 DriverInfoData->ProviderName[0] = '\0';
5023 ret = FALSE;
5024 }
5025 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5026 {
5027 /* Copy more fields */
5028 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
5029 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
5030 }
5031 }
5032 }
5033
5034 return ret;
5035 }
5036
5037
5038 /***********************************************************************
5039 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5040 */
5041 BOOL WINAPI
5042 SetupDiGetSelectedDriverW(
5043 IN HDEVINFO DeviceInfoSet,
5044 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5045 OUT PSP_DRVINFO_DATA_W DriverInfoData)
5046 {
5047 BOOL ret = FALSE;
5048
5049 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5050
5051 if (!DeviceInfoSet || !DriverInfoData)
5052 SetLastError(ERROR_INVALID_PARAMETER);
5053 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5054 SetLastError(ERROR_INVALID_HANDLE);
5055 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5056 SetLastError(ERROR_INVALID_HANDLE);
5057 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5058 SetLastError(ERROR_INVALID_USER_BUFFER);
5059 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5060 SetLastError(ERROR_INVALID_USER_BUFFER);
5061 else
5062 {
5063 SP_DEVINSTALL_PARAMS InstallParams;
5064
5065 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
5066 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
5067 {
5068 struct DriverInfoElement *driverInfo;
5069 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
5070 if (driverInfo == NULL)
5071 SetLastError(ERROR_NO_DRIVER_SELECTED);
5072 else
5073 {
5074 memcpy(
5075 &DriverInfoData->DriverType,
5076 &driverInfo->Info.DriverType,
5077 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
5078 ret = TRUE;
5079 }
5080 }
5081 }
5082
5083 TRACE("Returning %d\n", ret);
5084 return ret;
5085 }
5086
5087
5088 /***********************************************************************
5089 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5090 */
5091 BOOL WINAPI
5092 SetupDiSetSelectedDriverA(
5093 IN HDEVINFO DeviceInfoSet,
5094 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5095 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
5096 {
5097 SP_DRVINFO_DATA_V1_W DriverInfoDataW;
5098 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
5099 BOOL ret = FALSE;
5100
5101 if (DriverInfoData != NULL)
5102 {
5103 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
5104 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
5105 {
5106 SetLastError(ERROR_INVALID_PARAMETER);
5107 return FALSE;
5108 }
5109
5110 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5111 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5112
5113 if (DriverInfoDataW.Reserved == 0)
5114 {
5115 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5116
5117 /* convert the strings to unicode */
5118 if (!MultiByteToWideChar(CP_ACP,
5119 0,
5120 DriverInfoData->Description,
5121 LINE_LEN,
5122 DriverInfoDataW.Description,
5123 LINE_LEN) ||
5124 !MultiByteToWideChar(CP_ACP,
5125 0,
5126 DriverInfoData->ProviderName,
5127 LINE_LEN,
5128 DriverInfoDataW.ProviderName,
5129 LINE_LEN))
5130 {
5131 return FALSE;
5132 }
5133 }
5134
5135 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
5136 }
5137
5138 ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
5139 DeviceInfoData,
5140 pDriverInfoDataW);
5141
5142 if (ret && pDriverInfoDataW != NULL)
5143 {
5144 DriverInfoData->Reserved = DriverInfoDataW.Reserved;
5145 }
5146
5147 return ret;
5148 }
5149
5150
5151 /***********************************************************************
5152 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5153 */
5154 BOOL WINAPI
5155 SetupDiSetSelectedDriverW(
5156 IN HDEVINFO DeviceInfoSet,
5157 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5158 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
5159 {
5160 BOOL ret = FALSE;
5161
5162 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
5163
5164 if (!DeviceInfoSet)
5165 SetLastError(ERROR_INVALID_PARAMETER);
5166 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5167 SetLastError(ERROR_INVALID_HANDLE);
5168 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5169 SetLastError(ERROR_INVALID_HANDLE);
5170 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5171 SetLastError(ERROR_INVALID_USER_BUFFER);
5172 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
5173 SetLastError(ERROR_INVALID_USER_BUFFER);
5174 else
5175 {
5176 struct DriverInfoElement **pDriverInfo;
5177 PLIST_ENTRY ListHead, ItemList;
5178
5179 if (DeviceInfoData)
5180 {
5181 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
5182 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
5183 }
5184 else
5185 {
5186 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
5187 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
5188 }
5189
5190 if (!DriverInfoData)
5191 {
5192 *pDriverInfo = NULL;
5193 ret = TRUE;
5194 }
5195 else
5196 {
5197 /* Search selected driver in list */
5198 ItemList = ListHead->Flink;
5199 while (ItemList != ListHead)
5200 {
5201 if (DriverInfoData->Reserved != 0)
5202 {
5203 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
5204 break;
5205 }
5206 else
5207 {
5208 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5209 struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
5210 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
5211 && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
5212 && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
5213 {
5214 break;
5215 }
5216 }
5217 }
5218 if (ItemList == ListHead)
5219 SetLastError(ERROR_INVALID_PARAMETER);
5220 else
5221 {
5222 *pDriverInfo = (struct DriverInfoElement *)ItemList;
5223 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
5224 ret = TRUE;
5225 TRACE("Choosing driver whose rank is 0x%lx\n",
5226 ((struct DriverInfoElement *)ItemList)->DriverRank);
5227 if (DeviceInfoData)
5228 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
5229 }
5230 }
5231 }
5232
5233 TRACE("Returning %d\n", ret);
5234 return ret;
5235 }
5236
5237 /***********************************************************************
5238 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5239 */
5240 BOOL WINAPI
5241 SetupDiGetDriverInfoDetailA(
5242 IN HDEVINFO DeviceInfoSet,
5243 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5244 IN PSP_DRVINFO_DATA_A DriverInfoData,
5245 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
5246 IN DWORD DriverInfoDetailDataSize,
5247 OUT PDWORD RequiredSize OPTIONAL)
5248 {
5249 SP_DRVINFO_DATA_V2_W DriverInfoDataW;
5250 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
5251 DWORD BufSize = 0;
5252 DWORD HardwareIDLen = 0;
5253 BOOL ret = FALSE;
5254
5255 /* do some sanity checks, the unicode version might do more thorough checks */
5256 if (DriverInfoData == NULL ||
5257 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
5258 (DriverInfoDetailData != NULL &&
5259 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
5260 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
5261 {
5262 SetLastError(ERROR_INVALID_PARAMETER);
5263 goto Cleanup;
5264 }
5265
5266 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5267 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
5268 {
5269 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
5270 }
5271 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
5272 {
5273 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
5274 }
5275 else
5276 {
5277 SetLastError(ERROR_INVALID_PARAMETER);
5278 goto Cleanup;
5279 }
5280 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
5281 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
5282
5283 /* convert the strings to unicode */
5284 if (MultiByteToWideChar(CP_ACP,
5285 0,
5286 DriverInfoData->Description,
5287 LINE_LEN,
5288 DriverInfoDataW.Description,
5289 LINE_LEN) &&
5290 MultiByteToWideChar(CP_ACP,
5291 0,
5292 DriverInfoData->MfgName,
5293 LINE_LEN,
5294 DriverInfoDataW.MfgName,
5295 LINE_LEN) &&
5296 MultiByteToWideChar(CP_ACP,
5297 0,
5298 DriverInfoData->ProviderName,
5299 LINE_LEN,
5300 DriverInfoDataW.ProviderName,
5301 LINE_LEN))
5302 {
5303 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
5304 {
5305 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
5306 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
5307 }
5308
5309 if (DriverInfoDetailData != NULL)
5310 {
5311 /* calculate the unicode buffer size from the ansi buffer size */
5312 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
5313 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
5314 (HardwareIDLen * sizeof(WCHAR));
5315
5316 DriverInfoDetailDataW = MyMalloc(BufSize);
5317 if (DriverInfoDetailDataW == NULL)
5318 {
5319 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5320 goto Cleanup;
5321 }
5322
5323 /* initialize the buffer */
5324 ZeroMemory(DriverInfoDetailDataW,
5325 BufSize);
5326 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
5327 }
5328
5329 /* call the unicode version */
5330 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
5331 DeviceInfoData,
5332 &DriverInfoDataW,
5333 DriverInfoDetailDataW,
5334 BufSize,
5335 RequiredSize);
5336
5337 if (ret)
5338 {
5339 if (DriverInfoDetailDataW != NULL)
5340 {
5341 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5342 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
5343 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
5344 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
5345 if (WideCharToMultiByte(CP_ACP,
5346 0,
5347 DriverInfoDetailDataW->SectionName,
5348 LINE_LEN,
5349 DriverInfoDetailData->SectionName,
5350 LINE_LEN,
5351 NULL,
5352 NULL) &&
5353 WideCharToMultiByte(CP_ACP,
5354 0,
5355 DriverInfoDetailDataW->InfFileName,
5356 MAX_PATH,
5357 DriverInfoDetailData->InfFileName,
5358 MAX_PATH,
5359 NULL,
5360 NULL) &&
5361 WideCharToMultiByte(CP_ACP,
5362 0,
5363 DriverInfoDetailDataW->DrvDescription,
5364 LINE_LEN,
5365 DriverInfoDetailData->DrvDescription,
5366 LINE_LEN,
5367 NULL,
5368 NULL) &&
5369 WideCharToMultiByte(CP_ACP,
5370 0,
5371 DriverInfoDetailDataW->HardwareID,
5372 HardwareIDLen,
5373 DriverInfoDetailData->HardwareID,
5374 HardwareIDLen,
5375 NULL,
5376 NULL))
5377 {
5378 DWORD len, cnt = 0;
5379 DWORD hwidlen = HardwareIDLen;
5380 CHAR *s = DriverInfoDetailData->HardwareID;
5381
5382 /* count the strings in the list */
5383 while (*s != '\0')
5384 {
5385 len = lstrlenA(s) + 1;
5386 if (hwidlen > len)
5387 {
5388 cnt++;
5389 s += len;
5390 hwidlen -= len;
5391 }
5392 else
5393 {
5394 /* looks like the string list wasn't terminated... */
5395 SetLastError(ERROR_INVALID_USER_BUFFER);
5396 ret = FALSE;
5397 break;
5398 }
5399 }
5400
5401 /* make sure CompatIDsOffset points to the second string in the
5402 list, if present */
5403 if (cnt > 1)
5404 {
5405 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
5406 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
5407 DriverInfoDetailData->CompatIDsOffset + 1;
5408 }
5409 else
5410 {
5411 DriverInfoDetailData->CompatIDsOffset = 0;
5412 DriverInfoDetailData->CompatIDsLength = 0;
5413 }
5414 }
5415 else
5416 {
5417 ret = FALSE;
5418 }
5419 }
5420
5421 if (RequiredSize != NULL)
5422 {
5423 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
5424 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
5425 }
5426 }
5427 }
5428
5429 Cleanup:
5430 if (DriverInfoDetailDataW != NULL)
5431 {
5432 MyFree(DriverInfoDetailDataW);
5433 }
5434
5435 return ret;
5436 }
5437
5438 /***********************************************************************
5439 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5440 */
5441 BOOL WINAPI
5442 SetupDiGetDriverInfoDetailW(
5443 IN HDEVINFO DeviceInfoSet,
5444 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5445 IN PSP_DRVINFO_DATA_W DriverInfoData,
5446 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
5447 IN DWORD DriverInfoDetailDataSize,
5448 OUT PDWORD RequiredSize OPTIONAL)
5449 {
5450 BOOL ret = FALSE;
5451
5452 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
5453 DriverInfoData, DriverInfoDetailData,
5454 DriverInfoDetailDataSize, RequiredSize);
5455
5456 if (!DeviceInfoSet)
5457 SetLastError(ERROR_INVALID_PARAMETER);
5458 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5459 SetLastError(ERROR_INVALID_HANDLE);
5460 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5461 SetLastError(ERROR_INVALID_HANDLE);
5462 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5463 SetLastError(ERROR_INVALID_USER_BUFFER);
5464 else if (!DriverInfoData)
5465 SetLastError(ERROR_INVALID_PARAMETER);
5466 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
5467 SetLastError(ERROR_INVALID_PARAMETER);
5468 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
5469 SetLastError(ERROR_INVALID_PARAMETER);
5470 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
5471 SetLastError(ERROR_INVALID_USER_BUFFER);
5472 else if (DriverInfoData->Reserved == 0)
5473 SetLastError(ERROR_NO_DRIVER_SELECTED);
5474 else
5475 {
5476 struct DriverInfoElement *driverInfoElement;
5477 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
5478
5479 memcpy(
5480 DriverInfoDetailData,
5481 &driverInfoElement->Details,
5482 driverInfoElement->Details.cbSize);
5483 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5484 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5485 */
5486 ret = TRUE;
5487 }
5488
5489 TRACE("Returning %d\n", ret);
5490 return ret;
5491 }
5492
5493 /***********************************************************************
5494 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5495 */
5496 BOOL WINAPI
5497 SetupDiSelectBestCompatDrv(
5498 IN HDEVINFO DeviceInfoSet,
5499 IN PSP_DEVINFO_DATA DeviceInfoData)
5500 {
5501 SP_DRVINFO_DATA_W drvInfoData;
5502 BOOL ret;
5503
5504 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5505
5506 /* Drivers are sorted by rank in the driver list, so
5507 * the first driver in the list is the best one.
5508 */
5509 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
5510 ret = SetupDiEnumDriverInfoW(
5511 DeviceInfoSet,
5512 DeviceInfoData,
5513 SPDIT_COMPATDRIVER,
5514 0, /* Member index */
5515 &drvInfoData);
5516
5517 if (ret)
5518 {
5519 ret = SetupDiSetSelectedDriverW(
5520 DeviceInfoSet,
5521 DeviceInfoData,
5522 &drvInfoData);
5523 }
5524
5525 TRACE("Returning %d\n", ret);
5526 return ret;
5527 }
5528
5529 /***********************************************************************
5530 * SetupDiInstallDriverFiles (SETUPAPI.@)
5531 */
5532 BOOL WINAPI
5533 SetupDiInstallDriverFiles(
5534 IN HDEVINFO DeviceInfoSet,
5535 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5536 {
5537 BOOL ret = FALSE;
5538
5539 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5540
5541 if (!DeviceInfoSet)
5542 SetLastError(ERROR_INVALID_PARAMETER);
5543 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5544 SetLastError(ERROR_INVALID_HANDLE);
5545 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5546 SetLastError(ERROR_INVALID_HANDLE);
5547 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5548 SetLastError(ERROR_INVALID_USER_BUFFER);
5549 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
5550 SetLastError(ERROR_NO_DRIVER_SELECTED);
5551 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
5552 SetLastError(ERROR_NO_DRIVER_SELECTED);
5553 else
5554 {
5555 SP_DEVINSTALL_PARAMS_W InstallParams;
5556 struct DriverInfoElement *SelectedDriver;
5557 WCHAR SectionName[MAX_PATH];
5558 DWORD SectionNameLength = 0;
5559
5560 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5561 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5562 if (!ret)
5563 goto done;
5564
5565 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5566 if (!SelectedDriver)
5567 {
5568 SetLastError(ERROR_NO_DRIVER_SELECTED);
5569 goto done;
5570 }
5571
5572 ret = SetupDiGetActualSectionToInstallW(
5573 SelectedDriver->InfFileDetails->hInf,
5574 SelectedDriver->Details.SectionName,
5575 SectionName, MAX_PATH, &SectionNameLength, NULL);
5576 if (!ret)
5577 goto done;
5578
5579 if (!InstallParams.InstallMsgHandler)
5580 {
5581 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
5582 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5583 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5584 }
5585 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5586 SelectedDriver->InfFileDetails->hInf, SectionName,
5587 SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
5588 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5589 DeviceInfoSet, DeviceInfoData);
5590 }
5591
5592 done:
5593 TRACE("Returning %d\n", ret);
5594 return ret;
5595 }
5596
5597 /***********************************************************************
5598 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5599 */
5600 BOOL WINAPI
5601 SetupDiRegisterCoDeviceInstallers(
5602 IN HDEVINFO DeviceInfoSet,
5603 IN PSP_DEVINFO_DATA DeviceInfoData)
5604 {
5605 BOOL ret = FALSE; /* Return value */
5606
5607 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5608
5609 if (!DeviceInfoSet)
5610 SetLastError(ERROR_INVALID_PARAMETER);
5611 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5612 SetLastError(ERROR_INVALID_HANDLE);
5613 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5614 SetLastError(ERROR_INVALID_HANDLE);
5615 else if (!DeviceInfoData)
5616 SetLastError(ERROR_INVALID_PARAMETER);
5617 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5618 SetLastError(ERROR_INVALID_USER_BUFFER);
5619 else
5620 {
5621 SP_DEVINSTALL_PARAMS_W InstallParams;
5622 struct DriverInfoElement *SelectedDriver;
5623 BOOL Result;
5624 DWORD DoAction;
5625 WCHAR SectionName[MAX_PATH];
5626 DWORD SectionNameLength = 0;
5627 HKEY hKey = INVALID_HANDLE_VALUE;;
5628
5629 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5630 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5631 if (!Result)
5632 goto cleanup;
5633
5634 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5635 if (SelectedDriver == NULL)
5636 {
5637 SetLastError(ERROR_NO_DRIVER_SELECTED);
5638 goto cleanup;
5639 }
5640
5641 /* Get .CoInstallers section name */
5642 Result = SetupDiGetActualSectionToInstallW(
5643 SelectedDriver->InfFileDetails->hInf,
5644 SelectedDriver->Details.SectionName,
5645 SectionName, MAX_PATH, &SectionNameLength, NULL);
5646 if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
5647 goto cleanup;
5648 wcscat(SectionName, L".CoInstallers");
5649
5650 /* Open/Create driver key information */
5651 #if _WIN32_WINNT >= 0x502
5652 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5653 #else
5654 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5655 #endif
5656 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5657 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5658 if (hKey == INVALID_HANDLE_VALUE)
5659 goto cleanup;
5660
5661 /* Install .CoInstallers section */
5662 DoAction = SPINST_REGISTRY;
5663 if (!(InstallParams.Flags & DI_NOFILECOPY))
5664 {
5665 DoAction |= SPINST_FILES;
5666 if (!InstallParams.InstallMsgHandler)
5667 {
5668 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
5669 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5670 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5671 }
5672 }
5673 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5674 SelectedDriver->InfFileDetails->hInf, SectionName,
5675 DoAction, hKey, NULL, SP_COPY_NEWER,
5676 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5677 DeviceInfoSet, DeviceInfoData);
5678 if (!Result)
5679 goto cleanup;
5680
5681 ret = TRUE;
5682
5683 cleanup:
5684 if (hKey != INVALID_HANDLE_VALUE)
5685 RegCloseKey(hKey);
5686 }
5687
5688 TRACE("Returning %d\n", ret);
5689 return ret;
5690 }
5691
5692 /***********************************************************************
5693 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5694 */
5695 BOOL WINAPI
5696 SetupDiInstallDeviceInterfaces(
5697 IN HDEVINFO DeviceInfoSet,
5698 IN PSP_DEVINFO_DATA DeviceInfoData)
5699 {
5700 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5701
5702 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5703 //SetLastError(ERROR_GEN_FAILURE);
5704 //return FALSE;
5705 return TRUE;
5706 }
5707
5708 BOOL
5709 InfIsFromOEMLocation(
5710 IN PCWSTR FullName,
5711 OUT LPBOOL IsOEMLocation)
5712 {
5713 PWCHAR last;
5714
5715 last = strrchrW(FullName, '\\');
5716 if (!last)
5717 {
5718 /* No directory specified */
5719 *IsOEMLocation = FALSE;
5720 }
5721 else
5722 {
5723 WCHAR Windir[MAX_PATH];
5724 UINT ret;
5725
5726 ret = GetWindowsDirectory(Windir, MAX_PATH);
5727 if (ret == 0 || ret >= MAX_PATH)
5728 {
5729 SetLastError(ERROR_GEN_FAILURE);
5730 return FALSE;
5731 }
5732
5733 if (strncmpW(FullName, Windir, last - FullName) == 0)
5734 {
5735 /* The path is %SYSTEMROOT%\Inf */
5736 *IsOEMLocation = FALSE;
5737 }
5738 else
5739 {
5740 /* The file is in another place */
5741 *IsOEMLocation = TRUE;
5742 }
5743 }
5744 return TRUE;
5745 }
5746
5747 /***********************************************************************
5748 * SetupDiInstallDevice (SETUPAPI.@)
5749 */
5750 BOOL WINAPI
5751 SetupDiInstallDevice(
5752 IN HDEVINFO DeviceInfoSet,
5753 IN PSP_DEVINFO_DATA DeviceInfoData)
5754 {
5755 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5756 SP_DEVINSTALL_PARAMS_W InstallParams;
5757 struct DriverInfoElement *SelectedDriver;
5758 SYSTEMTIME DriverDate;
5759 WCHAR SectionName[MAX_PATH];
5760 WCHAR Buffer[32];
5761 DWORD SectionNameLength = 0;
5762 BOOL Result = FALSE;
5763 INFCONTEXT ContextService;
5764 INT Flags;
5765 ULONG DoAction;
5766 DWORD RequiredSize;
5767 LPCWSTR AssociatedService = NULL;
5768 LPWSTR pSectionName = NULL;
5769 WCHAR ClassName[MAX_CLASS_NAME_LEN];
5770 GUID ClassGuid;
5771 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
5772 BOOL RebootRequired = FALSE;
5773 HKEY hKey = INVALID_HANDLE_VALUE;
5774 HKEY hClassKey = INVALID_HANDLE_VALUE;
5775 BOOL NeedtoCopyFile;
5776 LONG rc;
5777 BOOL ret = FALSE; /* Return value */
5778
5779 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5780
5781 if (!DeviceInfoSet)
5782 SetLastError(ERROR_INVALID_PARAMETER);
5783 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5784 SetLastError(ERROR_INVALID_HANDLE);
5785 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5786 SetLastError(ERROR_INVALID_HANDLE);
5787 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5788 SetLastError(ERROR_INVALID_USER_BUFFER);
5789 else
5790 Result = TRUE;
5791
5792 if (!Result)
5793 {
5794 /* One parameter is bad */
5795 goto cleanup;
5796 }
5797
5798 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5799 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5800 if (!Result)
5801 goto cleanup;
5802
5803 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
5804 {
5805 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5806 goto cleanup;
5807 }
5808
5809 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5810 if (SelectedDriver == NULL)
5811 {
5812 SetLastError(ERROR_NO_DRIVER_SELECTED);
5813 goto cleanup;
5814 }
5815
5816 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
5817
5818 Result = SetupDiGetActualSectionToInstallW(
5819 SelectedDriver->InfFileDetails->hInf,
5820 SelectedDriver->Details.SectionName,
5821 SectionName, MAX_PATH, &SectionNameLength, NULL);
5822 if (!Result || SectionNameLength > MAX_PATH - 9)
5823 goto cleanup;
5824 pSectionName = &SectionName[wcslen(SectionName)];
5825
5826 /* Get information from [Version] section */
5827 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
5828 goto cleanup;
5829 /* Format ClassGuid to a string */
5830 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
5831 goto cleanup;
5832 RequiredSize = lstrlenW(lpGuidString);
5833 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
5834 if (!lpFullGuidString)
5835 {
5836 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5837 goto cleanup;
5838 }
5839 lpFullGuidString[0] = '{';
5840 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
5841 lpFullGuidString[RequiredSize + 1] = '}';
5842 lpFullGuidString[RequiredSize + 2] = '\0';
5843
5844 /* Open/Create driver key information */
5845 #if _WIN32_WINNT >= 0x502
5846 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5847 #else
5848 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5849 #endif
5850 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5851 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5852 if (hKey == INVALID_HANDLE_VALUE)
5853 goto cleanup;
5854
5855 /* Install main section */
5856 DoAction = SPINST_REGISTRY;
5857 if (!(InstallParams.Flags & DI_NOFILECOPY))
5858 {
5859 DoAction |= SPINST_FILES;
5860 if (!InstallParams.InstallMsgHandler)
5861 {
5862 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
5863 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5864 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5865 }
5866 }
5867 *pSectionName = '\0';
5868 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5869 SelectedDriver->InfFileDetails->hInf, SectionName,
5870 DoAction, hKey, NULL, SP_COPY_NEWER,
5871 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
5872 DeviceInfoSet, DeviceInfoData);
5873 if (!Result)
5874 goto cleanup;
5875 if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
5876 {
5877 if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
5878 {
5879 /* Delete resources allocated by SetupInitDefaultQueueCallback */
5880 SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
5881 }
5882 }
5883 InstallParams.Flags |= DI_NOFILECOPY;
5884 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5885
5886 /* Write information to driver key */
5887 *pSectionName = UNICODE_NULL;
5888 TRACE("Write information to driver key\n");
5889 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5890 TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
5891 TRACE("DriverVersion : '%u.%u.%u.%u'\n", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
5892 TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
5893 TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
5894 TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
5895 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
5896 TRACE("ProviderName : '%S'\n", SelectedDriver->Info.ProviderName);
5897 swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5898 rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
5899 if (rc == ERROR_SUCCESS)
5900 rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
5901 if (rc == ERROR_SUCCESS)
5902 rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5903 if (rc == ERROR_SUCCESS)
5904 {
5905 swprintf(Buffer, L"%u.%u.%u.%u", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
5906 rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
5907 }
5908 if (rc == ERROR_SUCCESS)
5909 rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
5910 if (rc == ERROR_SUCCESS)
5911 rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5912 if (rc == ERROR_SUCCESS)
5913 rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5914 if (rc == ERROR_SUCCESS)
5915 rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
5916 if (rc == ERROR_SUCCESS)
5917 rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
5918 if (rc != ERROR_SUCCESS)
5919 {
5920 SetLastError(rc);
5921 goto cleanup;
5922 }
5923 RegCloseKey(hKey);
5924 hKey = INVALID_HANDLE_VALUE;
5925
5926 /* FIXME: Process .LogConfigOverride section */
5927
5928 /* Install .Services section */
5929 wcscpy(pSectionName, L".Services");
5930 Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf, SectionName, NULL, &ContextService);
5931 while (Result)
5932 {
5933 LPWSTR ServiceName = NULL;
5934 LPWSTR ServiceSection = NULL;
5935
5936 Result = SetupGetStringFieldW(
5937 &ContextService,
5938 1, /* Field index */
5939 NULL, 0,
5940 &RequiredSize);
5941 if (!Result)
5942 goto nextfile;
5943 if (RequiredSize > 0)
5944 {
5945 /* We got the needed size for the buffer */
5946 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5947 if (!ServiceName)
5948 {
5949 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5950 goto nextfile;
5951 }
5952 Result = SetupGetStringFieldW(
5953 &ContextService,
5954 1, /* Field index */
5955 ServiceName, RequiredSize,
5956 &RequiredSize);
5957 if (!Result)
5958 goto nextfile;
5959 }
5960 Result = SetupGetIntField(
5961 &ContextService,
5962 2, /* Field index */
5963 &Flags);
5964 if (!Result)
5965 {
5966 /* The field may be empty. Ignore the error */
5967 Flags = 0;
5968 }
5969 Result = SetupGetStringFieldW(
5970 &ContextService,
5971 3, /* Field index */
5972 NULL, 0,
5973 &RequiredSize);
5974 if (!Result)
5975 {
5976 if (GetLastError() == ERROR_INVALID_PARAMETER)
5977 {
5978 /* This first is probably missing. It is not
5979 * required, so ignore the error */
5980 RequiredSize = 0;
5981 Result = TRUE;
5982 }
5983 else
5984 goto nextfile;
5985 }
5986 if (RequiredSize > 0)
5987 {
5988 /* We got the needed size for the buffer */
5989 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5990 if (!ServiceSection)
5991 {
5992 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5993 goto nextfile;
5994 }
5995 Result = SetupGetStringFieldW(
5996 &ContextService,
5997 3, /* Field index */
5998 ServiceSection, RequiredSize,
5999 &RequiredSize);
6000 if (!Result)
6001 goto nextfile;
6002
6003 SetLastError(ERROR_SUCCESS);
6004 Result = SetupInstallServicesFromInfSectionExW(
6005 SelectedDriver->InfFileDetails->hInf,
6006 ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
6007 }
6008 if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
6009 {
6010 AssociatedService = ServiceName;
6011 ServiceName = NULL;
6012 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
6013 RebootRequired = TRUE;
6014 }
6015 nextfile:
6016 HeapFree(GetProcessHeap(), 0, ServiceName);
6017 HeapFree(GetProcessHeap(), 0, ServiceSection);
6018 if (!Result)
6019 goto cleanup;
6020 Result = SetupFindNextLine(&ContextService, &ContextService);
6021 }
6022
6023 /* Copy .inf file to Inf\ directory (if needed) */
6024 Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
6025 if (!Result)
6026 goto cleanup;
6027 if (NeedtoCopyFile)
6028 {
6029 Result = SetupCopyOEMInfW(
6030 SelectedDriver->InfFileDetails->FullInfFileName,
6031 NULL,
6032 SPOST_NONE,
6033 SP_COPY_NOOVERWRITE,
6034 NULL, 0,
6035 NULL,
6036 NULL);
6037 if (!Result)
6038 goto cleanup;
6039 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6040 * to release use of current InfFile */
6041 }
6042
6043 /* Open device registry key */
6044 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
6045 if (hKey == INVALID_HANDLE_VALUE)
6046 goto cleanup;
6047
6048 /* Install .HW section */
6049 wcscpy(pSectionName, L".HW");
6050 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
6051 SelectedDriver->InfFileDetails->hInf, SectionName,
6052 SPINST_REGISTRY, hKey, NULL, 0,
6053 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
6054 DeviceInfoSet, DeviceInfoData);
6055 if (!Result)
6056 goto cleanup;
6057
6058 /* Write information to enum key */
6059 TRACE("Write information to enum key\n");
6060 TRACE("Class : '%S'\n", ClassName);
6061 TRACE("ClassGUID : '%S'\n", lpFullGuidString);
6062 TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
6063 TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
6064 TRACE("Service : '%S'\n", AssociatedService);
6065 rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
6066 if (rc == ERROR_SUCCESS)
6067 rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
6068 if (rc == ERROR_SUCCESS)
6069 rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
6070 if (rc == ERROR_SUCCESS)
6071 rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
6072 if (rc == ERROR_SUCCESS && *AssociatedService)
6073 rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
6074 if (rc != ERROR_SUCCESS)
6075 {
6076 SetLastError(rc);
6077 goto cleanup;
6078 }
6079
6080 /* Start the device */
6081 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
6082 {
6083 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
6084 NTSTATUS Status;
6085 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
6086 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
6087 ret = NT_SUCCESS(Status);
6088 }
6089 else
6090 ret = TRUE;
6091
6092 cleanup:
6093 /* End of installation */
6094 if (hClassKey != INVALID_HANDLE_VALUE)
6095 RegCloseKey(hClassKey);
6096 if (hKey != INVALID_HANDLE_VALUE)
6097 RegCloseKey(hKey);
6098 if (lpGuidString)
6099 RpcStringFreeW(&lpGuidString);
6100 HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
6101 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
6102
6103 TRACE("Returning %d\n", ret);
6104 return ret;
6105 }