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