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