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