7e6d27e7f55f972d7ecd018ae089422b03bb0c31
[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 DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
34 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
35 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
36
37 /* FIXME: header mess */
38 DEFINE_GUID(GUID_NULL,
39 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
40 typedef DWORD
41 (CALLBACK* CLASS_INSTALL_PROC) (
42 IN DI_FUNCTION InstallFunction,
43 IN HDEVINFO DeviceInfoSet,
44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
45 typedef BOOL
46 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
47 IN HDEVINFO DeviceInfoSet,
48 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
49 typedef DWORD
50 (CALLBACK* COINSTALLER_PROC) (
51 IN DI_FUNCTION InstallFunction,
52 IN HDEVINFO DeviceInfoSet,
53 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
54 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
55 typedef BOOL
56 (WINAPI* PROPERTY_PAGE_PROVIDER) (
57 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
58 IN LPFNADDPROPSHEETPAGE fAddFunc,
59 IN LPARAM lParam);
60 typedef BOOL
61 (*UPDATE_CLASS_PARAM_HANDLER) (
62 IN HDEVINFO DeviceInfoSet,
63 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
64 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
65 IN DWORD ClassInstallParamsSize);
66
67 struct CoInstallerElement
68 {
69 LIST_ENTRY ListEntry;
70
71 HMODULE Module;
72 COINSTALLER_PROC Function;
73 BOOL DoPostProcessing;
74 PVOID PrivateData;
75 };
76
77 static BOOL
78 PropertyChangeHandler(
79 IN HDEVINFO DeviceInfoSet,
80 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
81 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
82 IN DWORD ClassInstallParamsSize);
83
84 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
85 NULL, /* DIF_SELECTDEVICE */
86 NULL, /* DIF_INSTALLDEVICE */
87 NULL, /* DIF_ASSIGNRESOURCES */
88 NULL, /* DIF_PROPERTIES */
89 NULL, /* DIF_REMOVE */
90 NULL, /* DIF_FIRSTTIMESETUP */
91 NULL, /* DIF_FOUNDDEVICE */
92 NULL, /* DIF_SELECTCLASSDRIVERS */
93 NULL, /* DIF_VALIDATECLASSDRIVERS */
94 NULL, /* DIF_INSTALLCLASSDRIVERS */
95 NULL, /* DIF_CALCDISKSPACE */
96 NULL, /* DIF_DESTROYPRIVATEDATA */
97 NULL, /* DIF_VALIDATEDRIVER */
98 NULL, /* DIF_MOVEDEVICE */
99 NULL, /* DIF_DETECT */
100 NULL, /* DIF_INSTALLWIZARD */
101 NULL, /* DIF_DESTROYWIZARDDATA */
102 PropertyChangeHandler, /* DIF_PROPERTYCHANGE */
103 NULL, /* DIF_ENABLECLASS */
104 NULL, /* DIF_DETECTVERIFY */
105 NULL, /* DIF_INSTALLDEVICEFILES */
106 NULL, /* DIF_UNREMOVE */
107 NULL, /* DIF_SELECTBESTCOMPATDRV */
108 NULL, /* DIF_ALLOW_INSTALL */
109 NULL, /* DIF_REGISTERDEVICE */
110 NULL, /* DIF_NEWDEVICEWIZARD_PRESELECT */
111 NULL, /* DIF_NEWDEVICEWIZARD_SELECT */
112 NULL, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
113 NULL, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
114 NULL, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
115 NULL, /* DIF_UNUSED1 */
116 NULL, /* DIF_INSTALLINTERFACES */
117 NULL, /* DIF_DETECTCANCEL */
118 NULL, /* DIF_REGISTER_COINSTALLERS */
119 NULL, /* DIF_ADDPROPERTYPAGE_ADVANCED */
120 NULL, /* DIF_ADDPROPERTYPAGE_BASIC */
121 NULL, /* DIF_RESERVED1 */
122 NULL, /* DIF_TROUBLESHOOTER */
123 NULL, /* DIF_POWERMESSAGEWAKE */
124 NULL, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
125 NULL, /* DIF_UPDATEDRIVER_UI */
126 NULL /* DIF_RESERVED2 */
127 };
128
129 /***********************************************************************
130 * SetupDiBuildClassInfoList (SETUPAPI.@)
131 */
132 BOOL WINAPI SetupDiBuildClassInfoList(
133 DWORD Flags,
134 LPGUID ClassGuidList,
135 DWORD ClassGuidListSize,
136 PDWORD RequiredSize)
137 {
138 TRACE("\n");
139 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
140 ClassGuidListSize, RequiredSize,
141 NULL, NULL);
142 }
143
144 /***********************************************************************
145 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
146 */
147 BOOL WINAPI SetupDiBuildClassInfoListExA(
148 DWORD Flags,
149 LPGUID ClassGuidList,
150 DWORD ClassGuidListSize,
151 PDWORD RequiredSize,
152 LPCSTR MachineName,
153 PVOID Reserved)
154 {
155 LPWSTR MachineNameW = NULL;
156 BOOL bResult;
157
158 TRACE("\n");
159
160 if (MachineName)
161 {
162 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
163 if (MachineNameW == NULL) return FALSE;
164 }
165
166 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
167 ClassGuidListSize, RequiredSize,
168 MachineNameW, Reserved);
169
170 if (MachineNameW)
171 MyFree(MachineNameW);
172
173 return bResult;
174 }
175
176 /***********************************************************************
177 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
178 */
179 BOOL WINAPI SetupDiBuildClassInfoListExW(
180 DWORD Flags,
181 LPGUID ClassGuidList,
182 DWORD ClassGuidListSize,
183 PDWORD RequiredSize,
184 LPCWSTR MachineName,
185 PVOID Reserved)
186 {
187 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
188 HKEY hClassesKey;
189 HKEY hClassKey;
190 DWORD dwLength;
191 DWORD dwIndex;
192 LONG lError;
193 DWORD dwGuidListIndex = 0;
194
195 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
196 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
197
198 if (RequiredSize != NULL)
199 *RequiredSize = 0;
200
201 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
202 KEY_ENUMERATE_SUB_KEYS,
203 DIOCR_INSTALLER,
204 MachineName,
205 Reserved);
206 if (hClassesKey == INVALID_HANDLE_VALUE)
207 {
208 return FALSE;
209 }
210
211 for (dwIndex = 0; ; dwIndex++)
212 {
213 dwLength = MAX_GUID_STRING_LEN + 1;
214 lError = RegEnumKeyExW(hClassesKey,
215 dwIndex,
216 szKeyName,
217 &dwLength,
218 NULL,
219 NULL,
220 NULL,
221 NULL);
222 TRACE("RegEnumKeyExW() returns %ld\n", lError);
223 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
224 {
225 TRACE("Key name: %s\n", debugstr_w(szKeyName));
226
227 if (RegOpenKeyExW(hClassesKey,
228 szKeyName,
229 0,
230 KEY_QUERY_VALUE,
231 &hClassKey))
232 {
233 RegCloseKey(hClassesKey);
234 return FALSE;
235 }
236
237 if (!RegQueryValueExW(hClassKey,
238 REGSTR_VAL_NOUSECLASS,
239 NULL,
240 NULL,
241 NULL,
242 NULL))
243 {
244 TRACE("'NoUseClass' value found!\n");
245 RegCloseKey(hClassKey);
246 continue;
247 }
248
249 if ((Flags & DIBCI_NOINSTALLCLASS) &&
250 (!RegQueryValueExW(hClassKey,
251 REGSTR_VAL_NOINSTALLCLASS,
252 NULL,
253 NULL,
254 NULL,
255 NULL)))
256 {
257 TRACE("'NoInstallClass' value found!\n");
258 RegCloseKey(hClassKey);
259 continue;
260 }
261
262 if ((Flags & DIBCI_NODISPLAYCLASS) &&
263 (!RegQueryValueExW(hClassKey,
264 REGSTR_VAL_NODISPLAYCLASS,
265 NULL,
266 NULL,
267 NULL,
268 NULL)))
269 {
270 TRACE("'NoDisplayClass' value found!\n");
271 RegCloseKey(hClassKey);
272 continue;
273 }
274
275 RegCloseKey(hClassKey);
276
277 TRACE("Guid: %s\n", debugstr_w(szKeyName));
278 if (dwGuidListIndex < ClassGuidListSize)
279 {
280 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
281 {
282 szKeyName[37] = 0;
283 }
284 TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
285
286 UuidFromStringW(&szKeyName[1],
287 &ClassGuidList[dwGuidListIndex]);
288 }
289
290 dwGuidListIndex++;
291 }
292
293 if (lError != ERROR_SUCCESS)
294 break;
295 }
296
297 RegCloseKey(hClassesKey);
298
299 if (RequiredSize != NULL)
300 *RequiredSize = dwGuidListIndex;
301
302 if (ClassGuidListSize < dwGuidListIndex)
303 {
304 SetLastError(ERROR_INSUFFICIENT_BUFFER);
305 return FALSE;
306 }
307
308 return TRUE;
309 }
310
311 /***********************************************************************
312 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
313 */
314 BOOL WINAPI SetupDiClassGuidsFromNameA(
315 LPCSTR ClassName,
316 LPGUID ClassGuidList,
317 DWORD ClassGuidListSize,
318 PDWORD RequiredSize)
319 {
320 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
321 ClassGuidListSize, RequiredSize,
322 NULL, NULL);
323 }
324
325 /***********************************************************************
326 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
327 */
328 BOOL WINAPI SetupDiClassGuidsFromNameW(
329 LPCWSTR ClassName,
330 LPGUID ClassGuidList,
331 DWORD ClassGuidListSize,
332 PDWORD RequiredSize)
333 {
334 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
335 ClassGuidListSize, RequiredSize,
336 NULL, NULL);
337 }
338
339 /***********************************************************************
340 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
341 */
342 BOOL WINAPI SetupDiClassGuidsFromNameExA(
343 LPCSTR ClassName,
344 LPGUID ClassGuidList,
345 DWORD ClassGuidListSize,
346 PDWORD RequiredSize,
347 LPCSTR MachineName,
348 PVOID Reserved)
349 {
350 LPWSTR ClassNameW = NULL;
351 LPWSTR MachineNameW = NULL;
352 BOOL bResult;
353
354 TRACE("\n");
355
356 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
357 if (ClassNameW == NULL)
358 return FALSE;
359
360 if (MachineNameW)
361 {
362 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
363 if (MachineNameW == NULL)
364 {
365 MyFree(ClassNameW);
366 return FALSE;
367 }
368 }
369
370 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
371 ClassGuidListSize, RequiredSize,
372 MachineNameW, Reserved);
373
374 if (MachineNameW)
375 MyFree(MachineNameW);
376
377 MyFree(ClassNameW);
378
379 return bResult;
380 }
381
382 /***********************************************************************
383 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
384 */
385 BOOL WINAPI SetupDiClassGuidsFromNameExW(
386 LPCWSTR ClassName,
387 LPGUID ClassGuidList,
388 DWORD ClassGuidListSize,
389 PDWORD RequiredSize,
390 LPCWSTR MachineName,
391 PVOID Reserved)
392 {
393 WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
394 WCHAR szClassName[256];
395 HKEY hClassesKey;
396 HKEY hClassKey;
397 DWORD dwLength;
398 DWORD dwIndex;
399 LONG lError;
400 DWORD dwGuidListIndex = 0;
401
402 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
403 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
404
405 if (RequiredSize != NULL)
406 *RequiredSize = 0;
407
408 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
409 KEY_ENUMERATE_SUB_KEYS,
410 DIOCR_INSTALLER,
411 MachineName,
412 Reserved);
413 if (hClassesKey == INVALID_HANDLE_VALUE)
414 {
415 return FALSE;
416 }
417
418 for (dwIndex = 0; ; dwIndex++)
419 {
420 dwLength = MAX_GUID_STRING_LEN + 1;
421 lError = RegEnumKeyExW(hClassesKey,
422 dwIndex,
423 szKeyName,
424 &dwLength,
425 NULL,
426 NULL,
427 NULL,
428 NULL);
429 TRACE("RegEnumKeyExW() returns %ld\n", lError);
430 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
431 {
432 TRACE("Key name: %s\n", debugstr_w(szKeyName));
433
434 if (RegOpenKeyExW(hClassesKey,
435 szKeyName,
436 0,
437 KEY_QUERY_VALUE,
438 &hClassKey))
439 {
440 RegCloseKey(hClassesKey);
441 return FALSE;
442 }
443
444 dwLength = 256 * sizeof(WCHAR);
445 if (!RegQueryValueExW(hClassKey,
446 Class,
447 NULL,
448 NULL,
449 (LPBYTE)szClassName,
450 &dwLength))
451 {
452 TRACE("Class name: %s\n", debugstr_w(szClassName));
453
454 if (strcmpiW(szClassName, ClassName) == 0)
455 {
456 TRACE("Found matching class name\n");
457
458 TRACE("Guid: %s\n", debugstr_w(szKeyName));
459 if (dwGuidListIndex < ClassGuidListSize)
460 {
461 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
462 {
463 szKeyName[37] = 0;
464 }
465 TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
466
467 UuidFromStringW(&szKeyName[1],
468 &ClassGuidList[dwGuidListIndex]);
469 }
470
471 dwGuidListIndex++;
472 }
473 }
474
475 RegCloseKey(hClassKey);
476 }
477
478 if (lError != ERROR_SUCCESS)
479 break;
480 }
481
482 RegCloseKey(hClassesKey);
483
484 if (RequiredSize != NULL)
485 *RequiredSize = dwGuidListIndex;
486
487 if (ClassGuidListSize < dwGuidListIndex)
488 {
489 SetLastError(ERROR_INSUFFICIENT_BUFFER);
490 return FALSE;
491 }
492
493 return TRUE;
494 }
495
496 /***********************************************************************
497 * SetupDiClassNameFromGuidA (SETUPAPI.@)
498 */
499 BOOL WINAPI SetupDiClassNameFromGuidA(
500 const GUID* ClassGuid,
501 PSTR ClassName,
502 DWORD ClassNameSize,
503 PDWORD RequiredSize)
504 {
505 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
506 ClassNameSize, RequiredSize,
507 NULL, NULL);
508 }
509
510 /***********************************************************************
511 * SetupDiClassNameFromGuidW (SETUPAPI.@)
512 */
513 BOOL WINAPI SetupDiClassNameFromGuidW(
514 const GUID* ClassGuid,
515 PWSTR ClassName,
516 DWORD ClassNameSize,
517 PDWORD RequiredSize)
518 {
519 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
520 ClassNameSize, RequiredSize,
521 NULL, NULL);
522 }
523
524 /***********************************************************************
525 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
526 */
527 BOOL WINAPI SetupDiClassNameFromGuidExA(
528 const GUID* ClassGuid,
529 PSTR ClassName,
530 DWORD ClassNameSize,
531 PDWORD RequiredSize,
532 PCSTR MachineName,
533 PVOID Reserved)
534 {
535 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
536 LPWSTR MachineNameW = NULL;
537 BOOL ret;
538
539 if (MachineName)
540 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
541 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
542 NULL, MachineNameW, Reserved);
543 if (ret)
544 {
545 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
546 ClassNameSize, NULL, NULL);
547
548 if (!ClassNameSize && RequiredSize)
549 *RequiredSize = len;
550 }
551 MyFree(MachineNameW);
552 return ret;
553 }
554
555 /***********************************************************************
556 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
557 */
558 BOOL WINAPI SetupDiClassNameFromGuidExW(
559 const GUID* ClassGuid,
560 PWSTR ClassName,
561 DWORD ClassNameSize,
562 PDWORD RequiredSize,
563 PCWSTR MachineName,
564 PVOID Reserved)
565 {
566 HKEY hKey;
567 DWORD dwLength;
568 LONG rc;
569
570 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
571 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
572
573 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
574 KEY_QUERY_VALUE,
575 DIOCR_INSTALLER,
576 MachineName,
577 Reserved);
578 if (hKey == INVALID_HANDLE_VALUE)
579 {
580 return FALSE;
581 }
582
583 if (RequiredSize != NULL)
584 {
585 dwLength = 0;
586 rc = RegQueryValueExW(hKey,
587 Class,
588 NULL,
589 NULL,
590 NULL,
591 &dwLength);
592 if (rc != ERROR_SUCCESS)
593 {
594 SetLastError(rc);
595 RegCloseKey(hKey);
596 return FALSE;
597 }
598
599 *RequiredSize = dwLength / sizeof(WCHAR);
600 }
601
602 dwLength = ClassNameSize * sizeof(WCHAR);
603 rc = RegQueryValueExW(hKey,
604 Class,
605 NULL,
606 NULL,
607 (LPBYTE)ClassName,
608 &dwLength);
609 if (rc != ERROR_SUCCESS)
610 {
611 SetLastError(rc);
612 RegCloseKey(hKey);
613 return FALSE;
614 }
615
616 RegCloseKey(hKey);
617
618 return TRUE;
619 }
620
621 /***********************************************************************
622 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
623 */
624 HDEVINFO WINAPI
625 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
626 HWND hwndParent)
627 {
628 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
629 }
630
631 /***********************************************************************
632 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
633 */
634 HDEVINFO WINAPI
635 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
636 HWND hwndParent,
637 PCSTR MachineName,
638 PVOID Reserved)
639 {
640 LPWSTR MachineNameW = NULL;
641 HDEVINFO hDevInfo;
642
643 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
644 debugstr_a(MachineName), Reserved);
645
646 if (MachineName)
647 {
648 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
649 if (MachineNameW == NULL)
650 return (HDEVINFO)INVALID_HANDLE_VALUE;
651 }
652
653 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
654 MachineNameW, Reserved);
655
656 if (MachineNameW)
657 MyFree(MachineNameW);
658
659 return hDevInfo;
660 }
661
662 static DWORD
663 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
664 {
665 switch (cr)
666 {
667 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
668 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
669 case CR_SUCCESS: return ERROR_SUCCESS;
670 default:
671 /* FIXME */
672 return ERROR_GEN_FAILURE;
673 }
674
675 /* Does not happen */
676 }
677
678 /***********************************************************************
679 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
680 */
681 HDEVINFO WINAPI
682 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
683 HWND hwndParent,
684 PCWSTR MachineName,
685 PVOID Reserved)
686 {
687 struct DeviceInfoSet *list;
688 LPWSTR UNCServerName = NULL;
689 DWORD size;
690 DWORD rc;
691 //CONFIGRET cr;
692 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
693
694 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
695 debugstr_w(MachineName), Reserved);
696
697 size = FIELD_OFFSET(struct DeviceInfoSet, szData);
698 if (MachineName)
699 size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
700 list = HeapAlloc(GetProcessHeap(), 0, size);
701 if (!list)
702 {
703 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
704 goto cleanup;
705 }
706 memset(list, 0, sizeof(struct DeviceInfoSet));
707
708 list->magic = SETUP_DEV_INFO_SET_MAGIC;
709 memcpy(
710 &list->ClassGuid,
711 ClassGuid ? ClassGuid : &GUID_NULL,
712 sizeof(list->ClassGuid));
713 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
714 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
715 list->InstallParams.hwndParent = hwndParent;
716 if (MachineName)
717 {
718 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
719 if (rc != ERROR_SUCCESS)
720 {
721 SetLastError(rc);
722 goto cleanup;
723 }
724 UNCServerName = HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName) + 3) * sizeof(WCHAR));
725 if (!UNCServerName)
726 {
727 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
728 goto cleanup;
729 }
730
731 strcpyW(UNCServerName + 2, MachineName);
732 list->szData[0] = list->szData[1] = '\\';
733 strcpyW(list->szData + 2, MachineName);
734 list->MachineName = list->szData;
735 }
736 else
737 {
738 DWORD Size = MAX_PATH;
739 list->HKLM = HKEY_LOCAL_MACHINE;
740 UNCServerName = HeapAlloc(GetProcessHeap(), 0, (MAX_PATH + 2) * sizeof(WCHAR));
741 if (!UNCServerName)
742 {
743 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
744 goto cleanup;
745 }
746 if (!GetComputerNameW(UNCServerName + 2, &Size))
747 goto cleanup;
748 list->MachineName = NULL;
749 }
750 #if 0
751 UNCServerName[0] = UNCServerName[1] = '\\';
752 cr = CM_Connect_MachineW(UNCServerName, &list->hMachine);
753 if (cr != CR_SUCCESS)
754 {
755 SetLastError(GetErrorCodeFromCrCode(cr));
756 goto cleanup;
757 }
758 #endif
759 InitializeListHead(&list->DriverListHead);
760 InitializeListHead(&list->ListHead);
761
762 ret = (HDEVINFO)list;
763
764 cleanup:
765 if (ret == INVALID_HANDLE_VALUE)
766 {
767 if (list && list->HKLM != 0 && list->HKLM != HKEY_LOCAL_MACHINE)
768 RegCloseKey(list->HKLM);
769 HeapFree(GetProcessHeap(), 0, list);
770 }
771 HeapFree(GetProcessHeap(), 0, UNCServerName);
772 return ret;
773 }
774
775 /***********************************************************************
776 * SetupDiEnumDeviceInfo (SETUPAPI.@)
777 */
778 BOOL WINAPI SetupDiEnumDeviceInfo(
779 HDEVINFO DeviceInfoSet,
780 DWORD MemberIndex,
781 PSP_DEVINFO_DATA DeviceInfoData)
782 {
783 BOOL ret = FALSE;
784
785 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
786 if (!DeviceInfoData)
787 SetLastError(ERROR_INVALID_PARAMETER);
788 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
789 {
790 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
791
792 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
793 SetLastError(ERROR_INVALID_HANDLE);
794 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
795 SetLastError(ERROR_INVALID_USER_BUFFER);
796 else
797 {
798 PLIST_ENTRY ItemList = list->ListHead.Flink;
799 while (ItemList != &list->ListHead && MemberIndex-- > 0)
800 ItemList = ItemList->Flink;
801 if (ItemList == &list->ListHead)
802 SetLastError(ERROR_NO_MORE_ITEMS);
803 else
804 {
805 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
806 memcpy(&DeviceInfoData->ClassGuid,
807 &DevInfo->ClassGuid,
808 sizeof(GUID));
809 DeviceInfoData->DevInst = DevInfo->dnDevInst;
810 DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
811 ret = TRUE;
812 }
813 }
814 }
815 else
816 SetLastError(ERROR_INVALID_HANDLE);
817 return ret;
818 }
819
820 /***********************************************************************
821 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
822 */
823 BOOL WINAPI
824 SetupDiGetActualSectionToInstallA(
825 IN HINF InfHandle,
826 IN PCSTR InfSectionName,
827 OUT PSTR InfSectionWithExt OPTIONAL,
828 IN DWORD InfSectionWithExtSize,
829 OUT PDWORD RequiredSize OPTIONAL,
830 OUT PSTR *Extension OPTIONAL)
831 {
832 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
833 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
834 Extension, NULL);
835 }
836
837 /***********************************************************************
838 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
839 */
840 BOOL WINAPI
841 SetupDiGetActualSectionToInstallW(
842 IN HINF InfHandle,
843 IN PCWSTR InfSectionName,
844 OUT PWSTR InfSectionWithExt OPTIONAL,
845 IN DWORD InfSectionWithExtSize,
846 OUT PDWORD RequiredSize OPTIONAL,
847 OUT PWSTR *Extension OPTIONAL)
848 {
849 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
850 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
851 Extension, NULL);
852 }
853
854 /***********************************************************************
855 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
856 */
857 BOOL WINAPI
858 SetupDiGetActualSectionToInstallExA(
859 IN HINF InfHandle,
860 IN PCSTR InfSectionName,
861 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
862 OUT PSTR InfSectionWithExt OPTIONAL,
863 IN DWORD InfSectionWithExtSize,
864 OUT PDWORD RequiredSize OPTIONAL,
865 OUT PSTR* Extension OPTIONAL,
866 IN PVOID Reserved)
867 {
868 LPWSTR InfSectionNameW = NULL;
869 LPWSTR InfSectionWithExtW = NULL;
870 PWSTR ExtensionW;
871 BOOL bResult = FALSE;
872
873 TRACE("\n");
874
875 if (InfSectionName)
876 {
877 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
878 if (InfSectionNameW == NULL)
879 goto cleanup;
880 }
881 if (InfSectionWithExt)
882 {
883 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
884 if (InfSectionWithExtW == NULL)
885 goto cleanup;
886 }
887
888 bResult = SetupDiGetActualSectionToInstallExW(
889 InfHandle, InfSectionNameW, AlternatePlatformInfo,
890 InfSectionWithExt ? InfSectionWithExtW : NULL,
891 InfSectionWithExtSize,
892 RequiredSize,
893 Extension ? &ExtensionW : NULL,
894 Reserved);
895
896 if (bResult && InfSectionWithExt)
897 {
898 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
899 InfSectionWithExtSize, NULL, NULL) != 0;
900 }
901 if (bResult && Extension)
902 {
903 if (ExtensionW == NULL)
904 *Extension = NULL;
905 else
906 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
907 }
908
909 cleanup:
910 MyFree(InfSectionNameW);
911 MyFree(InfSectionWithExtW);
912
913 return bResult;
914 }
915
916 /***********************************************************************
917 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
918 */
919 BOOL WINAPI
920 SetupDiGetActualSectionToInstallExW(
921 IN HINF InfHandle,
922 IN PCWSTR InfSectionName,
923 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
924 OUT PWSTR InfSectionWithExt OPTIONAL,
925 IN DWORD InfSectionWithExtSize,
926 OUT PDWORD RequiredSize OPTIONAL,
927 OUT PWSTR* Extension OPTIONAL,
928 IN PVOID Reserved)
929 {
930 BOOL ret = FALSE;
931
932 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
933 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
934 RequiredSize, Extension, Reserved);
935
936 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
937 SetLastError(ERROR_INVALID_HANDLE);
938 else if (!InfSectionName)
939 SetLastError(ERROR_INVALID_PARAMETER);
940 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
941 SetLastError(ERROR_INVALID_USER_BUFFER);
942 else if (Reserved != NULL)
943 SetLastError(ERROR_INVALID_PARAMETER);
944 else
945 {
946 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
947 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
948 LPCWSTR pExtensionPlatform, pExtensionArchitecture;
949 WCHAR SectionName[LINE_LEN + 1];
950 LONG lLineCount = -1;
951 DWORD dwFullLength;
952
953 /* Fill platform info if needed */
954 if (AlternatePlatformInfo)
955 pPlatformInfo = AlternatePlatformInfo;
956 else if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
957 {
958 /* That's the first time we go here. We need to fill in the structure */
959 OSVERSIONINFO VersionInfo;
960 SYSTEM_INFO SystemInfo;
961 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
962 ret = GetVersionEx(&VersionInfo);
963 if (!ret)
964 goto done;
965 GetSystemInfo(&SystemInfo);
966 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
967 CurrentPlatform.Platform = VersionInfo.dwPlatformId;
968 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
969 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
970 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
971 CurrentPlatform.Reserved = 0;
972 }
973
974 static const WCHAR ExtensionPlatformNone[] = {'.',0};
975 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
976 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
977
978 static const WCHAR ExtensionArchitectureNone[] = {0};
979 static const WCHAR ExtensionArchitectureamd64[] = {'a','m','d','6','4',0};
980 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
981 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
982
983 /* Set various extensions values */
984 switch (pPlatformInfo->Platform)
985 {
986 case VER_PLATFORM_WIN32_WINDOWS:
987 pExtensionPlatform = ExtensionPlatformWindows;
988 break;
989 case VER_PLATFORM_WIN32_NT:
990 pExtensionPlatform = ExtensionPlatformNT;
991 break;
992 default:
993 pExtensionPlatform = ExtensionPlatformNone;
994 break;
995 }
996 switch (pPlatformInfo->ProcessorArchitecture)
997 {
998 case PROCESSOR_ARCHITECTURE_AMD64:
999 pExtensionArchitecture = ExtensionArchitectureamd64;
1000 break;
1001 case PROCESSOR_ARCHITECTURE_INTEL:
1002 pExtensionArchitecture = ExtensionArchitecturex86;
1003 break;
1004 case PROCESSOR_ARCHITECTURE_PPC:
1005 pExtensionArchitecture = ExtensionArchitectureppc;
1006 break;
1007 default:
1008 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo->ProcessorArchitecture);
1009 case PROCESSOR_ARCHITECTURE_UNKNOWN:
1010 pExtensionArchitecture = ExtensionArchitectureNone;
1011 break;
1012 }
1013
1014 SectionName[LINE_LEN] = UNICODE_NULL;
1015
1016 /* Test with platform.architecture.major.minor extension */
1017 snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu.%lu", InfSectionName,
1018 pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
1019 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1020 if (lLineCount != -1) goto sectionfound;
1021
1022 /* Test with platform.major.minor extension */
1023 snprintfW(SectionName, LINE_LEN, L"%s%s.%lu.%lu", InfSectionName,
1024 pExtensionPlatform, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
1025 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1026 if (lLineCount != -1) goto sectionfound;
1027
1028 /* Test with platform.architecture.major extension */
1029 snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu", InfSectionName,
1030 pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion);
1031 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1032 if (lLineCount != -1) goto sectionfound;
1033
1034 /* Test with platform.major extension */
1035 snprintfW(SectionName, LINE_LEN, L"%s%s.%lu", InfSectionName,
1036 pExtensionPlatform, pPlatformInfo->MajorVersion);
1037 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1038 if (lLineCount != -1) goto sectionfound;
1039
1040 /* Test with platform.architecture extension */
1041 snprintfW(SectionName, LINE_LEN, L"%s%s%s", InfSectionName,
1042 pExtensionPlatform, pExtensionArchitecture);
1043 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1044 if (lLineCount != -1) goto sectionfound;
1045
1046 /* Test with platform extension */
1047 snprintfW(SectionName, LINE_LEN, L"%s%s", InfSectionName,
1048 pExtensionPlatform);
1049 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1050 if (lLineCount != -1) goto sectionfound;
1051
1052 /* Test without extension */
1053 snprintfW(SectionName, LINE_LEN, L"%s", InfSectionName);
1054 lLineCount = SetupGetLineCountW(InfHandle, SectionName);
1055 if (lLineCount != -1) goto sectionfound;
1056
1057 /* No appropriate section found */
1058 SetLastError(ERROR_INVALID_PARAMETER);
1059 goto done;
1060
1061 sectionfound:
1062 dwFullLength = lstrlenW(SectionName);
1063 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1064 {
1065 if (InfSectionWithExtSize < (dwFullLength + 1))
1066 {
1067 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1068 goto done;
1069 }
1070
1071 lstrcpyW(InfSectionWithExt, SectionName);
1072 if (Extension != NULL)
1073 {
1074 DWORD dwLength = lstrlenW(SectionName);
1075 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1076 }
1077 }
1078
1079 if (RequiredSize != NULL)
1080 *RequiredSize = dwFullLength + 1;
1081
1082 ret = TRUE;
1083 }
1084
1085 done:
1086 TRACE("Returning %d\n", ret);
1087 return ret;
1088 }
1089
1090
1091 /***********************************************************************
1092 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1093 */
1094 BOOL WINAPI SetupDiGetClassDescriptionA(
1095 const GUID* ClassGuid,
1096 PSTR ClassDescription,
1097 DWORD ClassDescriptionSize,
1098 PDWORD RequiredSize)
1099 {
1100 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1101 ClassDescriptionSize,
1102 RequiredSize, NULL, NULL);
1103 }
1104
1105 /***********************************************************************
1106 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1107 */
1108 BOOL WINAPI SetupDiGetClassDescriptionW(
1109 const GUID* ClassGuid,
1110 PWSTR ClassDescription,
1111 DWORD ClassDescriptionSize,
1112 PDWORD RequiredSize)
1113 {
1114 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1115 ClassDescriptionSize,
1116 RequiredSize, NULL, NULL);
1117 }
1118
1119 /***********************************************************************
1120 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1121 */
1122 BOOL WINAPI SetupDiGetClassDescriptionExA(
1123 const GUID* ClassGuid,
1124 PSTR ClassDescription,
1125 DWORD ClassDescriptionSize,
1126 PDWORD RequiredSize,
1127 PCSTR MachineName,
1128 PVOID Reserved)
1129 {
1130 PWCHAR ClassDescriptionW;
1131 LPWSTR MachineNameW = NULL;
1132 BOOL ret;
1133
1134 TRACE("\n");
1135 if (ClassDescriptionSize > 0)
1136 {
1137 ClassDescriptionW = HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize * sizeof(WCHAR));
1138 if (!ClassDescriptionW)
1139 {
1140 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1141 ret = FALSE;
1142 goto end;
1143 }
1144 }
1145 else
1146 ClassDescriptionW = NULL;
1147
1148 if (MachineName)
1149 {
1150 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1151 if (!MachineNameW)
1152 {
1153 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1154 ret = FALSE;
1155 goto end;
1156 }
1157 }
1158
1159 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, ClassDescriptionSize * sizeof(WCHAR),
1160 NULL, MachineNameW, Reserved);
1161 if (ret)
1162 {
1163 int len = WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
1164 ClassDescriptionSize, NULL, NULL);
1165
1166 if (!ClassDescriptionSize && RequiredSize)
1167 *RequiredSize = len;
1168 }
1169
1170 end:
1171 HeapFree(GetProcessHeap(), 0, ClassDescriptionW);
1172 MyFree(MachineNameW);
1173 return ret;
1174 }
1175
1176 /***********************************************************************
1177 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1178 */
1179 BOOL WINAPI SetupDiGetClassDescriptionExW(
1180 const GUID* ClassGuid,
1181 PWSTR ClassDescription,
1182 DWORD ClassDescriptionSize,
1183 PDWORD RequiredSize,
1184 PCWSTR MachineName,
1185 PVOID Reserved)
1186 {
1187 HKEY hKey;
1188 DWORD dwLength;
1189
1190 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
1191 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
1192
1193 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1194 KEY_QUERY_VALUE,
1195 DIOCR_INSTALLER,
1196 MachineName,
1197 Reserved);
1198 if (hKey == INVALID_HANDLE_VALUE)
1199 {
1200 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1201 return FALSE;
1202 }
1203
1204 if (RequiredSize != NULL)
1205 {
1206 dwLength = 0;
1207 if (RegQueryValueExW(hKey,
1208 NULL,
1209 NULL,
1210 NULL,
1211 NULL,
1212 &dwLength))
1213 {
1214 RegCloseKey(hKey);
1215 return FALSE;
1216 }
1217
1218 *RequiredSize = dwLength / sizeof(WCHAR);
1219 }
1220
1221 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1222 if (RegQueryValueExW(hKey,
1223 NULL,
1224 NULL,
1225 NULL,
1226 (LPBYTE)ClassDescription,
1227 &dwLength))
1228 {
1229 RegCloseKey(hKey);
1230 return FALSE;
1231 }
1232
1233 RegCloseKey(hKey);
1234
1235 return TRUE;
1236 }
1237
1238 /***********************************************************************
1239 * SetupDiGetClassDevsA (SETUPAPI.@)
1240 */
1241 HDEVINFO WINAPI SetupDiGetClassDevsA(
1242 CONST GUID *class,
1243 LPCSTR enumstr,
1244 HWND parent,
1245 DWORD flags)
1246 {
1247 return SetupDiGetClassDevsExA(class, enumstr, parent,
1248 flags, NULL, NULL, NULL);
1249 }
1250
1251 /***********************************************************************
1252 * SetupDiGetClassDevsW (SETUPAPI.@)
1253 */
1254 HDEVINFO WINAPI SetupDiGetClassDevsW(
1255 CONST GUID *class,
1256 LPCWSTR enumstr,
1257 HWND parent,
1258 DWORD flags)
1259 {
1260 return SetupDiGetClassDevsExW(class, enumstr, parent,
1261 flags, NULL, NULL, NULL);
1262 }
1263
1264 /***********************************************************************
1265 * SetupDiGetClassDevsExA (SETUPAPI.@)
1266 */
1267 HDEVINFO WINAPI SetupDiGetClassDevsExA(
1268 CONST GUID *class,
1269 LPCSTR enumstr,
1270 HWND parent,
1271 DWORD flags,
1272 HDEVINFO deviceset,
1273 LPCSTR machine,
1274 PVOID reserved)
1275 {
1276 HDEVINFO ret;
1277 LPWSTR enumstrW = NULL;
1278 LPWSTR machineW = NULL;
1279
1280 if (enumstr)
1281 {
1282 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1283 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1284 if (!enumstrW)
1285 {
1286 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1287 goto end;
1288 }
1289 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1290 }
1291 if (machine)
1292 {
1293 int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
1294 machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1295 if (!machineW)
1296 {
1297 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1298 goto end;
1299 }
1300 MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
1301 }
1302 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, machineW, reserved);
1303
1304 end:
1305 HeapFree(GetProcessHeap(), 0, enumstrW);
1306 HeapFree(GetProcessHeap(), 0, machineW);
1307 return ret;
1308 }
1309
1310 static BOOL
1311 CreateDeviceInfoElement(
1312 IN struct DeviceInfoSet *list,
1313 IN LPCWSTR InstancePath,
1314 IN LPCGUID pClassGuid,
1315 OUT struct DeviceInfoElement **pDeviceInfo)
1316 {
1317 DWORD size;
1318 CONFIGRET cr;
1319 struct DeviceInfoElement *deviceInfo;
1320
1321 *pDeviceInfo = NULL;
1322
1323 size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
1324 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
1325 if (!deviceInfo)
1326 {
1327 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1328 return FALSE;
1329 }
1330 memset(deviceInfo, 0, size);
1331
1332 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
1333 if (cr != CR_SUCCESS)
1334 {
1335 SetLastError(GetErrorCodeFromCrCode(cr));
1336 return FALSE;
1337 }
1338
1339 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1340 wcscpy(deviceInfo->Data, InstancePath);
1341 deviceInfo->DeviceName = deviceInfo->Data;
1342 deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
1343 deviceInfo->DeviceDescription = NULL;
1344 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
1345 deviceInfo->CreationFlags = 0;
1346 InitializeListHead(&deviceInfo->DriverListHead);
1347 InitializeListHead(&deviceInfo->InterfaceListHead);
1348
1349 *pDeviceInfo = deviceInfo;
1350 return TRUE;
1351 }
1352
1353 static BOOL
1354 CreateDeviceInterface(
1355 IN struct DeviceInfoElement* deviceInfo,
1356 IN LPCWSTR SymbolicLink,
1357 IN LPCGUID pInterfaceGuid,
1358 OUT struct DeviceInterface **pDeviceInterface)
1359 {
1360 struct DeviceInterface *deviceInterface;
1361
1362 *pDeviceInterface = NULL;
1363
1364 deviceInterface = HeapAlloc(GetProcessHeap(), 0,
1365 FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
1366 if (!deviceInterface)
1367 {
1368 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1369 return FALSE;
1370 }
1371 deviceInterface->DeviceInfo = deviceInfo;
1372 wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
1373 deviceInterface->Flags = 0; /* FIXME */
1374 memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
1375
1376 *pDeviceInterface = deviceInterface;
1377 return TRUE;
1378 }
1379
1380 static LONG SETUP_CreateDevListFromEnumerator(
1381 struct DeviceInfoSet *list,
1382 LPCGUID pClassGuid OPTIONAL,
1383 LPCWSTR Enumerator,
1384 HKEY hEnumeratorKey) /* handle to Enumerator registry key */
1385 {
1386 HKEY hDeviceIdKey, hInstanceIdKey;
1387 WCHAR KeyBuffer[MAX_PATH];
1388 WCHAR InstancePath[MAX_PATH];
1389 LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
1390 struct DeviceInfoElement *deviceInfo;
1391 DWORD i = 0, j;
1392 DWORD dwLength, dwRegType;
1393 DWORD rc;
1394
1395 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1396 while (TRUE)
1397 {
1398 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1399 rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1400 if (rc == ERROR_NO_MORE_ITEMS)
1401 break;
1402 if (rc != ERROR_SUCCESS)
1403 return rc;
1404 i++;
1405
1406 /* Open device id sub key */
1407 rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
1408 if (rc != ERROR_SUCCESS)
1409 return rc;
1410 wcscpy(InstancePath, Enumerator);
1411 wcscat(InstancePath, L"\\");
1412 wcscat(InstancePath, KeyBuffer);
1413 wcscat(InstancePath, L"\\");
1414 pEndOfInstancePath = &InstancePath[wcslen(InstancePath)];
1415
1416 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1417 j = 0;
1418 while (TRUE)
1419 {
1420 GUID KeyGuid;
1421
1422 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1423 rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1424 if (rc == ERROR_NO_MORE_ITEMS)
1425 break;
1426 if (rc != ERROR_SUCCESS)
1427 {
1428 RegCloseKey(hDeviceIdKey);
1429 return rc;
1430 }
1431 j++;
1432
1433 /* Open instance id sub key */
1434 rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
1435 if (rc != ERROR_SUCCESS)
1436 {
1437 RegCloseKey(hDeviceIdKey);
1438 return rc;
1439 }
1440 *pEndOfInstancePath = '\0';
1441 wcscat(InstancePath, KeyBuffer);
1442
1443 /* Read ClassGUID value */
1444 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1445 rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength);
1446 RegCloseKey(hInstanceIdKey);
1447 if (rc == ERROR_FILE_NOT_FOUND)
1448 {
1449 if (pClassGuid)
1450 /* Skip this bad entry as we can't verify it */
1451 continue;
1452 /* Set a default GUID for this device */
1453 memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
1454 }
1455 else if (rc != ERROR_SUCCESS)
1456 {
1457 RegCloseKey(hDeviceIdKey);
1458 return rc;
1459 }
1460 else if (dwRegType != REG_SZ)
1461 {
1462 RegCloseKey(hDeviceIdKey);
1463 return ERROR_GEN_FAILURE;
1464 }
1465 else
1466 {
1467 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1468 if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
1469 /* Bad GUID, skip the entry */
1470 continue;
1471 }
1472
1473 if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
1474 {
1475 /* Skip this entry as it is not the right device class */
1476 continue;
1477 }
1478
1479 /* Add the entry to the list */
1480 if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo))
1481 {
1482 RegCloseKey(hDeviceIdKey);
1483 return GetLastError();
1484 }
1485 TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
1486 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1487 }
1488 RegCloseKey(hDeviceIdKey);
1489 }
1490
1491 return ERROR_SUCCESS;
1492 }
1493
1494 static LONG SETUP_CreateDevList(
1495 struct DeviceInfoSet *list,
1496 PCWSTR MachineName OPTIONAL,
1497 LPGUID class OPTIONAL,
1498 PCWSTR Enumerator OPTIONAL)
1499 {
1500 HKEY HKLM, hEnumKey, hEnumeratorKey;
1501 WCHAR KeyBuffer[MAX_PATH];
1502 DWORD i;
1503 DWORD dwLength;
1504 DWORD rc;
1505
1506 if (class && IsEqualIID(class, &GUID_NULL))
1507 class = NULL;
1508
1509 /* Open Enum key */
1510 if (MachineName != NULL)
1511 {
1512 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
1513 if (rc != ERROR_SUCCESS)
1514 return rc;
1515 }
1516 else
1517 HKLM = HKEY_LOCAL_MACHINE;
1518
1519 rc = RegOpenKeyExW(HKLM,
1520 REGSTR_PATH_SYSTEMENUM,
1521 0,
1522 KEY_ENUMERATE_SUB_KEYS,
1523 &hEnumKey);
1524 if (MachineName != NULL) RegCloseKey(HKLM);
1525 if (rc != ERROR_SUCCESS)
1526 return rc;
1527
1528 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1529 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1530 * for each one.
1531 */
1532 if (Enumerator)
1533 {
1534 rc = RegOpenKeyExW(
1535 hEnumKey,
1536 Enumerator,
1537 0,
1538 KEY_ENUMERATE_SUB_KEYS,
1539 &hEnumeratorKey);
1540 RegCloseKey(hEnumKey);
1541 if (rc != ERROR_SUCCESS)
1542 return rc;
1543 rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey);
1544 RegCloseKey(hEnumeratorKey);
1545 return rc;
1546 }
1547 else
1548 {
1549 /* Enumerate enumerators */
1550 i = 0;
1551 while (TRUE)
1552 {
1553 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1554 rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1555 if (rc == ERROR_NO_MORE_ITEMS)
1556 break;
1557 if (rc != ERROR_SUCCESS)
1558 {
1559 RegCloseKey(hEnumKey);
1560 return rc;
1561 }
1562 i++;
1563
1564 /* Open sub key */
1565 rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
1566 if (rc != ERROR_SUCCESS)
1567 {
1568 RegCloseKey(hEnumKey);
1569 return rc;
1570 }
1571
1572 /* Call SETUP_CreateDevListFromEnumerator */
1573 rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey);
1574 RegCloseKey(hEnumeratorKey);
1575 if (rc != ERROR_SUCCESS)
1576 {
1577 RegCloseKey(hEnumKey);
1578 return rc;
1579 }
1580 }
1581 RegCloseKey(hEnumKey);
1582 return ERROR_SUCCESS;
1583 }
1584 }
1585
1586 #ifndef __REACTOS__
1587 static LONG SETUP_CreateSerialDeviceList(
1588 struct DeviceInfoSet *list,
1589 PCWSTR MachineName,
1590 LPGUID InterfaceGuid,
1591 PCWSTR DeviceInstanceW)
1592 {
1593 static const size_t initialSize = 100;
1594 size_t size;
1595 WCHAR buf[initialSize];
1596 LPWSTR devices;
1597 static const WCHAR devicePrefixW[] = { 'C','O','M',0 };
1598 LPWSTR ptr;
1599 struct DeviceInfoElement *deviceInfo;
1600
1601 if (MachineName)
1602 WARN("'MachineName' is ignored on Wine!\n");
1603 if (DeviceInstanceW)
1604 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1605
1606 devices = buf;
1607 size = initialSize;
1608 while (TRUE)
1609 {
1610 if (QueryDosDeviceW(NULL, devices, size) != 0)
1611 break;
1612 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1613 {
1614 size *= 2;
1615 if (devices != buf)
1616 HeapFree(GetProcessHeap(), 0, devices);
1617 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1618 if (!devices)
1619 return ERROR_NOT_ENOUGH_MEMORY;
1620 *devices = '\0';
1621 }
1622 else
1623 {
1624 if (devices != buf)
1625 HeapFree(GetProcessHeap(), 0, devices);
1626 return GetLastError();
1627 }
1628 }
1629
1630 /* 'devices' is a MULTI_SZ string */
1631 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
1632 {
1633 if (strncmpW(devicePrefixW, ptr, sizeof(devicePrefixW) / sizeof(devicePrefixW[0]) - 1) == 0)
1634 {
1635 /* We have found a device */
1636 struct DeviceInterface *interfaceInfo;
1637 TRACE("Adding %s to list\n", debugstr_w(ptr));
1638 /* Step 1. Create a device info element */
1639 if (!CreateDeviceInfoElement(list, ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
1640 {
1641 if (devices != buf)
1642 HeapFree(GetProcessHeap(), 0, devices);
1643 return GetLastError();
1644 }
1645 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1646
1647 /* Step 2. Create an interface list for this element */
1648 if (!CreateDeviceInterface(deviceInfo, ptr, InterfaceGuid, &interfaceInfo))
1649 {
1650 if (devices != buf)
1651 HeapFree(GetProcessHeap(), 0, devices);
1652 return GetLastError();
1653 }
1654 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1655 }
1656 }
1657 if (devices != buf)
1658 HeapFree(GetProcessHeap(), 0, devices);
1659 return ERROR_SUCCESS;
1660 }
1661
1662 #else /* __REACTOS__ */
1663
1664 static LONG SETUP_CreateInterfaceList(
1665 struct DeviceInfoSet *list,
1666 PCWSTR MachineName,
1667 LPGUID InterfaceGuid,
1668 PCWSTR DeviceInstanceW /* OPTIONAL */)
1669 {
1670 HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1671 HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1672 HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1673 HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1674 HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1675 LONG rc;
1676 WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
1677 PWSTR InstancePath;
1678 DWORD i, j;
1679 DWORD dwLength, dwInstancePathLength;
1680 DWORD dwRegType;
1681 GUID ClassGuid;
1682 struct DeviceInfoElement *deviceInfo;
1683
1684 /* Open registry key related to this interface */
1685 hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
1686 if (hInterfaceKey == INVALID_HANDLE_VALUE)
1687 return GetLastError();
1688
1689 /* Enumerate sub keys of hInterfaceKey */
1690 i = 0;
1691 while (TRUE)
1692 {
1693 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1694 rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1695 if (rc == ERROR_NO_MORE_ITEMS)
1696 break;
1697 if (rc != ERROR_SUCCESS)
1698 {
1699 RegCloseKey(hInterfaceKey);
1700 return rc;
1701 }
1702 i++;
1703
1704 /* Open sub key */
1705 rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
1706 if (rc != ERROR_SUCCESS)
1707 {
1708 RegCloseKey(hInterfaceKey);
1709 return rc;
1710 }
1711
1712 /* Read DeviceInstance */
1713 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
1714 if (rc != ERROR_SUCCESS )
1715 {
1716 RegCloseKey(hDeviceInstanceKey);
1717 RegCloseKey(hInterfaceKey);
1718 return rc;
1719 }
1720 if (dwRegType != REG_SZ)
1721 {
1722 RegCloseKey(hDeviceInstanceKey);
1723 RegCloseKey(hInterfaceKey);
1724 return ERROR_GEN_FAILURE;
1725 }
1726 InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
1727 if (!InstancePath)
1728 {
1729 RegCloseKey(hDeviceInstanceKey);
1730 RegCloseKey(hInterfaceKey);
1731 return ERROR_NOT_ENOUGH_MEMORY;
1732 }
1733 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
1734 if (rc != ERROR_SUCCESS)
1735 {
1736 HeapFree(GetProcessHeap(), 0, InstancePath);
1737 RegCloseKey(hDeviceInstanceKey);
1738 RegCloseKey(hInterfaceKey);
1739 return rc;
1740 }
1741 InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
1742 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
1743
1744 if (DeviceInstanceW)
1745 {
1746 /* Check if device enumerator is not the right one */
1747 if (wcscmp(DeviceInstanceW, InstancePath) != 0)
1748 {
1749 HeapFree(GetProcessHeap(), 0, InstancePath);
1750 RegCloseKey(hDeviceInstanceKey);
1751 continue;
1752 }
1753 }
1754
1755 /* Find class GUID associated to the device instance */
1756 rc = RegOpenKeyExW(
1757 list->HKLM,
1758 REGSTR_PATH_SYSTEMENUM,
1759 0, /* Options */
1760 0,
1761 &hEnumKey);
1762 if (rc != ERROR_SUCCESS)
1763 {
1764 HeapFree(GetProcessHeap(), 0, InstancePath);
1765 RegCloseKey(hDeviceInstanceKey);
1766 RegCloseKey(hInterfaceKey);
1767 return rc;
1768 }
1769 rc = RegOpenKeyExW(
1770 hEnumKey,
1771 InstancePath,
1772 0, /* Options */
1773 KEY_QUERY_VALUE,
1774 &hKey);
1775 RegCloseKey(hEnumKey);
1776 if (rc != ERROR_SUCCESS)
1777 {
1778 HeapFree(GetProcessHeap(), 0, InstancePath);
1779 RegCloseKey(hDeviceInstanceKey);
1780 RegCloseKey(hInterfaceKey);
1781 return rc;
1782 }
1783 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
1784 rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1785 RegCloseKey(hKey);
1786 if (rc != ERROR_SUCCESS)
1787 {
1788 HeapFree(GetProcessHeap(), 0, InstancePath);
1789 RegCloseKey(hDeviceInstanceKey);
1790 RegCloseKey(hInterfaceKey);
1791 return rc;
1792 }
1793 KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
1794 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
1795 if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
1796 {
1797 HeapFree(GetProcessHeap(), 0, InstancePath);
1798 RegCloseKey(hDeviceInstanceKey);
1799 RegCloseKey(hInterfaceKey);
1800 return ERROR_GEN_FAILURE;
1801 }
1802 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
1803
1804 /* If current device doesn't match the list GUID (if any), skip this entry */
1805 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
1806 {
1807 HeapFree(GetProcessHeap(), 0, InstancePath);
1808 RegCloseKey(hDeviceInstanceKey);
1809 continue;
1810 }
1811
1812 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1813 j = 0;
1814 while (TRUE)
1815 {
1816 LPWSTR pSymbolicLink;
1817 struct DeviceInterface *interfaceInfo;
1818
1819 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
1820 rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
1821 if (rc == ERROR_NO_MORE_ITEMS)
1822 break;
1823 if (rc != ERROR_SUCCESS)
1824 {
1825 HeapFree(GetProcessHeap(), 0, InstancePath);
1826 RegCloseKey(hDeviceInstanceKey);
1827 RegCloseKey(hInterfaceKey);
1828 return rc;
1829 }
1830 j++;
1831 if (KeyBuffer[0] != '#')
1832 /* This entry doesn't represent an interesting entry */
1833 continue;
1834
1835 /* Open sub key */
1836 rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
1837 if (rc != ERROR_SUCCESS)
1838 {
1839 RegCloseKey(hDeviceInstanceKey);
1840 RegCloseKey(hInterfaceKey);
1841 return rc;
1842 }
1843
1844 /* Read SymbolicLink value */
1845 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
1846 if (rc != ERROR_SUCCESS )
1847 {
1848 RegCloseKey(hReferenceKey);
1849 RegCloseKey(hDeviceInstanceKey);
1850 RegCloseKey(hInterfaceKey);
1851 return rc;
1852 }
1853 if (dwRegType != REG_SZ)
1854 {
1855 RegCloseKey(hReferenceKey);
1856 RegCloseKey(hDeviceInstanceKey);
1857 RegCloseKey(hInterfaceKey);
1858 return ERROR_GEN_FAILURE;
1859 }
1860
1861 /* We have found a device */
1862 /* Step 1. Create a device info element */
1863 if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
1864 {
1865 RegCloseKey(hReferenceKey);
1866 RegCloseKey(hDeviceInstanceKey);
1867 RegCloseKey(hInterfaceKey);
1868 return GetLastError();
1869 }
1870 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
1871 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
1872
1873 /* Step 2. Create an interface list for this element */
1874 pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
1875 if (!pSymbolicLink)
1876 {
1877 RegCloseKey(hReferenceKey);
1878 RegCloseKey(hDeviceInstanceKey);
1879 RegCloseKey(hInterfaceKey);
1880 return ERROR_NOT_ENOUGH_MEMORY;
1881 }
1882 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
1883 pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
1884 RegCloseKey(hReferenceKey);
1885 if (rc != ERROR_SUCCESS)
1886 {
1887 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1888 RegCloseKey(hDeviceInstanceKey);
1889 RegCloseKey(hInterfaceKey);
1890 return rc;
1891 }
1892 if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
1893 {
1894 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1895 RegCloseKey(hDeviceInstanceKey);
1896 RegCloseKey(hInterfaceKey);
1897 return GetLastError();
1898 }
1899 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
1900 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
1901 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
1902 }
1903 RegCloseKey(hDeviceInstanceKey);
1904 }
1905 RegCloseKey(hInterfaceKey);
1906 return ERROR_SUCCESS;
1907 }
1908 #endif /* __REACTOS__ */
1909
1910 /***********************************************************************
1911 * SetupDiGetClassDevsExW (SETUPAPI.@)
1912 */
1913 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1914 CONST GUID *class,
1915 LPCWSTR enumstr,
1916 HWND parent,
1917 DWORD flags,
1918 HDEVINFO deviceset,
1919 LPCWSTR machine,
1920 PVOID reserved)
1921 {
1922 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1923 struct DeviceInfoSet *list;
1924 LPGUID pClassGuid;
1925 LONG rc;
1926
1927 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr),
1928 parent, flags, deviceset, debugstr_w(machine), reserved);
1929
1930 /* Create the deviceset if not set */
1931 if (deviceset)
1932 {
1933 list = (struct DeviceInfoSet *)deviceset;
1934 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
1935 {
1936 SetLastError(ERROR_INVALID_HANDLE);
1937 return INVALID_HANDLE_VALUE;
1938 }
1939 hDeviceInfo = deviceset;
1940 }
1941 else
1942 {
1943 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
1944 flags & DIGCF_DEVICEINTERFACE ? NULL : class,
1945 NULL, machine, NULL);
1946 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1947 return INVALID_HANDLE_VALUE;
1948 list = (struct DeviceInfoSet *)hDeviceInfo;
1949 }
1950
1951 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1952 pClassGuid = NULL;
1953 else
1954 pClassGuid = &list->ClassGuid;
1955
1956 if (flags & DIGCF_PRESENT)
1957 FIXME(": flag DIGCF_PRESENT ignored\n");
1958 if (flags & DIGCF_PROFILE)
1959 FIXME(": flag DIGCF_PROFILE ignored\n");
1960
1961 if (flags & DIGCF_ALLCLASSES)
1962 {
1963 rc = SETUP_CreateDevList(list, machine, pClassGuid, enumstr);
1964 if (rc != ERROR_SUCCESS)
1965 {
1966 SetLastError(rc);
1967 if (!deviceset)
1968 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1969 return INVALID_HANDLE_VALUE;
1970 }
1971 return hDeviceInfo;
1972 }
1973 else if (flags & DIGCF_DEVICEINTERFACE)
1974 {
1975 if (class == NULL)
1976 {
1977 SetLastError(ERROR_INVALID_PARAMETER);
1978 if (!deviceset)
1979 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1980 return INVALID_HANDLE_VALUE;
1981 }
1982
1983 #ifndef __REACTOS__
1984 /* Special case: find serial ports by calling QueryDosDevice */
1985 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
1986 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1987 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
1988 rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
1989 else
1990 {
1991 ERR("Wine can only enumerate serial devices at the moment!\n");
1992 rc = ERROR_INVALID_PARAMETER;
1993 }
1994 #else /* __REACTOS__ */
1995 rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
1996 #endif /* __REACTOS__ */
1997 if (rc != ERROR_SUCCESS)
1998 {
1999 SetLastError(rc);
2000 if (!deviceset)
2001 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2002 return INVALID_HANDLE_VALUE;
2003 }
2004 return hDeviceInfo;
2005 }
2006 else
2007 {
2008 rc = SETUP_CreateDevList(list, machine, (LPGUID)class, enumstr);
2009 if (rc != ERROR_SUCCESS)
2010 {
2011 SetLastError(rc);
2012 if (!deviceset)
2013 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2014 return INVALID_HANDLE_VALUE;
2015 }
2016 return hDeviceInfo;
2017 }
2018 }
2019
2020 /***********************************************************************
2021 * SetupDiGetClassImageIndex (SETUPAPI.@)
2022 */
2023
2024 static BOOL GetIconIndex(
2025 IN HKEY hClassKey,
2026 OUT PINT ImageIndex)
2027 {
2028 LPWSTR Buffer = NULL;
2029 DWORD dwRegType, dwLength;
2030 LONG rc;
2031 BOOL ret = FALSE;
2032
2033 /* Read icon registry key */
2034 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength);
2035 if (rc != ERROR_SUCCESS)
2036 {
2037 SetLastError(rc);
2038 goto cleanup;
2039 } else if (dwRegType != REG_SZ)
2040 {
2041 SetLastError(ERROR_INVALID_INDEX);
2042 goto cleanup;
2043 }
2044 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
2045 if (!Buffer)
2046 {
2047 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2048 goto cleanup;
2049 }
2050 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength);
2051 if (rc != ERROR_SUCCESS)
2052 {
2053 SetLastError(rc);
2054 goto cleanup;
2055 }
2056 /* make sure the returned buffer is NULL-terminated */
2057 Buffer[dwLength / sizeof(WCHAR)] = 0;
2058
2059 /* Transform icon value to a INT */
2060 *ImageIndex = atoiW(Buffer);
2061 ret = TRUE;
2062
2063 cleanup:
2064 MyFree(Buffer);
2065 return ret;
2066 }
2067
2068 BOOL WINAPI SetupDiGetClassImageIndex(
2069 IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
2070 IN CONST GUID *ClassGuid,
2071 OUT PINT ImageIndex)
2072 {
2073 struct ClassImageList *list;
2074 BOOL ret = FALSE;
2075
2076 TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
2077
2078 if (!ClassImageListData || !ClassGuid || !ImageIndex)
2079 SetLastError(ERROR_INVALID_PARAMETER);
2080 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
2081 SetLastError(ERROR_INVALID_USER_BUFFER);
2082 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
2083 SetLastError(ERROR_INVALID_USER_BUFFER);
2084 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
2085 SetLastError(ERROR_INVALID_USER_BUFFER);
2086 else if (!ImageIndex)
2087 SetLastError(ERROR_INVALID_PARAMETER);
2088 else
2089 {
2090 HKEY hKey = INVALID_HANDLE_VALUE;
2091 INT iconIndex;
2092
2093 /* Read Icon registry entry into Buffer */
2094 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL);
2095 if (hKey == INVALID_HANDLE_VALUE)
2096 goto cleanup;
2097 if (!GetIconIndex(hKey, &iconIndex))
2098 goto cleanup;
2099
2100 if (iconIndex >= 0)
2101 {
2102 SetLastError(ERROR_INVALID_INDEX);
2103 goto cleanup;
2104 }
2105
2106 *ImageIndex = -iconIndex;
2107 ret = TRUE;
2108
2109 cleanup:
2110 if (hKey != INVALID_HANDLE_VALUE)
2111 RegCloseKey(hKey);
2112 }
2113
2114 TRACE("Returning %d\n", ret);
2115 return ret;
2116 }
2117
2118 /***********************************************************************
2119 * SetupDiGetClassImageList(SETUPAPI.@)
2120 */
2121 BOOL WINAPI SetupDiGetClassImageList(
2122 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
2123 {
2124 return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
2125 }
2126
2127 /***********************************************************************
2128 * SetupDiGetClassImageListExA(SETUPAPI.@)
2129 */
2130 BOOL WINAPI SetupDiGetClassImageListExA(
2131 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
2132 IN PCSTR MachineName OPTIONAL,
2133 IN PVOID Reserved)
2134 {
2135 PWSTR MachineNameW = NULL;
2136 BOOL ret;
2137
2138 if (MachineName)
2139 {
2140 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2141 if (MachineNameW == NULL)
2142 return FALSE;
2143 }
2144
2145 ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
2146
2147 if (MachineNameW)
2148 MyFree(MachineNameW);
2149
2150 return ret;
2151 }
2152
2153 /***********************************************************************
2154 * SetupDiGetClassImageListExW(SETUPAPI.@)
2155 */
2156 BOOL WINAPI SetupDiGetClassImageListExW(
2157 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
2158 IN PCWSTR MachineName OPTIONAL,
2159 IN PVOID Reserved)
2160 {
2161 BOOL ret = FALSE;
2162
2163 TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
2164
2165 if (!ClassImageListData)
2166 SetLastError(ERROR_INVALID_PARAMETER);
2167 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
2168 SetLastError(ERROR_INVALID_USER_BUFFER);
2169 else if (Reserved)
2170 SetLastError(ERROR_INVALID_PARAMETER);
2171 else
2172 {
2173 struct ClassImageList *list = NULL;
2174 DWORD size;
2175
2176 size = FIELD_OFFSET(struct ClassImageList, szData);
2177 if (MachineName)
2178 size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
2179 list = HeapAlloc(GetProcessHeap(), 0, size);
2180 if (!list)
2181 {
2182 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2183 goto cleanup;
2184 }
2185 list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
2186 if (MachineName)
2187 {
2188 list->szData[0] = list->szData[1] = '\\';
2189 strcpyW(list->szData + 2, MachineName);
2190 list->MachineName = list->szData;
2191 }
2192 else
2193 {
2194 list->MachineName = NULL;
2195 }
2196
2197 ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
2198 ret = TRUE;
2199
2200 cleanup:
2201 if (!ret)
2202 MyFree(list);
2203 }
2204
2205 TRACE("Returning %d\n", ret);
2206 return ret;
2207 }
2208
2209 /***********************************************************************
2210 * SetupDiLoadClassIcon(SETUPAPI.@)
2211 */
2212 BOOL WINAPI SetupDiLoadClassIcon(
2213 IN CONST GUID *ClassGuid,
2214 OUT HICON *LargeIcon OPTIONAL,
2215 OUT PINT MiniIconIndex OPTIONAL)
2216 {
2217 BOOL ret = FALSE;
2218
2219 if (!ClassGuid)
2220 SetLastError(ERROR_INVALID_PARAMETER);
2221 else
2222 {
2223 LPWSTR Buffer = NULL;
2224 LPCWSTR DllName;
2225 INT iconIndex;
2226 HKEY hKey = INVALID_HANDLE_VALUE;
2227
2228 hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
2229 if (hKey == INVALID_HANDLE_VALUE)
2230 goto cleanup;
2231
2232 if (!GetIconIndex(hKey, &iconIndex))
2233 goto cleanup;
2234
2235 if (iconIndex > 0)
2236 {
2237 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2238 PWCHAR Comma;
2239 LONG rc;
2240 DWORD dwRegType, dwLength;
2241 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
2242 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
2243 {
2244 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
2245 if (Buffer == NULL)
2246 {
2247 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2248 goto cleanup;
2249 }
2250 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
2251 if (rc != ERROR_SUCCESS)
2252 {
2253 SetLastError(rc);
2254 goto cleanup;
2255 }
2256 /* make sure the returned buffer is NULL-terminated */
2257 Buffer[dwLength / sizeof(WCHAR)] = 0;
2258 }
2259 else if
2260 (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
2261 && dwRegType == REG_SZ)
2262 {
2263 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
2264 if (Buffer == NULL)
2265 {
2266 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2267 goto cleanup;
2268 }
2269 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
2270 if (rc != ERROR_SUCCESS)
2271 {
2272 SetLastError(rc);
2273 goto cleanup;
2274 }
2275 /* make sure the returned buffer is NULL-terminated */
2276 Buffer[dwLength / sizeof(WCHAR)] = 0;
2277 }
2278 else
2279 {
2280 /* Unable to find where to load the icon */
2281 SetLastError(ERROR_FILE_NOT_FOUND);
2282 goto cleanup;
2283 }
2284 Comma = strchrW(Buffer, ',');
2285 if (!Comma)
2286 {
2287 SetLastError(ERROR_GEN_FAILURE);
2288 goto cleanup;
2289 }
2290 *Comma = '\0';
2291 DllName = Buffer;
2292 }
2293 else
2294 {
2295 /* Look up icon in setupapi.dll */
2296 DllName = L"setupapi.dll";
2297 iconIndex = -iconIndex;
2298 }
2299
2300 TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
2301 if (LargeIcon)
2302 {
2303 if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1))
2304 {
2305 SetLastError(ERROR_INVALID_INDEX);
2306 goto cleanup;
2307 }
2308 }
2309 if (MiniIconIndex)
2310 *MiniIconIndex = iconIndex;
2311 ret = TRUE;
2312
2313 cleanup:
2314 if (hKey != INVALID_HANDLE_VALUE)
2315 RegCloseKey(hKey);
2316 MyFree(Buffer);
2317 }
2318
2319 TRACE("Returning %d\n", ret);
2320 return ret;
2321 }
2322
2323 /***********************************************************************
2324 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2325 */
2326 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2327 HDEVINFO DeviceInfoSet,
2328 PSP_DEVINFO_DATA DeviceInfoData,
2329 CONST GUID * InterfaceClassGuid,
2330 DWORD MemberIndex,
2331 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2332 {
2333 BOOL ret = FALSE;
2334
2335 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
2336 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2337
2338 if (!DeviceInterfaceData)
2339 SetLastError(ERROR_INVALID_PARAMETER);
2340 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2341 SetLastError(ERROR_INVALID_USER_BUFFER);
2342 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
2343 {
2344 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2345
2346 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
2347 {
2348 PLIST_ENTRY ItemList = list->ListHead.Flink;
2349 BOOL Found = FALSE;
2350 while (ItemList != &list->ListHead && !Found)
2351 {
2352 PLIST_ENTRY InterfaceListEntry;
2353 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
2354 if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
2355 {
2356 /* We are not searching for this element */
2357 ItemList = ItemList->Flink;
2358 continue;
2359 }
2360 InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
2361 while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
2362 {
2363 struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
2364 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2365 {
2366 InterfaceListEntry = InterfaceListEntry->Flink;
2367 continue;
2368 }
2369 if (MemberIndex-- == 0)
2370 {
2371 /* return this item */
2372 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2373 &DevItf->InterfaceClassGuid,
2374 sizeof(GUID));
2375 DeviceInterfaceData->Flags = 0; /* FIXME */
2376 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2377 Found = TRUE;
2378 }
2379 InterfaceListEntry = InterfaceListEntry->Flink;
2380 }
2381 ItemList = ItemList->Flink;
2382 }
2383 if (!Found)
2384 SetLastError(ERROR_NO_MORE_ITEMS);
2385 else
2386 ret = TRUE;
2387 }
2388 else
2389 SetLastError(ERROR_INVALID_HANDLE);
2390 }
2391 else
2392 SetLastError(ERROR_INVALID_HANDLE);
2393 return ret;
2394 }
2395
2396 static VOID ReferenceInfFile(struct InfFileDetails* infFile)
2397 {
2398 InterlockedIncrement(&infFile->References);
2399 }
2400
2401 static VOID DereferenceInfFile(struct InfFileDetails* infFile)
2402 {
2403 if (InterlockedDecrement(&infFile->References) == 0)
2404 {
2405 SetupCloseInfFile(infFile->hInf);
2406 HeapFree(GetProcessHeap(), 0, infFile);
2407 }
2408 }
2409
2410 static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
2411 {
2412 DereferenceInfFile(driverInfo->InfFileDetails);
2413 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
2414 HeapFree(GetProcessHeap(), 0, driverInfo);
2415 return TRUE;
2416 }
2417
2418 static BOOL DestroyClassInstallParams(struct ClassInstallParams* installParams)
2419 {
2420 HeapFree(GetProcessHeap(), 0, installParams->PropChange);
2421 return TRUE;
2422 }
2423
2424 static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
2425 {
2426 PLIST_ENTRY ListEntry;
2427 struct DriverInfoElement *driverInfo;
2428
2429 while (!IsListEmpty(&deviceInfo->DriverListHead))
2430 {
2431 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
2432 driverInfo = (struct DriverInfoElement *)ListEntry;
2433 if (!DestroyDriverInfoElement(driverInfo))
2434 return FALSE;
2435 }
2436 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
2437 {
2438 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
2439 HeapFree(GetProcessHeap(), 0, ListEntry);
2440 }
2441 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
2442 HeapFree(GetProcessHeap(), 0, deviceInfo);
2443 return TRUE;
2444 }
2445
2446 static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
2447 {
2448 PLIST_ENTRY ListEntry;
2449 struct DeviceInfoElement *deviceInfo;
2450
2451 while (!IsListEmpty(&list->ListHead))
2452 {
2453 ListEntry = RemoveHeadList(&list->ListHead);
2454 deviceInfo = (struct DeviceInfoElement *)ListEntry;
2455 if (!DestroyDeviceInfoElement(deviceInfo))
2456 return FALSE;
2457 }
2458 if (list->HKLM != HKEY_LOCAL_MACHINE)
2459 RegCloseKey(list->HKLM);
2460 CM_Disconnect_Machine(list->hMachine);
2461 DestroyClassInstallParams(&list->ClassInstallParams);
2462 HeapFree(GetProcessHeap(), 0, list);
2463 return TRUE;
2464 }
2465
2466 /***********************************************************************
2467 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2468 */
2469 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2470 {
2471 BOOL ret = FALSE;
2472
2473 TRACE("%p\n", devinfo);
2474 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
2475 {
2476 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2477
2478 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
2479 ret = DestroyDeviceInfoSet(list);
2480 else
2481 SetLastError(ERROR_INVALID_HANDLE);
2482 }
2483 else
2484 SetLastError(ERROR_INVALID_HANDLE);
2485
2486 TRACE("Returning %d\n", ret);
2487 return ret;
2488 }
2489
2490 /***********************************************************************
2491 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2492 */
2493 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2494 HDEVINFO DeviceInfoSet,
2495 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2496 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2497 DWORD DeviceInterfaceDetailDataSize,
2498 PDWORD RequiredSize,
2499 PSP_DEVINFO_DATA DeviceInfoData)
2500 {
2501 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2502 DWORD sizeW = 0, sizeA;
2503 BOOL ret = FALSE;
2504
2505 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2506 DeviceInterfaceData, DeviceInterfaceDetailData,
2507 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2508
2509 if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
2510 SetLastError(ERROR_INVALID_USER_BUFFER);
2511 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2512 SetLastError(ERROR_INVALID_PARAMETER);
2513 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
2514 SetLastError(ERROR_INVALID_PARAMETER);
2515 else
2516 {
2517 if (DeviceInterfaceDetailData != NULL)
2518 {
2519 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2520 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2521 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
2522 if (!DeviceInterfaceDetailDataW)
2523 {
2524 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2525 }
2526 }
2527 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2528 {
2529 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2530 ret = SetupDiGetDeviceInterfaceDetailW(
2531 DeviceInfoSet,
2532 DeviceInterfaceData,
2533 DeviceInterfaceDetailDataW,
2534 sizeW,
2535 &sizeW,
2536 DeviceInfoData);
2537 sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2538 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2539 if (RequiredSize)
2540 *RequiredSize = sizeA;
2541 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
2542 {
2543 if (!WideCharToMultiByte(
2544 CP_ACP, 0,
2545 DeviceInterfaceDetailDataW->DevicePath, -1,
2546 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2547 NULL, NULL))
2548 {
2549 ret = FALSE;
2550 }
2551 }
2552 }
2553 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
2554 }
2555
2556 TRACE("Returning %d\n", ret);
2557 return ret;
2558 }
2559
2560 /***********************************************************************
2561 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2562 */
2563 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2564 HDEVINFO DeviceInfoSet,
2565 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2566 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2567 DWORD DeviceInterfaceDetailDataSize,
2568 PDWORD RequiredSize,
2569 PSP_DEVINFO_DATA DeviceInfoData)
2570 {
2571 BOOL ret = FALSE;
2572
2573 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
2574 DeviceInterfaceData, DeviceInterfaceDetailData,
2575 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2576
2577 if (!DeviceInfoSet || !DeviceInterfaceData)
2578 SetLastError(ERROR_INVALID_PARAMETER);
2579 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2580 SetLastError(ERROR_INVALID_HANDLE);
2581 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2582 SetLastError(ERROR_INVALID_HANDLE);
2583 else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2584 SetLastError(ERROR_INVALID_USER_BUFFER);
2585 else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
2586 SetLastError(ERROR_INVALID_USER_BUFFER);
2587 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2588 SetLastError(ERROR_INVALID_USER_BUFFER);
2589 else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
2590 SetLastError(ERROR_INVALID_PARAMETER);
2591 else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
2592 SetLastError(ERROR_INVALID_PARAMETER);
2593 else
2594 {
2595 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2596 LPCWSTR devName = deviceInterface->SymbolicLink;
2597 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
2598 (lstrlenW(devName) + 1) * sizeof(WCHAR);
2599
2600 if (sizeRequired > DeviceInterfaceDetailDataSize)
2601 {
2602 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2603 if (RequiredSize)
2604 *RequiredSize = sizeRequired;
2605 }
2606 else
2607 {
2608 wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
2609 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
2610 if (DeviceInfoData)
2611 {
2612 memcpy(&DeviceInfoData->ClassGuid,
2613 &deviceInterface->DeviceInfo->ClassGuid,
2614 sizeof(GUID));
2615 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
2616 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
2617 }
2618 ret = TRUE;
2619 }
2620 }
2621
2622 TRACE("Returning %d\n", ret);
2623 return ret;
2624 }
2625
2626 /***********************************************************************
2627 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2628 */
2629 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
2630 HDEVINFO devinfo,
2631 PSP_DEVINFO_DATA DeviceInfoData,
2632 DWORD Property,
2633 PDWORD PropertyRegDataType,
2634 PBYTE PropertyBuffer,
2635 DWORD PropertyBufferSize,
2636 PDWORD RequiredSize)
2637 {
2638 BOOL bResult;
2639 BOOL bIsStringProperty;
2640 DWORD RegType;
2641 DWORD RequiredSizeA, RequiredSizeW;
2642 DWORD PropertyBufferSizeW;
2643 PBYTE PropertyBufferW;
2644
2645 TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
2646 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2647 RequiredSize);
2648
2649 PropertyBufferSizeW = PropertyBufferSize * 2;
2650 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
2651
2652 bResult = SetupDiGetDeviceRegistryPropertyW(
2653 devinfo,
2654 DeviceInfoData,
2655 Property,
2656 &RegType,
2657 PropertyBufferW,
2658 PropertyBufferSizeW,
2659 &RequiredSizeW);
2660
2661 if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2662 {
2663 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
2664
2665 if (bIsStringProperty)
2666 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
2667 else
2668 RequiredSizeA = RequiredSizeW;
2669 if (RequiredSize)
2670 *RequiredSize = RequiredSizeA;
2671 if (PropertyRegDataType)
2672 *PropertyRegDataType = RegType;
2673 }
2674
2675 if (!bResult)
2676 {
2677 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2678 return bResult;
2679 }
2680
2681 if (RequiredSizeA <= PropertyBufferSize)
2682 {
2683 if (bIsStringProperty && PropertyBufferSize > 0)
2684 {
2685 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
2686 {
2687 /* Last error is already set by WideCharToMultiByte */
2688 bResult = FALSE;
2689 }
2690 }
2691 else
2692 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
2693 }
2694 else
2695 {
2696 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2697 bResult = FALSE;
2698 }
2699
2700 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
2701 return bResult;
2702 }
2703
2704 /***********************************************************************
2705 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2706 */
2707 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
2708 HDEVINFO DeviceInfoSet,
2709 PSP_DEVINFO_DATA DeviceInfoData,
2710 DWORD Property,
2711 PDWORD PropertyRegDataType,
2712 PBYTE PropertyBuffer,
2713 DWORD PropertyBufferSize,
2714 PDWORD RequiredSize)
2715 {
2716 HKEY hEnumKey, hKey;
2717 DWORD rc;
2718 BOOL ret = FALSE;
2719
2720 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
2721 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
2722 RequiredSize);
2723
2724 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2725 SetLastError(ERROR_INVALID_HANDLE);
2726 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2727 SetLastError(ERROR_INVALID_HANDLE);
2728 else if (!DeviceInfoData)
2729 SetLastError(ERROR_INVALID_PARAMETER);
2730 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2731 SetLastError(ERROR_INVALID_USER_BUFFER);
2732 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
2733 SetLastError(ERROR_INVALID_PARAMETER);
2734 else
2735 {
2736 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
2737 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2738
2739 switch (Property)
2740 {
2741 case SPDRP_CAPABILITIES:
2742 case SPDRP_CLASS:
2743 case SPDRP_CLASSGUID:
2744 case SPDRP_COMPATIBLEIDS:
2745 case SPDRP_CONFIGFLAGS:
2746 case SPDRP_DEVICEDESC:
2747 case SPDRP_DRIVER:
2748 case SPDRP_FRIENDLYNAME:
2749 case SPDRP_HARDWAREID:
2750 case SPDRP_LOCATION_INFORMATION:
2751 case SPDRP_LOWERFILTERS:
2752 case SPDRP_MFG:
2753 case SPDRP_SECURITY:
2754 case SPDRP_SERVICE:
2755 case SPDRP_UI_NUMBER:
2756 case SPDRP_UI_NUMBER_DESC_FORMAT:
2757 case SPDRP_UPPERFILTERS:
2758 {
2759 LPCWSTR RegistryPropertyName;
2760 DWORD BufferSize;
2761
2762 switch (Property)
2763 {
2764 case SPDRP_CAPABILITIES:
2765 RegistryPropertyName = REGSTR_VAL_CAPABILITIES; break;
2766 case SPDRP_CLASS:
2767 RegistryPropertyName = REGSTR_VAL_CLASS; break;
2768 case SPDRP_CLASSGUID:
2769 RegistryPropertyName = REGSTR_VAL_CLASSGUID; break;
2770 case SPDRP_COMPATIBLEIDS:
2771 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS; break;
2772 case SPDRP_CONFIGFLAGS:
2773 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS; break;
2774 case SPDRP_DEVICEDESC:
2775 RegistryPropertyName = REGSTR_VAL_DEVDESC; break;
2776 case SPDRP_DRIVER:
2777 RegistryPropertyName = REGSTR_VAL_DRIVER; break;
2778 case SPDRP_FRIENDLYNAME:
2779 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME; break;
2780 case SPDRP_HARDWAREID:
2781 RegistryPropertyName = REGSTR_VAL_HARDWAREID; break;
2782 case SPDRP_LOCATION_INFORMATION:
2783 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION; break;
2784 case SPDRP_LOWERFILTERS:
2785 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS; break;
2786 case SPDRP_MFG:
2787 RegistryPropertyName = REGSTR_VAL_MFG; break;
2788 case SPDRP_SECURITY:
2789 RegistryPropertyName = L"Security"; break;
2790 case SPDRP_SERVICE:
2791 RegistryPropertyName = REGSTR_VAL_SERVICE; break;
2792 case SPDRP_UI_NUMBER:
2793 RegistryPropertyName = REGSTR_VAL_UI_NUMBER; break;
2794 case SPDRP_UI_NUMBER_DESC_FORMAT:
2795 RegistryPropertyName = L"UINumberDescFormat"; break;
2796 case SPDRP_UPPERFILTERS:
2797 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
2798 default:
2799 /* Should not happen */
2800 RegistryPropertyName = NULL; break;
2801 }
2802
2803 /* Open registry key name */
2804 rc = RegOpenKeyExW(
2805 list->HKLM,
2806 REGSTR_PATH_SYSTEMENUM,
2807 0, /* Options */
2808 0,
2809 &hEnumKey);
2810 if (rc != ERROR_SUCCESS)
2811 {
2812 SetLastError(rc);
2813 break;
2814 }
2815 rc = RegOpenKeyExW(
2816 hEnumKey,
2817 DevInfo->Data,
2818 0, /* Options */
2819 KEY_QUERY_VALUE,
2820 &hKey);
2821 RegCloseKey(hEnumKey);
2822 if (rc != ERROR_SUCCESS)
2823 {
2824 SetLastError(rc);
2825 break;
2826 }
2827 /* Read registry entry */
2828 BufferSize = PropertyBufferSize;
2829 rc = RegQueryValueExW(
2830 hKey,
2831 RegistryPropertyName,
2832 NULL, /* Reserved */
2833 PropertyRegDataType,
2834 PropertyBuffer,
2835 &BufferSize);
2836 if (RequiredSize)
2837 *RequiredSize = BufferSize;
2838 switch(rc) {
2839 case ERROR_SUCCESS:
2840 if (PropertyBuffer != NULL || BufferSize == 0)
2841 ret = TRUE;
2842 else
2843 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2844 break;
2845 case ERROR_MORE_DATA:
2846 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2847 break;
2848 default:
2849 SetLastError(rc);
2850 }
2851 RegCloseKey(hKey);
2852 break;
2853 }
2854
2855 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
2856 {
2857 DWORD required = (wcslen(DevInfo->Data) + 1) * sizeof(WCHAR);
2858
2859 if (PropertyRegDataType)
2860 *PropertyRegDataType = REG_SZ;
2861 if (RequiredSize)
2862 *RequiredSize = required;
2863 if (PropertyBufferSize >= required)
2864 {
2865 wcscpy((LPWSTR)PropertyBuffer, DevInfo->Data);
2866 ret = TRUE;
2867 }
2868 else
2869 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2870 break;
2871 }
2872
2873 /*case SPDRP_BUSTYPEGUID:
2874 case SPDRP_LEGACYBUSTYPE:
2875 case SPDRP_BUSNUMBER:
2876 case SPDRP_ENUMERATOR_NAME:
2877 case SPDRP_SECURITY_SDS:
2878 case SPDRP_DEVTYPE:
2879 case SPDRP_EXCLUSIVE:
2880 case SPDRP_CHARACTERISTICS:
2881 case SPDRP_ADDRESS:
2882 case SPDRP_DEVICE_POWER_DATA:*/
2883 #if (WINVER >= 0x501)
2884 /*case SPDRP_REMOVAL_POLICY:
2885 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2886 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2887 case SPDRP_INSTALL_STATE:*/
2888 #endif
2889
2890 default:
2891 {
2892 ERR("Property 0x%lx not implemented\n", Property);
2893 SetLastError(ERROR_NOT_SUPPORTED);
2894 }
2895 }
2896 }
2897
2898 TRACE("Returning %d\n", ret);
2899 return ret;
2900 }
2901
2902 /***********************************************************************
2903 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2904 */
2905 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2906 IN HDEVINFO DeviceInfoSet,
2907 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2908 IN DWORD Property,
2909 IN CONST BYTE *PropertyBuffer,
2910 IN DWORD PropertyBufferSize)
2911 {
2912 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2913 Property, PropertyBuffer, PropertyBufferSize);
2914 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2915 return FALSE;
2916 }
2917
2918 /***********************************************************************
2919 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2920 */
2921 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2922 IN HDEVINFO DeviceInfoSet,
2923 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
2924 IN DWORD Property,
2925 IN const BYTE *PropertyBuffer,
2926 IN DWORD PropertyBufferSize)
2927 {
2928 struct DeviceInfoSet *list;
2929 BOOL ret = FALSE;
2930
2931 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2932 Property, PropertyBuffer, PropertyBufferSize);
2933
2934 if (!DeviceInfoSet)
2935 SetLastError(ERROR_INVALID_HANDLE);
2936 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2937 SetLastError(ERROR_INVALID_HANDLE);
2938 else if (!DeviceInfoData)
2939 SetLastError(ERROR_INVALID_HANDLE);
2940 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2941 SetLastError(ERROR_INVALID_USER_BUFFER);
2942 else
2943 {
2944 switch (Property)
2945 {
2946 case SPDRP_COMPATIBLEIDS:
2947 case SPDRP_CONFIGFLAGS:
2948 case SPDRP_FRIENDLYNAME:
2949 case SPDRP_HARDWAREID:
2950 case SPDRP_LOCATION_INFORMATION:
2951 case SPDRP_LOWERFILTERS:
2952 case SPDRP_SECURITY:
2953 case SPDRP_SERVICE:
2954 case SPDRP_UI_NUMBER_DESC_FORMAT:
2955 case SPDRP_UPPERFILTERS:
2956 {
2957 LPCWSTR RegistryPropertyName;
2958 DWORD RegistryDataType;
2959 HKEY hKey;
2960 LONG rc;
2961
2962 switch (Property)
2963 {
2964 case SPDRP_COMPATIBLEIDS:
2965 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS;
2966 RegistryDataType = REG_MULTI_SZ;
2967 break;
2968 case SPDRP_CONFIGFLAGS:
2969 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
2970 RegistryDataType = REG_DWORD;
2971 break;
2972 case SPDRP_FRIENDLYNAME:
2973 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
2974 RegistryDataType = REG_SZ;
2975 break;
2976 case SPDRP_HARDWAREID:
2977 RegistryPropertyName = REGSTR_VAL_HARDWAREID;
2978 RegistryDataType = REG_MULTI_SZ;
2979 break;
2980 case SPDRP_LOCATION_INFORMATION:
2981 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
2982 RegistryDataType = REG_SZ;
2983 break;
2984 case SPDRP_LOWERFILTERS:
2985 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
2986 RegistryDataType = REG_MULTI_SZ;
2987 break;
2988 case SPDRP_SECURITY:
2989 RegistryPropertyName = L"Security";
2990 RegistryDataType = REG_BINARY;
2991 break;
2992 case SPDRP_SERVICE:
2993 RegistryPropertyName = REGSTR_VAL_SERVICE;
2994 RegistryDataType = REG_SZ;
2995 break;
2996 case SPDRP_UI_NUMBER_DESC_FORMAT:
2997 RegistryPropertyName = L"UINumberDescFormat";
2998 RegistryDataType = REG_SZ;
2999 break;
3000 case SPDRP_UPPERFILTERS:
3001 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS;
3002 RegistryDataType = REG_MULTI_SZ;
3003 break;
3004 default:
3005 /* Should not happen */
3006 RegistryPropertyName = NULL;
3007 RegistryDataType = REG_BINARY;
3008 break;
3009 }
3010 /* Open device registry key */
3011 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
3012 if (hKey != INVALID_HANDLE_VALUE)
3013 {
3014 /* Write new data */
3015 rc = RegSetValueExW(
3016 hKey,
3017 RegistryPropertyName,
3018 0, /* Reserved */
3019 RegistryDataType,
3020 PropertyBuffer,
3021 PropertyBufferSize);
3022 if (rc == ERROR_SUCCESS)
3023 ret = TRUE;
3024 else
3025 SetLastError(rc);
3026 RegCloseKey(hKey);
3027 }
3028 break;
3029 }
3030
3031 /*case SPDRP_CHARACTERISTICS:
3032 case SPDRP_DEVTYPE:
3033 case SPDRP_EXCLUSIVE:*/
3034 #if (WINVER >= 0x501)
3035 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3036 #endif
3037 //case SPDRP_SECURITY_SDS:
3038
3039 default:
3040 {
3041 ERR("Property 0x%lx not implemented\n", Property);
3042 SetLastError(ERROR_NOT_SUPPORTED);
3043 }
3044 }
3045 }
3046
3047 TRACE("Returning %d\n", ret);
3048 return ret;
3049 }
3050
3051
3052 /***********************************************************************
3053 * SetupDiInstallClassA (SETUPAPI.@)
3054 */
3055 BOOL WINAPI SetupDiInstallClassA(
3056 IN HWND hwndParent OPTIONAL,
3057 IN PCSTR InfFileName,
3058 IN DWORD Flags,
3059 IN HSPFILEQ FileQueue OPTIONAL)
3060 {
3061 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3062 }
3063
3064
3065 /***********************************************************************
3066 * SetupDiInstallClassW (SETUPAPI.@)
3067 */
3068 BOOL WINAPI SetupDiInstallClassW(
3069 IN HWND hwndParent OPTIONAL,
3070 IN PCWSTR InfFileName,
3071 IN DWORD Flags,
3072 IN HSPFILEQ FileQueue OPTIONAL)
3073 {
3074 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3075 }
3076
3077
3078 /***********************************************************************
3079 * SetupDiInstallClassExA (SETUPAPI.@)
3080 */
3081 BOOL WINAPI SetupDiInstallClassExA(
3082 IN HWND hwndParent OPTIONAL,
3083 IN PCSTR InfFileName OPTIONAL,
3084 IN DWORD Flags,
3085 IN HSPFILEQ FileQueue OPTIONAL,
3086 IN const GUID* InterfaceClassGuid OPTIONAL,
3087 IN PVOID Reserved1,
3088 IN PVOID Reserved2)
3089 {
3090 PWSTR InfFileNameW = NULL;
3091 BOOL Result;
3092
3093 if (InfFileName)
3094 {
3095 InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
3096 if (InfFileNameW == NULL)
3097 {
3098 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3099 return FALSE;
3100 }
3101 }
3102
3103 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3104 FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3105
3106 MyFree(InfFileNameW);
3107
3108 return Result;
3109 }
3110
3111
3112 static HKEY CreateClassKey(HINF hInf)
3113 {
3114 WCHAR FullBuffer[MAX_PATH];
3115 WCHAR Buffer[MAX_PATH];
3116 DWORD RequiredSize;
3117 HKEY hClassKey;
3118
3119 Buffer[0] = '\\';
3120 if (!SetupGetLineTextW(NULL,
3121 hInf,
3122 Version,
3123 ClassGUID,
3124 &Buffer[1],
3125 MAX_PATH - 1,
3126 &RequiredSize))
3127 {
3128 return INVALID_HANDLE_VALUE;
3129 }
3130
3131 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3132 lstrcatW(FullBuffer, Buffer);
3133
3134
3135 if (!SetupGetLineTextW(NULL,
3136 hInf,
3137 Version,
3138 Class,
3139 Buffer,
3140 MAX_PATH,
3141 &RequiredSize))
3142 {
3143 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
3144 return INVALID_HANDLE_VALUE;
3145 }
3146
3147 if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3148 FullBuffer,
3149 0,
3150 NULL,
3151 REG_OPTION_NON_VOLATILE,
3152 KEY_SET_VALUE,
3153 NULL,
3154 &hClassKey,
3155 NULL))
3156 {
3157 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
3158 return INVALID_HANDLE_VALUE;
3159 }
3160
3161 if (ERROR_SUCCESS != RegSetValueExW(hClassKey,
3162 Class,
3163 0,
3164 REG_SZ,
3165 (LPBYTE)Buffer,
3166 RequiredSize * sizeof(WCHAR)))
3167 {
3168 RegCloseKey(hClassKey);
3169 RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
3170 return INVALID_HANDLE_VALUE;
3171 }
3172
3173 return hClassKey;
3174 }
3175
3176
3177 static BOOL
3178 InstallServicesSection(
3179 IN HINF hInf,
3180 IN PCWSTR SectionName,
3181 IN HDEVINFO DeviceInfoSet OPTIONAL,
3182 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
3183 OUT PCWSTR* pAssociatedService OPTIONAL,
3184 OUT PBOOL pRebootRequired OPTIONAL)
3185 {
3186 INFCONTEXT ContextService;
3187 INFCONTEXT ContextInclude;
3188 DWORD RequiredSize;
3189 INT Flags;
3190 BOOL ret = FALSE;
3191
3192 /* Parse 'Include' line */
3193 if (SetupFindFirstLineW(hInf, SectionName, L"Include", &ContextInclude))
3194 {
3195 DWORD Index = 1;
3196 while (TRUE)
3197 {
3198 static WCHAR szBuffer[MAX_PATH];
3199 PWSTR pBuffer = NULL;
3200 DWORD required;
3201
3202 ret = SetupGetStringFieldW(&ContextInclude, Index, szBuffer, MAX_PATH, &required);
3203 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
3204 break;
3205 else if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3206 {
3207 pBuffer = MyMalloc(required);
3208 ret = SetupGetStringFieldW(&ContextInclude, Index, pBuffer, required, &required);
3209 }
3210 if (ret)
3211 ret = SetupOpenAppendInfFileW(pBuffer ? pBuffer : szBuffer, hInf, NULL);
3212
3213 MyFree(pBuffer);
3214 if (!ret)
3215 goto done;
3216 Index++;
3217 }
3218 }
3219
3220 /* Parse 'Needs' line */
3221 if (SetupFindFirstLineW(hInf, SectionName, L"Needs", &ContextInclude))
3222 {
3223 DWORD Index = 1;
3224 while (TRUE)
3225 {
3226 static WCHAR szBuffer[MAX_PATH];
3227 PWSTR pBuffer = NULL;
3228 DWORD required;
3229
3230 ret = SetupGetStringFieldW(&ContextInclude, Index, szBuffer, MAX_PATH, &required);
3231 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
3232 break;
3233 else if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3234 {
3235 pBuffer = MyMalloc(required);
3236 ret = SetupGetStringFieldW(&ContextInclude, Index, pBuffer, required, &required);
3237 }
3238 if (ret)
3239 {
3240 ret = InstallServicesSection(hInf, pBuffer ? pBuffer : szBuffer,
3241 DeviceInfoSet, DeviceInfoData, pAssociatedService, pRebootRequired);
3242 }
3243
3244 MyFree(pBuffer);
3245 if (!ret)
3246 goto done;
3247 Index++;
3248 }
3249 }
3250
3251 ret = SetupFindFirstLineW(hInf, SectionName, NULL, &ContextService);
3252 while (ret)
3253 {
3254 LPWSTR ServiceName = NULL;
3255 LPWSTR ServiceSection = NULL;
3256
3257 ret = SetupGetStringFieldW(
3258 &ContextService,
3259 1, /* Field index */
3260 NULL, 0,
3261 &RequiredSize);
3262 if (!ret)
3263 goto nextservice;
3264 if (RequiredSize > 0)
3265 {
3266 /* We got the needed size for the buffer */
3267 ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3268 if (!ServiceName)
3269 {
3270 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3271 goto nextservice;
3272 }
3273 ret = SetupGetStringFieldW(
3274 &ContextService,
3275 1, /* Field index */
3276 ServiceName, RequiredSize,
3277 &RequiredSize);
3278 if (!ret)
3279 goto nextservice;
3280 }
3281 ret = SetupGetIntField(
3282 &ContextService,
3283 2, /* Field index */
3284 &Flags);
3285 if (!ret)
3286 {
3287 /* The field may be empty. Ignore the error */
3288 Flags = 0;
3289 }
3290 ret = SetupGetStringFieldW(
3291 &ContextService,
3292 3, /* Field index */
3293 NULL, 0,
3294 &RequiredSize);
3295 if (!ret)
3296 {
3297 if (GetLastError() == ERROR_INVALID_PARAMETER)
3298 {
3299 /* This first is probably missing. It is not
3300 * required, so ignore the error */
3301 RequiredSize = 0;
3302 ret = TRUE;
3303 }
3304 else
3305 goto nextservice;
3306 }
3307 if (RequiredSize > 0)
3308 {
3309 /* We got the needed size for the buffer */
3310 ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
3311 if (!ServiceSection)
3312 {
3313 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3314 goto nextservice;
3315 }
3316 ret = SetupGetStringFieldW(
3317 &ContextService,
3318 3, /* Field index */
3319 ServiceSection, RequiredSize,
3320 &RequiredSize);
3321 if (!ret)
3322 goto nextservice;
3323
3324 SetLastError(ERROR_SUCCESS);
3325 ret = SetupInstallServicesFromInfSectionExW(
3326 hInf,
3327 ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
3328 }
3329 if (ret && (Flags & SPSVCINST_ASSOCSERVICE))
3330 {
3331 if (pAssociatedService)
3332 {
3333 *pAssociatedService = ServiceName;
3334 ServiceName = NULL;
3335 }
3336 if (pRebootRequired && GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
3337 *pRebootRequired = TRUE;
3338 }
3339 nextservice:
3340 HeapFree(GetProcessHeap(), 0, ServiceName);
3341 HeapFree(GetProcessHeap(), 0, ServiceSection);
3342 if (!ret)
3343 goto done;
3344 ret = SetupFindNextLine(&ContextService, &ContextService);
3345 }
3346
3347 ret = TRUE;
3348
3349 done:
3350 return ret;
3351 }
3352
3353 /***********************************************************************
3354 * SetupDiInstallClassExW (SETUPAPI.@)
3355 */
3356 BOOL WINAPI SetupDiInstallClassExW(
3357 IN HWND hwndParent OPTIONAL,
3358 IN PCWSTR InfFileName OPTIONAL,
3359 IN DWORD Flags,
3360 IN HSPFILEQ FileQueue OPTIONAL,
3361 IN const GUID* InterfaceClassGuid OPTIONAL,
3362 IN PVOID Reserved1,
3363 IN PVOID Reserved2)
3364 {
3365 BOOL ret = FALSE;
3366
3367 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags,
3368 FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2);
3369
3370 if (!InfFileName && !InterfaceClassGuid)
3371 SetLastError(ERROR_INVALID_PARAMETER);
3372 else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
3373 {
3374 TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
3375 SetLastError(ERROR_INVALID_FLAGS);
3376 }
3377 else if ((Flags & DI_NOVCP) && FileQueue == NULL)
3378 SetLastError(ERROR_INVALID_PARAMETER);
3379 else if (Reserved1 != NULL)
3380 SetLastError(ERROR_INVALID_PARAMETER);
3381 else if (Reserved2 != NULL)
3382 SetLastError(ERROR_INVALID_PARAMETER);
3383 else
3384 {
3385 WCHAR SectionName[MAX_PATH];
3386 HINF hInf = INVALID_HANDLE_VALUE;
3387 HKEY hClassKey = INVALID_HANDLE_VALUE;
3388 PVOID callback_context = NULL;
3389
3390 if (InterfaceClassGuid)
3391 {
3392 /* SetupDiCreateDeviceInterface??? */
3393 FIXME("Installing an interface is not implemented\n");
3394 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3395 }
3396 else
3397 {
3398 if (Flags & DI_NOVCP)
3399 FIXME("FileQueue argument ignored\n");
3400 if (Flags & (DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
3401 FIXME("Flags 0x%lx ignored\n", Flags & (DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
3402
3403 /* Open the .inf file */
3404 hInf = SetupOpenInfFileW(
3405 InfFileName,
3406 NULL,
3407 INF_STYLE_WIN4,
3408 NULL);
3409 if (hInf == INVALID_HANDLE_VALUE)
3410 goto cleanup;
3411
3412 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3413 hClassKey = CreateClassKey(hInf);
3414 if (hClassKey == INVALID_HANDLE_VALUE)
3415 goto cleanup;
3416
3417 /* Try to append a layout file */
3418 ret = SetupOpenAppendInfFileW(NULL, hInf, NULL);
3419 if (!ret)
3420 goto cleanup;
3421
3422 /* Retrieve the actual section name */
3423 ret = SetupDiGetActualSectionToInstallW(
3424 hInf,
3425 ClassInstall32,
3426 SectionName,
3427 MAX_PATH - wcslen(DotServices),
3428 NULL,
3429 NULL);
3430 if (!ret)
3431 goto cleanup;
3432
3433 callback_context = SetupInitDefaultQueueCallback(hwndParent);
3434 if (!callback_context)
3435 goto cleanup;
3436
3437 ret = SetupInstallFromInfSectionW(
3438 hwndParent,
3439 hInf,
3440 SectionName,
3441 SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG,
3442 hClassKey,
3443 NULL, /* SourceRootPath */
3444 0, /* CopyFlags */
3445 SetupDefaultQueueCallbackW,
3446 callback_context,
3447 NULL,
3448 NULL);
3449 if (!ret)
3450 goto cleanup;
3451
3452 /* Install .Services section */
3453 lstrcatW(SectionName, DotServices);
3454 ret = InstallServicesSection(hInf, SectionName, NULL, NULL, NULL, NULL);
3455 if (!ret)
3456 goto cleanup;
3457
3458 ret = TRUE;
3459 }
3460
3461 cleanup:
3462 if (hInf != INVALID_HANDLE_VALUE)
3463 SetupCloseInfFile(hInf);
3464 if (hClassKey != INVALID_HANDLE_VALUE)
3465 RegCloseKey(hClassKey);
3466 SetupTermDefaultQueueCallback(callback_context);
3467 }
3468
3469 TRACE("Returning %d\n", ret);
3470 return ret;
3471 }
3472
3473
3474 /***********************************************************************
3475 * SetupDiOpenClassRegKey (SETUPAPI.@)
3476 */
3477 HKEY WINAPI SetupDiOpenClassRegKey(
3478 const GUID* ClassGuid,
3479 REGSAM samDesired)
3480 {
3481 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3482 DIOCR_INSTALLER, NULL, NULL);
3483 }
3484
3485
3486 /***********************************************************************
3487 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3488 */
3489 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3490 const GUID* ClassGuid OPTIONAL,
3491 REGSAM samDesired,
3492 DWORD Flags,
3493 PCSTR MachineName OPTIONAL,
3494 PVOID Reserved)
3495 {
3496 PWSTR MachineNameW = NULL;
3497 HKEY hKey;
3498
3499 TRACE("\n");
3500
3501 if (MachineName)
3502 {
3503 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3504 if (MachineNameW == NULL)
3505 return INVALID_HANDLE_VALUE;
3506 }
3507
3508 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3509 Flags, MachineNameW, Reserved);
3510
3511 if (MachineNameW)
3512 MyFree(MachineNameW);
3513
3514 return hKey;
3515 }
3516
3517
3518 /***********************************************************************
3519 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3520 */
3521 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3522 const GUID* ClassGuid OPTIONAL,
3523 REGSAM samDesired,
3524 DWORD Flags,
3525 PCWSTR MachineName OPTIONAL,
3526 PVOID Reserved)
3527 {
3528 LPWSTR lpGuidString;
3529 LPWSTR lpFullGuidString;
3530 DWORD dwLength;
3531 HKEY HKLM;
3532 HKEY hClassesKey;
3533 HKEY hClassKey;
3534 DWORD rc;
3535 LPCWSTR lpKeyName;
3536
3537 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3538 Flags, debugstr_w(MachineName), Reserved);
3539
3540 if (Flags == DIOCR_INSTALLER)
3541 {
3542 lpKeyName = REGSTR_PATH_CLASS_NT;
3543 }
3544 else if (Flags == DIOCR_INTERFACE)
3545 {
3546 lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
3547 }
3548 else
3549 {
3550 ERR("Invalid Flags parameter!\n");
3551 SetLastError(ERROR_INVALID_FLAGS);
3552 return INVALID_HANDLE_VALUE;
3553 }
3554
3555 if (MachineName != NULL)
3556 {
3557 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
3558 if (rc != ERROR_SUCCESS)
3559 {
3560 SetLastError(rc);
3561 return INVALID_HANDLE_VALUE;
3562 }
3563 }
3564 else
3565 HKLM = HKEY_LOCAL_MACHINE;
3566
3567 rc = RegOpenKeyExW(HKLM,
3568 lpKeyName,
3569 0,
3570 ClassGuid ? 0 : samDesired,
3571 &hClassesKey);
3572 if (MachineName != NULL) RegCloseKey(HKLM);
3573 if (rc != ERROR_SUCCESS)
3574 {
3575 SetLastError(rc);
3576 return INVALID_HANDLE_VALUE;
3577 }
3578
3579 if (ClassGuid == NULL)
3580 return hClassesKey;
3581
3582 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
3583 {
3584 SetLastError(ERROR_GEN_FAILURE);
3585 RegCloseKey(hClassesKey);
3586 return INVALID_HANDLE_VALUE;
3587 }
3588
3589 dwLength = lstrlenW(lpGuidString);
3590 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR));
3591 if (!lpFullGuidString)
3592 {
3593 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3594 RpcStringFreeW(&lpGuidString);
3595 return INVALID_HANDLE_VALUE;
3596 }
3597 lpFullGuidString[0] = '{';
3598 memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR));
3599 lpFullGuidString[dwLength + 1] = '}';
3600 lpFullGuidString[dwLength + 2] = '\0';
3601 RpcStringFreeW(&lpGuidString);
3602
3603 rc = RegOpenKeyExW(hClassesKey,
3604 lpFullGuidString,
3605 0,
3606 samDesired,
3607 &hClassKey);
3608 if (rc != ERROR_SUCCESS)
3609 {
3610 SetLastError(rc);
3611 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
3612 RegCloseKey(hClassesKey);
3613 return INVALID_HANDLE_VALUE;
3614 }
3615
3616 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
3617 RegCloseKey(hClassesKey);
3618
3619 return hClassKey;
3620 }
3621
3622 /***********************************************************************
3623 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3624 */
3625 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3626 HDEVINFO DeviceInfoSet,
3627 PCWSTR DevicePath,
3628 DWORD OpenFlags,
3629 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3630 {
3631 FIXME("%p %s %08lx %p\n",
3632 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3633 return FALSE;
3634 }
3635
3636 /***********************************************************************
3637 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3638 */
3639 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3640 HDEVINFO DeviceInfoSet,
3641 PCSTR DevicePath,
3642 DWORD OpenFlags,
3643 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3644 {
3645 LPWSTR DevicePathW = NULL;
3646 BOOL bResult;
3647
3648 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3649
3650 DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
3651 if (DevicePathW == NULL)
3652 return FALSE;
3653
3654 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
3655 DevicePathW, OpenFlags, DeviceInterfaceData);
3656
3657 MyFree(DevicePathW);
3658
3659 return bResult;
3660 }
3661
3662 /***********************************************************************
3663 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3664 */
3665 BOOL WINAPI SetupDiSetClassInstallParamsA(
3666 HDEVINFO DeviceInfoSet,
3667 PSP_DEVINFO_DATA DeviceInfoData,
3668 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3669 DWORD ClassInstallParamsSize)
3670 {
3671 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
3672 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3673 return FALSE;
3674 }
3675
3676 /***********************************************************************
3677 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3678 */
3679 BOOL WINAPI SetupDiSetClassInstallParamsW(
3680 IN HDEVINFO DeviceInfoSet,
3681 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
3682 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
3683 IN DWORD ClassInstallParamsSize)
3684 {
3685 struct DeviceInfoSet *list;
3686 BOOL ret = FALSE;
3687
3688 TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData,
3689 ClassInstallParams, ClassInstallParamsSize);
3690
3691 if (!DeviceInfoSet)
3692 SetLastError(ERROR_INVALID_PARAMETER);
3693 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3694 SetLastError(ERROR_INVALID_HANDLE);
3695 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3696 SetLastError(ERROR_INVALID_HANDLE);
3697 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3698 SetLastError(ERROR_INVALID_USER_BUFFER);
3699 else if (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER))
3700 SetLastError(ERROR_INVALID_USER_BUFFER);
3701 else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER))
3702 SetLastError(ERROR_INVALID_PARAMETER);
3703 else if (!ClassInstallParams && ClassInstallParamsSize != 0)
3704 SetLastError(ERROR_INVALID_PARAMETER);
3705 else
3706 {
3707 SP_DEVINSTALL_PARAMS_W InstallParams;
3708 BOOL Result;
3709
3710 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
3711 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3712 if (!Result)
3713 goto done;
3714
3715 if (ClassInstallParams)
3716 {
3717 /* Check parameters in ClassInstallParams */
3718 if (ClassInstallParams->InstallFunction < DIF_SELECTDEVICE
3719 || ClassInstallParams->InstallFunction - DIF_SELECTDEVICE >= sizeof(UpdateClassInstallParamHandlers)/sizeof(UpdateClassInstallParamHandlers[0]))
3720 {
3721 SetLastError(ERROR_INVALID_USER_BUFFER);
3722 goto done;
3723 }
3724 else if (UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE] == NULL)
3725 {
3726 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams->InstallFunction);
3727 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3728 goto done;
3729 }
3730 ret = UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE](DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize);
3731 if (!ret)
3732 goto done;
3733 InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
3734 }
3735 else
3736 {
3737 InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS;
3738 }
3739
3740 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3741 }
3742
3743 done:
3744 TRACE("Returning %d\n", ret);
3745 return ret;
3746 }
3747
3748 static BOOL PropertyChangeHandler(
3749 IN HDEVINFO DeviceInfoSet,
3750 IN PSP_DEVINFO_DATA DeviceInfoData,
3751 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
3752 IN DWORD ClassInstallParamsSize)
3753 {
3754 PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
3755 BOOL ret = FALSE;
3756
3757 if (!DeviceInfoData)
3758 SetLastError(ERROR_INVALID_PARAMETER);
3759 else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
3760 SetLastError(ERROR_INVALID_PARAMETER);
3761 else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE
3762 && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE
3763 && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP)
3764 SetLastError(ERROR_INVALID_FLAGS);
3765 else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL
3766 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
3767 SetLastError(ERROR_INVALID_FLAGS);
3768 else if (PropChangeParams
3769 && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP)
3770 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
3771 SetLastError(ERROR_INVALID_USER_BUFFER);
3772 else
3773 {
3774 PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
3775 if (!DeviceInfoData)
3776 {
3777 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
3778 CurrentPropChangeParams = &list->ClassInstallParams.PropChange;
3779 }
3780 else
3781 {
3782 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
3783 CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChange;
3784 }
3785 if (*CurrentPropChangeParams)
3786 {
3787 MyFree(*CurrentPropChangeParams);
3788 *CurrentPropChangeParams = NULL;
3789 }
3790 if (PropChangeParams)
3791 {
3792 *CurrentPropChangeParams = MyMalloc(sizeof(SP_PROPCHANGE_PARAMS));
3793 if (!*CurrentPropChangeParams)
3794 {
3795 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3796 goto done;
3797 }
3798 memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS));
3799 }
3800 ret = TRUE;
3801 }
3802
3803 done:
3804 return ret;
3805 }
3806
3807 static DWORD
3808 GetFunctionPointer(
3809 IN PWSTR InstallerName,
3810 OUT HMODULE* ModulePointer,
3811 OUT PVOID* FunctionPointer)
3812 {
3813 HMODULE hModule = NULL;
3814 LPSTR FunctionNameA = NULL;
3815 PWCHAR Comma;
3816 DWORD rc;
3817
3818 *ModulePointer = NULL;
3819 *FunctionPointer = NULL;
3820
3821 Comma = strchrW(InstallerName, ',');
3822 if (!Comma)
3823 {
3824 rc = ERROR_INVALID_PARAMETER;
3825 goto cleanup;
3826 }
3827
3828 /* Load library */
3829 *Comma = '\0';
3830 hModule = LoadLibraryW(InstallerName);
3831 *Comma = ',';
3832 if (!hModule)
3833 {
3834 rc = GetLastError();
3835 goto cleanup;
3836 }
3837
3838 /* Skip comma spaces */
3839 while (*Comma == ',' || isspaceW(*Comma))
3840 Comma++;
3841
3842 /* W->A conversion for function name */
3843 FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
3844 if (!FunctionNameA)
3845 {
3846 rc = GetLastError();
3847 goto cleanup;
3848 }
3849
3850 /* Search function */
3851 *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
3852 if (!*FunctionPointer)
3853 {
3854 rc = GetLastError();
3855 goto cleanup;
3856 }
3857
3858 *ModulePointer = hModule;
3859 rc = ERROR_SUCCESS;
3860
3861 cleanup:
3862 if (rc != ERROR_SUCCESS && hModule)
3863 FreeLibrary(hModule);
3864 MyFree(FunctionNameA);
3865 return rc;
3866 }
3867
3868 static DWORD
3869 FreeFunctionPointer(
3870 IN HMODULE ModulePointer,
3871 IN PVOID FunctionPointer)
3872 {
3873 if (ModulePointer == NULL)
3874 return ERROR_SUCCESS;
3875 if (FreeLibrary(ModulePointer))
3876 return ERROR_SUCCESS;
3877 else
3878 return GetLastError();
3879 }
3880
3881 /***********************************************************************
3882 * SetupDiCallClassInstaller (SETUPAPI.@)
3883 */
3884 BOOL WINAPI SetupDiCallClassInstaller(
3885 IN DI_FUNCTION InstallFunction,
3886 IN HDEVINFO DeviceInfoSet,
3887 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3888 {
3889 BOOL ret = FALSE;
3890
3891 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3892
3893 if (!DeviceInfoSet)
3894 SetLastError(ERROR_INVALID_PARAMETER);
3895 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3896 SetLastError(ERROR_INVALID_HANDLE);
3897 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3898 SetLastError(ERROR_INVALID_HANDLE);
3899 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
3900 SetLastError(ERROR_INVALID_HANDLE);
3901 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3902 SetLastError(ERROR_INVALID_USER_BUFFER);
3903 else
3904 {
3905 SP_DEVINSTALL_PARAMS_W InstallParams;
3906 #define CLASS_COINSTALLER 0x1
3907 #define DEVICE_COINSTALLER 0x2
3908 #define CLASS_INSTALLER 0x4
3909 UCHAR CanHandle = 0;
3910 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
3911
3912 switch (InstallFunction)
3913 {
3914 case DIF_ALLOW_INSTALL:
3915 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3916 break;
3917 case DIF_DESTROYPRIVATEDATA:
3918 CanHandle = CLASS_INSTALLER;
3919 break;
3920 case DIF_INSTALLDEVICE:
3921 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3922 DefaultHandler = SetupDiInstallDevice;
3923 break;
3924 case DIF_INSTALLDEVICEFILES:
3925 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3926 DefaultHandler = SetupDiInstallDriverFiles;
3927 break;
3928 case DIF_INSTALLINTERFACES:
3929 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3930 DefaultHandler = SetupDiInstallDeviceInterfaces;
3931 break;
3932 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
3933 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3934 break;
3935 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
3936 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3937 break;
3938 case DIF_NEWDEVICEWIZARD_PREANALYZE:
3939 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3940 break;
3941 case DIF_PROPERTYCHANGE:
3942 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3943 DefaultHandler = SetupDiChangeState;
3944 break;
3945 case DIF_REGISTER_COINSTALLERS:
3946 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3947 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
3948 break;
3949 case DIF_SELECTBESTCOMPATDRV:
3950 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3951 DefaultHandler = SetupDiSelectBestCompatDrv;
3952 break;
3953 default:
3954 ERR("Install function %u not supported\n", InstallFunction);
3955 SetLastError(ERROR_NOT_SUPPORTED);
3956 }
3957
3958 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3959 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
3960 /* Don't process this call, as a parameter is invalid */
3961 CanHandle = 0;
3962
3963 if (CanHandle != 0)
3964 {
3965 LIST_ENTRY ClassCoInstallersListHead;
3966 LIST_ENTRY DeviceCoInstallersListHead;
3967 HMODULE ClassInstallerLibrary = NULL;
3968 CLASS_INSTALL_PROC ClassInstaller = NULL;
3969 COINSTALLER_CONTEXT_DATA Context;
3970 PLIST_ENTRY ListEntry;
3971 HKEY hKey;
3972 DWORD dwRegType, dwLength;
3973 DWORD rc = NO_ERROR;
3974
3975 InitializeListHead(&ClassCoInstallersListHead);
3976 InitializeListHead(&DeviceCoInstallersListHead);
3977
3978 if (CanHandle & DEVICE_COINSTALLER)
3979 {
3980 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
3981 if (hKey != INVALID_HANDLE_VALUE)
3982 {
3983 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
3984 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3985 {
3986 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3987 if (KeyBuffer != NULL)
3988 {
3989 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3990 if (rc == ERROR_SUCCESS)
3991 {
3992 LPWSTR ptr;
3993 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3994 {
3995 /* Add coinstaller to DeviceCoInstallersListHead list */
3996 struct CoInstallerElement *coinstaller;
3997 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
3998 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3999 if (!coinstaller)
4000 continue;
4001 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
4002 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4003 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
4004 else
4005 HeapFree(GetProcessHeap(), 0, coinstaller);
4006 }
4007 }
4008 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4009 }
4010 }
4011 RegCloseKey(hKey);
4012 }
4013 }
4014 if (CanHandle & CLASS_COINSTALLER)
4015 {
4016 rc = RegOpenKeyEx(
4017 HKEY_LOCAL_MACHINE,
4018 REGSTR_PATH_CODEVICEINSTALLERS,
4019 0, /* Options */
4020 KEY_QUERY_VALUE,
4021 &hKey);
4022 if (rc == ERROR_SUCCESS)
4023 {
4024 LPWSTR lpGuidString;
4025 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
4026 {
4027 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
4028 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4029 {
4030 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4031 if (KeyBuffer != NULL)
4032 {
4033 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4034 if (rc == ERROR_SUCCESS)
4035 {
4036 LPWSTR ptr;
4037 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4038 {
4039 /* Add coinstaller to ClassCoInstallersListHead list */
4040 struct CoInstallerElement *coinstaller;
4041 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
4042 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4043 if (!coinstaller)
4044 continue;
4045 memset(coinstaller, 0, sizeof(struct CoInstallerElement));
4046 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4047 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
4048 else
4049 HeapFree(GetProcessHeap(), 0, coinstaller);
4050 }
4051 }
4052 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4053 }
4054 }
4055 RpcStringFreeW(&lpGuidString);
4056 }
4057 RegCloseKey(hKey);
4058 }
4059 }
4060 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
4061 {
4062 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
4063 if (hKey != INVALID_HANDLE_VALUE)
4064 {
4065 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
4066 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
4067 {
4068 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4069 if (KeyBuffer != NULL)
4070 {
4071 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4072 if (rc == ERROR_SUCCESS)
4073 {
4074 /* Get ClassInstaller function pointer */
4075 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
4076 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
4077 {
4078 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
4079 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4080 }
4081 }
4082 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4083 }
4084 }
4085 RegCloseKey(hKey);
4086 }
4087 }
4088
4089 /* Call Class co-installers */
4090 Context.PostProcessing = FALSE;
4091 rc = NO_ERROR;
4092 ListEntry = ClassCoInstallersListHead.Flink;
4093 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
4094 {
4095 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
4096 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4097 coinstaller->PrivateData = Context.PrivateData;
4098 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
4099 {
4100 coinstaller->DoPostProcessing = TRUE;
4101 rc = NO_ERROR;
4102 }
4103 ListEntry = ListEntry->Flink;
4104 }
4105
4106 /* Call Device co-installers */
4107 ListEntry = DeviceCoInstallersListHead.Flink;
4108 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
4109 {
4110 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
4111 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4112 coinstaller->PrivateData = Context.PrivateData;
4113 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
4114 {
4115 coinstaller->DoPostProcessing = TRUE;
4116 rc = NO_ERROR;
4117 }
4118 ListEntry = ListEntry->Flink;
4119 }
4120
4121 /* Call Class installer */
4122 if (ClassInstaller)
4123 {
4124 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
4125 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
4126 }
4127 else
4128 rc = ERROR_DI_DO_DEFAULT;
4129
4130 /* Call default handler */
4131 if (rc == ERROR_DI_DO_DEFAULT)
4132 {
4133 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
4134 {
4135 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
4136 rc = NO_ERROR;
4137 else
4138 rc = GetLastError();
4139 }
4140 else
4141 rc = NO_ERROR;
4142 }
4143
4144 /* Call Class co-installers that required postprocessing */
4145 Context.PostProcessing = TRUE;
4146 ListEntry = ClassCoInstallersListHead.Flink;
4147 while (ListEntry != &ClassCoInstallersListHead)
4148 {
4149 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
4150 if (coinstaller->DoPostProcessing)
4151 {
4152 Context.InstallResult = rc;
4153 Context.PrivateData = coinstaller->PrivateData;
4154 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4155 }
4156 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4157 ListEntry = ListEntry->Flink;
4158 }
4159
4160 /* Call Device co-installers that required postprocessing */
4161 ListEntry = DeviceCoInstallersListHead.Flink;
4162 while (ListEntry != &DeviceCoInstallersListHead)
4163 {
4164 struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
4165 if (coinstaller->DoPostProcessing)
4166 {
4167 Context.InstallResult = rc;
4168 Context.PrivateData = coinstaller->PrivateData;
4169 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4170 }
4171 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4172 ListEntry = ListEntry->Flink;
4173 }
4174
4175 /* Free allocated memory */
4176 while (!IsListEmpty(&ClassCoInstallersListHead))
4177 {
4178 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
4179 HeapFree(GetProcessHeap(), 0, ListEntry);
4180 }
4181 while (!IsListEmpty(&DeviceCoInstallersListHead))
4182 {
4183 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
4184 HeapFree(GetProcessHeap(), 0, ListEntry);
4185 }
4186
4187 ret = (rc == NO_ERROR);
4188 }
4189 }
4190
4191 TRACE("Returning %d\n", ret);
4192 return ret;
4193 }
4194
4195 /***********************************************************************
4196 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4197 */
4198 BOOL WINAPI SetupDiGetDeviceInfoListClass(
4199 IN HDEVINFO DeviceInfoSet,
4200 OUT LPGUID ClassGuid)
4201 {
4202 struct DeviceInfoSet *list;
4203 BOOL ret = FALSE;
4204
4205 TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
4206
4207 if (!DeviceInfoSet)
4208 SetLastError(ERROR_INVALID_HANDLE);
4209 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4210 SetLastError(ERROR_INVALID_HANDLE);
4211 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
4212 SetLastError(ERROR_NO_ASSOCIATED_CLASS);
4213 else
4214 {
4215 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
4216
4217 ret = TRUE;
4218 }
4219
4220 TRACE("Returning %d\n", ret);
4221 return ret;
4222 }
4223
4224 /***********************************************************************
4225 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4226 */
4227 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
4228 IN HDEVINFO DeviceInfoSet,
4229 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
4230 {
4231 struct DeviceInfoSet *list;
4232 BOOL ret = FALSE;
4233
4234 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
4235
4236 if (!DeviceInfoSet)
4237 SetLastError(ERROR_INVALID_HANDLE);
4238 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4239 SetLastError(ERROR_INVALID_HANDLE);
4240 else if (!DeviceInfoListDetailData)
4241 SetLastError(ERROR_INVALID_PARAMETER);
4242 else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
4243 SetLastError(ERROR_INVALID_USER_BUFFER);
4244 else
4245 {
4246 memcpy(
4247 &DeviceInfoListDetailData->ClassGuid,
4248 &list->ClassGuid,
4249 sizeof(GUID));
4250 DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
4251 if (list->MachineName)
4252 strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
4253 else
4254 DeviceInfoListDetailData->RemoteMachineName[0] = 0;
4255
4256 ret = TRUE;
4257 }
4258
4259 TRACE("Returning %d\n", ret);
4260 return ret;
4261 }
4262
4263 /***********************************************************************
4264 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4265 */
4266 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
4267 IN HDEVINFO DeviceInfoSet,
4268 IN PSP_DEVINFO_DATA DeviceInfoData,
4269 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4270 {
4271 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4272 BOOL ret = FALSE;
4273
4274 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4275
4276 if (DeviceInstallParams == NULL)
4277 SetLastError(ERROR_INVALID_PARAMETER);
4278 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
4279 SetLastError(ERROR_INVALID_USER_BUFFER);
4280 else
4281 {
4282 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4283 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4284
4285 if (ret)
4286 {
4287 /* Do W->A conversion */
4288 memcpy(
4289 DeviceInstallParams,
4290 &deviceInstallParamsW,
4291 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
4292 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
4293 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
4294 {
4295 DeviceInstallParams->DriverPath[0] = '\0';
4296 ret = FALSE;
4297 }
4298 }
4299 }
4300
4301 TRACE("Returning %d\n", ret);
4302 return ret;
4303 }
4304
4305 /***********************************************************************
4306 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4307 */
4308 BOOL WINAPI SetupDiGetDeviceInstallParamsW(
4309 IN HDEVINFO DeviceInfoSet,
4310 IN PSP_DEVINFO_DATA DeviceInfoData,
4311 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4312 {
4313 struct DeviceInfoSet *list;
4314 BOOL ret = FALSE;
4315
4316 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4317
4318 if (!DeviceInfoSet)
4319 SetLastError(ERROR_INVALID_HANDLE);
4320 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4321 SetLastError(ERROR_INVALID_HANDLE);
4322 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4323 SetLastError(ERROR_INVALID_USER_BUFFER);
4324 else if (!DeviceInstallParams)
4325 SetLastError(ERROR_INVALID_PARAMETER);
4326 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4327 SetLastError(ERROR_INVALID_USER_BUFFER);
4328 else
4329 {
4330 PSP_DEVINSTALL_PARAMS_W Source;
4331
4332 if (DeviceInfoData)
4333 Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
4334 else
4335 Source = &list->InstallParams;
4336 memcpy(DeviceInstallParams, Source, Source->cbSize);
4337 ret = TRUE;
4338 }
4339
4340 TRACE("Returning %d\n", ret);
4341 return ret;
4342 }
4343
4344 /***********************************************************************
4345 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4346 */
4347 BOOL WINAPI SetupDiSetDeviceInstallParamsW(
4348 IN HDEVINFO DeviceInfoSet,
4349 IN PSP_DEVINFO_DATA DeviceInfoData,
4350 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4351 {
4352 struct DeviceInfoSet *list;
4353 BOOL ret = FALSE;
4354
4355 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4356
4357 if (!DeviceInfoSet)
4358 SetLastError(ERROR_INVALID_HANDLE);
4359 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4360 SetLastError(ERROR_INVALID_HANDLE);
4361 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4362 SetLastError(ERROR_INVALID_USER_BUFFER);
4363 else if (!DeviceInstallParams)
4364 SetLastError(ERROR_INVALID_PARAMETER);
4365 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4366 SetLastError(ERROR_INVALID_USER_BUFFER);
4367 else
4368 {
4369 PSP_DEVINSTALL_PARAMS_W Destination;
4370
4371 /* FIXME: Validate parameters */
4372
4373 if (DeviceInfoData)
4374 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
4375 else
4376 Destination = &list->InstallParams;
4377 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
4378 ret = TRUE;
4379 }
4380
4381 TRACE("Returning %d\n", ret);
4382 return ret;
4383 }
4384
4385 /***********************************************************************
4386 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4387 */
4388 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
4389 IN HDEVINFO DeviceInfoSet,
4390 IN PSP_DEVINFO_DATA DeviceInfoData,
4391 OUT PSTR DeviceInstanceId OPTIONAL,
4392 IN DWORD DeviceInstanceIdSize,
4393 OUT PDWORD RequiredSize OPTIONAL)
4394 {
4395 PWSTR DeviceInstanceIdW = NULL;
4396 BOOL ret = FALSE;
4397
4398 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
4399 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
4400
4401 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
4402 SetLastError(ERROR_INVALID_PARAMETER);
4403 else
4404 {
4405 if (DeviceInstanceIdSize != 0)
4406 {
4407 DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
4408 if (DeviceInstanceIdW == NULL)
4409 return FALSE;
4410 }
4411
4412 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
4413 DeviceInstanceIdW, DeviceInstanceIdSize,
4414 RequiredSize);
4415
4416 if (ret && DeviceInstanceIdW != NULL)
4417 {
4418 if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
4419 DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
4420 {
4421 DeviceInstanceId[0] = '\0';
4422 ret = FALSE;
4423 }
4424 }
4425 }
4426
4427 TRACE("Returning %d\n", ret);
4428 return ret;
4429 }
4430
4431 /***********************************************************************
4432 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4433 */
4434 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
4435 IN HDEVINFO DeviceInfoSet,
4436 IN PSP_DEVINFO_DATA DeviceInfoData,
4437 OUT PWSTR DeviceInstanceId OPTIONAL,
4438 IN DWORD DeviceInstanceIdSize,
4439 OUT PDWORD RequiredSize OPTIONAL)
4440 {
4441 BOOL ret = FALSE;
4442
4443 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
4444 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
4445
4446 if (!DeviceInfoSet)
4447 SetLastError(ERROR_INVALID_HANDLE);
4448 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4449 SetLastError(ERROR_INVALID_HANDLE);
4450 else if (!DeviceInfoData)
4451 SetLastError(ERROR_INVALID_PARAMETER);
4452 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4453 SetLastError(ERROR_INVALID_USER_BUFFER);
4454 else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
4455 SetLastError(ERROR_INVALID_PARAMETER);
4456 else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
4457 SetLastError(ERROR_INVALID_PARAMETER);
4458 else
4459 {
4460 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4461 DWORD required;
4462
4463 required = (wcslen(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
4464 if (RequiredSize)
4465 *RequiredSize = required;
4466
4467 if (required <= DeviceInstanceIdSize)
4468 {
4469 wcscpy(DeviceInstanceId, DevInfo->DeviceName);
4470 ret = TRUE;
4471 }
4472 else
4473 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4474 }
4475
4476 TRACE("Returning %d\n", ret);
4477 return ret;
4478 }
4479
4480 /***********************************************************************
4481 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4482 */
4483 BOOL WINAPI SetupDiGetClassDevPropertySheetsA(
4484 IN HDEVINFO DeviceInfoSet,
4485 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4486 IN LPPROPSHEETHEADERA PropertySheetHeader,
4487 IN DWORD PropertySheetHeaderPageListSize,
4488 OUT PDWORD RequiredSize OPTIONAL,
4489 IN DWORD PropertySheetType)
4490 {
4491 PROPSHEETHEADERW psh;
4492 BOOL ret = FALSE;
4493
4494 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4495 PropertySheetHeader, PropertySheetHeaderPageListSize,
4496 RequiredSize, PropertySheetType);
4497
4498 psh.dwFlags = PropertySheetHeader->dwFlags;
4499 psh.phpage = PropertySheetHeader->phpage;
4500 psh.nPages = PropertySheetHeader->nPages;
4501
4502 ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
4503 PropertySheetHeaderPageListSize, RequiredSize,
4504 PropertySheetType);
4505 if (ret)
4506 {
4507 PropertySheetHeader->nPages = psh.nPages;
4508 }
4509
4510 TRACE("Returning %d\n", ret);
4511 return ret;
4512 }
4513
4514 struct ClassDevPropertySheetsData
4515 {
4516 HPROPSHEETPAGE *PropertySheetPages;
4517 DWORD MaximumNumberOfPages;
4518 DWORD NumberOfPages;
4519 };
4520
4521 static BOOL WINAPI GetClassDevPropertySheetsCallback(
4522 IN HPROPSHEETPAGE hPropSheetPage,
4523 IN OUT LPARAM lParam)
4524 {
4525 struct ClassDevPropertySheetsData *PropPageData;
4526
4527 PropPageData = (struct ClassDevPropertySheetsData *)lParam;
4528
4529 if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages)
4530 {
4531 *PropPageData->PropertySheetPages = hPropSheetPage;
4532 PropPageData->PropertySheetPages++;
4533 }
4534
4535 PropPageData->NumberOfPages++;
4536 return TRUE;
4537 }
4538
4539 /***********************************************************************
4540 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4541 */
4542 BOOL WINAPI SetupDiGetClassDevPropertySheetsW(
4543 IN HDEVINFO DeviceInfoSet,
4544 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4545 IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
4546 IN DWORD PropertySheetHeaderPageListSize,
4547 OUT PDWORD RequiredSize OPTIONAL,
4548 IN DWORD PropertySheetType)
4549 {
4550 struct DeviceInfoSet *list;
4551 BOOL ret = FALSE;
4552
4553 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4554 PropertySheetHeader, PropertySheetHeaderPageListSize,
4555 RequiredSize, PropertySheetType);
4556
4557 if (!DeviceInfoSet)
4558 SetLastError(ERROR_INVALID_HANDLE);
4559 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4560 SetLastError(ERROR_INVALID_HANDLE);
4561 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4562 SetLastError(ERROR_INVALID_HANDLE);
4563 else if (!PropertySheetHeader)
4564 SetLastError(ERROR_INVALID_PARAMETER);
4565 else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
4566 SetLastError(ERROR_INVALID_FLAGS);
4567 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4568 SetLastError(ERROR_INVALID_USER_BUFFER);
4569 else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
4570 SetLastError(ERROR_INVALID_PARAMETER);
4571 else if (!PropertySheetHeader)
4572 SetLastError(ERROR_INVALID_PARAMETER);
4573 else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
4574 && PropertySheetType != DIGCDP_FLAG_BASIC
4575 && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
4576 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
4577 SetLastError(ERROR_INVALID_PARAMETER);
4578 else
4579 {
4580 HKEY hKey = INVALID_HANDLE_VALUE;
4581 SP_PROPSHEETPAGE_REQUEST Request;
4582 LPWSTR PropPageProvider = NULL;
4583 HMODULE hModule = NULL;
4584 PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
4585 struct ClassDevPropertySheetsData PropPageData;
4586 DWORD dwLength, dwRegType;
4587 DWORD rc;
4588
4589 if (DeviceInfoData)
4590 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
4591 else
4592 {
4593 hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
4594 DIOCR_INSTALLER, list->MachineName + 2, NULL);
4595 }
4596 if (hKey == INVALID_HANDLE_VALUE)
4597 goto cleanup;
4598
4599 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength);
4600 if (rc == ERROR_FILE_NOT_FOUND)
4601 {
4602 /* No registry key. As it is optional, don't say it's a bad error */
4603 if (RequiredSize)
4604 *RequiredSize = 0;
4605 ret = TRUE;
4606 goto cleanup;
4607 }
4608 else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
4609 {
4610 SetLastError(rc);
4611 goto cleanup;
4612 }
4613
4614 PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
4615 if (!PropPageProvider)
4616 {
4617 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4618 goto cleanup;
4619 }
4620 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
4621 if (rc != ERROR_SUCCESS)
4622 {
4623 SetLastError(rc);
4624 goto cleanup;
4625 }
4626 PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
4627
4628 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
4629 if (rc != ERROR_SUCCESS)
4630 {
4631 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
4632 goto cleanup;
4633 }
4634
4635 Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
4636 Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
4637 Request.DeviceInfoSet = DeviceInfoSet;
4638 Request.DeviceInfoData = DeviceInfoData;
4639 PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages];
4640 PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages;
4641 PropPageData.NumberOfPages = 0;
4642 ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
4643 if (!ret)
4644 goto cleanup;
4645
4646 if (RequiredSize)
4647 *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages;
4648 if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages)
4649 {
4650 PropertySheetHeader->nPages += PropPageData.NumberOfPages;
4651 ret = TRUE;
4652 }
4653 else
4654 {
4655 PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages;
4656 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4657 }
4658
4659 cleanup:
4660 if (hKey != INVALID_HANDLE_VALUE)
4661 RegCloseKey(hKey);
4662 HeapFree(GetProcessHeap(), 0, PropPageProvider);
4663 FreeFunctionPointer(hModule, pPropPageProvider);
4664 }
4665
4666 TRACE("Returning %d\n", ret);
4667 return ret;
4668 }
4669
4670 /***********************************************************************
4671 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4672 */
4673 HKEY WINAPI SetupDiCreateDevRegKeyA(
4674 IN HDEVINFO DeviceInfoSet,
4675 IN PSP_DEVINFO_DATA DeviceInfoData,
4676 IN DWORD Scope,
4677 IN DWORD HwProfile,
4678 IN DWORD KeyType,
4679 IN HINF InfHandle OPTIONAL,
4680 IN PCSTR InfSectionName OPTIONAL)
4681 {
4682 PCWSTR InfSectionNameW = NULL;
4683 HKEY ret = INVALID_HANDLE_VALUE;
4684
4685 if (InfSectionName)
4686 {
4687 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
4688 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
4689 }
4690
4691 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
4692 DeviceInfoData,
4693 Scope,
4694 HwProfile,
4695 KeyType,
4696 InfHandle,
4697 InfSectionNameW);
4698
4699 if (InfSectionNameW != NULL)
4700 MyFree((PVOID)InfSectionNameW);
4701
4702 return ret;
4703 }
4704
4705 static HKEY
4706 OpenHardwareProfileKey(
4707 IN HKEY HKLM,
4708 IN DWORD HwProfile,
4709 IN DWORD samDesired)
4710 {
4711 HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
4712 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
4713 HKEY ret = INVALID_HANDLE_VALUE;
4714 LONG rc;
4715
4716 rc = RegOpenKeyExW(HKLM,
4717 REGSTR_PATH_HWPROFILES,
4718 0,
4719 0,
4720 &hHWProfilesKey);
4721 if (rc != ERROR_SUCCESS)
4722 {
4723 SetLastError(rc);
4724 goto cleanup;
4725 }
4726 if (HwProfile == 0)
4727 {
4728 rc = RegOpenKeyExW(
4729 hHWProfilesKey,
4730 REGSTR_KEY_CURRENT,
4731 0,
4732 KEY_CREATE_SUB_KEY,
4733 &hHWProfileKey);
4734 }
4735 else
4736 {
4737 WCHAR subKey[5];
4738 snprintfW(subKey, 4, L"%04lu", HwProfile);
4739 subKey[4] = '\0';
4740 rc = RegOpenKeyExW(
4741 hHWProfilesKey,
4742 subKey,
4743 0,
4744 KEY_CREATE_SUB_KEY,
4745 &hHWProfileKey);
4746 }
4747 if (rc != ERROR_SUCCESS)
4748 {
4749 SetLastError(rc);
4750 goto cleanup;
4751 }
4752 ret = hHWProfileKey;
4753
4754 cleanup:
4755 if (hHWProfilesKey != INVALID_HANDLE_VALUE)
4756 RegCloseKey(hHWProfilesKey);
4757 if (hHWProfileKey != INVALID_HANDLE_VALUE && hHWProfileKey != ret)
4758 RegCloseKey(hHWProfileKey);
4759 return ret;
4760 }
4761
4762 /***********************************************************************
4763 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4764 */
4765 HKEY WINAPI SetupDiCreateDevRegKeyW(
4766 IN HDEVINFO DeviceInfoSet,
4767 IN PSP_DEVINFO_DATA DeviceInfoData,
4768 IN DWORD Scope,
4769 IN DWORD HwProfile,
4770 IN DWORD KeyType,
4771 IN HINF InfHandle OPTIONAL,
4772 IN PCWSTR InfSectionName OPTIONAL)
4773 {
4774 struct DeviceInfoSet *list;
4775 HKEY ret = INVALID_HANDLE_VALUE;
4776
4777 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
4778 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
4779
4780 if (!DeviceInfoSet)
4781 SetLastError(ERROR_INVALID_HANDLE);
4782 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4783 SetLastError(ERROR_INVALID_HANDLE);
4784 else if (!DeviceInfoData)
4785 SetLastError(ERROR_INVALID_PARAMETER);
4786 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4787 SetLastError(ERROR_INVALID_USER_BUFFER);
4788 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4789 SetLastError(ERROR_INVALID_PARAMETER);
4790 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4791 SetLastError(ERROR_INVALID_PARAMETER);
4792 else if (InfHandle && !InfSectionName)
4793 SetLastError(ERROR_INVALID_PARAMETER);
4794 else if (!InfHandle && InfSectionName)
4795 SetLastError(ERROR_INVALID_PARAMETER);
4796 else
4797 {
4798 LPWSTR lpGuidString = NULL;
4799 LPWSTR DriverKey = NULL; /* {GUID}\Index */
4800 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
4801 DWORD Index; /* Index used in the DriverKey name */
4802 DWORD rc;
4803 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
4804 HKEY hEnumKey = INVALID_HANDLE_VALUE;
4805 HKEY hClassKey = INVALID_HANDLE_VALUE;
4806 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
4807 HKEY hKey = INVALID_HANDLE_VALUE;
4808 HKEY RootKey;
4809
4810 if (Scope == DICS_FLAG_GLOBAL)
4811 RootKey = list->HKLM;
4812 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4813 {
4814 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
4815 if (hHWProfileKey == INVALID_HANDLE_VALUE)
4816 goto cleanup;
4817 RootKey = hHWProfileKey;
4818 }
4819
4820 if (KeyType == DIREG_DEV)
4821 {
4822 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4823
4824 rc = RegCreateKeyExW(
4825 RootKey,
4826 REGSTR_PATH_SYSTEMENUM,
4827 0,
4828 NULL,
4829 REG_OPTION_NON_VOLATILE,
4830 KEY_CREATE_SUB_KEY,
4831 NULL,
4832 &hEnumKey,
4833 NULL);
4834 if (rc != ERROR_SUCCESS)
4835 {
4836 SetLastError(rc);
4837 goto cleanup;
4838 }
4839 rc = RegCreateKeyExW(
4840 hEnumKey,
4841 deviceInfo->DeviceName,
4842 0,
4843 NULL,
4844 REG_OPTION_NON_VOLATILE,
4845 #if _WIN32_WINNT >= 0x502
4846 KEY_READ | KEY_WRITE,
4847 #else
4848 KEY_ALL_ACCESS,
4849 #endif
4850 NULL,
4851 &hKey,
4852 NULL);
4853 if (rc != ERROR_SUCCESS)
4854 {
4855 SetLastError(rc);
4856 goto cleanup;
4857 }
4858 }
4859 else /* KeyType == DIREG_DRV */
4860 {
4861 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
4862 goto cleanup;
4863 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4864 DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
4865 if (!DriverKey)
4866 {
4867 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4868 goto cleanup;
4869 }
4870 wcscpy(DriverKey, L"{");
4871 wcscat(DriverKey, lpGuidString);
4872 wcscat(DriverKey, L"}\\");
4873 pDeviceInstance = &DriverKey[wcslen(DriverKey)];
4874 rc = RegOpenKeyExW(RootKey,
4875 REGSTR_PATH_CLASS_NT,
4876 0,
4877 KEY_CREATE_SUB_KEY,
4878 &hClassKey);
4879 if (rc != ERROR_SUCCESS)
4880 {
4881 SetLastError(rc);
4882 goto cleanup;
4883 }
4884
4885 /* Try all values for Index between 0 and 9999 */
4886 Index = 0;
4887 while (Index <= 9999)
4888 {
4889 DWORD Disposition;
4890 wsprintf(pDeviceInstance, L"%04lu", Index);
4891 rc = RegCreateKeyEx(hClassKey,
4892 DriverKey,
4893 0,
4894 NULL,
4895 REG_OPTION_NON_VOLATILE,
4896 #if _WIN32_WINNT >= 0x502
4897 KEY_READ | KEY_WRITE,
4898 #else
4899 KEY_ALL_ACCESS,
4900 #endif
4901 NULL,
4902 &hKey,
4903 &Disposition);
4904 if (rc != ERROR_SUCCESS)
4905 {
4906 SetLastError(rc);
4907 goto cleanup;
4908 }
4909 if (Disposition == REG_CREATED_NEW_KEY)
4910 break;
4911 RegCloseKey(hKey);
4912 hKey = INVALID_HANDLE_VALUE;
4913 Index++;
4914 }
4915 if (Index > 9999)
4916 {
4917 /* Unable to create more than 9999 devices within the same class */
4918 SetLastError(ERROR_GEN_FAILURE);
4919 goto cleanup;
4920 }
4921
4922 /* Open device key, to write Driver value */
4923 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
4924 if (hDeviceKey == INVALID_HANDLE_VALUE)
4925 goto cleanup;
4926 rc = RegSetValueEx(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
4927 if (rc != ERROR_SUCCESS)
4928 {
4929 SetLastError(rc);
4930 goto cleanup;
4931 }
4932 }
4933
4934 /* Do installation of the specified section */
4935 if (InfHandle)
4936 {
4937 FIXME("Need to install section %s in file %p\n",
4938 debugstr_w(InfSectionName), InfHandle);
4939 }
4940 ret = hKey;
4941
4942 cleanup:
4943 if (lpGuidString)
4944 RpcStringFreeW(&lpGuidString);
4945 HeapFree(GetProcessHeap(), 0, DriverKey);
4946 if (hHWProfileKey != INVALID_HANDLE_VALUE)
4947 RegCloseKey(hHWProfileKey);
4948 if (hEnumKey != INVALID_HANDLE_VALUE)
4949 RegCloseKey(hEnumKey);
4950 if (hClassKey != INVALID_HANDLE_VALUE)
4951 RegCloseKey(hClassKey);
4952 if (hDeviceKey != INVALID_HANDLE_VALUE)
4953 RegCloseKey(hDeviceKey);
4954 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
4955 RegCloseKey(hKey);
4956 }
4957
4958 TRACE("Returning 0x%p\n", ret);
4959 return ret;
4960 }
4961
4962 /***********************************************************************
4963 * SetupDiOpenDevRegKey (SETUPAPI.@)
4964 */
4965 HKEY WINAPI SetupDiOpenDevRegKey(
4966 HDEVINFO DeviceInfoSet,
4967 PSP_DEVINFO_DATA DeviceInfoData,
4968 DWORD Scope,
4969 DWORD HwProfile,
4970 DWORD KeyType,
4971 REGSAM samDesired)
4972 {
4973 struct DeviceInfoSet *list;
4974 HKEY ret = INVALID_HANDLE_VALUE;
4975
4976 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4977 Scope, HwProfile, KeyType, samDesired);
4978
4979 if (!DeviceInfoSet)
4980 SetLastError(ERROR_INVALID_HANDLE);
4981 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4982 SetLastError(ERROR_INVALID_HANDLE);
4983 else if (!DeviceInfoData)
4984 SetLastError(ERROR_INVALID_PARAMETER);
4985 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4986 SetLastError(ERROR_INVALID_USER_BUFFER);
4987 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4988 SetLastError(ERROR_INVALID_PARAMETER);
4989 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4990 SetLastError(ERROR_INVALID_PARAMETER);
4991 else
4992 {
4993 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4994 LPWSTR DriverKey = NULL;
4995 DWORD dwLength = 0;
4996 DWORD dwRegType;
4997 DWORD rc;
4998 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
4999 HKEY hEnumKey = INVALID_HANDLE_VALUE;
5000 HKEY hKey = INVALID_HANDLE_VALUE;
5001 HKEY RootKey;
5002
5003 if (Scope == DICS_FLAG_GLOBAL)
5004 RootKey = list->HKLM;
5005 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
5006 {
5007 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, 0);
5008 if (hHWProfileKey == INVALID_HANDLE_VALUE)
5009 goto cleanup;
5010 RootKey = hHWProfileKey;
5011 }
5012
5013 rc = RegOpenKeyExW(
5014 RootKey,
5015 REGSTR_PATH_SYSTEMENUM,
5016 0, /* Options */
5017 0,
5018 &hEnumKey);
5019 if (rc != ERROR_SUCCESS)
5020 {
5021 SetLastError(rc);
5022 goto cleanup;
5023 }
5024 rc = RegOpenKeyExW(
5025 hEnumKey,
5026 deviceInfo->DeviceName,
5027 0, /* Options */
5028 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
5029 &hKey);
5030 RegCloseKey(hEnumKey);
5031 hEnumKey = INVALID_HANDLE_VALUE;
5032 if (rc != ERROR_SUCCESS)
5033 {
5034 SetLastError(rc);
5035 goto cleanup;
5036 }
5037 if (KeyType == DIREG_DEV)
5038 {
5039 /* We're done. Just return the hKey handle */
5040 ret = hKey;
5041 goto cleanup;
5042 }
5043 /* Read the 'Driver' key */
5044 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
5045 if (rc != ERROR_SUCCESS)
5046 {
5047 SetLastError(rc);
5048 goto cleanup;
5049 }
5050 else if (dwRegType != REG_SZ)
5051 {
5052 SetLastError(ERROR_GEN_FAILURE);
5053 goto cleanup;
5054 }
5055 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
5056 if (!DriverKey)
5057 {
5058 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5059 goto cleanup;
5060 }
5061 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
5062 if (rc != ERROR_SUCCESS)
5063 {
5064 SetLastError(rc);
5065 goto cleanup;
5066 }
5067 RegCloseKey(hKey);
5068 hKey = INVALID_HANDLE_VALUE;
5069 /* Need to open the driver key */
5070 rc = RegOpenKeyExW(
5071 RootKey,
5072 REGSTR_PATH_CLASS_NT,
5073 0, /* Options */
5074 0,
5075 &hEnumKey);
5076 if (rc != ERROR_SUCCESS)
5077 {
5078 SetLastError(rc);
5079 goto cleanup;
5080 }
5081 rc = RegOpenKeyExW(
5082 hEnumKey,
5083 DriverKey,
5084 0, /* Options */
5085 samDesired,
5086 &hKey);
5087 if (rc != ERROR_SUCCESS)
5088 {
5089 SetLastError(rc);
5090 goto cleanup;
5091 }
5092 ret = hKey;
5093
5094 cleanup:
5095 if (hHWProfileKey != INVALID_HANDLE_VALUE)
5096 RegCloseKey(hHWProfileKey);
5097 if (hEnumKey != INVALID_HANDLE_VALUE)
5098 RegCloseKey(hEnumKey);
5099 if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
5100 RegCloseKey(hKey);
5101 }
5102
5103 TRACE("Returning 0x%p\n", ret);
5104 return ret;
5105 }
5106
5107 /***********************************************************************
5108 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5109 */
5110 BOOL WINAPI SetupDiCreateDeviceInfoA(
5111 HDEVINFO DeviceInfoSet,
5112 PCSTR DeviceName,
5113 CONST GUID *ClassGuid,
5114 PCSTR DeviceDescription,
5115 HWND hwndParent,
5116 DWORD CreationFlags,
5117 PSP_DEVINFO_DATA DeviceInfoData)
5118 {
5119 LPWSTR DeviceNameW = NULL;
5120 LPWSTR DeviceDescriptionW = NULL;
5121 BOOL bResult;
5122
5123 TRACE("\n");
5124
5125 if (DeviceName)
5126 {
5127 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
5128 if (DeviceNameW == NULL) return FALSE;
5129 }
5130 if (DeviceDescription)
5131 {
5132 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
5133 if (DeviceDescriptionW == NULL)
5134 {
5135 if (DeviceNameW) MyFree(DeviceNameW);
5136 return FALSE;
5137 }
5138 }
5139
5140 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
5141 ClassGuid, DeviceDescriptionW,
5142 hwndParent, CreationFlags,
5143 DeviceInfoData);
5144
5145 if (DeviceNameW) MyFree(DeviceNameW);
5146 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
5147
5148 return bResult;
5149 }
5150
5151 /***********************************************************************
5152 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5153 */
5154 BOOL WINAPI SetupDiCreateDeviceInfoW(
5155 HDEVINFO DeviceInfoSet,
5156 PCWSTR DeviceName,
5157 CONST GUID *ClassGuid,
5158 PCWSTR DeviceDescription,
5159 HWND hwndParent,
5160 DWORD CreationFlags,
5161 PSP_DEVINFO_DATA DeviceInfoData)
5162 {
5163 struct DeviceInfoSet *list;
5164 BOOL ret = FALSE;
5165
5166 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
5167 debugstr_guid(ClassGuid), DeviceDescription,
5168 hwndParent, CreationFlags, DeviceInfoData);
5169
5170 if (!DeviceInfoSet)
5171 SetLastError(ERROR_INVALID_HANDLE);
5172 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5173 SetLastError(ERROR_INVALID_HANDLE);
5174 else if (!ClassGuid)
5175 SetLastError(ERROR_INVALID_PARAMETER);
5176 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
5177 SetLastError(ERROR_CLASS_MISMATCH);
5178 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
5179 {
5180 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
5181 SetLastError(ERROR_INVALID_FLAGS);
5182 }
5183 else
5184 {
5185 SP_DEVINFO_DATA DevInfo;
5186
5187 if (CreationFlags & DICD_GENERATE_ID)
5188 {
5189 /* Generate a new unique ID for this device */
5190 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5191 FIXME("not implemented\n");
5192 }
5193 else
5194 {
5195 /* Device name is fully qualified. Try to open it */
5196 BOOL rc;
5197
5198 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
5199 rc = SetupDiOpenDeviceInfoW(
5200 DeviceInfoSet,
5201 DeviceName,
5202 NULL, /* hwndParent */
5203 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
5204 &DevInfo);
5205
5206 if (rc)
5207 {
5208 /* SetupDiOpenDeviceInfoW has already added
5209 * the device info to the device info set
5210 */
5211 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
5212 }
5213 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
5214 {
5215 struct DeviceInfoElement *deviceInfo;
5216
5217 if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
5218 {
5219 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
5220
5221 if (!DeviceInfoData)
5222 ret = TRUE;
5223 else
5224 {
5225 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
5226 {
5227 SetLastError(ERROR_INVALID_USER_BUFFER);
5228 }
5229 else
5230 {
5231 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
5232 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
5233 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
5234 ret = TRUE;
5235 }
5236 }
5237 }
5238 }
5239 }
5240 }
5241
5242 TRACE("Returning %d\n", ret);
5243 return ret;
5244 }
5245
5246 /***********************************************************************
5247 * Helper functions for SetupDiBuildDriverInfoList
5248 */
5249 static BOOL
5250 AddDriverToList(
5251 IN PLIST_ENTRY DriverListHead,
5252 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5253 IN LPGUID ClassGuid,
5254 IN INFCONTEXT ContextDevice,
5255 IN struct InfFileDetails *InfFileDetails,
5256 IN LPCWSTR InfFile,
5257 IN LPCWSTR ProviderName,
5258 IN LPCWSTR ManufacturerName,
5259 IN LPCWSTR MatchingId,
5260 FILETIME DriverDate,
5261 DWORDLONG DriverVersion,
5262 IN DWORD Rank)
5263 {
5264 struct DriverInfoElement *driverInfo = NULL;
5265 HANDLE hFile = INVALID_HANDLE_VALUE;
5266 DWORD RequiredSize = 128; /* Initial buffer size */
5267 BOOL Result = FALSE;
5268 PLIST_ENTRY PreviousEntry;
5269 LPWSTR InfInstallSection = NULL;
5270 BOOL ret = FALSE;
5271
5272 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
5273 if (!driverInfo)
5274 {
5275 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5276 goto cleanup;
5277 }
5278 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
5279
5280 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
5281 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
5282
5283 /* Copy InfFileName field */
5284 wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
5285 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
5286
5287 /* Fill InfDate field */
5288 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5289 GENERIC_READ, FILE_SHARE_READ,
5290 NULL, OPEN_EXISTING, 0, NULL);
5291 if (hFile == INVALID_HANDLE_VALUE)
5292 goto cleanup;
5293 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5294 if (!Result)
5295 goto cleanup;*/
5296
5297 /* Fill SectionName field */
5298 Result = SetupGetStringFieldW(
5299 &ContextDevice,
5300 1,
5301 driverInfo->Details.SectionName, LINE_LEN,
5302 NULL);
5303 if (!Result)
5304 goto cleanup;
5305
5306 /* Fill DrvDescription field */
5307 Result = SetupGetStringFieldW(
5308 &ContextDevice,
5309 0, /* Field index */
5310 driverInfo->Details.DrvDescription, LINE_LEN,
5311 NULL);
5312
5313 /* Copy MatchingId information */
5314 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
5315 if (!driverInfo->MatchingId)
5316 {
5317 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5318 goto cleanup;
5319 }
5320 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
5321
5322 /* Get inf install section */
5323 Result = FALSE;
5324 RequiredSize = 128; /* Initial buffer size */
5325 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5326 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5327 {
5328 HeapFree(GetProcessHeap(), 0, InfInstallSection);
5329 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5330 if (!InfInstallSection)
5331 goto cleanup;
5332 Result = SetupGetStringFieldW(
5333 &ContextDevice,
5334 1, /* Field index */
5335 InfInstallSection, RequiredSize,
5336 &RequiredSize);
5337 }
5338 if (!Result)
5339 goto cleanup;
5340
5341 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5342 driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
5343
5344 driverInfo->DriverRank = Rank;
5345 memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
5346 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
5347 driverInfo->Info.DriverType = DriverType;
5348 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
5349 wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
5350 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
5351 wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
5352 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
5353 if (ProviderName)
5354 {
5355 wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
5356 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
5357 }
5358 else
5359 driverInfo->Info.ProviderName[0] = '\0';
5360 driverInfo->Info.DriverDate = DriverDate;
5361 driverInfo->Info.DriverVersion = DriverVersion;
5362 ReferenceInfFile(InfFileDetails);
5363 driverInfo->InfFileDetails = InfFileDetails;
5364
5365 /* Insert current driver in driver list, according to its rank */
5366 PreviousEntry = DriverListHead->Flink;
5367 while (PreviousEntry != DriverListHead)
5368 {
5369 struct DriverInfoElement *CurrentDriver;
5370 CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
5371 if (CurrentDriver->DriverRank > Rank ||
5372 (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
5373 {
5374 /* Insert before the current item */
5375 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
5376 break;
5377 }
5378 PreviousEntry = PreviousEntry->Flink;
5379 }
5380 if (PreviousEntry == DriverListHead)
5381 {
5382 /* Insert at the end of the list */
5383 InsertTailList(DriverListHead, &driverInfo->ListEntry);
5384 }
5385
5386 ret = TRUE;
5387
5388 cleanup:
5389 if (!ret)
5390 {
5391 if (driverInfo)
5392 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
5393 HeapFree(GetProcessHeap(), 0, driverInfo);
5394 }
5395 if (hFile != INVALID_HANDLE_VALUE)
5396 CloseHandle(hFile);
5397 HeapFree(GetProcessHeap(), 0, InfInstallSection);
5398
5399 return ret;
5400 }
5401
5402 static BOOL
5403 GetVersionInformationFromInfFile(
5404 IN HINF hInf,
5405 OUT LPGUID ClassGuid,
5406 OUT LPWSTR* pProviderName,
5407 OUT FILETIME* DriverDate,
5408 OUT DWORDLONG* DriverVersion)
5409 {
5410 DWORD RequiredSize;
5411 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
5412 LPWSTR DriverVer = NULL;
5413 LPWSTR ProviderName = NULL;
5414 LPWSTR pComma; /* Points into DriverVer */
5415 LPWSTR pVersion = NULL; /* Points into DriverVer */
5416 SYSTEMTIME SystemTime;
5417 BOOL Result;
5418 BOOL ret = FALSE; /* Final result */
5419
5420 /* Get class Guid */
5421 if (!SetupGetLineTextW(
5422 NULL, /* Context */
5423 hInf,
5424 L"Version", L"ClassGUID",
5425 guidW, sizeof(guidW),
5426 NULL /* Required size */))
5427 {
5428 goto cleanup;
5429 }
5430 guidW[37] = '\0'; /* Replace the } by a NULL character */
5431 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
5432 {
5433 SetLastError(ERROR_GEN_FAILURE);
5434 goto cleanup;
5435 }
5436
5437 /* Get provider name */
5438 Result = SetupGetLineTextW(
5439 NULL, /* Context */
5440 hInf, L"Version", L"Provider",
5441 NULL, 0,
5442 &RequiredSize);
5443 if (Result)
5444 {
5445 /* We know know the needed buffer size */
5446 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5447 if (!ProviderName)
5448 {
5449 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5450 goto cleanup;
5451 }
5452 Result = SetupGetLineTextW(
5453 NULL, /* Context */
5454 hInf, L"Version", L"Provider",
5455 ProviderName, RequiredSize,
5456 &RequiredSize);
5457 }
5458 if (!Result)
5459 goto cleanup;
5460 *pProviderName = ProviderName;
5461
5462 /* Read the "DriverVer" value */
5463 Result = SetupGetLineTextW(
5464 NULL, /* Context */
5465 hInf, L"Version", L"DriverVer",
5466 NULL, 0,
5467 &RequiredSize);
5468 if (Result)
5469 {
5470 /* We know know the needed buffer size */
5471 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5472 if (!DriverVer)
5473 {
5474 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5475 goto cleanup;
5476 }
5477 Result = SetupGetLineTextW(
5478 NULL, /* Context */
5479 hInf, L"Version", L"DriverVer",
5480 DriverVer, RequiredSize,
5481 &RequiredSize);
5482 }
5483 if (!Result)
5484 goto cleanup;
5485
5486 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5487 pComma = wcschr(DriverVer, ',');
5488 if (pComma != NULL)
5489 {
5490 *pComma = UNICODE_NULL;
5491 pVersion = pComma + 1;
5492 }
5493 /* Get driver date version. Invalid date = 00/00/00 */
5494 memset(DriverDate, 0, sizeof(FILETIME));
5495 if (wcslen(DriverVer) == 10
5496 && (DriverVer[2] == '-' || DriverVer[2] == '/')
5497 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
5498 {
5499 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
5500 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
5501 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
5502 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
5503 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
5504 SystemTimeToFileTime(&SystemTime, DriverDate);
5505 }
5506 /* Get driver version. Invalid version = 0.0.0.0 */
5507 *DriverVersion = 0;
5508 if (pVersion)
5509 {
5510 WORD Major, Minor = 0, Revision = 0, Build = 0;
5511 LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
5512 LARGE_INTEGER fullVersion;
5513
5514 pMinor = strchrW(pVersion, '.');
5515 if (pMinor)
5516 {
5517 *pMinor = 0;
5518 pRevision = strchrW(++pMinor, '.');
5519 Minor = atoiW(pMinor);
5520 }
5521 if (pRevision)
5522 {
5523 *pRevision = 0;
5524 pBuild = strchrW(++pRevision, '.');
5525 Revision = atoiW(pRevision);
5526 }
5527 if (pBuild)
5528 {
5529 *pBuild = 0;
5530 pBuild++;
5531 Build = atoiW(pBuild);
5532 }
5533 Major = atoiW(pVersion);
5534 fullVersion.u.HighPart = Major << 16 | Minor;
5535 fullVersion.u.LowPart = Revision << 16 | Build;
5536 memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
5537 }
5538
5539 ret = TRUE;
5540
5541 cleanup:
5542 if (!ret)
5543 HeapFree(GetProcessHeap(), 0, ProviderName);
5544 HeapFree(GetProcessHeap(), 0, DriverVer);
5545
5546 return ret;
5547 }
5548
5549 /***********************************************************************
5550 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5551 */
5552 BOOL WINAPI
5553 SetupDiBuildDriverInfoList(
5554 IN HDEVINFO DeviceInfoSet,
5555 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5556 IN DWORD DriverType)
5557 {
5558 struct DeviceInfoSet *list;
5559 SP_DEVINSTALL_PARAMS_W InstallParams;
5560 PVOID Buffer = NULL;
5561 struct InfFileDetails *currentInfFileDetails = NULL;
5562 LPWSTR ProviderName = NULL;
5563 LPWSTR ManufacturerName = NULL;
5564 WCHAR ManufacturerSection[LINE_LEN + 1];
5565 LPWSTR HardwareIDs = NULL;
5566 LPWSTR CompatibleIDs = NULL;
5567 LPWSTR FullInfFileName = NULL;
5568 FILETIME DriverDate;
5569 DWORDLONG DriverVersion = 0;
5570 DWORD RequiredSize;
5571 BOOL ret = FALSE;
5572
5573 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
5574
5575 if (!DeviceInfoSet)
5576 SetLastError(ERROR_INVALID_HANDLE);
5577 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5578 SetLastError(ERROR_INVALID_HANDLE);
5579 else if (list->HKLM != HKEY_LOCAL_MACHINE)
5580 SetLastError(ERROR_INVALID_HANDLE);
5581 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5582 SetLastError(ERROR_INVALID_PARAMETER);
5583 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
5584 SetLastError(ERROR_INVALID_PARAMETER);
5585 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5586 SetLastError(ERROR_INVALID_PARAMETER);
5587 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5588 SetLastError(ERROR_INVALID_USER_BUFFER);
5589 else
5590 {
5591 BOOL Result;
5592
5593 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
5594 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5595 if (!Result)
5596 goto done;
5597
5598 if (DriverType == SPDIT_COMPATDRIVER)
5599 {
5600 /* Get hardware IDs list */
5601 Result = FALSE;
5602 RequiredSize = 512; /* Initial buffer size */
5603 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5604 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5605 {
5606 HeapFree(GetProcessHeap(), 0, HardwareIDs);
5607 HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
5608 if (!HardwareIDs)
5609 {
5610 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5611 goto done;
5612 }
5613 Result = SetupDiGetDeviceRegistryPropertyW(
5614 DeviceInfoSet,
5615 DeviceInfoData,
5616 SPDRP_HARDWAREID,
5617 NULL,
5618 (PBYTE)HardwareIDs,
5619 RequiredSize,
5620 &RequiredSize);
5621 }
5622 if (!Result)
5623 goto done;
5624
5625 /* Get compatible IDs list */
5626 Result = FALSE;
5627 RequiredSize = 512; /* Initial buffer size */
5628 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5629 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5630 {
5631 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5632 CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
5633 if (!CompatibleIDs)
5634 {
5635 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5636 goto done;
5637 }
5638 Result = SetupDiGetDeviceRegistryPropertyW(
5639 DeviceInfoSet,
5640 DeviceInfoData,
5641 SPDRP_COMPATIBLEIDS,
5642 NULL,
5643 (PBYTE)CompatibleIDs,
5644 RequiredSize,
5645 &RequiredSize);
5646 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
5647 {
5648 /* No compatible ID for this device */
5649 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5650 CompatibleIDs = NULL;
5651 Result = TRUE;
5652 }
5653 }
5654 if (!Result)
5655 goto done;
5656 }
5657
5658 if (InstallParams.Flags & DI_ENUMSINGLEINF)
5659 {
5660 /* InstallParams.DriverPath contains the name of a .inf file */
5661 RequiredSize = wcslen(InstallParams.DriverPath) + 2;
5662 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5663 if (!Buffer)
5664 {
5665 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5666 goto done;
5667 }
5668 wcscpy(Buffer, InstallParams.DriverPath);
5669 ((LPWSTR)Buffer)[RequiredSize - 1] = 0;
5670 Result = TRUE;
5671 }
5672 else
5673 {
5674 /* Enumerate .inf files */
5675 Result = FALSE;
5676 RequiredSize = 32768; /* Initial buffer size */
5677 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5678 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5679 {
5680 HeapFree(GetProcessHeap(), 0, Buffer);
5681 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5682 if (!Buffer)
5683 {
5684 Result = FALSE;
5685 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5686 break;
5687 }
5688 Result = SetupGetInfFileListW(
5689 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
5690 INF_STYLE_WIN4,
5691 Buffer, RequiredSize,
5692 &RequiredSize);
5693 }
5694 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
5695 {
5696 /* No .inf file in specified directory. So, we should
5697 * success as we created an empty driver info list.
5698 */
5699 ret = TRUE;
5700 goto done;
5701 }
5702 }
5703 if (Result)
5704 {
5705 LPCWSTR filename;
5706 LPWSTR pFullFilename;
5707
5708 if (InstallParams.Flags & DI_ENUMSINGLEINF)
5709 {
5710 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
5711 if (!FullInfFileName)
5712 goto done;
5713 pFullFilename = &FullInfFileName[0];
5714 }
5715 else if (*InstallParams.DriverPath)
5716 {
5717 DWORD len;
5718 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
5719 if (len == 0)
5720 goto done;
5721 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
5722 if (!FullInfFileName)
5723 goto done;
5724 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
5725 if (len == 0)
5726 goto done;
5727 if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
5728 wcscat(FullInfFileName, L"\\");
5729 pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
5730 }
5731 else
5732 {
5733 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
5734 if (!FullInfFileName)
5735 goto done;
5736 pFullFilename = &FullInfFileName[0];
5737 }
5738
5739 for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
5740 {
5741 INFCONTEXT ContextManufacturer, ContextDevice;
5742 GUID ClassGuid;
5743
5744 wcscpy(pFullFilename, filename);
5745 TRACE("Opening file %S\n", FullInfFileName);
5746
5747 currentInfFileDetails = HeapAlloc(
5748 GetProcessHeap(),
5749 0,
5750 FIELD_OFFSET(struct InfFileDetails, FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) + UNICODE_NULL);
5751 if (!currentInfFileDetails)
5752 continue;
5753 memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
5754 wcscpy(currentInfFileDetails->FullInfFileName, FullInfFileName);
5755
5756 currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
5757 ReferenceInfFile(currentInfFileDetails);
5758 if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
5759 {
5760 HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
5761 currentInfFileDetails = NULL;
5762 continue;
5763 }
5764
5765 if (!GetVersionInformationFromInfFile(
5766 currentInfFileDetails->hInf,
5767 &ClassGuid,
5768 &ProviderName,
5769 &DriverDate,
5770 &DriverVersion))
5771 {
5772 SetupCloseInfFile(currentInfFileDetails->hInf);
5773 HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
5774 currentInfFileDetails = NULL;
5775 continue;
5776 }
5777
5778 if (DriverType == SPDIT_CLASSDRIVER)
5779 {
5780 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5781 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
5782 {
5783 goto next;
5784 }
5785 }
5786
5787 /* Get the manufacturers list */
5788 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
5789 while (Result)
5790 {
5791 Result = SetupGetStringFieldW(
5792 &ContextManufacturer,
5793 0, /* Field index */
5794 NULL, 0,
5795 &RequiredSize);
5796 if (Result)
5797 {
5798 /* We got the needed size for the buffer */
5799 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5800 if (!ManufacturerName)
5801 {
5802 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5803 goto done;
5804 }
5805 Result = SetupGetStringFieldW(
5806 &ContextManufacturer,
5807 0, /* Field index */
5808 ManufacturerName, RequiredSize,
5809 &RequiredSize);
5810 }
5811 /* Get manufacturer section name */
5812 Result = SetupGetStringFieldW(
5813 &ContextManufacturer,
5814 1, /* Field index */
5815 ManufacturerSection, LINE_LEN,
5816 &RequiredSize);
5817 if (Result)
5818 {
5819 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
5820 /* Add (possible) extension to manufacturer section name */
5821 Result = SetupDiGetActualSectionToInstallW(
5822 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
5823 if (Result)
5824 {
5825 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
5826 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
5827 }
5828 }
5829 while (Result)
5830 {
5831 if (DriverType == SPDIT_CLASSDRIVER)
5832 {
5833 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5834 if (!AddDriverToList(
5835 &list->DriverListHead,
5836 DriverType,
5837 &ClassGuid,
5838 ContextDevice,
5839 currentInfFileDetails,
5840 filename,
5841 ProviderName,
5842 ManufacturerName,
5843 NULL,
5844 DriverDate, DriverVersion,
5845 0))
5846 {
5847 break;
5848 }
5849 }
5850 else /* DriverType = SPDIT_COMPATDRIVER */
5851 {
5852 /* 1. Get all fields */
5853 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
5854 DWORD DriverRank;
5855 DWORD i;
5856 LPCWSTR currentId;
5857 BOOL DriverAlreadyAdded;
5858
5859 for (i = 2; i <= FieldCount; i++)
5860 {
5861 LPWSTR DeviceId = NULL;
5862 Result = FALSE;
5863 RequiredSize = 128; /* Initial buffer size */
5864 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5865 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5866 {
5867 HeapFree(GetProcessHeap(), 0, DeviceId);
5868 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5869 if (!DeviceId)
5870 {
5871 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5872 goto done;
5873 }
5874 Result = SetupGetStringFieldW(
5875 &ContextDevice,
5876 i,
5877 DeviceId, RequiredSize,
5878 &RequiredSize);
5879 }
5880 if (!Result)
5881 {
5882 HeapFree(GetProcessHeap(), 0, DeviceId);
5883 goto done;
5884 }
5885 DriverAlreadyAdded = FALSE;
5886 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
5887 {
5888 if (wcsicmp(DeviceId, currentId) == 0)
5889 {
5890 AddDriverToList(
5891 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
5892 DriverType,
5893 &ClassGuid,
5894 ContextDevice,
5895 currentInfFileDetails,
5896 filename,
5897 ProviderName,
5898 ManufacturerName,
5899 currentId,
5900 DriverDate, DriverVersion,
5901 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
5902 DriverAlreadyAdded = TRUE;
5903 }
5904 }
5905 if (CompatibleIDs)
5906 {
5907 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
5908 {
5909 if (wcsicmp(DeviceId, currentId) == 0)
5910 {
5911 AddDriverToList(
5912 &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
5913 DriverType,
5914 &ClassGuid,
5915 ContextDevice,
5916 currentInfFileDetails,
5917 filename,
5918 ProviderName,
5919 ManufacturerName,
5920 currentId,
5921 DriverDate, DriverVersion,
5922 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
5923 DriverAlreadyAdded = TRUE;
5924 }
5925 }
5926 }
5927 HeapFree(GetProcessHeap(), 0, DeviceId);
5928 }
5929 }
5930 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
5931 }
5932
5933 HeapFree(GetProcessHeap(), 0, ManufacturerName);
5934 ManufacturerName = NULL;
5935 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
5936 }
5937
5938 ret = TRUE;
5939 next:
5940 HeapFree(GetProcessHeap(), 0, ProviderName);
5941 ProviderName = NULL;
5942
5943 DereferenceInfFile(currentInfFileDetails);
5944 currentInfFileDetails = NULL;
5945 }
5946 ret = TRUE;
5947 }
5948 }
5949
5950 done:
5951 if (ret)
5952 {
5953 if (DeviceInfoData)
5954 {
5955 InstallParams.Flags |= DI_DIDCOMPAT;
5956 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
5957 }
5958 else
5959 {
5960 InstallParams.Flags |= DI_DIDCLASS;
5961 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
5962 }
5963 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5964 }
5965
5966 HeapFree(GetProcessHeap(), 0, ProviderName);
5967 HeapFree(GetProcessHeap(), 0, ManufacturerName);
5968 HeapFree(GetProcessHeap(), 0, HardwareIDs);
5969 HeapFree(GetProcessHeap(), 0, CompatibleIDs);
5970 HeapFree(GetProcessHeap(), 0, FullInfFileName);
5971 if (currentInfFileDetails)
5972 DereferenceInfFile(currentInfFileDetails);
5973 HeapFree(GetProcessHeap(), 0, Buffer);
5974
5975 TRACE("Returning %d\n", ret);
5976 return ret;
5977 }
5978
5979 /***********************************************************************
5980 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5981 */
5982 BOOL WINAPI
5983 SetupDiDeleteDeviceInfo(
5984 IN HDEVINFO DeviceInfoSet,
5985 IN PSP_DEVINFO_DATA DeviceInfoData)
5986 {
5987 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5988
5989 FIXME("not implemented\n");
5990 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5991 return FALSE;
5992 }
5993
5994
5995 /***********************************************************************
5996 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5997 */
5998 BOOL WINAPI
5999 SetupDiDestroyDriverInfoList(
6000 IN HDEVINFO DeviceInfoSet,
6001 IN PSP_DEVINFO_DATA DeviceInfoData,
6002 IN DWORD DriverType)
6003 {
6004 struct DeviceInfoSet *list;
6005 BOOL ret = FALSE;
6006
6007 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
6008
6009 if (!DeviceInfoSet)
6010 SetLastError(ERROR_INVALID_HANDLE);
6011 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6012 SetLastError(ERROR_INVALID_HANDLE);
6013 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
6014 SetLastError(ERROR_INVALID_PARAMETER);
6015 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
6016 SetLastError(ERROR_INVALID_PARAMETER);
6017 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6018 SetLastError(ERROR_INVALID_USER_BUFFER);
6019 else
6020 {
6021 PLIST_ENTRY ListEntry;
6022 struct DriverInfoElement *driverInfo;
6023 SP_DEVINSTALL_PARAMS_W InstallParams;
6024
6025 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6026 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
6027 goto done;
6028
6029 if (!DeviceInfoData)
6030 /* Fall back to destroying class driver list */
6031 DriverType = SPDIT_CLASSDRIVER;
6032
6033 if (DriverType == SPDIT_CLASSDRIVER)
6034 {
6035 while (!IsListEmpty(&list->DriverListHead))
6036 {
6037 ListEntry = RemoveHeadList(&list->DriverListHead);
6038 driverInfo = (struct DriverInfoElement *)ListEntry;
6039 DestroyDriverInfoElement(driverInfo);
6040 }
6041 InstallParams.Reserved = 0;
6042 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
6043 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
6044 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
6045 }
6046 else
6047 {
6048 SP_DEVINSTALL_PARAMS_W InstallParamsSet;
6049 struct DeviceInfoElement *deviceInfo;
6050
6051 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6052 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
6053 goto done;
6054 deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6055 while (!IsListEmpty(&deviceInfo->DriverListHead))
6056 {
6057 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
6058 driverInfo = (struct DriverInfoElement *)ListEntry;
6059 if ((PVOID)InstallParamsSet.Reserved == driverInfo)
6060 {
6061 InstallParamsSet.Reserved = 0;
6062 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
6063 }
6064 DestroyDriverInfoElement(driverInfo);
6065 }
6066 InstallParams.Reserved = 0;
6067 InstallParams.Flags &= ~DI_DIDCOMPAT;
6068 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
6069 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6070 }
6071 }
6072
6073 done:
6074 TRACE("Returning %d\n", ret);
6075 return ret;
6076 }
6077
6078
6079 /***********************************************************************
6080 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6081 */
6082 BOOL WINAPI
6083 SetupDiOpenDeviceInfoA(
6084 IN HDEVINFO DeviceInfoSet,
6085 IN PCSTR DeviceInstanceId,
6086 IN HWND hwndParent OPTIONAL,
6087 IN DWORD OpenFlags,
6088 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6089 {
6090 LPWSTR DeviceInstanceIdW = NULL;
6091 BOOL bResult;
6092
6093 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
6094
6095 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
6096 if (DeviceInstanceIdW == NULL)
6097 return FALSE;
6098
6099 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
6100 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
6101
6102 MyFree(DeviceInstanceIdW);
6103
6104 return bResult;
6105 }
6106
6107
6108 /***********************************************************************
6109 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6110 */
6111 BOOL WINAPI
6112 SetupDiOpenDeviceInfoW(
6113 IN HDEVINFO DeviceInfoSet,
6114 IN PCWSTR DeviceInstanceId,
6115 IN HWND hwndParent OPTIONAL,
6116 IN DWORD OpenFlags,
6117 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6118 {
6119 struct DeviceInfoSet *list;
6120 HKEY hEnumKey, hKey;
6121 DWORD rc;
6122 BOOL ret = FALSE;
6123
6124 TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
6125
6126 if (OpenFlags & DIOD_CANCEL_REMOVE)
6127 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6128
6129 if (!DeviceInfoSet)
6130 SetLastError(ERROR_INVALID_HANDLE);
6131 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6132 SetLastError(ERROR_INVALID_HANDLE);
6133 else if (!DeviceInstanceId)
6134 SetLastError(ERROR_INVALID_PARAMETER);
6135 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
6136 {
6137 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
6138 SetLastError(ERROR_INVALID_FLAGS);
6139 }
6140 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6141 SetLastError(ERROR_INVALID_USER_BUFFER);
6142 else
6143 {
6144 struct DeviceInfoElement *deviceInfo = NULL;
6145 /* Search if device already exists in DeviceInfoSet.
6146 * If yes, return the existing element
6147 * If no, create a new element using informations in registry
6148 */
6149 PLIST_ENTRY ItemList = list->ListHead.Flink;
6150 while (ItemList != &list->ListHead)
6151 {
6152 // TODO
6153 //if (good one)
6154 // break;
6155 FIXME("not implemented\n");
6156 ItemList = ItemList->Flink;
6157 }
6158
6159 if (deviceInfo)
6160 {
6161 /* good one found */
6162 ret = TRUE;
6163 }
6164 else
6165 {
6166 /* Open supposed registry key */
6167 rc = RegOpenKeyExW(
6168 list->HKLM,
6169 REGSTR_PATH_SYSTEMENUM,
6170 0, /* Options */
6171 0,
6172 &hEnumKey);
6173 if (rc != ERROR_SUCCESS)
6174 {
6175 SetLastError(rc);
6176 return FALSE;
6177 }
6178 rc = RegOpenKeyExW(
6179 hEnumKey,
6180 DeviceInstanceId,
6181 0, /* Options */
6182 KEY_QUERY_VALUE,
6183 &hKey);
6184 RegCloseKey(hEnumKey);
6185 if (rc != ERROR_SUCCESS)
6186 {
6187 if (rc == ERROR_FILE_NOT_FOUND)
6188 rc = ERROR_NO_SUCH_DEVINST;
6189 SetLastError(rc);
6190 return FALSE;
6191 }
6192
6193 /* FIXME: try to get ClassGUID from registry, instead of
6194 * sending GUID_NULL to CreateDeviceInfoElement
6195 */
6196 if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
6197 {
6198 RegCloseKey(hKey);
6199 return FALSE;
6200 }
6201 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
6202
6203 RegCloseKey(hKey);
6204 ret = TRUE;
6205 }
6206
6207 if (ret && deviceInfo && DeviceInfoData)
6208 {
6209 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
6210 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
6211 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
6212 }
6213 }
6214
6215 return ret;
6216 }
6217
6218
6219 /***********************************************************************
6220 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6221 */
6222 BOOL WINAPI
6223 SetupDiEnumDriverInfoA(
6224 IN HDEVINFO DeviceInfoSet,
6225 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6226 IN DWORD DriverType,
6227 IN DWORD MemberIndex,
6228 OUT PSP_DRVINFO_DATA_A DriverInfoData)
6229 {
6230 SP_DRVINFO_DATA_V2_W driverInfoData2W;
6231 BOOL ret = FALSE;
6232
6233 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
6234 DriverType, MemberIndex, DriverInfoData);
6235
6236 if (DriverInfoData == NULL)
6237 SetLastError(ERROR_INVALID_PARAMETER);
6238 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
6239 SetLastError(ERROR_INVALID_USER_BUFFER);
6240 else
6241 {
6242 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
6243 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
6244 DriverType, MemberIndex, &driverInfoData2W);
6245
6246 if (ret)
6247 {
6248 /* Do W->A conversion */
6249 DriverInfoData->DriverType = driverInfoData2W.DriverType;
6250 DriverInfoData->Reserved = driverInfoData2W.Reserved;
6251 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
6252 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
6253 {
6254 DriverInfoData->Description[0] = '\0';
6255 ret = FALSE;
6256 }
6257 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
6258 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
6259 {
6260 DriverInfoData->MfgName[0] = '\0';
6261 ret = FALSE;
6262 }
6263 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
6264 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
6265 {
6266 DriverInfoData->ProviderName[0] = '\0';
6267 ret = FALSE;
6268 }
6269 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
6270 {
6271 /* Copy more fields */
6272 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
6273 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
6274 }
6275 }
6276 }
6277
6278 TRACE("Returning %d\n", ret);
6279 return ret;
6280 }
6281
6282
6283 /***********************************************************************
6284 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6285 */
6286 BOOL WINAPI
6287 SetupDiEnumDriverInfoW(
6288 IN HDEVINFO DeviceInfoSet,
6289 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6290 IN DWORD DriverType,
6291 IN DWORD MemberIndex,
6292 OUT PSP_DRVINFO_DATA_W DriverInfoData)
6293 {
6294 PLIST_ENTRY ListHead;
6295 BOOL ret = FALSE;
6296
6297 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
6298 DriverType, MemberIndex, DriverInfoData);
6299
6300 if (!DeviceInfoSet || !DriverInfoData)
6301 SetLastError(ERROR_INVALID_PARAMETER);
6302 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6303 SetLastError(ERROR_INVALID_HANDLE);
6304 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6305 SetLastError(ERROR_INVALID_HANDLE);
6306 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
6307 SetLastError(ERROR_INVALID_PARAMETER);
6308 else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
6309 SetLastError(ERROR_INVALID_PARAMETER);
6310 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
6311 SetLastError(ERROR_INVALID_PARAMETER);
6312 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6313 SetLastError(ERROR_INVALID_USER_BUFFER);
6314 else
6315 {
6316 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6317 PLIST_ENTRY ItemList;
6318 if (DriverType == SPDIT_CLASSDRIVER ||
6319 devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
6320 {
6321 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
6322 }
6323 else
6324 {
6325 ListHead = &devInfo->DriverListHead;
6326 }
6327
6328 ItemList = ListHead->Flink;
6329 while (ItemList != ListHead && MemberIndex-- > 0)
6330 ItemList = ItemList->Flink;
6331 if (ItemList == ListHead)
6332 SetLastError(ERROR_NO_MORE_ITEMS);
6333 else
6334 {
6335 struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
6336
6337 memcpy(
6338 &DriverInfoData->DriverType,
6339 &DrvInfo->Info.DriverType,
6340 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
6341 ret = TRUE;
6342 }
6343 }
6344
6345 TRACE("Returning %d\n", ret);
6346 return ret;
6347 }
6348
6349
6350 /***********************************************************************
6351 * SetupDiGetSelectedDevice (SETUPAPI.@)
6352 */
6353 BOOL WINAPI
6354 SetupDiGetSelectedDevice(
6355 IN HDEVINFO DeviceInfoSet,
6356 OUT PSP_DEVINFO_DATA DeviceInfoData)
6357 {
6358 struct DeviceInfoSet *list;
6359 BOOL ret = FALSE;
6360
6361 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6362
6363 if (!DeviceInfoSet)
6364 SetLastError(ERROR_INVALID_HANDLE);
6365 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6366 SetLastError(ERROR_INVALID_HANDLE);
6367 else if (list->SelectedDevice == NULL)
6368 SetLastError(ERROR_NO_DEVICE_SELECTED);
6369 else if (!DeviceInfoData)
6370 SetLastError(ERROR_INVALID_PARAMETER);
6371 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6372 SetLastError(ERROR_INVALID_USER_BUFFER);
6373 else
6374 {
6375 memcpy(&DeviceInfoData->ClassGuid,
6376 &list->SelectedDevice->ClassGuid,
6377 sizeof(GUID));
6378 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
6379 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
6380 ret = TRUE;
6381 }
6382
6383 TRACE("Returning %d\n", ret);
6384 return ret;
6385 }
6386
6387
6388 /***********************************************************************
6389 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6390 */
6391 BOOL WINAPI
6392 SetupDiGetSelectedDriverA(
6393 IN HDEVINFO DeviceInfoSet,
6394 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6395 OUT PSP_DRVINFO_DATA_A DriverInfoData)
6396 {
6397 SP_DRVINFO_DATA_V2_W driverInfoData2W;
6398 BOOL ret = FALSE;
6399
6400 if (DriverInfoData == NULL)
6401 SetLastError(ERROR_INVALID_PARAMETER);
6402 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
6403 SetLastError(ERROR_INVALID_USER_BUFFER);
6404 else
6405 {
6406 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
6407
6408 ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
6409 DeviceInfoData,
6410 &driverInfoData2W);
6411
6412 if (ret)
6413 {
6414 /* Do W->A conversion */
6415 DriverInfoData->DriverType = driverInfoData2W.DriverType;
6416 DriverInfoData->Reserved = driverInfoData2W.Reserved;
6417 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
6418 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
6419 {
6420 DriverInfoData->Description[0] = '\0';
6421 ret = FALSE;
6422 }
6423 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
6424 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
6425 {
6426 DriverInfoData->MfgName[0] = '\0';
6427 ret = FALSE;
6428 }
6429 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
6430 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
6431 {
6432 DriverInfoData->ProviderName[0] = '\0';
6433 ret = FALSE;
6434 }
6435 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
6436 {
6437 /* Copy more fields */
6438 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
6439 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
6440 }
6441 }
6442 }
6443
6444 return ret;
6445 }
6446
6447
6448 /***********************************************************************
6449 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6450 */
6451 BOOL WINAPI
6452 SetupDiGetSelectedDriverW(
6453 IN HDEVINFO DeviceInfoSet,
6454 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6455 OUT PSP_DRVINFO_DATA_W DriverInfoData)
6456 {
6457 BOOL ret = FALSE;
6458
6459 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
6460
6461 if (!DeviceInfoSet || !DriverInfoData)
6462 SetLastError(ERROR_INVALID_PARAMETER);
6463 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6464 SetLastError(ERROR_INVALID_HANDLE);
6465 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6466 SetLastError(ERROR_INVALID_HANDLE);
6467 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6468 SetLastError(ERROR_INVALID_USER_BUFFER);
6469 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6470 SetLastError(ERROR_INVALID_USER_BUFFER);
6471 else
6472 {
6473 SP_DEVINSTALL_PARAMS InstallParams;
6474
6475 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
6476 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
6477 {
6478 struct DriverInfoElement *driverInfo;
6479 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
6480 if (driverInfo == NULL)
6481 SetLastError(ERROR_NO_DRIVER_SELECTED);
6482 else
6483 {
6484 memcpy(
6485 &DriverInfoData->DriverType,
6486 &driverInfo->Info.DriverType,
6487 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
6488 ret = TRUE;
6489 }
6490 }
6491 }
6492
6493 TRACE("Returning %d\n", ret);
6494 return ret;
6495 }
6496
6497
6498 /***********************************************************************
6499 * SetupDiSetSelectedDevice (SETUPAPI.@)
6500 */
6501 BOOL WINAPI
6502 SetupDiSetSelectedDevice(
6503 IN HDEVINFO DeviceInfoSet,
6504 IN PSP_DEVINFO_DATA DeviceInfoData)
6505 {
6506 struct DeviceInfoSet *list;
6507 BOOL ret = FALSE;
6508
6509 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6510
6511 if (!DeviceInfoSet)
6512 SetLastError(ERROR_INVALID_HANDLE);
6513 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6514 SetLastError(ERROR_INVALID_HANDLE);
6515 else if (!DeviceInfoData)
6516 SetLastError(ERROR_INVALID_PARAMETER);
6517 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6518 SetLastError(ERROR_INVALID_USER_BUFFER);
6519 else if (DeviceInfoData->Reserved == 0)
6520 SetLastError(ERROR_INVALID_USER_BUFFER);
6521 else
6522 {
6523 list->SelectedDevice = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6524 ret = TRUE;
6525 }
6526
6527 TRACE("Returning %d\n", ret);
6528 return ret;
6529 }
6530
6531
6532 /***********************************************************************
6533 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6534 */
6535 BOOL WINAPI
6536 SetupDiSetSelectedDriverA(
6537 IN HDEVINFO DeviceInfoSet,
6538 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6539 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
6540 {
6541 SP_DRVINFO_DATA_V1_W DriverInfoDataW;
6542 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
6543 BOOL ret = FALSE;
6544
6545 if (DriverInfoData != NULL)
6546 {
6547 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
6548 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
6549 {
6550 SetLastError(ERROR_INVALID_PARAMETER);
6551 return FALSE;
6552 }
6553
6554 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
6555 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
6556
6557 if (DriverInfoDataW.Reserved == 0)
6558 {
6559 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
6560
6561 /* convert the strings to unicode */
6562 if (!MultiByteToWideChar(CP_ACP,
6563 0,
6564 DriverInfoData->Description,
6565 LINE_LEN,
6566 DriverInfoDataW.Description,
6567 LINE_LEN) ||
6568 !MultiByteToWideChar(CP_ACP,
6569 0,
6570 DriverInfoData->ProviderName,
6571 LINE_LEN,
6572 DriverInfoDataW.ProviderName,
6573 LINE_LEN))
6574 {
6575 return FALSE;
6576 }
6577 }
6578
6579 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
6580 }
6581
6582 ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
6583 DeviceInfoData,
6584 pDriverInfoDataW);
6585
6586 if (ret && pDriverInfoDataW != NULL)
6587 {
6588 DriverInfoData->Reserved = DriverInfoDataW.Reserved;
6589 }
6590
6591 return ret;
6592 }
6593
6594
6595 /***********************************************************************
6596 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6597 */
6598 BOOL WINAPI
6599 SetupDiSetSelectedDriverW(
6600 IN HDEVINFO DeviceInfoSet,
6601 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6602 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
6603 {
6604 BOOL ret = FALSE;
6605
6606 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
6607
6608 if (!DeviceInfoSet)
6609 SetLastError(ERROR_INVALID_PARAMETER);
6610 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6611 SetLastError(ERROR_INVALID_HANDLE);
6612 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6613 SetLastError(ERROR_INVALID_HANDLE);
6614 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6615 SetLastError(ERROR_INVALID_USER_BUFFER);
6616 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6617 SetLastError(ERROR_INVALID_USER_BUFFER);
6618 else
6619 {
6620 struct DriverInfoElement **pDriverInfo;
6621 PLIST_ENTRY ListHead, ItemList;
6622
6623 if (DeviceInfoData)
6624 {
6625 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
6626 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
6627 }
6628 else
6629 {
6630 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
6631 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
6632 }
6633
6634 if (!DriverInfoData)
6635 {
6636 *pDriverInfo = NULL;
6637 ret = TRUE;
6638 }
6639 else
6640 {
6641 /* Search selected driver in list */
6642 ItemList = ListHead->Flink;
6643 while (ItemList != ListHead)
6644 {
6645 if (DriverInfoData->Reserved != 0)
6646 {
6647 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
6648 break;
6649 }
6650 else
6651 {
6652 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6653 struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
6654 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
6655 && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
6656 && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
6657 {
6658 break;
6659 }
6660 }
6661 }
6662 if (ItemList == ListHead)
6663 SetLastError(ERROR_INVALID_PARAMETER);
6664 else
6665 {
6666 *pDriverInfo = (struct DriverInfoElement *)ItemList;
6667 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
6668 ret = TRUE;
6669 TRACE("Choosing driver whose rank is 0x%lx\n",
6670 ((struct DriverInfoElement *)ItemList)->DriverRank);
6671 if (DeviceInfoData)
6672 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
6673 }
6674 }
6675 }
6676
6677 TRACE("Returning %d\n", ret);
6678 return ret;
6679 }
6680
6681 /***********************************************************************
6682 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6683 */
6684 BOOL WINAPI
6685 SetupDiGetDriverInfoDetailA(
6686 IN HDEVINFO DeviceInfoSet,
6687 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6688 IN PSP_DRVINFO_DATA_A DriverInfoData,
6689 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
6690 IN DWORD DriverInfoDetailDataSize,
6691 OUT PDWORD RequiredSize OPTIONAL)
6692 {
6693 SP_DRVINFO_DATA_V2_W DriverInfoDataW;
6694 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
6695 DWORD BufSize = 0;
6696 DWORD HardwareIDLen = 0;
6697 BOOL ret = FALSE;
6698
6699 /* do some sanity checks, the unicode version might do more thorough checks */
6700 if (DriverInfoData == NULL ||
6701 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
6702 (DriverInfoDetailData != NULL &&
6703 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
6704 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
6705 {
6706 SetLastError(ERROR_INVALID_PARAMETER);
6707 goto Cleanup;
6708 }
6709
6710 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6711 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
6712 {
6713 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
6714 }
6715 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
6716 {
6717 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
6718 }
6719 else
6720 {
6721 SetLastError(ERROR_INVALID_PARAMETER);
6722 goto Cleanup;
6723 }
6724 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
6725 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
6726
6727 /* convert the strings to unicode */
6728 if (MultiByteToWideChar(CP_ACP,
6729 0,
6730 DriverInfoData->Description,
6731 LINE_LEN,
6732 DriverInfoDataW.Description,
6733 LINE_LEN) &&
6734 MultiByteToWideChar(CP_ACP,
6735 0,
6736 DriverInfoData->MfgName,
6737 LINE_LEN,
6738 DriverInfoDataW.MfgName,
6739 LINE_LEN) &&
6740 MultiByteToWideChar(CP_ACP,
6741 0,
6742 DriverInfoData->ProviderName,
6743 LINE_LEN,
6744 DriverInfoDataW.ProviderName,
6745 LINE_LEN))
6746 {
6747 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
6748 {
6749 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
6750 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
6751 }
6752
6753 if (DriverInfoDetailData != NULL)
6754 {
6755 /* calculate the unicode buffer size from the ansi buffer size */
6756 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
6757 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
6758 (HardwareIDLen * sizeof(WCHAR));
6759
6760 DriverInfoDetailDataW = MyMalloc(BufSize);
6761 if (DriverInfoDetailDataW == NULL)
6762 {
6763 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6764 goto Cleanup;
6765 }
6766
6767 /* initialize the buffer */
6768 ZeroMemory(DriverInfoDetailDataW,
6769 BufSize);
6770 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
6771 }
6772
6773 /* call the unicode version */
6774 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
6775 DeviceInfoData,
6776 &DriverInfoDataW,
6777 DriverInfoDetailDataW,
6778 BufSize,
6779 RequiredSize);
6780
6781 if (ret)
6782 {
6783 if (DriverInfoDetailDataW != NULL)
6784 {
6785 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6786 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
6787 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
6788 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
6789 if (WideCharToMultiByte(CP_ACP,
6790 0,
6791 DriverInfoDetailDataW->SectionName,
6792 LINE_LEN,
6793 DriverInfoDetailData->SectionName,
6794 LINE_LEN,
6795 NULL,
6796 NULL) &&
6797 WideCharToMultiByte(CP_ACP,
6798 0,
6799 DriverInfoDetailDataW->InfFileName,
6800 MAX_PATH,
6801 DriverInfoDetailData->InfFileName,
6802 MAX_PATH,
6803 NULL,
6804 NULL) &&
6805 WideCharToMultiByte(CP_ACP,
6806 0,
6807 DriverInfoDetailDataW->DrvDescription,
6808 LINE_LEN,
6809 DriverInfoDetailData->DrvDescription,
6810 LINE_LEN,
6811 NULL,
6812 NULL) &&
6813 WideCharToMultiByte(CP_ACP,
6814 0,
6815 DriverInfoDetailDataW->HardwareID,
6816 HardwareIDLen,
6817 DriverInfoDetailData->HardwareID,
6818 HardwareIDLen,
6819 NULL,
6820 NULL))
6821 {
6822 DWORD len, cnt = 0;
6823 DWORD hwidlen = HardwareIDLen;
6824 CHAR *s = DriverInfoDetailData->HardwareID;
6825
6826 /* count the strings in the list */
6827 while (*s != '\0')
6828 {
6829 len = lstrlenA(s) + 1;
6830 if (hwidlen > len)
6831 {
6832 cnt++;
6833 s += len;
6834 hwidlen -= len;
6835 }
6836 else
6837 {
6838 /* looks like the string list wasn't terminated... */
6839 SetLastError(ERROR_INVALID_USER_BUFFER);
6840 ret = FALSE;
6841 break;
6842 }
6843 }
6844
6845 /* make sure CompatIDsOffset points to the second string in the
6846 list, if present */
6847 if (cnt > 1)
6848 {
6849 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
6850 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
6851 DriverInfoDetailData->CompatIDsOffset + 1;
6852 }
6853 else
6854 {
6855 DriverInfoDetailData->CompatIDsOffset = 0;
6856 DriverInfoDetailData->CompatIDsLength = 0;
6857 }
6858 }
6859 else
6860 {
6861 ret = FALSE;
6862 }
6863 }
6864
6865 if (RequiredSize != NULL)
6866 {
6867 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
6868 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
6869 }
6870 }
6871 }
6872
6873 Cleanup:
6874 if (DriverInfoDetailDataW != NULL)
6875 {
6876 MyFree(DriverInfoDetailDataW);
6877 }
6878
6879 return ret;
6880 }
6881
6882 /***********************************************************************
6883 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6884 */
6885 BOOL WINAPI
6886 SetupDiGetDriverInfoDetailW(
6887 IN HDEVINFO DeviceInfoSet,
6888 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6889 IN PSP_DRVINFO_DATA_W DriverInfoData,
6890 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
6891 IN DWORD DriverInfoDetailDataSize,
6892 OUT PDWORD RequiredSize OPTIONAL)
6893 {
6894 BOOL ret = FALSE;
6895
6896 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
6897 DriverInfoData, DriverInfoDetailData,
6898 DriverInfoDetailDataSize, RequiredSize);
6899
6900 if (!DeviceInfoSet)
6901 SetLastError(ERROR_INVALID_PARAMETER);
6902 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6903 SetLastError(ERROR_INVALID_HANDLE);
6904 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6905 SetLastError(ERROR_INVALID_HANDLE);
6906 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6907 SetLastError(ERROR_INVALID_USER_BUFFER);
6908 else if (!DriverInfoData)
6909 SetLastError(ERROR_INVALID_PARAMETER);
6910 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
6911 SetLastError(ERROR_INVALID_PARAMETER);
6912 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
6913 SetLastError(ERROR_INVALID_PARAMETER);
6914 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
6915 SetLastError(ERROR_INVALID_USER_BUFFER);
6916 else if (DriverInfoData->Reserved == 0)
6917 SetLastError(ERROR_NO_DRIVER_SELECTED);
6918 else
6919 {
6920 struct DriverInfoElement *driverInfoElement;
6921 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
6922
6923 memcpy(
6924 DriverInfoDetailData,
6925 &driverInfoElement->Details,
6926 driverInfoElement->Details.cbSize);
6927 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6928 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6929 */
6930 ret = TRUE;
6931 }
6932
6933 TRACE("Returning %d\n", ret);
6934 return ret;
6935 }
6936
6937 /* Return the current hardware profile id, or -1 if error */
6938 static DWORD
6939 GetCurrentHwProfile(
6940 IN HDEVINFO DeviceInfoSet)
6941 {
6942 HKEY hKey = INVALID_HANDLE_VALUE;
6943 DWORD dwRegType, dwLength;
6944 DWORD hwProfile;
6945 LONG rc;
6946 DWORD ret = (DWORD)-1;
6947
6948 rc = RegOpenKeyExW(
6949 ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
6950 REGSTR_PATH_IDCONFIGDB,
6951 0, /* Options */
6952 KEY_QUERY_VALUE,
6953 &hKey);
6954 if (rc != ERROR_SUCCESS)
6955 {
6956 SetLastError(rc);
6957 goto cleanup;
6958 }
6959
6960 dwLength = sizeof(DWORD);
6961 rc = RegQueryValueExW(
6962 hKey,
6963 REGSTR_VAL_CURRENTCONFIG,
6964 NULL,
6965 &dwRegType,
6966 (LPBYTE)&hwProfile, &dwLength);
6967 if (rc != ERROR_SUCCESS)
6968 {
6969 SetLastError(rc);
6970 goto cleanup;
6971 }
6972 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
6973 {
6974 SetLastError(ERROR_GEN_FAILURE);
6975 goto cleanup;
6976 }
6977
6978 ret = hwProfile;
6979
6980 cleanup:
6981 if (hKey != INVALID_HANDLE_VALUE)
6982 RegCloseKey(hKey);
6983
6984 return hwProfile;
6985 }
6986
6987 static BOOL
6988 ResetDevice(
6989 IN HDEVINFO DeviceInfoSet,
6990 IN PSP_DEVINFO_DATA DeviceInfoData)
6991 {
6992 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
6993 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6994 NTSTATUS Status;
6995
6996 if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
6997 {
6998 /* At the moment, I only know how to start local devices */
6999 SetLastError(ERROR_INVALID_COMPUTERNAME);
7000 return FALSE;
7001 }
7002
7003 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, deviceInfo->DeviceName);
7004 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
7005 SetLastError(RtlNtStatusToDosError(Status));
7006 return NT_SUCCESS(Status);
7007 }
7008
7009 static BOOL StopDevice(
7010 IN HDEVINFO DeviceInfoSet,
7011 IN PSP_DEVINFO_DATA DeviceInfoData)
7012 {
7013 FIXME("Stub %p %p\n", DeviceInfoSet, DeviceInfoData);
7014 return TRUE;
7015 }
7016
7017 /***********************************************************************
7018 * SetupDiChangeState (SETUPAPI.@)
7019 */
7020 BOOL WINAPI
7021 SetupDiChangeState(
7022 IN HDEVINFO DeviceInfoSet,
7023 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
7024 {
7025 PSP_PROPCHANGE_PARAMS PropChange;
7026 HKEY hKey = INVALID_HANDLE_VALUE;
7027 LPCWSTR RegistryValueName;
7028 DWORD dwConfigFlags, dwLength, dwRegType;
7029 LONG rc;
7030 BOOL ret = FALSE;
7031
7032 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7033
7034 if (!DeviceInfoData)
7035 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChange;
7036 else
7037 PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChange;
7038 if (!PropChange)
7039 {
7040 SetLastError(ERROR_INVALID_PARAMETER);
7041 goto cleanup;
7042 }
7043
7044 if (PropChange->Scope == DICS_FLAG_GLOBAL)
7045 RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
7046 else
7047 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
7048
7049 switch (PropChange->StateChange)
7050 {
7051 case DICS_ENABLE:
7052 case DICS_DISABLE:
7053 {
7054 /* Enable/disable device in registry */
7055 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
7056 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
7057 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
7058 if (hKey == INVALID_HANDLE_VALUE)
7059 break;
7060 dwLength = sizeof(DWORD);
7061 rc = RegQueryValueExW(
7062 hKey,
7063 RegistryValueName,
7064 NULL,
7065 &dwRegType,
7066 (LPBYTE)&dwConfigFlags, &dwLength);
7067 if (rc == ERROR_FILE_NOT_FOUND)
7068 dwConfigFlags = 0;
7069 else if (rc != ERROR_SUCCESS)
7070 {
7071 SetLastError(rc);
7072 goto cleanup;
7073 }
7074 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
7075 {
7076 SetLastError(ERROR_GEN_FAILURE);
7077 goto cleanup;
7078 }
7079 if (PropChange->StateChange == DICS_ENABLE)
7080 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
7081 else
7082 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
7083 rc = RegSetValueEx(
7084 hKey,
7085 RegistryValueName,
7086 0,
7087 REG_DWORD,
7088 (LPBYTE)&dwConfigFlags, sizeof(DWORD));
7089 if (rc != ERROR_SUCCESS)
7090 {
7091 SetLastError(rc);
7092 goto cleanup;
7093 }
7094
7095 /* Enable/disable device if needed */
7096 if (PropChange->Scope == DICS_FLAG_GLOBAL
7097 || PropChange->HwProfile == 0
7098 || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
7099 {
7100 if (PropChange->StateChange == DICS_ENABLE)
7101 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
7102 else
7103 ret = StopDevice(DeviceInfoSet, DeviceInfoData);
7104 }
7105 else
7106 ret = TRUE;
7107 break;
7108 }
7109 case DICS_PROPCHANGE:
7110 {
7111 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
7112 break;
7113 }
7114 default:
7115 {
7116 FIXME("Unknown StateChange 0x%lx\n", PropChange->StateChange);
7117 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
7118 }
7119 }
7120
7121 cleanup:
7122 if (hKey != INVALID_HANDLE_VALUE)
7123 RegCloseKey(hKey);
7124
7125 TRACE("Returning %d\n", ret);
7126 return ret;
7127 }
7128
7129 /***********************************************************************
7130 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7131 */
7132 BOOL WINAPI
7133 SetupDiSelectBestCompatDrv(
7134 IN HDEVINFO DeviceInfoSet,
7135 IN PSP_DEVINFO_DATA DeviceInfoData)
7136 {
7137 SP_DRVINFO_DATA_W drvInfoData;
7138 BOOL ret;
7139
7140 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7141
7142 /* Drivers are sorted by rank in the driver list, so
7143 * the first driver in the list is the best one.
7144 */
7145 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
7146 ret = SetupDiEnumDriverInfoW(
7147 DeviceInfoSet,
7148 DeviceInfoData,
7149 SPDIT_COMPATDRIVER,
7150 0, /* Member index */
7151 &drvInfoData);
7152
7153 if (ret)
7154 {
7155 ret = SetupDiSetSelectedDriverW(
7156 DeviceInfoSet,
7157 DeviceInfoData,
7158 &drvInfoData);
7159 }
7160
7161 TRACE("Returning %d\n", ret);
7162 return ret;
7163 }
7164
7165 /***********************************************************************
7166 * SetupDiInstallDriverFiles (SETUPAPI.@)
7167 */
7168 BOOL WINAPI
7169 SetupDiInstallDriverFiles(
7170 IN HDEVINFO DeviceInfoSet,
7171 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
7172 {
7173 BOOL ret = FALSE;
7174
7175 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7176
7177 if (!DeviceInfoSet)
7178 SetLastError(ERROR_INVALID_PARAMETER);
7179 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7180 SetLastError(ERROR_INVALID_HANDLE);
7181 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7182 SetLastError(ERROR_INVALID_HANDLE);
7183 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7184 SetLastError(ERROR_INVALID_USER_BUFFER);
7185 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
7186 SetLastError(ERROR_NO_DRIVER_SELECTED);
7187 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
7188 SetLastError(ERROR_NO_DRIVER_SELECTED);
7189 else
7190 {
7191 SP_DEVINSTALL_PARAMS_W InstallParams;
7192 struct DriverInfoElement *SelectedDriver;
7193 WCHAR SectionName[MAX_PATH];
7194 DWORD SectionNameLength = 0;
7195
7196 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7197 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7198 if (!ret)
7199 goto done;
7200
7201 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
7202 if (!SelectedDriver)
7203 {
7204 SetLastError(ERROR_NO_DRIVER_SELECTED);
7205 goto done;
7206 }
7207
7208 ret = SetupDiGetActualSectionToInstallW(
7209 SelectedDriver->InfFileDetails->hInf,
7210 SelectedDriver->Details.SectionName,
7211 SectionName, MAX_PATH, &SectionNameLength, NULL);
7212 if (!ret)
7213 goto done;
7214
7215 if (!InstallParams.InstallMsgHandler)
7216 {
7217 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
7218 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
7219 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7220 }
7221 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7222 SelectedDriver->InfFileDetails->hInf, SectionName,
7223 SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
7224 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
7225 DeviceInfoSet, DeviceInfoData);
7226 }
7227
7228 done:
7229 TRACE("Returning %d\n", ret);
7230 return ret;
7231 }
7232
7233 /***********************************************************************
7234 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7235 */
7236 BOOL WINAPI
7237 SetupDiRegisterCoDeviceInstallers(
7238 IN HDEVINFO DeviceInfoSet,
7239 IN PSP_DEVINFO_DATA DeviceInfoData)
7240 {
7241 BOOL ret = FALSE; /* Return value */
7242
7243 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7244
7245 if (!DeviceInfoSet)
7246 SetLastError(ERROR_INVALID_PARAMETER);
7247 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7248 SetLastError(ERROR_INVALID_HANDLE);
7249 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7250 SetLastError(ERROR_INVALID_HANDLE);
7251 else if (!DeviceInfoData)
7252 SetLastError(ERROR_INVALID_PARAMETER);
7253 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7254 SetLastError(ERROR_INVALID_USER_BUFFER);
7255 else
7256 {
7257 SP_DEVINSTALL_PARAMS_W InstallParams;
7258 struct DriverInfoElement *SelectedDriver;
7259 BOOL Result;
7260 DWORD DoAction;
7261 WCHAR SectionName[MAX_PATH];
7262 DWORD SectionNameLength = 0;
7263 HKEY hKey = INVALID_HANDLE_VALUE;
7264
7265 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7266 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7267 if (!Result)
7268 goto cleanup;
7269
7270 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
7271 if (SelectedDriver == NULL)
7272 {
7273 SetLastError(ERROR_NO_DRIVER_SELECTED);
7274 goto cleanup;
7275 }
7276
7277 /* Get .CoInstallers section name */
7278 Result = SetupDiGetActualSectionToInstallW(
7279 SelectedDriver->InfFileDetails->hInf,
7280 SelectedDriver->Details.SectionName,
7281 SectionName, MAX_PATH, &SectionNameLength, NULL);
7282 if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
7283 goto cleanup;
7284 wcscat(SectionName, L".CoInstallers");
7285
7286 /* Open/Create driver key information */
7287 #if _WIN32_WINNT >= 0x502
7288 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
7289 #else
7290 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
7291 #endif
7292 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
7293 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
7294 if (hKey == INVALID_HANDLE_VALUE)
7295 goto cleanup;
7296
7297 /* Install .CoInstallers section */
7298 DoAction = SPINST_REGISTRY;
7299 if (!(InstallParams.Flags & DI_NOFILECOPY))
7300 {
7301 DoAction |= SPINST_FILES;
7302 if (!InstallParams.InstallMsgHandler)
7303 {
7304 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
7305 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
7306 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7307 }
7308 }
7309 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7310 SelectedDriver->InfFileDetails->hInf, SectionName,
7311 DoAction, hKey, NULL, SP_COPY_NEWER,
7312 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
7313 DeviceInfoSet, DeviceInfoData);
7314 if (!Result)
7315 goto cleanup;
7316
7317 ret = TRUE;
7318
7319 cleanup:
7320 if (hKey != INVALID_HANDLE_VALUE)
7321 RegCloseKey(hKey);
7322 }
7323
7324 TRACE("Returning %d\n", ret);
7325 return ret;
7326 }
7327
7328 /***********************************************************************
7329 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7330 */
7331 BOOL WINAPI
7332 SetupDiInstallDeviceInterfaces(
7333 IN HDEVINFO DeviceInfoSet,
7334 IN PSP_DEVINFO_DATA DeviceInfoData)
7335 {
7336 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7337
7338 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
7339 //SetLastError(ERROR_GEN_FAILURE);
7340 //return FALSE;
7341 return TRUE;
7342 }
7343
7344 BOOL
7345 InfIsFromOEMLocation(
7346 IN PCWSTR FullName,
7347 OUT LPBOOL IsOEMLocation)
7348 {
7349 PWCHAR last;
7350
7351 last = strrchrW(FullName, '\\');
7352 if (!last)
7353 {
7354 /* No directory specified */
7355 *IsOEMLocation = FALSE;
7356 }
7357 else
7358 {
7359 WCHAR Windir[MAX_PATH];
7360 UINT ret;
7361
7362 ret = GetWindowsDirectory(Windir, MAX_PATH);
7363 if (ret == 0 || ret >= MAX_PATH)
7364 {
7365 SetLastError(ERROR_GEN_FAILURE);
7366 return FALSE;
7367 }
7368
7369 if (strncmpW(FullName, Windir, last - FullName) == 0)
7370 {
7371 /* The path is %SYSTEMROOT%\Inf */
7372 *IsOEMLocation = FALSE;
7373 }
7374 else
7375 {
7376 /* The file is in another place */
7377 *IsOEMLocation = TRUE;
7378 }
7379 }
7380 return TRUE;
7381 }
7382
7383 /***********************************************************************
7384 * SetupDiInstallDevice (SETUPAPI.@)
7385 */
7386 BOOL WINAPI
7387 SetupDiInstallDevice(
7388 IN HDEVINFO DeviceInfoSet,
7389 IN PSP_DEVINFO_DATA DeviceInfoData)
7390 {
7391 SP_DEVINSTALL_PARAMS_W InstallParams;
7392 struct DriverInfoElement *SelectedDriver;
7393 SYSTEMTIME DriverDate;
7394 WCHAR SectionName[MAX_PATH];
7395 WCHAR Buffer[32];
7396 DWORD SectionNameLength = 0;
7397 BOOL Result = FALSE;
7398 ULONG DoAction;
7399 DWORD RequiredSize;
7400 LPCWSTR AssociatedService = NULL;
7401 LPWSTR pSectionName = NULL;
7402 WCHAR ClassName[MAX_CLASS_NAME_LEN];
7403 GUID ClassGuid;
7404 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
7405 BOOL RebootRequired = FALSE;
7406 HKEY hKey = INVALID_HANDLE_VALUE;
7407 HKEY hClassKey = INVALID_HANDLE_VALUE;
7408 BOOL NeedtoCopyFile;
7409 LARGE_INTEGER fullVersion;
7410 LONG rc;
7411 BOOL ret = FALSE; /* Return value */
7412
7413 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7414
7415 if (!DeviceInfoSet)
7416 SetLastError(ERROR_INVALID_PARAMETER);
7417 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7418 SetLastError(ERROR_INVALID_HANDLE);
7419 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7420 SetLastError(ERROR_INVALID_HANDLE);
7421 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7422 SetLastError(ERROR_INVALID_USER_BUFFER);
7423 else
7424 Result = TRUE;
7425
7426 if (!Result)
7427 {
7428 /* One parameter is bad */
7429 goto cleanup;
7430 }
7431
7432 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7433 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7434 if (!Result)
7435 goto cleanup;
7436
7437 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
7438 {
7439 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7440 goto cleanup;
7441 }
7442
7443 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
7444 if (SelectedDriver == NULL)
7445 {
7446 SetLastError(ERROR_NO_DRIVER_SELECTED);
7447 goto cleanup;
7448 }
7449
7450 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
7451
7452 Result = SetupDiGetActualSectionToInstallW(
7453 SelectedDriver->InfFileDetails->hInf,
7454 SelectedDriver->Details.SectionName,
7455 SectionName, MAX_PATH, &SectionNameLength, NULL);
7456 if (!Result || SectionNameLength > MAX_PATH - wcslen(DotServices))
7457 goto cleanup;
7458 pSectionName = &SectionName[wcslen(SectionName)];
7459
7460 /* Get information from [Version] section */
7461 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
7462 goto cleanup;
7463 /* Format ClassGuid to a string */
7464 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
7465 goto cleanup;
7466 RequiredSize = lstrlenW(lpGuidString);
7467 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
7468 if (!lpFullGuidString)
7469 {
7470 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
7471 goto cleanup;
7472 }
7473 lpFullGuidString[0] = '{';
7474 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
7475 lpFullGuidString[RequiredSize + 1] = '}';
7476 lpFullGuidString[RequiredSize + 2] = '\0';
7477
7478 /* Open/Create driver key information */
7479 #if _WIN32_WINNT >= 0x502
7480 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
7481 #else
7482 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
7483 #endif
7484 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
7485 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
7486 if (hKey == INVALID_HANDLE_VALUE)
7487 goto cleanup;
7488
7489 /* Install main section */
7490 DoAction = SPINST_REGISTRY;
7491 if (!(InstallParams.Flags & DI_NOFILECOPY))
7492 {
7493 DoAction |= SPINST_FILES;
7494 if (!InstallParams.InstallMsgHandler)
7495 {
7496 InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
7497 InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
7498 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7499 }
7500 }
7501 *pSectionName = '\0';
7502 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7503 SelectedDriver->InfFileDetails->hInf, SectionName,
7504 DoAction, hKey, NULL, SP_COPY_NEWER,
7505 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
7506 DeviceInfoSet, DeviceInfoData);
7507 if (!Result)
7508 goto cleanup;
7509 if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
7510 {
7511 if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
7512 {
7513 /* Delete resources allocated by SetupInitDefaultQueueCallback */
7514 SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
7515 }
7516 }
7517 InstallParams.Flags |= DI_NOFILECOPY;
7518 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7519
7520 /* Write information to driver key */
7521 *pSectionName = UNICODE_NULL;
7522 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
7523 TRACE("Write information to driver key\n");
7524 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
7525 TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
7526 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
7527 TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
7528 TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
7529 TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
7530 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
7531 TRACE("ProviderName : '%S'\n", SelectedDriver->Info.ProviderName);
7532 swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
7533 rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
7534 if (rc == ERROR_SUCCESS)
7535 rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
7536 if (rc == ERROR_SUCCESS)
7537 rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
7538 if (rc == ERROR_SUCCESS)
7539 {
7540 swprintf(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
7541 rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
7542 }
7543 if (rc == ERROR_SUCCESS)
7544 rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
7545 if (rc == ERROR_SUCCESS)
7546 rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
7547 if (rc == ERROR_SUCCESS)
7548 rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
7549 if (rc == ERROR_SUCCESS)
7550 rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
7551 if (rc == ERROR_SUCCESS)
7552 rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
7553 if (rc != ERROR_SUCCESS)
7554 {
7555 SetLastError(rc);
7556 goto cleanup;
7557 }
7558 RegCloseKey(hKey);
7559 hKey = INVALID_HANDLE_VALUE;
7560
7561 /* FIXME: Process .LogConfigOverride section */
7562
7563 /* Install .Services section */
7564 wcscpy(pSectionName, DotServices);
7565 Result = InstallServicesSection(
7566 SelectedDriver->InfFileDetails->hInf,
7567 SectionName,
7568 DeviceInfoSet,
7569 DeviceInfoData,
7570 &AssociatedService,
7571 &RebootRequired);
7572 if (!Result)
7573 goto cleanup;
7574
7575 /* Copy .inf file to Inf\ directory (if needed) */
7576 Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
7577 if (!Result)
7578 goto cleanup;
7579 if (NeedtoCopyFile)
7580 {
7581 Result = SetupCopyOEMInfW(
7582 SelectedDriver->InfFileDetails->FullInfFileName,
7583 NULL,
7584 SPOST_NONE,
7585 SP_COPY_NOOVERWRITE,
7586 NULL, 0,
7587 NULL,
7588 NULL);
7589 if (!Result)
7590 goto cleanup;
7591 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7592 * to release use of current InfFile */
7593 }
7594
7595 /* Open device registry key */
7596 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
7597 if (hKey == INVALID_HANDLE_VALUE)
7598 goto cleanup;
7599
7600 /* Install .HW section */
7601 wcscpy(pSectionName, L".HW");
7602 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7603 SelectedDriver->InfFileDetails->hInf, SectionName,
7604 SPINST_REGISTRY, hKey, NULL, 0,
7605 InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
7606 DeviceInfoSet, DeviceInfoData);
7607 if (!Result)
7608 goto cleanup;
7609
7610 /* Write information to enum key */
7611 TRACE("Write information to enum key\n");
7612 TRACE("Class : '%S'\n", ClassName);
7613 TRACE("ClassGUID : '%S'\n", lpFullGuidString);
7614 TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
7615 TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
7616 TRACE("Service : '%S'\n", AssociatedService);
7617 rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
7618 if (rc == ERROR_SUCCESS)
7619 rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
7620 if (rc == ERROR_SUCCESS)
7621 rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
7622 if (rc == ERROR_SUCCESS)
7623 rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
7624 if (rc == ERROR_SUCCESS && AssociatedService && *AssociatedService)
7625 rc = RegSetValueEx(hKey, REGSTR_VAL_SERVICE, 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
7626 if (rc != ERROR_SUCCESS)
7627 {
7628 SetLastError(rc);
7629 goto cleanup;
7630 }
7631
7632 /* Start the device */
7633 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
7634 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
7635 else
7636 ret = TRUE;
7637
7638 cleanup:
7639 /* End of installation */
7640 if (hClassKey != INVALID_HANDLE_VALUE)
7641 RegCloseKey(hClassKey);
7642 if (hKey != INVALID_HANDLE_VALUE)
7643 RegCloseKey(hKey);
7644 if (lpGuidString)
7645 RpcStringFreeW(&lpGuidString);
7646 HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
7647 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
7648
7649 TRACE("Returning %d\n", ret);
7650 return ret;
7651 }