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