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