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