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