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