264144cab499c61f56ffa298fee0282595c0f26f
[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 ERR("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 = SetupDiSelectDevice;
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_DONOTCALLCONFIGMG | /* 0x00020000 */
4495 DI_CLASSINSTALLPARAMS | /* 0x00100000 */
4496 DI_NODI_DEFAULTACTION | /* 0x00200000 */
4497 DI_QUIETINSTALL | /* 0x00800000 */
4498 DI_NOFILECOPY | /* 0x01000000 */
4499 DI_DRIVERPAGE_ADDED; /* 0x04000000 */
4500 DWORD SupportedFlagsEx =
4501 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */
4502 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
4503 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
4504 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
4505 DI_FLAGSEX_NO_DRVREG_MODIFY; /* 0x00008000 */
4506 BOOL ret = FALSE;
4507
4508 /* FIXME: add support for more flags */
4509
4510 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4511 * It should be checked before accessing to other values
4512 * of the SP_DEVINSTALL_PARAMS structure */
4513
4514 if (DeviceInstallParams->Flags & ~SupportedFlags)
4515 {
4516 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
4517 SetLastError(ERROR_INVALID_FLAGS);
4518 }
4519 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
4520 {
4521 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
4522 SetLastError(ERROR_INVALID_FLAGS);
4523 }
4524 else if ((DeviceInstallParams->Flags & DI_NOVCP)
4525 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
4526 SetLastError(ERROR_INVALID_USER_BUFFER);
4527 else
4528 {
4529 /* FIXME: check Reserved field */
4530 ret = TRUE;
4531 }
4532
4533 return ret;
4534 }
4535
4536 /***********************************************************************
4537 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4538 */
4539 BOOL WINAPI
4540 SetupDiSetDeviceInstallParamsW(
4541 IN HDEVINFO DeviceInfoSet,
4542 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4543 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4544 {
4545 struct DeviceInfoSet *list;
4546 BOOL ret = FALSE;
4547
4548 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4549
4550 if (!DeviceInfoSet)
4551 SetLastError(ERROR_INVALID_HANDLE);
4552 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4553 SetLastError(ERROR_INVALID_HANDLE);
4554 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4555 SetLastError(ERROR_INVALID_USER_BUFFER);
4556 else if (!DeviceInstallParams)
4557 SetLastError(ERROR_INVALID_PARAMETER);
4558 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4559 SetLastError(ERROR_INVALID_USER_BUFFER);
4560 else if (CheckDeviceInstallParameters(DeviceInstallParams))
4561 {
4562 PSP_DEVINSTALL_PARAMS_W Destination;
4563
4564 if (DeviceInfoData)
4565 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
4566 else
4567 Destination = &list->InstallParams;
4568 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
4569 ret = TRUE;
4570 }
4571
4572 TRACE("Returning %d\n", ret);
4573 return ret;
4574 }
4575
4576 /***********************************************************************
4577 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4578 */
4579 BOOL WINAPI
4580 SetupDiGetDeviceInstanceIdA(
4581 IN HDEVINFO DeviceInfoSet,
4582 IN PSP_DEVINFO_DATA DeviceInfoData,
4583 OUT PSTR DeviceInstanceId OPTIONAL,
4584 IN DWORD DeviceInstanceIdSize,
4585 OUT PDWORD RequiredSize OPTIONAL)
4586 {
4587 PWSTR DeviceInstanceIdW = NULL;
4588 BOOL ret = FALSE;
4589
4590 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
4591 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
4592
4593 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
4594 SetLastError(ERROR_INVALID_PARAMETER);
4595 else
4596 {
4597 if (DeviceInstanceIdSize != 0)
4598 {
4599 DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
4600 if (DeviceInstanceIdW == NULL)
4601 return FALSE;
4602 }
4603
4604 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
4605 DeviceInstanceIdW, DeviceInstanceIdSize,
4606 RequiredSize);
4607
4608 if (ret && DeviceInstanceIdW != NULL)
4609 {
4610 if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
4611 DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
4612 {
4613 DeviceInstanceId[0] = '\0';
4614 ret = FALSE;
4615 }
4616 }
4617 }
4618
4619 TRACE("Returning %d\n", ret);
4620 return ret;
4621 }
4622
4623 /***********************************************************************
4624 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4625 */
4626 BOOL WINAPI
4627 SetupDiGetDeviceInstanceIdW(
4628 IN HDEVINFO DeviceInfoSet,
4629 IN PSP_DEVINFO_DATA DeviceInfoData,
4630 OUT PWSTR DeviceInstanceId OPTIONAL,
4631 IN DWORD DeviceInstanceIdSize,
4632 OUT PDWORD RequiredSize OPTIONAL)
4633 {
4634 BOOL ret = FALSE;
4635
4636 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
4637 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
4638
4639 if (!DeviceInfoSet)
4640 SetLastError(ERROR_INVALID_HANDLE);
4641 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4642 SetLastError(ERROR_INVALID_HANDLE);
4643 else if (!DeviceInfoData)
4644 SetLastError(ERROR_INVALID_PARAMETER);
4645 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4646 SetLastError(ERROR_INVALID_USER_BUFFER);
4647 else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
4648 SetLastError(ERROR_INVALID_PARAMETER);
4649 else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
4650 SetLastError(ERROR_INVALID_PARAMETER);
4651 else
4652 {
4653 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
4654 DWORD required;
4655
4656 required = (strlenW(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
4657 if (RequiredSize)
4658 *RequiredSize = required;
4659
4660 if (required <= DeviceInstanceIdSize)
4661 {
4662 strcpyW(DeviceInstanceId, DevInfo->DeviceName);
4663 ret = TRUE;
4664 }
4665 else
4666 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4667 }
4668
4669 TRACE("Returning %d\n", ret);
4670 return ret;
4671 }
4672
4673 /***********************************************************************
4674 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4675 */
4676 BOOL WINAPI
4677 SetupDiGetClassDevPropertySheetsA(
4678 IN HDEVINFO DeviceInfoSet,
4679 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4680 IN LPPROPSHEETHEADERA PropertySheetHeader,
4681 IN DWORD PropertySheetHeaderPageListSize,
4682 OUT PDWORD RequiredSize OPTIONAL,
4683 IN DWORD PropertySheetType)
4684 {
4685 PROPSHEETHEADERW psh;
4686 BOOL ret = FALSE;
4687
4688 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4689 PropertySheetHeader, PropertySheetHeaderPageListSize,
4690 RequiredSize, PropertySheetType);
4691
4692 psh.dwFlags = PropertySheetHeader->dwFlags;
4693 psh.phpage = PropertySheetHeader->phpage;
4694 psh.nPages = PropertySheetHeader->nPages;
4695
4696 ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
4697 PropertySheetHeaderPageListSize, RequiredSize,
4698 PropertySheetType);
4699 if (ret)
4700 {
4701 PropertySheetHeader->nPages = psh.nPages;
4702 }
4703
4704 TRACE("Returning %d\n", ret);
4705 return ret;
4706 }
4707
4708 struct ClassDevPropertySheetsData
4709 {
4710 HPROPSHEETPAGE *PropertySheetPages;
4711 DWORD MaximumNumberOfPages;
4712 DWORD NumberOfPages;
4713 };
4714
4715 static BOOL WINAPI
4716 GetClassDevPropertySheetsCallback(
4717 IN HPROPSHEETPAGE hPropSheetPage,
4718 IN OUT LPARAM lParam)
4719 {
4720 struct ClassDevPropertySheetsData *PropPageData;
4721
4722 PropPageData = (struct ClassDevPropertySheetsData *)lParam;
4723
4724 if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages)
4725 {
4726 *PropPageData->PropertySheetPages = hPropSheetPage;
4727 PropPageData->PropertySheetPages++;
4728 }
4729
4730 PropPageData->NumberOfPages++;
4731 return TRUE;
4732 }
4733
4734 /***********************************************************************
4735 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4736 */
4737 BOOL WINAPI
4738 SetupDiGetClassDevPropertySheetsW(
4739 IN HDEVINFO DeviceInfoSet,
4740 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4741 IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
4742 IN DWORD PropertySheetHeaderPageListSize,
4743 OUT PDWORD RequiredSize OPTIONAL,
4744 IN DWORD PropertySheetType)
4745 {
4746 struct DeviceInfoSet *list;
4747 BOOL ret = FALSE;
4748
4749 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
4750 PropertySheetHeader, PropertySheetHeaderPageListSize,
4751 RequiredSize, PropertySheetType);
4752
4753 if (!DeviceInfoSet)
4754 SetLastError(ERROR_INVALID_HANDLE);
4755 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4756 SetLastError(ERROR_INVALID_HANDLE);
4757 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4758 SetLastError(ERROR_INVALID_HANDLE);
4759 else if (!PropertySheetHeader)
4760 SetLastError(ERROR_INVALID_PARAMETER);
4761 else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
4762 SetLastError(ERROR_INVALID_FLAGS);
4763 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4764 SetLastError(ERROR_INVALID_USER_BUFFER);
4765 else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
4766 SetLastError(ERROR_INVALID_PARAMETER);
4767 else if (!PropertySheetHeader)
4768 SetLastError(ERROR_INVALID_PARAMETER);
4769 else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
4770 && PropertySheetType != DIGCDP_FLAG_BASIC
4771 && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
4772 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
4773 SetLastError(ERROR_INVALID_PARAMETER);
4774 else
4775 {
4776 HKEY hKey = INVALID_HANDLE_VALUE;
4777 SP_PROPSHEETPAGE_REQUEST Request;
4778 LPWSTR PropPageProvider = NULL;
4779 HMODULE hModule = NULL;
4780 PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
4781 struct ClassDevPropertySheetsData PropPageData;
4782 DWORD dwLength, dwRegType;
4783 DWORD rc;
4784
4785 if (DeviceInfoData)
4786 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
4787 else
4788 {
4789 hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
4790 DIOCR_INSTALLER, list->MachineName + 2, NULL);
4791 }
4792 if (hKey == INVALID_HANDLE_VALUE)
4793 goto cleanup;
4794
4795 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength);
4796 if (rc == ERROR_FILE_NOT_FOUND)
4797 {
4798 /* No registry key. As it is optional, don't say it's a bad error */
4799 if (RequiredSize)
4800 *RequiredSize = 0;
4801 ret = TRUE;
4802 goto cleanup;
4803 }
4804 else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
4805 {
4806 SetLastError(rc);
4807 goto cleanup;
4808 }
4809
4810 PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
4811 if (!PropPageProvider)
4812 {
4813 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4814 goto cleanup;
4815 }
4816 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
4817 if (rc != ERROR_SUCCESS)
4818 {
4819 SetLastError(rc);
4820 goto cleanup;
4821 }
4822 PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
4823
4824 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
4825 if (rc != ERROR_SUCCESS)
4826 {
4827 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
4828 goto cleanup;
4829 }
4830
4831 Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
4832 Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
4833 Request.DeviceInfoSet = DeviceInfoSet;
4834 Request.DeviceInfoData = DeviceInfoData;
4835 PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages];
4836 PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages;
4837 PropPageData.NumberOfPages = 0;
4838 ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
4839 if (!ret)
4840 goto cleanup;
4841
4842 if (RequiredSize)
4843 *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages;
4844 if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages)
4845 {
4846 PropertySheetHeader->nPages += PropPageData.NumberOfPages;
4847 ret = TRUE;
4848 }
4849 else
4850 {
4851 PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages;
4852 SetLastError(ERROR_INSUFFICIENT_BUFFER);
4853 }
4854
4855 cleanup:
4856 if (hKey != INVALID_HANDLE_VALUE)
4857 RegCloseKey(hKey);
4858 HeapFree(GetProcessHeap(), 0, PropPageProvider);
4859 FreeFunctionPointer(hModule, pPropPageProvider);
4860 }
4861
4862 TRACE("Returning %d\n", ret);
4863 return ret;
4864 }
4865
4866 /***********************************************************************
4867 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4868 */
4869 HKEY WINAPI
4870 SetupDiCreateDevRegKeyA(
4871 IN HDEVINFO DeviceInfoSet,
4872 IN PSP_DEVINFO_DATA DeviceInfoData,
4873 IN DWORD Scope,
4874 IN DWORD HwProfile,
4875 IN DWORD KeyType,
4876 IN HINF InfHandle OPTIONAL,
4877 IN PCSTR InfSectionName OPTIONAL)
4878 {
4879 PCWSTR InfSectionNameW = NULL;
4880 HKEY ret = INVALID_HANDLE_VALUE;
4881
4882 if (InfSectionName)
4883 {
4884 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
4885 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
4886 }
4887
4888 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
4889 DeviceInfoData,
4890 Scope,
4891 HwProfile,
4892 KeyType,
4893 InfHandle,
4894 InfSectionNameW);
4895
4896 if (InfSectionNameW != NULL)
4897 MyFree((PVOID)InfSectionNameW);
4898
4899 return ret;
4900 }
4901
4902 static HKEY
4903 OpenHardwareProfileKey(
4904 IN HKEY HKLM,
4905 IN DWORD HwProfile,
4906 IN DWORD samDesired)
4907 {
4908 HKEY hHWProfilesKey = NULL;
4909 HKEY hHWProfileKey = NULL;
4910 HKEY ret = INVALID_HANDLE_VALUE;
4911 LONG rc;
4912
4913 rc = RegOpenKeyExW(HKLM,
4914 REGSTR_PATH_HWPROFILES,
4915 0,
4916 0,
4917 &hHWProfilesKey);
4918 if (rc != ERROR_SUCCESS)
4919 {
4920 SetLastError(rc);
4921 goto cleanup;
4922 }
4923 if (HwProfile == 0)
4924 {
4925 rc = RegOpenKeyExW(
4926 hHWProfilesKey,
4927 REGSTR_KEY_CURRENT,
4928 0,
4929 KEY_CREATE_SUB_KEY,
4930 &hHWProfileKey);
4931 }
4932 else
4933 {
4934 WCHAR subKey[5];
4935 snprintfW(subKey, 4, L"%04lu", HwProfile);
4936 subKey[4] = '\0';
4937 rc = RegOpenKeyExW(
4938 hHWProfilesKey,
4939 subKey,
4940 0,
4941 KEY_CREATE_SUB_KEY,
4942 &hHWProfileKey);
4943 }
4944 if (rc != ERROR_SUCCESS)
4945 {
4946 SetLastError(rc);
4947 goto cleanup;
4948 }
4949 ret = hHWProfileKey;
4950
4951 cleanup:
4952 if (hHWProfilesKey != NULL)
4953 RegCloseKey(hHWProfilesKey);
4954 if (hHWProfileKey != NULL && hHWProfileKey != ret)
4955 RegCloseKey(hHWProfileKey);
4956 return ret;
4957 }
4958
4959 /***********************************************************************
4960 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4961 */
4962 HKEY WINAPI
4963 SetupDiCreateDevRegKeyW(
4964 IN HDEVINFO DeviceInfoSet,
4965 IN PSP_DEVINFO_DATA DeviceInfoData,
4966 IN DWORD Scope,
4967 IN DWORD HwProfile,
4968 IN DWORD KeyType,
4969 IN HINF InfHandle OPTIONAL,
4970 IN PCWSTR InfSectionName OPTIONAL)
4971 {
4972 struct DeviceInfoSet *list;
4973 HKEY ret = INVALID_HANDLE_VALUE;
4974
4975 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
4976 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
4977
4978 if (!DeviceInfoSet)
4979 SetLastError(ERROR_INVALID_HANDLE);
4980 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
4981 SetLastError(ERROR_INVALID_HANDLE);
4982 else if (!DeviceInfoData)
4983 SetLastError(ERROR_INVALID_PARAMETER);
4984 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4985 SetLastError(ERROR_INVALID_USER_BUFFER);
4986 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
4987 SetLastError(ERROR_INVALID_PARAMETER);
4988 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
4989 SetLastError(ERROR_INVALID_PARAMETER);
4990 else if (InfHandle && !InfSectionName)
4991 SetLastError(ERROR_INVALID_PARAMETER);
4992 else if (!InfHandle && InfSectionName)
4993 SetLastError(ERROR_INVALID_PARAMETER);
4994 else
4995 {
4996 LPWSTR lpGuidString = NULL;
4997 LPWSTR DriverKey = NULL; /* {GUID}\Index */
4998 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
4999 DWORD Index; /* Index used in the DriverKey name */
5000 DWORD rc;
5001 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
5002 HKEY hEnumKey = NULL;
5003 HKEY hClassKey = NULL;
5004 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
5005 HKEY hKey = NULL;
5006 HKEY RootKey;
5007
5008 if (Scope == DICS_FLAG_GLOBAL)
5009 RootKey = list->HKLM;
5010 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
5011 {
5012 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
5013 if (hHWProfileKey == INVALID_HANDLE_VALUE)
5014 goto cleanup;
5015 RootKey = hHWProfileKey;
5016 }
5017
5018 if (KeyType == DIREG_DEV)
5019 {
5020 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5021
5022 rc = RegCreateKeyExW(
5023 RootKey,
5024 REGSTR_PATH_SYSTEMENUM,
5025 0,
5026 NULL,
5027 REG_OPTION_NON_VOLATILE,
5028 KEY_CREATE_SUB_KEY,
5029 NULL,
5030 &hEnumKey,
5031 NULL);
5032 if (rc != ERROR_SUCCESS)
5033 {
5034 SetLastError(rc);
5035 goto cleanup;
5036 }
5037 rc = RegCreateKeyExW(
5038 hEnumKey,
5039 deviceInfo->DeviceName,
5040 0,
5041 NULL,
5042 REG_OPTION_NON_VOLATILE,
5043 #if _WIN32_WINNT >= 0x502
5044 KEY_READ | KEY_WRITE,
5045 #else
5046 KEY_ALL_ACCESS,
5047 #endif
5048 NULL,
5049 &hKey,
5050 NULL);
5051 if (rc != ERROR_SUCCESS)
5052 {
5053 SetLastError(rc);
5054 goto cleanup;
5055 }
5056 }
5057 else /* KeyType == DIREG_DRV */
5058 {
5059 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
5060 goto cleanup;
5061 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
5062 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
5063 if (!DriverKey)
5064 {
5065 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5066 goto cleanup;
5067 }
5068 strcpyW(DriverKey, L"{");
5069 strcatW(DriverKey, lpGuidString);
5070 strcatW(DriverKey, L"}\\");
5071 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
5072 rc = RegOpenKeyExW(RootKey,
5073 REGSTR_PATH_CLASS_NT,
5074 0,
5075 KEY_CREATE_SUB_KEY,
5076 &hClassKey);
5077 if (rc != ERROR_SUCCESS)
5078 {
5079 SetLastError(rc);
5080 goto cleanup;
5081 }
5082
5083 /* Try all values for Index between 0 and 9999 */
5084 Index = 0;
5085 while (Index <= 9999)
5086 {
5087 DWORD Disposition;
5088 wsprintf(pDeviceInstance, L"%04lu", Index);
5089 rc = RegCreateKeyEx(hClassKey,
5090 DriverKey,
5091 0,
5092 NULL,
5093 REG_OPTION_NON_VOLATILE,
5094 #if _WIN32_WINNT >= 0x502
5095 KEY_READ | KEY_WRITE,
5096 #else
5097 KEY_ALL_ACCESS,
5098 #endif
5099 NULL,
5100 &hKey,
5101 &Disposition);
5102 if (rc != ERROR_SUCCESS)
5103 {
5104 SetLastError(rc);
5105 goto cleanup;
5106 }
5107 if (Disposition == REG_CREATED_NEW_KEY)
5108 break;
5109 RegCloseKey(hKey);
5110 hKey = NULL;
5111 Index++;
5112 }
5113 if (Index > 9999)
5114 {
5115 /* Unable to create more than 9999 devices within the same class */
5116 SetLastError(ERROR_GEN_FAILURE);
5117 goto cleanup;
5118 }
5119
5120 /* Open device key, to write Driver value */
5121 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
5122 if (hDeviceKey == INVALID_HANDLE_VALUE)
5123 goto cleanup;
5124 rc = RegSetValueEx(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
5125 if (rc != ERROR_SUCCESS)
5126 {
5127 SetLastError(rc);
5128 goto cleanup;
5129 }
5130 }
5131
5132 /* Do installation of the specified section */
5133 if (InfHandle)
5134 {
5135 FIXME("Need to install section %s in file %p\n",
5136 debugstr_w(InfSectionName), InfHandle);
5137 }
5138 ret = hKey;
5139
5140 cleanup:
5141 if (lpGuidString)
5142 RpcStringFreeW(&lpGuidString);
5143 HeapFree(GetProcessHeap(), 0, DriverKey);
5144 if (hHWProfileKey != INVALID_HANDLE_VALUE)
5145 RegCloseKey(hHWProfileKey);
5146 if (hEnumKey != NULL)
5147 RegCloseKey(hEnumKey);
5148 if (hClassKey != NULL)
5149 RegCloseKey(hClassKey);
5150 if (hDeviceKey != INVALID_HANDLE_VALUE)
5151 RegCloseKey(hDeviceKey);
5152 if (hKey != NULL && hKey != ret)
5153 RegCloseKey(hKey);
5154 }
5155
5156 TRACE("Returning 0x%p\n", ret);
5157 return ret;
5158 }
5159
5160 /***********************************************************************
5161 * SetupDiOpenDevRegKey (SETUPAPI.@)
5162 */
5163 HKEY WINAPI
5164 SetupDiOpenDevRegKey(
5165 IN HDEVINFO DeviceInfoSet,
5166 IN PSP_DEVINFO_DATA DeviceInfoData,
5167 IN DWORD Scope,
5168 IN DWORD HwProfile,
5169 IN DWORD KeyType,
5170 IN REGSAM samDesired)
5171 {
5172 struct DeviceInfoSet *list;
5173 HKEY ret = INVALID_HANDLE_VALUE;
5174
5175 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
5176 Scope, HwProfile, KeyType, samDesired);
5177
5178 if (!DeviceInfoSet)
5179 SetLastError(ERROR_INVALID_HANDLE);
5180 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5181 SetLastError(ERROR_INVALID_HANDLE);
5182 else if (!DeviceInfoData)
5183 SetLastError(ERROR_INVALID_PARAMETER);
5184 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5185 SetLastError(ERROR_INVALID_USER_BUFFER);
5186 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
5187 SetLastError(ERROR_INVALID_PARAMETER);
5188 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
5189 SetLastError(ERROR_INVALID_PARAMETER);
5190 else
5191 {
5192 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5193 LPWSTR DriverKey = NULL;
5194 DWORD dwLength = 0;
5195 DWORD dwRegType;
5196 DWORD rc;
5197 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
5198 HKEY hEnumKey = NULL;
5199 HKEY hKey = NULL;
5200 HKEY RootKey;
5201
5202 if (Scope == DICS_FLAG_GLOBAL)
5203 RootKey = list->HKLM;
5204 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
5205 {
5206 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, 0);
5207 if (hHWProfileKey == INVALID_HANDLE_VALUE)
5208 goto cleanup;
5209 RootKey = hHWProfileKey;
5210 }
5211
5212 rc = RegOpenKeyExW(
5213 RootKey,
5214 REGSTR_PATH_SYSTEMENUM,
5215 0, /* Options */
5216 0,
5217 &hEnumKey);
5218 if (rc != ERROR_SUCCESS)
5219 {
5220 SetLastError(rc);
5221 goto cleanup;
5222 }
5223 rc = RegOpenKeyExW(
5224 hEnumKey,
5225 deviceInfo->DeviceName,
5226 0, /* Options */
5227 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
5228 &hKey);
5229 RegCloseKey(hEnumKey);
5230 hEnumKey = NULL;
5231 if (rc != ERROR_SUCCESS)
5232 {
5233 SetLastError(rc);
5234 goto cleanup;
5235 }
5236 if (KeyType == DIREG_DEV)
5237 {
5238 /* We're done. Just return the hKey handle */
5239 ret = hKey;
5240 goto cleanup;
5241 }
5242 /* Read the 'Driver' key */
5243 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
5244 if (rc != ERROR_SUCCESS)
5245 {
5246 SetLastError(rc);
5247 goto cleanup;
5248 }
5249 else if (dwRegType != REG_SZ)
5250 {
5251 SetLastError(ERROR_GEN_FAILURE);
5252 goto cleanup;
5253 }
5254 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
5255 if (!DriverKey)
5256 {
5257 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5258 goto cleanup;
5259 }
5260 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
5261 if (rc != ERROR_SUCCESS)
5262 {
5263 SetLastError(rc);
5264 goto cleanup;
5265 }
5266 RegCloseKey(hKey);
5267 hKey = NULL;
5268 /* Need to open the driver key */
5269 rc = RegOpenKeyExW(
5270 RootKey,
5271 REGSTR_PATH_CLASS_NT,
5272 0, /* Options */
5273 0,
5274 &hEnumKey);
5275 if (rc != ERROR_SUCCESS)
5276 {
5277 SetLastError(rc);
5278 goto cleanup;
5279 }
5280 rc = RegOpenKeyExW(
5281 hEnumKey,
5282 DriverKey,
5283 0, /* Options */
5284 samDesired,
5285 &hKey);
5286 if (rc != ERROR_SUCCESS)
5287 {
5288 SetLastError(rc);
5289 goto cleanup;
5290 }
5291 ret = hKey;
5292
5293 cleanup:
5294 if (hHWProfileKey != INVALID_HANDLE_VALUE)
5295 RegCloseKey(hHWProfileKey);
5296 if (hEnumKey != NULL)
5297 RegCloseKey(hEnumKey);
5298 if (hKey != NULL && hKey != ret)
5299 RegCloseKey(hKey);
5300 }
5301
5302 TRACE("Returning 0x%p\n", ret);
5303 return ret;
5304 }
5305
5306 /***********************************************************************
5307 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5308 */
5309 BOOL WINAPI
5310 SetupDiCreateDeviceInfoA(
5311 IN HDEVINFO DeviceInfoSet,
5312 IN PCSTR DeviceName,
5313 IN CONST GUID *ClassGuid,
5314 IN PCSTR DeviceDescription OPTIONAL,
5315 IN HWND hwndParent OPTIONAL,
5316 IN DWORD CreationFlags,
5317 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5318 {
5319 LPWSTR DeviceNameW = NULL;
5320 LPWSTR DeviceDescriptionW = NULL;
5321 BOOL bResult;
5322
5323 TRACE("\n");
5324
5325 if (DeviceName)
5326 {
5327 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
5328 if (DeviceNameW == NULL) return FALSE;
5329 }
5330 if (DeviceDescription)
5331 {
5332 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
5333 if (DeviceDescriptionW == NULL)
5334 {
5335 if (DeviceNameW) MyFree(DeviceNameW);
5336 return FALSE;
5337 }
5338 }
5339
5340 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
5341 ClassGuid, DeviceDescriptionW,
5342 hwndParent, CreationFlags,
5343 DeviceInfoData);
5344
5345 if (DeviceNameW) MyFree(DeviceNameW);
5346 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
5347
5348 return bResult;
5349 }
5350
5351 /***********************************************************************
5352 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5353 */
5354 BOOL WINAPI
5355 SetupDiCreateDeviceInfoW(
5356 IN HDEVINFO DeviceInfoSet,
5357 IN PCWSTR DeviceName,
5358 IN CONST GUID *ClassGuid,
5359 IN PCWSTR DeviceDescription OPTIONAL,
5360 IN HWND hwndParent OPTIONAL,
5361 IN DWORD CreationFlags,
5362 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5363 {
5364 struct DeviceInfoSet *list;
5365 BOOL ret = FALSE;
5366
5367 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet, debugstr_w(DeviceName),
5368 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
5369 hwndParent, CreationFlags, DeviceInfoData);
5370
5371 if (!DeviceInfoSet)
5372 SetLastError(ERROR_INVALID_HANDLE);
5373 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5374 SetLastError(ERROR_INVALID_HANDLE);
5375 else if (!ClassGuid)
5376 SetLastError(ERROR_INVALID_PARAMETER);
5377 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
5378 SetLastError(ERROR_CLASS_MISMATCH);
5379 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
5380 {
5381 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
5382 SetLastError(ERROR_INVALID_FLAGS);
5383 }
5384 else
5385 {
5386 SP_DEVINFO_DATA DevInfo;
5387
5388 if (CreationFlags & DICD_GENERATE_ID)
5389 {
5390 /* Generate a new unique ID for this device */
5391 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5392 FIXME("not implemented\n");
5393 }
5394 else
5395 {
5396 /* Device name is fully qualified. Try to open it */
5397 BOOL rc;
5398
5399 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
5400 rc = SetupDiOpenDeviceInfoW(
5401 DeviceInfoSet,
5402 DeviceName,
5403 NULL, /* hwndParent */
5404 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
5405 &DevInfo);
5406
5407 if (rc)
5408 {
5409 /* SetupDiOpenDeviceInfoW has already added
5410 * the device info to the device info set
5411 */
5412 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
5413 }
5414 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
5415 {
5416 struct DeviceInfoElement *deviceInfo;
5417
5418 if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
5419 {
5420 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
5421
5422 if (!DeviceInfoData)
5423 ret = TRUE;
5424 else
5425 {
5426 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
5427 {
5428 SetLastError(ERROR_INVALID_USER_BUFFER);
5429 }
5430 else
5431 {
5432 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
5433 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
5434 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
5435 ret = TRUE;
5436 }
5437 }
5438 }
5439 }
5440 }
5441 }
5442
5443 TRACE("Returning %d\n", ret);
5444 return ret;
5445 }
5446
5447 /***********************************************************************
5448 * Helper functions for SetupDiBuildDriverInfoList
5449 */
5450 static BOOL
5451 AddDriverToList(
5452 IN PLIST_ENTRY DriverListHead,
5453 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5454 IN LPGUID ClassGuid,
5455 IN INFCONTEXT ContextDevice,
5456 IN struct InfFileDetails *InfFileDetails,
5457 IN LPCWSTR InfFile,
5458 IN LPCWSTR ProviderName,
5459 IN LPCWSTR ManufacturerName,
5460 IN LPCWSTR MatchingId,
5461 FILETIME DriverDate,
5462 DWORDLONG DriverVersion,
5463 IN DWORD Rank)
5464 {
5465 struct DriverInfoElement *driverInfo = NULL;
5466 HANDLE hFile = INVALID_HANDLE_VALUE;
5467 DWORD RequiredSize = 128; /* Initial buffer size */
5468 BOOL Result = FALSE;
5469 PLIST_ENTRY PreviousEntry;
5470 LPWSTR InfInstallSection = NULL;
5471 BOOL ret = FALSE;
5472
5473 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
5474 if (!driverInfo)
5475 {
5476 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5477 goto cleanup;
5478 }
5479 memset(driverInfo, 0, sizeof(struct DriverInfoElement));
5480
5481 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
5482 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
5483
5484 /* Copy InfFileName field */
5485 strncpyW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
5486 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
5487
5488 /* Fill InfDate field */
5489 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5490 GENERIC_READ, FILE_SHARE_READ,
5491 NULL, OPEN_EXISTING, 0, NULL);
5492 if (hFile == INVALID_HANDLE_VALUE)
5493 goto cleanup;
5494 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5495 if (!Result)
5496 goto cleanup;*/
5497
5498 /* Fill SectionName field */
5499 Result = SetupGetStringFieldW(
5500 &ContextDevice,
5501 1,
5502 driverInfo->Details.SectionName, LINE_LEN,
5503 NULL);
5504 if (!Result)
5505 goto cleanup;
5506
5507 /* Fill DrvDescription field */
5508 Result = SetupGetStringFieldW(
5509 &ContextDevice,
5510 0, /* Field index */
5511 driverInfo->Details.DrvDescription, LINE_LEN,
5512 NULL);
5513
5514 /* Copy MatchingId information */
5515 if (MatchingId)
5516 {
5517 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
5518 if (!driverInfo->MatchingId)
5519 {
5520 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5521 goto cleanup;
5522 }
5523 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
5524 }
5525 else
5526 driverInfo->MatchingId = NULL;
5527
5528 /* Get inf install section */
5529 Result = FALSE;
5530 RequiredSize = 128; /* Initial buffer size */
5531 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5532 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5533 {
5534 HeapFree(GetProcessHeap(), 0, InfInstallSection);
5535 InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5536 if (!InfInstallSection)
5537 goto cleanup;
5538 Result = SetupGetStringFieldW(
5539 &ContextDevice,
5540 1, /* Field index */
5541 InfInstallSection, RequiredSize,
5542 &RequiredSize);
5543 }
5544 if (!Result)
5545 goto cleanup;
5546
5547 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
5548 debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile),
5549 debugstr_w(InfInstallSection), Rank);
5550
5551 driverInfo->DriverRank = Rank;
5552 memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
5553 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
5554 driverInfo->Info.DriverType = DriverType;
5555 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
5556 strncpyW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
5557 driverInfo->Info.Description[LINE_LEN - 1] = '\0';
5558 strncpyW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
5559 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
5560 if (ProviderName)
5561 {
5562 strncpyW(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
5563 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
5564 }
5565 else
5566 driverInfo->Info.ProviderName[0] = '\0';
5567 driverInfo->Info.DriverDate = DriverDate;
5568 driverInfo->Info.DriverVersion = DriverVersion;
5569 ReferenceInfFile(InfFileDetails);
5570 driverInfo->InfFileDetails = InfFileDetails;
5571
5572 /* Insert current driver in driver list, according to its rank */
5573 PreviousEntry = DriverListHead->Flink;
5574 while (PreviousEntry != DriverListHead)
5575 {
5576 struct DriverInfoElement *CurrentDriver;
5577 CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
5578 if (CurrentDriver->DriverRank > Rank ||
5579 (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
5580 {
5581 /* Insert before the current item */
5582 InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
5583 break;
5584 }
5585 PreviousEntry = PreviousEntry->Flink;
5586 }
5587 if (PreviousEntry == DriverListHead)
5588 {
5589 /* Insert at the end of the list */
5590 InsertTailList(DriverListHead, &driverInfo->ListEntry);
5591 }
5592
5593 ret = TRUE;
5594
5595 cleanup:
5596 if (!ret)
5597 {
5598 if (driverInfo)
5599 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
5600 HeapFree(GetProcessHeap(), 0, driverInfo);
5601 }
5602 if (hFile != INVALID_HANDLE_VALUE)
5603 CloseHandle(hFile);
5604 HeapFree(GetProcessHeap(), 0, InfInstallSection);
5605
5606 return ret;
5607 }
5608
5609 static BOOL
5610 GetVersionInformationFromInfFile(
5611 IN HINF hInf,
5612 OUT LPGUID ClassGuid,
5613 OUT LPWSTR* pProviderName,
5614 OUT FILETIME* DriverDate,
5615 OUT DWORDLONG* DriverVersion)
5616 {
5617 DWORD RequiredSize;
5618 WCHAR guidW[MAX_GUID_STRING_LEN + 1];
5619 LPWSTR DriverVer = NULL;
5620 LPWSTR ProviderName = NULL;
5621 LPWSTR pComma; /* Points into DriverVer */
5622 LPWSTR pVersion = NULL; /* Points into DriverVer */
5623 SYSTEMTIME SystemTime;
5624 BOOL Result;
5625 BOOL ret = FALSE; /* Final result */
5626
5627 /* Get class Guid */
5628 if (!SetupGetLineTextW(
5629 NULL, /* Context */
5630 hInf,
5631 Version, ClassGUID,
5632 guidW, sizeof(guidW),
5633 NULL /* Required size */))
5634 {
5635 goto cleanup;
5636 }
5637 guidW[37] = '\0'; /* Replace the } by a NULL character */
5638 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
5639 {
5640 SetLastError(ERROR_GEN_FAILURE);
5641 goto cleanup;
5642 }
5643
5644 /* Get provider name */
5645 Result = SetupGetLineTextW(
5646 NULL, /* Context */
5647 hInf, Version, INF_PROVIDER,
5648 NULL, 0,
5649 &RequiredSize);
5650 if (Result)
5651 {
5652 /* We know know the needed buffer size */
5653 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5654 if (!ProviderName)
5655 {
5656 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5657 goto cleanup;
5658 }
5659 Result = SetupGetLineTextW(
5660 NULL, /* Context */
5661 hInf, Version, INF_PROVIDER,
5662 ProviderName, RequiredSize,
5663 &RequiredSize);
5664 }
5665 if (!Result)
5666 goto cleanup;
5667 *pProviderName = ProviderName;
5668
5669 /* Read the "DriverVer" value */
5670 Result = SetupGetLineTextW(
5671 NULL, /* Context */
5672 hInf, Version, INF_DRIVER_VER,
5673 NULL, 0,
5674 &RequiredSize);
5675 if (Result)
5676 {
5677 /* We know know the needed buffer size */
5678 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5679 if (!DriverVer)
5680 {
5681 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5682 goto cleanup;
5683 }
5684 Result = SetupGetLineTextW(
5685 NULL, /* Context */
5686 hInf, Version, INF_DRIVER_VER,
5687 DriverVer, RequiredSize,
5688 &RequiredSize);
5689 }
5690 if (!Result)
5691 goto cleanup;
5692
5693 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5694 pComma = strchrW(DriverVer, ',');
5695 if (pComma != NULL)
5696 {
5697 *pComma = UNICODE_NULL;
5698 pVersion = pComma + 1;
5699 }
5700 /* Get driver date version. Invalid date = 00/00/00 */
5701 memset(DriverDate, 0, sizeof(FILETIME));
5702 if (strlenW(DriverVer) == 10
5703 && (DriverVer[2] == '-' || DriverVer[2] == '/')
5704 && (DriverVer[5] == '-' || DriverVer[5] == '/'))
5705 {
5706 memset(&SystemTime, 0, sizeof(SYSTEMTIME));
5707 DriverVer[2] = DriverVer[5] = UNICODE_NULL;
5708 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
5709 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
5710 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
5711 SystemTimeToFileTime(&SystemTime, DriverDate);
5712 }
5713 /* Get driver version. Invalid version = 0.0.0.0 */
5714 *DriverVersion = 0;
5715 if (pVersion)
5716 {
5717 WORD Major, Minor = 0, Revision = 0, Build = 0;
5718 LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
5719 LARGE_INTEGER fullVersion;
5720
5721 pMinor = strchrW(pVersion, '.');
5722 if (pMinor)
5723 {
5724 *pMinor = 0;
5725 pRevision = strchrW(++pMinor, '.');
5726 Minor = atoiW(pMinor);
5727 }
5728 if (pRevision)
5729 {
5730 *pRevision = 0;
5731 pBuild = strchrW(++pRevision, '.');
5732 Revision = atoiW(pRevision);
5733 }
5734 if (pBuild)
5735 {
5736 *pBuild = 0;
5737 pBuild++;
5738 Build = atoiW(pBuild);
5739 }
5740 Major = atoiW(pVersion);
5741 fullVersion.u.HighPart = Major << 16 | Minor;
5742 fullVersion.u.LowPart = Revision << 16 | Build;
5743 memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
5744 }
5745
5746 ret = TRUE;
5747
5748 cleanup:
5749 if (!ret)
5750 HeapFree(GetProcessHeap(), 0, ProviderName);
5751 HeapFree(GetProcessHeap(), 0, DriverVer);
5752
5753 return ret;
5754 }
5755
5756 static BOOL
5757 GetHardwareAndCompatibleIDsLists(
5758 IN HDEVINFO DeviceInfoSet,
5759 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
5760 OUT LPWSTR *pHardwareIDs OPTIONAL,
5761 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL,
5762 OUT LPWSTR *pCompatibleIDs OPTIONAL,
5763 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL)
5764 {
5765 LPWSTR HardwareIDs = NULL;
5766 LPWSTR CompatibleIDs = NULL;
5767 DWORD RequiredSize;
5768 BOOL Result;
5769
5770 /* Get hardware IDs list */
5771 Result = FALSE;
5772 RequiredSize = 512; /* Initial buffer size */
5773 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5774 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5775 {
5776 MyFree(HardwareIDs);
5777 HardwareIDs = MyMalloc(RequiredSize);
5778 if (!HardwareIDs)
5779 {
5780 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5781 goto done;
5782 }
5783 Result = SetupDiGetDeviceRegistryPropertyW(
5784 DeviceInfoSet,
5785 DeviceInfoData,
5786 SPDRP_HARDWAREID,
5787 NULL,
5788 (PBYTE)HardwareIDs,
5789 RequiredSize,
5790 &RequiredSize);
5791 }
5792 if (!Result)
5793 {
5794 if (GetLastError() == ERROR_FILE_NOT_FOUND)
5795 {
5796 /* No hardware ID for this device */
5797 MyFree(HardwareIDs);
5798 HardwareIDs = NULL;
5799 RequiredSize = 0;
5800 }
5801 else
5802 goto done;
5803 }
5804 if (pHardwareIDs)
5805 *pHardwareIDs = HardwareIDs;
5806 if (pHardwareIDsRequiredSize)
5807 *pHardwareIDsRequiredSize = RequiredSize;
5808
5809 /* Get compatible IDs list */
5810 Result = FALSE;
5811 RequiredSize = 512; /* Initial buffer size */
5812 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5813 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5814 {
5815 MyFree(CompatibleIDs);
5816 CompatibleIDs = MyMalloc(RequiredSize);
5817 if (!CompatibleIDs)
5818 {
5819 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5820 goto done;
5821 }
5822 Result = SetupDiGetDeviceRegistryPropertyW(
5823 DeviceInfoSet,
5824 DeviceInfoData,
5825 SPDRP_COMPATIBLEIDS,
5826 NULL,
5827 (PBYTE)CompatibleIDs,
5828 RequiredSize,
5829 &RequiredSize);
5830 }
5831 if (!Result)
5832 {
5833 if (GetLastError() == ERROR_FILE_NOT_FOUND)
5834 {
5835 /* No compatible ID for this device */
5836 MyFree(CompatibleIDs);
5837 CompatibleIDs = NULL;
5838 RequiredSize = 0;
5839 }
5840 else
5841 goto done;
5842 }
5843 if (pCompatibleIDs)
5844 *pCompatibleIDs = CompatibleIDs;
5845 if (pCompatibleIDsRequiredSize)
5846 *pCompatibleIDsRequiredSize = RequiredSize;
5847
5848 Result = TRUE;
5849
5850 done:
5851 if (!Result)
5852 {
5853 MyFree(HardwareIDs);
5854 MyFree(CompatibleIDs);
5855 }
5856 return Result;
5857 }
5858
5859 static struct InfFileDetails *
5860 CreateInfFileDetails(
5861 IN LPCWSTR InfFileName)
5862 {
5863 struct InfFileDetails *details;
5864 PWCHAR last;
5865 DWORD Needed;
5866
5867 last = strrchrW(InfFileName, '\\');
5868 Needed = FIELD_OFFSET(struct InfFileDetails, szData)
5869 + strlenW(InfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
5870 if (last != NULL)
5871 Needed += (last - InfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
5872
5873 details = HeapAlloc(GetProcessHeap(), 0, Needed);
5874 if (!details)
5875 {
5876 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5877 return NULL;
5878 }
5879
5880 memset(details, 0, Needed);
5881 if (last)
5882 {
5883 details->DirectoryName = details->szData;
5884 details->FullInfFileName = &details->szData[last - InfFileName + 1];
5885 strncpyW(details->DirectoryName, InfFileName, last - InfFileName);
5886 }
5887 else
5888 details->FullInfFileName = details->szData;
5889 strcpyW(details->FullInfFileName, InfFileName);
5890 ReferenceInfFile(details);
5891 details->hInf = SetupOpenInfFileW(InfFileName, NULL, INF_STYLE_WIN4, NULL);
5892 if (details->hInf == INVALID_HANDLE_VALUE)
5893 {
5894 HeapFree(GetProcessHeap(), 0, details);
5895 return NULL;
5896 }
5897 return details;
5898 }
5899
5900 /***********************************************************************
5901 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5902 */
5903 BOOL WINAPI
5904 SetupDiBuildDriverInfoList(
5905 IN HDEVINFO DeviceInfoSet,
5906 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
5907 IN DWORD DriverType)
5908 {
5909 struct DeviceInfoSet *list;
5910 SP_DEVINSTALL_PARAMS_W InstallParams;
5911 PVOID Buffer = NULL;
5912 struct InfFileDetails *currentInfFileDetails = NULL;
5913 LPWSTR ProviderName = NULL;
5914 LPWSTR ManufacturerName = NULL;
5915 WCHAR ManufacturerSection[LINE_LEN + 1];
5916 LPWSTR HardwareIDs = NULL;
5917 LPWSTR CompatibleIDs = NULL;
5918 LPWSTR FullInfFileName = NULL;
5919 LPWSTR ExcludeFromSelect = NULL;
5920 FILETIME DriverDate;
5921 DWORDLONG DriverVersion = 0;
5922 DWORD RequiredSize;
5923 BOOL ret = FALSE;
5924
5925 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
5926
5927 if (!DeviceInfoSet)
5928 SetLastError(ERROR_INVALID_HANDLE);
5929 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
5930 SetLastError(ERROR_INVALID_HANDLE);
5931 else if (list->HKLM != HKEY_LOCAL_MACHINE)
5932 SetLastError(ERROR_INVALID_HANDLE);
5933 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
5934 SetLastError(ERROR_INVALID_PARAMETER);
5935 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
5936 SetLastError(ERROR_INVALID_PARAMETER);
5937 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5938 SetLastError(ERROR_INVALID_USER_BUFFER);
5939 else
5940 {
5941 PLIST_ENTRY pDriverListHead = &list->DriverListHead;
5942 BOOL Result;
5943
5944 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5945 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5946 if (!Result)
5947 goto done;
5948
5949 if (DeviceInfoData)
5950 {
5951 struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
5952 if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
5953 pDriverListHead = &devInfo->DriverListHead;
5954 }
5955
5956 if (DriverType == SPDIT_COMPATDRIVER)
5957 {
5958 /* Get hardware and compatible IDs lists */
5959 Result = GetHardwareAndCompatibleIDsLists(
5960 DeviceInfoSet,
5961 DeviceInfoData,
5962 &HardwareIDs,
5963 NULL,
5964 &CompatibleIDs,
5965 NULL);
5966 if (!Result)
5967 goto done;
5968 if (!HardwareIDs && !CompatibleIDs)
5969 {
5970 SetLastError(ERROR_FILE_NOT_FOUND);
5971 goto done;
5972 }
5973 }
5974
5975 if (InstallParams.Flags & DI_ENUMSINGLEINF)
5976 {
5977 /* InstallParams.DriverPath contains the name of a .inf file */
5978 RequiredSize = strlenW(InstallParams.DriverPath) + 2;
5979 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5980 if (!Buffer)
5981 {
5982 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5983 goto done;
5984 }
5985 strcpyW(Buffer, InstallParams.DriverPath);
5986 ((LPWSTR)Buffer)[RequiredSize - 1] = 0;
5987 Result = TRUE;
5988 }
5989 else
5990 {
5991 /* Enumerate .inf files */
5992 Result = FALSE;
5993 RequiredSize = 32768; /* Initial buffer size */
5994 SetLastError(ERROR_INSUFFICIENT_BUFFER);
5995 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
5996 {
5997 HeapFree(GetProcessHeap(), 0, Buffer);
5998 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
5999 if (!Buffer)
6000 {
6001 Result = FALSE;
6002 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6003 break;
6004 }
6005 Result = SetupGetInfFileListW(
6006 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
6007 INF_STYLE_WIN4,
6008 Buffer, RequiredSize,
6009 &RequiredSize);
6010 }
6011 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
6012 {
6013 /* No .inf file in specified directory. So, we should
6014 * success as we created an empty driver info list.
6015 */
6016 ret = TRUE;
6017 goto done;
6018 }
6019 }
6020 if (Result)
6021 {
6022 LPCWSTR filename;
6023 LPWSTR pFullFilename;
6024
6025 if (InstallParams.Flags & DI_ENUMSINGLEINF)
6026 {
6027 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
6028 if (!FullInfFileName)
6029 goto done;
6030 pFullFilename = &FullInfFileName[0];
6031 }
6032 else if (*InstallParams.DriverPath)
6033 {
6034 DWORD len;
6035 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
6036 if (len == 0)
6037 goto done;
6038 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
6039 if (!FullInfFileName)
6040 goto done;
6041 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
6042 if (len == 0)
6043 goto done;
6044 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\')
6045 strcatW(FullInfFileName, L"\\");
6046 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)];
6047 }
6048 else
6049 {
6050 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
6051 if (!FullInfFileName)
6052 goto done;
6053 pFullFilename = &FullInfFileName[0];
6054 }
6055
6056 for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1)
6057 {
6058 INFCONTEXT ContextManufacturer, ContextDevice;
6059 GUID ClassGuid;
6060
6061 strcpyW(pFullFilename, filename);
6062 TRACE("Opening file %s\n", debugstr_w(FullInfFileName));
6063
6064 currentInfFileDetails = CreateInfFileDetails(FullInfFileName);
6065 if (!currentInfFileDetails)
6066 continue;
6067
6068 if (!GetVersionInformationFromInfFile(
6069 currentInfFileDetails->hInf,
6070 &ClassGuid,
6071 &ProviderName,
6072 &DriverDate,
6073 &DriverVersion))
6074 {
6075 DereferenceInfFile(currentInfFileDetails);
6076 currentInfFileDetails = NULL;
6077 continue;
6078 }
6079
6080 if (DriverType == SPDIT_CLASSDRIVER)
6081 {
6082 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
6083 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
6084 {
6085 goto next;
6086 }
6087 }
6088
6089 if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS)
6090 {
6091 /* Read ExcludeFromSelect control flags */
6092 /* FIXME */
6093 }
6094 else
6095 FIXME("ExcludeFromSelect list ignored\n");
6096
6097 /* Get the manufacturers list */
6098 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer);
6099 while (Result)
6100 {
6101 Result = SetupGetStringFieldW(
6102 &ContextManufacturer,
6103 0, /* Field index */
6104 NULL, 0,
6105 &RequiredSize);
6106 if (Result)
6107 {
6108 /* We got the needed size for the buffer */
6109 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
6110 if (!ManufacturerName)
6111 {
6112 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6113 goto done;
6114 }
6115 Result = SetupGetStringFieldW(
6116 &ContextManufacturer,
6117 0, /* Field index */
6118 ManufacturerName, RequiredSize,
6119 &RequiredSize);
6120 }
6121 /* Get manufacturer section name */
6122 Result = SetupGetStringFieldW(
6123 &ContextManufacturer,
6124 1, /* Field index */
6125 ManufacturerSection, LINE_LEN,
6126 &RequiredSize);
6127 if (Result)
6128 {
6129 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
6130 /* Add (possible) extension to manufacturer section name */
6131 Result = SetupDiGetActualSectionToInstallW(
6132 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
6133 if (Result)
6134 {
6135 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection));
6136 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
6137 }
6138 }
6139 while (Result)
6140 {
6141 if (DriverType == SPDIT_CLASSDRIVER)
6142 {
6143 /* FIXME: Check ExcludeFromSelect list */
6144 if (!AddDriverToList(
6145 pDriverListHead,
6146 DriverType,
6147 &ClassGuid,
6148 ContextDevice,
6149 currentInfFileDetails,
6150 FullInfFileName,
6151 ProviderName,
6152 ManufacturerName,
6153 NULL,
6154 DriverDate, DriverVersion,
6155 0))
6156 {
6157 break;
6158 }
6159 }
6160 else /* DriverType = SPDIT_COMPATDRIVER */
6161 {
6162 /* 1. Get all fields */
6163 DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
6164 DWORD DriverRank;
6165 DWORD i;
6166 LPCWSTR currentId;
6167 BOOL DriverAlreadyAdded;
6168
6169 for (i = 2; i <= FieldCount; i++)
6170 {
6171 LPWSTR DeviceId = NULL;
6172 Result = FALSE;
6173 RequiredSize = 128; /* Initial buffer size */
6174 SetLastError(ERROR_INSUFFICIENT_BUFFER);
6175 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
6176 {
6177 HeapFree(GetProcessHeap(), 0, DeviceId);
6178 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
6179 if (!DeviceId)
6180 {
6181 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
6182 goto done;
6183 }
6184 Result = SetupGetStringFieldW(
6185 &ContextDevice,
6186 i,
6187 DeviceId, RequiredSize,
6188 &RequiredSize);
6189 }
6190 if (!Result)
6191 {
6192 HeapFree(GetProcessHeap(), 0, DeviceId);
6193 goto done;
6194 }
6195 /* FIXME: Check ExcludeFromSelect list */
6196 DriverAlreadyAdded = FALSE;
6197 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
6198 {
6199 if (strcmpiW(DeviceId, currentId) == 0)
6200 {
6201 AddDriverToList(
6202 pDriverListHead,
6203 DriverType,
6204 &ClassGuid,
6205 ContextDevice,
6206 currentInfFileDetails,
6207 FullInfFileName,
6208 ProviderName,
6209 ManufacturerName,
6210 currentId,
6211 DriverDate, DriverVersion,
6212 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
6213 DriverAlreadyAdded = TRUE;
6214 }
6215 }
6216 if (CompatibleIDs)
6217 {
6218 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
6219 {
6220 if (strcmpiW(DeviceId, currentId) == 0)
6221 {
6222 AddDriverToList(
6223 pDriverListHead,
6224 DriverType,
6225 &ClassGuid,
6226 ContextDevice,
6227 currentInfFileDetails,
6228 FullInfFileName,
6229 ProviderName,
6230 ManufacturerName,
6231 currentId,
6232 DriverDate, DriverVersion,
6233 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
6234 DriverAlreadyAdded = TRUE;
6235 }
6236 }
6237 }
6238 HeapFree(GetProcessHeap(), 0, DeviceId);
6239 }
6240 }
6241 Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
6242 }
6243
6244 HeapFree(GetProcessHeap(), 0, ManufacturerName);
6245 ManufacturerName = NULL;
6246 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
6247 }
6248
6249 ret = TRUE;
6250 next:
6251 HeapFree(GetProcessHeap(), 0, ProviderName);
6252 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
6253 ProviderName = ExcludeFromSelect = NULL;
6254
6255 DereferenceInfFile(currentInfFileDetails);
6256 currentInfFileDetails = NULL;
6257 }
6258 ret = TRUE;
6259 }
6260 }
6261
6262 done:
6263 if (ret)
6264 {
6265 if (DeviceInfoData)
6266 {
6267 InstallParams.Flags |= DI_DIDCOMPAT;
6268 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
6269 }
6270 else
6271 {
6272 InstallParams.Flags |= DI_DIDCLASS;
6273 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
6274 }
6275 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6276 }
6277
6278 HeapFree(GetProcessHeap(), 0, ProviderName);
6279 HeapFree(GetProcessHeap(), 0, ManufacturerName);
6280 MyFree(HardwareIDs);
6281 MyFree(CompatibleIDs);
6282 HeapFree(GetProcessHeap(), 0, FullInfFileName);
6283 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
6284 if (currentInfFileDetails)
6285 DereferenceInfFile(currentInfFileDetails);
6286 HeapFree(GetProcessHeap(), 0, Buffer);
6287
6288 TRACE("Returning %d\n", ret);
6289 return ret;
6290 }
6291
6292 /***********************************************************************
6293 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
6294 */
6295 BOOL WINAPI
6296 SetupDiDeleteDeviceInfo(
6297 IN HDEVINFO DeviceInfoSet,
6298 IN PSP_DEVINFO_DATA DeviceInfoData)
6299 {
6300 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6301
6302 FIXME("not implemented\n");
6303 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
6304 return FALSE;
6305 }
6306
6307
6308 /***********************************************************************
6309 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
6310 */
6311 BOOL WINAPI
6312 SetupDiDestroyDriverInfoList(
6313 IN HDEVINFO DeviceInfoSet,
6314 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6315 IN DWORD DriverType)
6316 {
6317 struct DeviceInfoSet *list;
6318 BOOL ret = FALSE;
6319
6320 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
6321
6322 if (!DeviceInfoSet)
6323 SetLastError(ERROR_INVALID_HANDLE);
6324 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6325 SetLastError(ERROR_INVALID_HANDLE);
6326 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
6327 SetLastError(ERROR_INVALID_PARAMETER);
6328 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
6329 SetLastError(ERROR_INVALID_PARAMETER);
6330 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6331 SetLastError(ERROR_INVALID_USER_BUFFER);
6332 else
6333 {
6334 PLIST_ENTRY ListEntry;
6335 struct DriverInfoElement *driverInfo;
6336 SP_DEVINSTALL_PARAMS_W InstallParams;
6337
6338 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6339 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
6340 goto done;
6341
6342 if (!DeviceInfoData)
6343 /* Fall back to destroying class driver list */
6344 DriverType = SPDIT_CLASSDRIVER;
6345
6346 if (DriverType == SPDIT_CLASSDRIVER)
6347 {
6348 while (!IsListEmpty(&list->DriverListHead))
6349 {
6350 ListEntry = RemoveHeadList(&list->DriverListHead);
6351 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
6352 DestroyDriverInfoElement(driverInfo);
6353 }
6354 InstallParams.Reserved = 0;
6355 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
6356 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
6357 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
6358 }
6359 else
6360 {
6361 SP_DEVINSTALL_PARAMS_W InstallParamsSet;
6362 struct DeviceInfoElement *deviceInfo;
6363
6364 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6365 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
6366 goto done;
6367 deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6368 while (!IsListEmpty(&deviceInfo->DriverListHead))
6369 {
6370 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
6371 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
6372 if ((PVOID)InstallParamsSet.Reserved == driverInfo)
6373 {
6374 InstallParamsSet.Reserved = 0;
6375 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
6376 }
6377 DestroyDriverInfoElement(driverInfo);
6378 }
6379 InstallParams.Reserved = 0;
6380 InstallParams.Flags &= ~DI_DIDCOMPAT;
6381 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
6382 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
6383 }
6384 }
6385
6386 done:
6387 TRACE("Returning %d\n", ret);
6388 return ret;
6389 }
6390
6391
6392 /***********************************************************************
6393 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6394 */
6395 BOOL WINAPI
6396 SetupDiOpenDeviceInfoA(
6397 IN HDEVINFO DeviceInfoSet,
6398 IN PCSTR DeviceInstanceId,
6399 IN HWND hwndParent OPTIONAL,
6400 IN DWORD OpenFlags,
6401 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6402 {
6403 LPWSTR DeviceInstanceIdW = NULL;
6404 BOOL bResult;
6405
6406 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
6407
6408 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
6409 if (DeviceInstanceIdW == NULL)
6410 return FALSE;
6411
6412 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
6413 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
6414
6415 MyFree(DeviceInstanceIdW);
6416
6417 return bResult;
6418 }
6419
6420
6421 /***********************************************************************
6422 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6423 */
6424 BOOL WINAPI
6425 SetupDiOpenDeviceInfoW(
6426 IN HDEVINFO DeviceInfoSet,
6427 IN PCWSTR DeviceInstanceId,
6428 IN HWND hwndParent OPTIONAL,
6429 IN DWORD OpenFlags,
6430 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
6431 {
6432 struct DeviceInfoSet *list;
6433 HKEY hEnumKey, hKey = NULL;
6434 DWORD rc;
6435 BOOL ret = FALSE;
6436
6437 TRACE("%p %s %p %lx %p\n",
6438 DeviceInfoSet, debugstr_w(DeviceInstanceId),
6439 hwndParent, OpenFlags, DeviceInfoData);
6440
6441 if (OpenFlags & DIOD_CANCEL_REMOVE)
6442 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6443
6444 if (!DeviceInfoSet)
6445 SetLastError(ERROR_INVALID_HANDLE);
6446 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6447 SetLastError(ERROR_INVALID_HANDLE);
6448 else if (!DeviceInstanceId)
6449 SetLastError(ERROR_INVALID_PARAMETER);
6450 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
6451 {
6452 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
6453 SetLastError(ERROR_INVALID_FLAGS);
6454 }
6455 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6456 SetLastError(ERROR_INVALID_USER_BUFFER);
6457 else
6458 {
6459 struct DeviceInfoElement *deviceInfo = NULL;
6460 /* Search if device already exists in DeviceInfoSet.
6461 * If yes, return the existing element
6462 * If no, create a new element using informations in registry
6463 */
6464 PLIST_ENTRY ItemList = list->ListHead.Flink;
6465 while (ItemList != &list->ListHead)
6466 {
6467 // TODO
6468 //if (good one)
6469 // break;
6470 FIXME("not implemented\n");
6471 ItemList = ItemList->Flink;
6472 }
6473
6474 if (deviceInfo)
6475 {
6476 /* good one found */
6477 ret = TRUE;
6478 }
6479 else
6480 {
6481 /* Open supposed registry key */
6482 rc = RegOpenKeyExW(
6483 list->HKLM,
6484 REGSTR_PATH_SYSTEMENUM,
6485 0, /* Options */
6486 0,
6487 &hEnumKey);
6488 if (rc != ERROR_SUCCESS)
6489 {
6490 SetLastError(rc);
6491 goto cleanup;
6492 }
6493 rc = RegOpenKeyExW(
6494 hEnumKey,
6495 DeviceInstanceId,
6496 0, /* Options */
6497 KEY_QUERY_VALUE,
6498 &hKey);
6499 RegCloseKey(hEnumKey);
6500 if (rc != ERROR_SUCCESS)
6501 {
6502 if (rc == ERROR_FILE_NOT_FOUND)
6503 rc = ERROR_NO_SUCH_DEVINST;
6504 SetLastError(rc);
6505 goto cleanup;
6506 }
6507
6508 /* FIXME: try to get ClassGUID from registry, instead of
6509 * sending GUID_NULL to CreateDeviceInfoElement
6510 */
6511 if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
6512 goto cleanup;
6513 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
6514
6515 ret = TRUE;
6516 }
6517
6518 if (ret && deviceInfo && DeviceInfoData)
6519 {
6520 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
6521 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
6522 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
6523 }
6524 }
6525
6526 cleanup:
6527 if (hKey != NULL)
6528 RegCloseKey(hKey);
6529 return ret;
6530 }
6531
6532
6533 /***********************************************************************
6534 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6535 */
6536 BOOL WINAPI
6537 SetupDiEnumDriverInfoA(
6538 IN HDEVINFO DeviceInfoSet,
6539 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6540 IN DWORD DriverType,
6541 IN DWORD MemberIndex,
6542 OUT PSP_DRVINFO_DATA_A DriverInfoData)
6543 {
6544 SP_DRVINFO_DATA_V2_W driverInfoData2W;
6545 BOOL ret = FALSE;
6546
6547 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
6548 DriverType, MemberIndex, DriverInfoData);
6549
6550 if (DriverInfoData == NULL)
6551 SetLastError(ERROR_INVALID_PARAMETER);
6552 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
6553 SetLastError(ERROR_INVALID_USER_BUFFER);
6554 else
6555 {
6556 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
6557 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
6558 DriverType, MemberIndex, &driverInfoData2W);
6559
6560 if (ret)
6561 {
6562 /* Do W->A conversion */
6563 DriverInfoData->DriverType = driverInfoData2W.DriverType;
6564 DriverInfoData->Reserved = driverInfoData2W.Reserved;
6565 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
6566 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
6567 {
6568 DriverInfoData->Description[0] = '\0';
6569 ret = FALSE;
6570 }
6571 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
6572 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
6573 {
6574 DriverInfoData->MfgName[0] = '\0';
6575 ret = FALSE;
6576 }
6577 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
6578 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
6579 {
6580 DriverInfoData->ProviderName[0] = '\0';
6581 ret = FALSE;
6582 }
6583 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
6584 {
6585 /* Copy more fields */
6586 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
6587 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
6588 }
6589 }
6590 }
6591
6592 TRACE("Returning %d\n", ret);
6593 return ret;
6594 }
6595
6596
6597 /***********************************************************************
6598 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6599 */
6600 BOOL WINAPI
6601 SetupDiEnumDriverInfoW(
6602 IN HDEVINFO DeviceInfoSet,
6603 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6604 IN DWORD DriverType,
6605 IN DWORD MemberIndex,
6606 OUT PSP_DRVINFO_DATA_W DriverInfoData)
6607 {
6608 PLIST_ENTRY ListHead;
6609 BOOL ret = FALSE;
6610
6611 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
6612 DriverType, MemberIndex, DriverInfoData);
6613
6614 if (!DeviceInfoSet || !DriverInfoData)
6615 SetLastError(ERROR_INVALID_PARAMETER);
6616 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6617 SetLastError(ERROR_INVALID_HANDLE);
6618 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6619 SetLastError(ERROR_INVALID_HANDLE);
6620 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
6621 SetLastError(ERROR_INVALID_PARAMETER);
6622 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
6623 SetLastError(ERROR_INVALID_PARAMETER);
6624 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6625 SetLastError(ERROR_INVALID_USER_BUFFER);
6626 else
6627 {
6628 struct DeviceInfoElement *devInfo = NULL;
6629 PLIST_ENTRY ItemList;
6630 if (DeviceInfoData)
6631 devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6632 if (!devInfo || (devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
6633 {
6634 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
6635 }
6636 else
6637 {
6638 ListHead = &devInfo->DriverListHead;
6639 }
6640
6641 ItemList = ListHead->Flink;
6642 while (ItemList != ListHead && MemberIndex-- > 0)
6643 ItemList = ItemList->Flink;
6644 if (ItemList == ListHead)
6645 SetLastError(ERROR_NO_MORE_ITEMS);
6646 else
6647 {
6648 struct DriverInfoElement *DrvInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
6649
6650 memcpy(
6651 &DriverInfoData->DriverType,
6652 &DrvInfo->Info.DriverType,
6653 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
6654 ret = TRUE;
6655 }
6656 }
6657
6658 TRACE("Returning %d\n", ret);
6659 return ret;
6660 }
6661
6662
6663 /***********************************************************************
6664 * SetupDiGetSelectedDevice (SETUPAPI.@)
6665 */
6666 BOOL WINAPI
6667 SetupDiGetSelectedDevice(
6668 IN HDEVINFO DeviceInfoSet,
6669 OUT PSP_DEVINFO_DATA DeviceInfoData)
6670 {
6671 struct DeviceInfoSet *list;
6672 BOOL ret = FALSE;
6673
6674 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6675
6676 if (!DeviceInfoSet)
6677 SetLastError(ERROR_INVALID_HANDLE);
6678 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6679 SetLastError(ERROR_INVALID_HANDLE);
6680 else if (list->SelectedDevice == NULL)
6681 SetLastError(ERROR_NO_DEVICE_SELECTED);
6682 else if (!DeviceInfoData)
6683 SetLastError(ERROR_INVALID_PARAMETER);
6684 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6685 SetLastError(ERROR_INVALID_USER_BUFFER);
6686 else
6687 {
6688 memcpy(&DeviceInfoData->ClassGuid,
6689 &list->SelectedDevice->ClassGuid,
6690 sizeof(GUID));
6691 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
6692 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
6693 ret = TRUE;
6694 }
6695
6696 TRACE("Returning %d\n", ret);
6697 return ret;
6698 }
6699
6700
6701 /***********************************************************************
6702 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6703 */
6704 BOOL WINAPI
6705 SetupDiGetSelectedDriverA(
6706 IN HDEVINFO DeviceInfoSet,
6707 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6708 OUT PSP_DRVINFO_DATA_A DriverInfoData)
6709 {
6710 SP_DRVINFO_DATA_V2_W driverInfoData2W;
6711 BOOL ret = FALSE;
6712
6713 if (DriverInfoData == NULL)
6714 SetLastError(ERROR_INVALID_PARAMETER);
6715 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
6716 SetLastError(ERROR_INVALID_USER_BUFFER);
6717 else
6718 {
6719 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
6720
6721 ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
6722 DeviceInfoData,
6723 &driverInfoData2W);
6724
6725 if (ret)
6726 {
6727 /* Do W->A conversion */
6728 DriverInfoData->DriverType = driverInfoData2W.DriverType;
6729 DriverInfoData->Reserved = driverInfoData2W.Reserved;
6730 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
6731 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
6732 {
6733 DriverInfoData->Description[0] = '\0';
6734 ret = FALSE;
6735 }
6736 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
6737 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
6738 {
6739 DriverInfoData->MfgName[0] = '\0';
6740 ret = FALSE;
6741 }
6742 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
6743 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
6744 {
6745 DriverInfoData->ProviderName[0] = '\0';
6746 ret = FALSE;
6747 }
6748 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
6749 {
6750 /* Copy more fields */
6751 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
6752 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
6753 }
6754 }
6755 }
6756
6757 return ret;
6758 }
6759
6760
6761 /***********************************************************************
6762 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6763 */
6764 BOOL WINAPI
6765 SetupDiGetSelectedDriverW(
6766 IN HDEVINFO DeviceInfoSet,
6767 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6768 OUT PSP_DRVINFO_DATA_W DriverInfoData)
6769 {
6770 BOOL ret = FALSE;
6771
6772 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
6773
6774 if (!DeviceInfoSet || !DriverInfoData)
6775 SetLastError(ERROR_INVALID_PARAMETER);
6776 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6777 SetLastError(ERROR_INVALID_HANDLE);
6778 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6779 SetLastError(ERROR_INVALID_HANDLE);
6780 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6781 SetLastError(ERROR_INVALID_USER_BUFFER);
6782 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6783 SetLastError(ERROR_INVALID_USER_BUFFER);
6784 else
6785 {
6786 SP_DEVINSTALL_PARAMS InstallParams;
6787
6788 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
6789 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
6790 {
6791 struct DriverInfoElement *driverInfo;
6792 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
6793 if (driverInfo == NULL)
6794 SetLastError(ERROR_NO_DRIVER_SELECTED);
6795 else
6796 {
6797 memcpy(
6798 &DriverInfoData->DriverType,
6799 &driverInfo->Info.DriverType,
6800 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
6801 ret = TRUE;
6802 }
6803 }
6804 }
6805
6806 TRACE("Returning %d\n", ret);
6807 return ret;
6808 }
6809
6810
6811 /***********************************************************************
6812 * SetupDiSetSelectedDevice (SETUPAPI.@)
6813 */
6814 BOOL WINAPI
6815 SetupDiSetSelectedDevice(
6816 IN HDEVINFO DeviceInfoSet,
6817 IN PSP_DEVINFO_DATA DeviceInfoData)
6818 {
6819 struct DeviceInfoSet *list;
6820 BOOL ret = FALSE;
6821
6822 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
6823
6824 if (!DeviceInfoSet)
6825 SetLastError(ERROR_INVALID_HANDLE);
6826 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6827 SetLastError(ERROR_INVALID_HANDLE);
6828 else if (!DeviceInfoData)
6829 SetLastError(ERROR_INVALID_PARAMETER);
6830 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6831 SetLastError(ERROR_INVALID_USER_BUFFER);
6832 else if (DeviceInfoData->Reserved == 0)
6833 SetLastError(ERROR_INVALID_USER_BUFFER);
6834 else
6835 {
6836 list->SelectedDevice = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
6837 ret = TRUE;
6838 }
6839
6840 TRACE("Returning %d\n", ret);
6841 return ret;
6842 }
6843
6844
6845 /***********************************************************************
6846 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6847 */
6848 BOOL WINAPI
6849 SetupDiSetSelectedDriverA(
6850 IN HDEVINFO DeviceInfoSet,
6851 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6852 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
6853 {
6854 SP_DRVINFO_DATA_V1_W DriverInfoDataW;
6855 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
6856 BOOL ret = FALSE;
6857
6858 if (DriverInfoData != NULL)
6859 {
6860 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
6861 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
6862 {
6863 SetLastError(ERROR_INVALID_PARAMETER);
6864 return FALSE;
6865 }
6866
6867 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
6868 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
6869
6870 if (DriverInfoDataW.Reserved == 0)
6871 {
6872 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
6873
6874 /* convert the strings to unicode */
6875 if (!MultiByteToWideChar(CP_ACP,
6876 0,
6877 DriverInfoData->Description,
6878 LINE_LEN,
6879 DriverInfoDataW.Description,
6880 LINE_LEN) ||
6881 !MultiByteToWideChar(CP_ACP,
6882 0,
6883 DriverInfoData->ProviderName,
6884 LINE_LEN,
6885 DriverInfoDataW.ProviderName,
6886 LINE_LEN))
6887 {
6888 return FALSE;
6889 }
6890 }
6891
6892 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
6893 }
6894
6895 ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
6896 DeviceInfoData,
6897 pDriverInfoDataW);
6898
6899 if (ret && pDriverInfoDataW != NULL)
6900 {
6901 DriverInfoData->Reserved = DriverInfoDataW.Reserved;
6902 }
6903
6904 return ret;
6905 }
6906
6907
6908 /***********************************************************************
6909 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6910 */
6911 BOOL WINAPI
6912 SetupDiSetSelectedDriverW(
6913 IN HDEVINFO DeviceInfoSet,
6914 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
6915 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
6916 {
6917 BOOL ret = FALSE;
6918
6919 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
6920
6921 if (!DeviceInfoSet)
6922 SetLastError(ERROR_INVALID_PARAMETER);
6923 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
6924 SetLastError(ERROR_INVALID_HANDLE);
6925 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
6926 SetLastError(ERROR_INVALID_HANDLE);
6927 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
6928 SetLastError(ERROR_INVALID_USER_BUFFER);
6929 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
6930 SetLastError(ERROR_INVALID_USER_BUFFER);
6931 else
6932 {
6933 struct DriverInfoElement **pDriverInfo;
6934 PLIST_ENTRY ListHead, ItemList;
6935
6936 if (DeviceInfoData)
6937 {
6938 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
6939 ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
6940 }
6941 else
6942 {
6943 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
6944 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
6945 }
6946
6947 if (!DriverInfoData)
6948 {
6949 *pDriverInfo = NULL;
6950 ret = TRUE;
6951 }
6952 else
6953 {
6954 /* Search selected driver in list */
6955 ItemList = ListHead->Flink;
6956 while (ItemList != ListHead)
6957 {
6958 if (DriverInfoData->Reserved != 0)
6959 {
6960 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
6961 break;
6962 }
6963 else
6964 {
6965 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6966 struct DriverInfoElement *driverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
6967 if (driverInfo->Info.DriverType == DriverInfoData->DriverType
6968 && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0
6969 && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
6970 {
6971 break;
6972 }
6973 }
6974 ItemList = ItemList->Flink;
6975 }
6976 if (ItemList == ListHead)
6977 SetLastError(ERROR_INVALID_PARAMETER);
6978 else
6979 {
6980 *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
6981 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
6982 ret = TRUE;
6983 TRACE("Choosing driver whose rank is 0x%lx\n",
6984 (*pDriverInfo)->DriverRank);
6985 if (DeviceInfoData)
6986 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
6987 }
6988 }
6989 }
6990
6991 TRACE("Returning %d\n", ret);
6992 return ret;
6993 }
6994
6995 /***********************************************************************
6996 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6997 */
6998 BOOL WINAPI
6999 SetupDiGetDriverInfoDetailA(
7000 IN HDEVINFO DeviceInfoSet,
7001 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
7002 IN PSP_DRVINFO_DATA_A DriverInfoData,
7003 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
7004 IN DWORD DriverInfoDetailDataSize,
7005 OUT PDWORD RequiredSize OPTIONAL)
7006 {
7007 SP_DRVINFO_DATA_V2_W DriverInfoDataW;
7008 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
7009 DWORD BufSize = 0;
7010 DWORD HardwareIDLen = 0;
7011 BOOL ret = FALSE;
7012
7013 /* do some sanity checks, the unicode version might do more thorough checks */
7014 if (DriverInfoData == NULL ||
7015 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
7016 (DriverInfoDetailData != NULL &&
7017 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
7018 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
7019 {
7020 SetLastError(ERROR_INVALID_PARAMETER);
7021 goto Cleanup;
7022 }
7023
7024 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
7025 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
7026 {
7027 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
7028 }
7029 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
7030 {
7031 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
7032 }
7033 else
7034 {
7035 SetLastError(ERROR_INVALID_PARAMETER);
7036 goto Cleanup;
7037 }
7038 DriverInfoDataW.DriverType = DriverInfoData->DriverType;
7039 DriverInfoDataW.Reserved = DriverInfoData->Reserved;
7040
7041 /* convert the strings to unicode */
7042 if (MultiByteToWideChar(CP_ACP,
7043 0,
7044 DriverInfoData->Description,
7045 LINE_LEN,
7046 DriverInfoDataW.Description,
7047 LINE_LEN) &&
7048 MultiByteToWideChar(CP_ACP,
7049 0,
7050 DriverInfoData->MfgName,
7051 LINE_LEN,
7052 DriverInfoDataW.MfgName,
7053 LINE_LEN) &&
7054 MultiByteToWideChar(CP_ACP,
7055 0,
7056 DriverInfoData->ProviderName,
7057 LINE_LEN,
7058 DriverInfoDataW.ProviderName,
7059 LINE_LEN))
7060 {
7061 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
7062 {
7063 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
7064 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
7065 }
7066
7067 if (DriverInfoDetailData != NULL)
7068 {
7069 /* calculate the unicode buffer size from the ansi buffer size */
7070 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
7071 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
7072 (HardwareIDLen * sizeof(WCHAR));
7073
7074 DriverInfoDetailDataW = MyMalloc(BufSize);
7075 if (DriverInfoDetailDataW == NULL)
7076 {
7077 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
7078 goto Cleanup;
7079 }
7080
7081 /* initialize the buffer */
7082 ZeroMemory(DriverInfoDetailDataW,
7083 BufSize);
7084 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
7085 }
7086
7087 /* call the unicode version */
7088 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
7089 DeviceInfoData,
7090 &DriverInfoDataW,
7091 DriverInfoDetailDataW,
7092 BufSize,
7093 RequiredSize);
7094
7095 if (ret)
7096 {
7097 if (DriverInfoDetailDataW != NULL)
7098 {
7099 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
7100 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
7101 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
7102 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
7103 if (WideCharToMultiByte(CP_ACP,
7104 0,
7105 DriverInfoDetailDataW->SectionName,
7106 LINE_LEN,
7107 DriverInfoDetailData->SectionName,
7108 LINE_LEN,
7109 NULL,
7110 NULL) &&
7111 WideCharToMultiByte(CP_ACP,
7112 0,
7113 DriverInfoDetailDataW->InfFileName,
7114 MAX_PATH,
7115 DriverInfoDetailData->InfFileName,
7116 MAX_PATH,
7117 NULL,
7118 NULL) &&
7119 WideCharToMultiByte(CP_ACP,
7120 0,
7121 DriverInfoDetailDataW->DrvDescription,
7122 LINE_LEN,
7123 DriverInfoDetailData->DrvDescription,
7124 LINE_LEN,
7125 NULL,
7126 NULL) &&
7127 WideCharToMultiByte(CP_ACP,
7128 0,
7129 DriverInfoDetailDataW->HardwareID,
7130 HardwareIDLen,
7131 DriverInfoDetailData->HardwareID,
7132 HardwareIDLen,
7133 NULL,
7134 NULL))
7135 {
7136 DWORD len, cnt = 0;
7137 DWORD hwidlen = HardwareIDLen;
7138 CHAR *s = DriverInfoDetailData->HardwareID;
7139
7140 /* count the strings in the list */
7141 while (*s != '\0')
7142 {
7143 len = lstrlenA(s) + 1;
7144 if (hwidlen > len)
7145 {
7146 cnt++;
7147 s += len;
7148 hwidlen -= len;
7149 }
7150 else
7151 {
7152 /* looks like the string list wasn't terminated... */
7153 SetLastError(ERROR_INVALID_USER_BUFFER);
7154 ret = FALSE;
7155 break;
7156 }
7157 }
7158
7159 /* make sure CompatIDsOffset points to the second string in the
7160 list, if present */
7161 if (cnt > 1)
7162 {
7163 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
7164 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
7165 DriverInfoDetailData->CompatIDsOffset + 1;
7166 }
7167 else
7168 {
7169 DriverInfoDetailData->CompatIDsOffset = 0;
7170 DriverInfoDetailData->CompatIDsLength = 0;
7171 }
7172 }
7173 else
7174 {
7175 ret = FALSE;
7176 }
7177 }
7178
7179 if (RequiredSize != NULL)
7180 {
7181 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
7182 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
7183 }
7184 }
7185 }
7186
7187 Cleanup:
7188 if (DriverInfoDetailDataW != NULL)
7189 {
7190 MyFree(DriverInfoDetailDataW);
7191 }
7192
7193 return ret;
7194 }
7195
7196 /***********************************************************************
7197 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
7198 */
7199 BOOL WINAPI
7200 SetupDiGetDriverInfoDetailW(
7201 IN HDEVINFO DeviceInfoSet,
7202 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
7203 IN PSP_DRVINFO_DATA_W DriverInfoData,
7204 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
7205 IN DWORD DriverInfoDetailDataSize,
7206 OUT PDWORD RequiredSize OPTIONAL)
7207 {
7208 BOOL ret = FALSE;
7209
7210 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
7211 DriverInfoData, DriverInfoDetailData,
7212 DriverInfoDetailDataSize, RequiredSize);
7213
7214 if (!DeviceInfoSet)
7215 SetLastError(ERROR_INVALID_PARAMETER);
7216 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7217 SetLastError(ERROR_INVALID_HANDLE);
7218 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7219 SetLastError(ERROR_INVALID_HANDLE);
7220 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7221 SetLastError(ERROR_INVALID_USER_BUFFER);
7222 else if (!DriverInfoData)
7223 SetLastError(ERROR_INVALID_PARAMETER);
7224 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
7225 SetLastError(ERROR_INVALID_PARAMETER);
7226 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
7227 SetLastError(ERROR_INVALID_PARAMETER);
7228 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
7229 SetLastError(ERROR_INVALID_USER_BUFFER);
7230 else if (DriverInfoData->Reserved == 0)
7231 SetLastError(ERROR_NO_DRIVER_SELECTED);
7232 else
7233 {
7234 struct DriverInfoElement *driverInfoElement;
7235 LPWSTR HardwareIDs = NULL;
7236 LPWSTR CompatibleIDs = NULL;
7237 LPWSTR pBuffer = NULL;
7238 LPCWSTR DeviceID = NULL;
7239 ULONG HardwareIDsSize, CompatibleIDsSize;
7240 ULONG sizeNeeded, sizeLeft, size;
7241 BOOL Result;
7242
7243 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
7244
7245 /* Get hardware and compatible IDs lists */
7246 Result = GetHardwareAndCompatibleIDsLists(
7247 DeviceInfoSet,
7248 DeviceInfoData,
7249 &HardwareIDs, &HardwareIDsSize,
7250 &CompatibleIDs, &CompatibleIDsSize);
7251 if (!Result)
7252 goto done;
7253
7254 sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)
7255 + HardwareIDsSize + CompatibleIDsSize;
7256 if (RequiredSize)
7257 *RequiredSize = sizeNeeded;
7258
7259 if (!DriverInfoDetailData)
7260 {
7261 ret = TRUE;
7262 goto done;
7263 }
7264
7265 memcpy(
7266 DriverInfoDetailData,
7267 &driverInfoElement->Details,
7268 driverInfoElement->Details.cbSize);
7269 DriverInfoDetailData->CompatIDsOffset = 0;
7270 DriverInfoDetailData->CompatIDsLength = 0;
7271
7272 sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR);
7273 pBuffer = DriverInfoDetailData->HardwareID;
7274 /* Add as many as possible HardwareIDs in the list */
7275 DeviceID = HardwareIDs;
7276 while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
7277 {
7278 TRACE("Adding %s to list\n", debugstr_w(DeviceID));
7279 wcscpy(pBuffer, DeviceID);
7280 DeviceID += size + 1;
7281 pBuffer += size + 1;
7282 sizeLeft -= size + 1;
7283 DriverInfoDetailData->CompatIDsOffset += size + 1;
7284 }
7285 if (sizeLeft > 0)
7286 {
7287 *pBuffer = UNICODE_NULL;
7288 sizeLeft--;
7289 DriverInfoDetailData->CompatIDsOffset++;
7290 }
7291 /* Add as many as possible CompatibleIDs in the list */
7292 DeviceID = CompatibleIDs;
7293 while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
7294 {
7295 TRACE("Adding %s to list\n", debugstr_w(DeviceID));
7296 wcscpy(pBuffer, DeviceID);
7297 DeviceID += size + 1;
7298 pBuffer += size + 1;
7299 sizeLeft -= size + 1;
7300 DriverInfoDetailData->CompatIDsLength += size + 1;
7301 }
7302 if (sizeLeft > 0)
7303 {
7304 *pBuffer = UNICODE_NULL;
7305 sizeLeft--;
7306 DriverInfoDetailData->CompatIDsLength++;
7307 }
7308
7309 if (sizeNeeded > DriverInfoDetailDataSize)
7310 SetLastError(ERROR_INSUFFICIENT_BUFFER);
7311 else
7312 ret = TRUE;
7313
7314 done:
7315 MyFree(HardwareIDs);
7316 MyFree(CompatibleIDs);
7317 }
7318
7319 TRACE("Returning %d\n", ret);
7320 return ret;
7321 }
7322
7323 /* Return the current hardware profile id, or -1 if error */
7324 static DWORD
7325 GetCurrentHwProfile(
7326 IN HDEVINFO DeviceInfoSet)
7327 {
7328 HKEY hKey = NULL;
7329 DWORD dwRegType, dwLength;
7330 DWORD hwProfile;
7331 LONG rc;
7332 DWORD ret = (DWORD)-1;
7333
7334 rc = RegOpenKeyExW(
7335 ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
7336 REGSTR_PATH_IDCONFIGDB,
7337 0, /* Options */
7338 KEY_QUERY_VALUE,
7339 &hKey);
7340 if (rc != ERROR_SUCCESS)
7341 {
7342 SetLastError(rc);
7343 goto cleanup;
7344 }
7345
7346 dwLength = sizeof(DWORD);
7347 rc = RegQueryValueExW(
7348 hKey,
7349 REGSTR_VAL_CURRENTCONFIG,
7350 NULL,
7351 &dwRegType,
7352 (LPBYTE)&hwProfile, &dwLength);
7353 if (rc != ERROR_SUCCESS)
7354 {
7355 SetLastError(rc);
7356 goto cleanup;
7357 }
7358 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
7359 {
7360 SetLastError(ERROR_GEN_FAILURE);
7361 goto cleanup;
7362 }
7363
7364 ret = hwProfile;
7365
7366 cleanup:
7367 if (hKey != NULL)
7368 RegCloseKey(hKey);
7369
7370 return hwProfile;
7371 }
7372
7373 static BOOL
7374 ResetDevice(
7375 IN HDEVINFO DeviceInfoSet,
7376 IN PSP_DEVINFO_DATA DeviceInfoData)
7377 {
7378 #ifndef __WINESRC__
7379 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
7380 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
7381 NTSTATUS Status;
7382
7383 if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
7384 {
7385 /* At the moment, I only know how to start local devices */
7386 SetLastError(ERROR_INVALID_COMPUTERNAME);
7387 return FALSE;
7388 }
7389
7390 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, deviceInfo->DeviceName);
7391 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
7392 SetLastError(RtlNtStatusToDosError(Status));
7393 return NT_SUCCESS(Status);
7394 #else
7395 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
7396 return TRUE;
7397 #endif
7398 }
7399
7400 static BOOL StopDevice(
7401 IN HDEVINFO DeviceInfoSet,
7402 IN PSP_DEVINFO_DATA DeviceInfoData)
7403 {
7404 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
7405 return TRUE;
7406 }
7407
7408 /***********************************************************************
7409 * SetupDiChangeState (SETUPAPI.@)
7410 */
7411 BOOL WINAPI
7412 SetupDiChangeState(
7413 IN HDEVINFO DeviceInfoSet,
7414 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
7415 {
7416 PSP_PROPCHANGE_PARAMS PropChange;
7417 HKEY hKey = INVALID_HANDLE_VALUE;
7418 LPCWSTR RegistryValueName;
7419 DWORD dwConfigFlags, dwLength, dwRegType;
7420 LONG rc;
7421 BOOL ret = FALSE;
7422
7423 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7424
7425 if (!DeviceInfoData)
7426 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChange;
7427 else
7428 PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChange;
7429 if (!PropChange)
7430 {
7431 SetLastError(ERROR_INVALID_PARAMETER);
7432 goto cleanup;
7433 }
7434
7435 if (PropChange->Scope == DICS_FLAG_GLOBAL)
7436 RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
7437 else
7438 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
7439
7440 switch (PropChange->StateChange)
7441 {
7442 case DICS_ENABLE:
7443 case DICS_DISABLE:
7444 {
7445 /* Enable/disable device in registry */
7446 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
7447 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
7448 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
7449 if (hKey == INVALID_HANDLE_VALUE)
7450 break;
7451 dwLength = sizeof(DWORD);
7452 rc = RegQueryValueExW(
7453 hKey,
7454 RegistryValueName,
7455 NULL,
7456 &dwRegType,
7457 (LPBYTE)&dwConfigFlags, &dwLength);
7458 if (rc == ERROR_FILE_NOT_FOUND)
7459 dwConfigFlags = 0;
7460 else if (rc != ERROR_SUCCESS)
7461 {
7462 SetLastError(rc);
7463 goto cleanup;
7464 }
7465 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
7466 {
7467 SetLastError(ERROR_GEN_FAILURE);
7468 goto cleanup;
7469 }
7470 if (PropChange->StateChange == DICS_ENABLE)
7471 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
7472 else
7473 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
7474 rc = RegSetValueEx(
7475 hKey,
7476 RegistryValueName,
7477 0,
7478 REG_DWORD,
7479 (LPBYTE)&dwConfigFlags, sizeof(DWORD));
7480 if (rc != ERROR_SUCCESS)
7481 {
7482 SetLastError(rc);
7483 goto cleanup;
7484 }
7485
7486 /* Enable/disable device if needed */
7487 if (PropChange->Scope == DICS_FLAG_GLOBAL
7488 || PropChange->HwProfile == 0
7489 || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
7490 {
7491 if (PropChange->StateChange == DICS_ENABLE)
7492 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
7493 else
7494 ret = StopDevice(DeviceInfoSet, DeviceInfoData);
7495 }
7496 else
7497 ret = TRUE;
7498 break;
7499 }
7500 case DICS_PROPCHANGE:
7501 {
7502 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
7503 break;
7504 }
7505 default:
7506 {
7507 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange);
7508 SetLastError(ERROR_NOT_SUPPORTED);
7509 }
7510 }
7511
7512 cleanup:
7513 if (hKey != INVALID_HANDLE_VALUE)
7514 RegCloseKey(hKey);
7515
7516 TRACE("Returning %d\n", ret);
7517 return ret;
7518 }
7519
7520 /***********************************************************************
7521 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7522 */
7523 BOOL WINAPI
7524 SetupDiSelectBestCompatDrv(
7525 IN HDEVINFO DeviceInfoSet,
7526 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
7527 {
7528 SP_DRVINFO_DATA_W drvInfoData;
7529 BOOL ret;
7530
7531 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7532
7533 /* Drivers are sorted by rank in the driver list, so
7534 * the first driver in the list is the best one.
7535 */
7536 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
7537 ret = SetupDiEnumDriverInfoW(
7538 DeviceInfoSet,
7539 DeviceInfoData,
7540 SPDIT_COMPATDRIVER,
7541 0, /* Member index */
7542 &drvInfoData);
7543
7544 if (ret)
7545 {
7546 ret = SetupDiSetSelectedDriverW(
7547 DeviceInfoSet,
7548 DeviceInfoData,
7549 &drvInfoData);
7550 }
7551
7552 TRACE("Returning %d\n", ret);
7553 return ret;
7554 }
7555
7556 /***********************************************************************
7557 * SetupDiSelectDevice (SETUPAPI.@)
7558 */
7559 BOOL WINAPI
7560 SetupDiSelectDevice(
7561 IN HDEVINFO DeviceInfoSet,
7562 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
7563 {
7564 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData);
7565 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
7566 return FALSE;
7567 }
7568
7569 /***********************************************************************
7570 * SetupDiInstallDriverFiles (SETUPAPI.@)
7571 */
7572 BOOL WINAPI
7573 SetupDiInstallDriverFiles(
7574 IN HDEVINFO DeviceInfoSet,
7575 IN PSP_DEVINFO_DATA DeviceInfoData)
7576 {
7577 BOOL ret = FALSE;
7578
7579 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7580
7581 if (!DeviceInfoSet)
7582 SetLastError(ERROR_INVALID_PARAMETER);
7583 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7584 SetLastError(ERROR_INVALID_HANDLE);
7585 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7586 SetLastError(ERROR_INVALID_HANDLE);
7587 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7588 SetLastError(ERROR_INVALID_USER_BUFFER);
7589 else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
7590 SetLastError(ERROR_NO_DRIVER_SELECTED);
7591 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
7592 SetLastError(ERROR_NO_DRIVER_SELECTED);
7593 else
7594 {
7595 SP_DEVINSTALL_PARAMS_W InstallParams;
7596 struct DriverInfoElement *SelectedDriver;
7597 WCHAR SectionName[MAX_PATH];
7598 DWORD SectionNameLength = 0;
7599 PVOID InstallMsgHandler;
7600 PVOID InstallMsgHandlerContext;
7601 PVOID Context = NULL;
7602
7603 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7604 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7605 if (!ret)
7606 goto done;
7607
7608 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
7609 if (!SelectedDriver)
7610 {
7611 SetLastError(ERROR_NO_DRIVER_SELECTED);
7612 goto done;
7613 }
7614
7615 ret = SetupDiGetActualSectionToInstallW(
7616 SelectedDriver->InfFileDetails->hInf,
7617 SelectedDriver->Details.SectionName,
7618 SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL);
7619 if (!ret)
7620 goto done;
7621
7622 if (InstallParams.InstallMsgHandler)
7623 {
7624 InstallMsgHandler = InstallParams.InstallMsgHandler;
7625 InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext;
7626 }
7627 else
7628 {
7629 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
7630 if (!Context)
7631 goto cleanup;
7632 InstallMsgHandler = SetupDefaultQueueCallback;
7633 InstallMsgHandlerContext = Context;
7634 }
7635 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7636 SelectedDriver->InfFileDetails->hInf, SectionName,
7637 SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
7638 InstallMsgHandler, InstallMsgHandlerContext,
7639 DeviceInfoSet, DeviceInfoData);
7640 if (!ret)
7641 goto done;
7642
7643 /* Install files from .CoInstallers section */
7644 lstrcatW(SectionName, DotCoInstallers);
7645 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7646 SelectedDriver->InfFileDetails->hInf, SectionName,
7647 SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
7648 InstallMsgHandler, InstallMsgHandlerContext,
7649 DeviceInfoSet, DeviceInfoData);
7650 if (!ret)
7651 goto done;
7652
7653 /* Set the DI_NOFILECOPY flag to prevent another
7654 * installation during SetupDiInstallDevice */
7655 InstallParams.Flags |= DI_NOFILECOPY;
7656 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7657
7658 cleanup:
7659 if (Context)
7660 SetupTermDefaultQueueCallback(Context);
7661 }
7662
7663 done:
7664 TRACE("Returning %d\n", ret);
7665 return ret;
7666 }
7667
7668 /***********************************************************************
7669 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7670 */
7671 BOOL WINAPI
7672 SetupDiRegisterCoDeviceInstallers(
7673 IN HDEVINFO DeviceInfoSet,
7674 IN PSP_DEVINFO_DATA DeviceInfoData)
7675 {
7676 BOOL ret = FALSE; /* Return value */
7677
7678 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7679
7680 if (!DeviceInfoSet)
7681 SetLastError(ERROR_INVALID_PARAMETER);
7682 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7683 SetLastError(ERROR_INVALID_HANDLE);
7684 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7685 SetLastError(ERROR_INVALID_HANDLE);
7686 else if (!DeviceInfoData)
7687 SetLastError(ERROR_INVALID_PARAMETER);
7688 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7689 SetLastError(ERROR_INVALID_USER_BUFFER);
7690 else
7691 {
7692 SP_DEVINSTALL_PARAMS_W InstallParams;
7693 struct DriverInfoElement *SelectedDriver;
7694 BOOL Result;
7695 DWORD DoAction;
7696 WCHAR SectionName[MAX_PATH];
7697 DWORD SectionNameLength = 0;
7698 HKEY hKey = INVALID_HANDLE_VALUE;
7699 PVOID Context = NULL;
7700
7701 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7702 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7703 if (!Result)
7704 goto cleanup;
7705
7706 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
7707 if (SelectedDriver == NULL)
7708 {
7709 SetLastError(ERROR_NO_DRIVER_SELECTED);
7710 goto cleanup;
7711 }
7712
7713 /* Get .CoInstallers section name */
7714 Result = SetupDiGetActualSectionToInstallW(
7715 SelectedDriver->InfFileDetails->hInf,
7716 SelectedDriver->Details.SectionName,
7717 SectionName, MAX_PATH, &SectionNameLength, NULL);
7718 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1)
7719 goto cleanup;
7720 lstrcatW(SectionName, DotCoInstallers);
7721
7722 /* Open/Create driver key information */
7723 #if _WIN32_WINNT >= 0x502
7724 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
7725 #else
7726 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
7727 #endif
7728 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
7729 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
7730 if (hKey == INVALID_HANDLE_VALUE)
7731 goto cleanup;
7732
7733 /* Install .CoInstallers section */
7734 DoAction = SPINST_REGISTRY;
7735 if (!(InstallParams.Flags & DI_NOFILECOPY))
7736 {
7737 DoAction |= SPINST_FILES;
7738 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
7739 if (!Context)
7740 goto cleanup;
7741 }
7742 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
7743 SelectedDriver->InfFileDetails->hInf, SectionName,
7744 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
7745 SetupDefaultQueueCallback, Context,
7746 DeviceInfoSet, DeviceInfoData);
7747 if (!Result)
7748 goto cleanup;
7749
7750 ret = TRUE;
7751
7752 cleanup:
7753 if (Context)
7754 SetupTermDefaultQueueCallback(Context);
7755 if (hKey != INVALID_HANDLE_VALUE)
7756 RegCloseKey(hKey);
7757 }
7758
7759 TRACE("Returning %d\n", ret);
7760 return ret;
7761 }
7762
7763 static BOOL
7764 InstallOneInterface(
7765 IN LPGUID InterfaceGuid,
7766 IN LPCWSTR ReferenceString,
7767 IN LPCWSTR InterfaceSection,
7768 IN UINT InterfaceFlags)
7769 {
7770 if (InterfaceFlags != 0)
7771 {
7772 SetLastError(ERROR_INVALID_PARAMETER);
7773 return FALSE;
7774 }
7775
7776 FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid),
7777 debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags);
7778 return TRUE;
7779 }
7780
7781 /***********************************************************************
7782 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7783 */
7784 BOOL WINAPI
7785 SetupDiInstallDeviceInterfaces(
7786 IN HDEVINFO DeviceInfoSet,
7787 IN PSP_DEVINFO_DATA DeviceInfoData)
7788 {
7789 struct DeviceInfoSet *list = NULL;
7790 BOOL ret = FALSE;
7791
7792 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7793
7794 if (!DeviceInfoSet)
7795 SetLastError(ERROR_INVALID_PARAMETER);
7796 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7797 SetLastError(ERROR_INVALID_HANDLE);
7798 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7799 SetLastError(ERROR_INVALID_HANDLE);
7800 else if (!DeviceInfoData)
7801 SetLastError(ERROR_INVALID_PARAMETER);
7802 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7803 SetLastError(ERROR_INVALID_USER_BUFFER);
7804 else
7805 {
7806 struct DriverInfoElement *SelectedDriver;
7807 SP_DEVINSTALL_PARAMS_W InstallParams;
7808 WCHAR SectionName[MAX_PATH];
7809 DWORD SectionNameLength = 0;
7810 INFCONTEXT ContextInterface;
7811 LPWSTR InterfaceGuidString = NULL;
7812 LPWSTR ReferenceString = NULL;
7813 LPWSTR InterfaceSection = NULL;
7814 INT InterfaceFlags;
7815 GUID InterfaceGuid;
7816 BOOL Result;
7817
7818 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7819 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7820 if (!Result)
7821 goto cleanup;
7822
7823 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
7824 if (SelectedDriver == NULL)
7825 {
7826 SetLastError(ERROR_NO_DRIVER_SELECTED);
7827 ret = FALSE;
7828 goto cleanup;
7829 }
7830
7831 /* Get .Interfaces section name */
7832 Result = SetupDiGetActualSectionToInstallW(
7833 SelectedDriver->InfFileDetails->hInf,
7834 SelectedDriver->Details.SectionName,
7835 SectionName, MAX_PATH, &SectionNameLength, NULL);
7836 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotInterfaces) - 1)
7837 goto cleanup;
7838 strcatW(SectionName, DotInterfaces);
7839
7840 ret = TRUE;
7841 Result = SetupFindFirstLineW(
7842 SelectedDriver->InfFileDetails->hInf,
7843 SectionName,
7844 AddInterface,
7845 &ContextInterface);
7846 while (ret && Result)
7847 {
7848 ret = GetStringField(&ContextInterface, 1, &InterfaceGuidString);
7849 if (!ret)
7850 goto cleanup;
7851 else if (strlenW(InterfaceGuidString) != MAX_GUID_STRING_LEN - 1)
7852 {
7853 SetLastError(ERROR_INVALID_PARAMETER);
7854 ret = FALSE;
7855 goto cleanup;
7856 }
7857
7858 InterfaceGuidString[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */
7859 if (UuidFromStringW(&InterfaceGuidString[1], &InterfaceGuid) != RPC_S_OK)
7860 {
7861 /* Bad GUID, skip the entry */
7862 SetLastError(ERROR_INVALID_PARAMETER);
7863 ret = FALSE;
7864 goto cleanup;
7865 }
7866
7867 ret = GetStringField(&ContextInterface, 2, &ReferenceString);
7868 if (!ret)
7869 goto cleanup;
7870
7871 ret = GetStringField(&ContextInterface, 3, &InterfaceSection);
7872 if (!ret)
7873 goto cleanup;
7874
7875 ret = SetupGetIntField(
7876 &ContextInterface,
7877 4, /* Field index */
7878 &InterfaceFlags);
7879 if (!ret)
7880 {
7881 if (GetLastError() == ERROR_INVALID_PARAMETER)
7882 {
7883 /* The field may be empty. Ignore the error */
7884 InterfaceFlags = 0;
7885 ret = TRUE;
7886 }
7887 else
7888 goto cleanup;
7889 }
7890
7891 /* Install Interface */
7892 ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags);
7893
7894 cleanup:
7895 MyFree(InterfaceGuidString);
7896 MyFree(ReferenceString);
7897 MyFree(InterfaceSection);
7898 InterfaceGuidString = ReferenceString = InterfaceSection = NULL;
7899 Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface);
7900 }
7901 }
7902
7903 TRACE("Returning %d\n", ret);
7904 return ret;
7905 }
7906
7907 static BOOL
7908 InfIsFromOEMLocation(
7909 IN PCWSTR FullName,
7910 OUT LPBOOL IsOEMLocation)
7911 {
7912 PWCHAR last;
7913
7914 last = strrchrW(FullName, '\\');
7915 if (!last)
7916 {
7917 /* No directory specified */
7918 *IsOEMLocation = FALSE;
7919 }
7920 else
7921 {
7922 WCHAR Windir[MAX_PATH];
7923 UINT ret;
7924
7925 ret = GetWindowsDirectory(Windir, MAX_PATH);
7926 if (ret == 0 || ret >= MAX_PATH)
7927 {
7928 SetLastError(ERROR_GEN_FAILURE);
7929 return FALSE;
7930 }
7931
7932 if (strncmpW(FullName, Windir, last - FullName) == 0)
7933 {
7934 /* The path is %WINDIR%\Inf */
7935 *IsOEMLocation = FALSE;
7936 }
7937 else
7938 {
7939 /* The file is in another place */
7940 *IsOEMLocation = TRUE;
7941 }
7942 }
7943 return TRUE;
7944 }
7945
7946 /***********************************************************************
7947 * SetupDiInstallDevice (SETUPAPI.@)
7948 */
7949 BOOL WINAPI
7950 SetupDiInstallDevice(
7951 IN HDEVINFO DeviceInfoSet,
7952 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
7953 {
7954 SP_DEVINSTALL_PARAMS_W InstallParams;
7955 struct DriverInfoElement *SelectedDriver;
7956 SYSTEMTIME DriverDate;
7957 WCHAR SectionName[MAX_PATH];
7958 WCHAR Buffer[32];
7959 DWORD SectionNameLength = 0;
7960 BOOL Result = FALSE;
7961 ULONG DoAction;
7962 DWORD RequiredSize;
7963 LPWSTR pSectionName = NULL;
7964 WCHAR ClassName[MAX_CLASS_NAME_LEN];
7965 GUID ClassGuid;
7966 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
7967 BOOL RebootRequired = FALSE;
7968 HKEY hKey = INVALID_HANDLE_VALUE;
7969 BOOL NeedtoCopyFile;
7970 LARGE_INTEGER fullVersion;
7971 LONG rc;
7972 PVOID Context = NULL;
7973 BOOL ret = FALSE; /* Return value */
7974
7975 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
7976
7977 if (!DeviceInfoSet)
7978 SetLastError(ERROR_INVALID_PARAMETER);
7979 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
7980 SetLastError(ERROR_INVALID_HANDLE);
7981 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
7982 SetLastError(ERROR_INVALID_HANDLE);
7983 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
7984 SetLastError(ERROR_INVALID_USER_BUFFER);
7985 else
7986 Result = TRUE;
7987
7988 if (!Result)
7989 {
7990 /* One parameter is bad */
7991 goto cleanup;
7992 }
7993
7994 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
7995 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
7996 if (!Result)
7997 goto cleanup;
7998
7999 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
8000 {
8001 /* Set FAILEDINSTALL in ConfigFlags registry value */
8002 DWORD ConfigFlags, regType;
8003 Result = SetupDiGetDeviceRegistryPropertyW(
8004 DeviceInfoSet,
8005 DeviceInfoData,
8006 SPDRP_CONFIGFLAGS,
8007 &regType,
8008 (PBYTE)&ConfigFlags,
8009 sizeof(ConfigFlags),
8010 NULL);
8011 if (!Result || regType != REG_DWORD)
8012 {
8013 SetLastError(ERROR_GEN_FAILURE);
8014 goto cleanup;
8015 }
8016 ConfigFlags |= DNF_DISABLED;
8017 Result = SetupDiSetDeviceRegistryPropertyW(
8018 DeviceInfoSet,
8019 DeviceInfoData,
8020 SPDRP_CONFIGFLAGS,
8021 (PBYTE)&ConfigFlags,
8022 sizeof(ConfigFlags));
8023 if (!Result)
8024 {
8025 SetLastError(ERROR_GEN_FAILURE);
8026 goto cleanup;
8027 }
8028
8029 ret = TRUE;
8030 goto cleanup;
8031 }
8032
8033 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
8034 if (SelectedDriver == NULL)
8035 {
8036 SetLastError(ERROR_NO_DRIVER_SELECTED);
8037 goto cleanup;
8038 }
8039
8040 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
8041
8042 Result = SetupDiGetActualSectionToInstallW(
8043 SelectedDriver->InfFileDetails->hInf,
8044 SelectedDriver->Details.SectionName,
8045 SectionName, MAX_PATH, &SectionNameLength, NULL);
8046 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices))
8047 goto cleanup;
8048 pSectionName = &SectionName[strlenW(SectionName)];
8049
8050 /* Get information from [Version] section */
8051 if (!SetupDiGetINFClassW(SelectedDriver->InfFileDetails->FullInfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
8052 goto cleanup;
8053 /* Format ClassGuid to a string */
8054 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
8055 goto cleanup;
8056 RequiredSize = lstrlenW(lpGuidString);
8057 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
8058 if (!lpFullGuidString)
8059 {
8060 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
8061 goto cleanup;
8062 }
8063 lpFullGuidString[0] = '{';
8064 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
8065 lpFullGuidString[RequiredSize + 1] = '}';
8066 lpFullGuidString[RequiredSize + 2] = '\0';
8067
8068 /* Open/Create driver key information */
8069 #if _WIN32_WINNT >= 0x502
8070 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
8071 #else
8072 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
8073 #endif
8074 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
8075 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
8076 if (hKey == INVALID_HANDLE_VALUE)
8077 goto cleanup;
8078
8079 /* Install main section */
8080 DoAction = 0;
8081 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
8082 DoAction |= SPINST_REGISTRY;
8083 if (!(InstallParams.Flags & DI_NOFILECOPY))
8084 {
8085 DoAction |= SPINST_FILES;
8086 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
8087 if (!Context)
8088 goto cleanup;
8089 }
8090 *pSectionName = '\0';
8091 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
8092 SelectedDriver->InfFileDetails->hInf, SectionName,
8093 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
8094 SetupDefaultQueueCallback, Context,
8095 DeviceInfoSet, DeviceInfoData);
8096 if (!Result)
8097 goto cleanup;
8098 InstallParams.Flags |= DI_NOFILECOPY;
8099 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
8100
8101 /* Write information to driver key */
8102 *pSectionName = UNICODE_NULL;
8103 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
8104 TRACE("Write information to driver key\n");
8105 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
8106 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
8107 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
8108 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->Details.InfFileName));
8109 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
8110 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
8111 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
8112 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName));
8113 sprintfW(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
8114 rc = RegSetValueEx(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
8115 if (rc == ERROR_SUCCESS)
8116 rc = RegSetValueEx(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
8117 if (rc == ERROR_SUCCESS)
8118 rc = RegSetValueEx(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
8119 if (rc == ERROR_SUCCESS)
8120 {
8121 sprintfW(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
8122 rc = RegSetValueEx(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
8123 }
8124 if (rc == ERROR_SUCCESS)
8125 rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (strlenW(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
8126 if (rc == ERROR_SUCCESS)
8127 rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
8128 if (rc == ERROR_SUCCESS)
8129 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));
8130 if (rc == ERROR_SUCCESS)
8131 rc = RegSetValueEx(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
8132 if (rc == ERROR_SUCCESS)
8133 rc = RegSetValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
8134 if (rc != ERROR_SUCCESS)
8135 {
8136 SetLastError(rc);
8137 goto cleanup;
8138 }
8139 RegCloseKey(hKey);
8140 hKey = INVALID_HANDLE_VALUE;
8141
8142 /* FIXME: Process .LogConfigOverride section */
8143
8144 /* Install .Services section */
8145 strcpyW(pSectionName, DotServices);
8146 Result = SetupInstallServicesFromInfSectionExW(
8147 SelectedDriver->InfFileDetails->hInf,
8148 SectionName,
8149 0,
8150 DeviceInfoSet,
8151 DeviceInfoData,
8152 NULL,
8153 NULL);
8154 if (!Result)
8155 goto cleanup;
8156 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
8157 RebootRequired = TRUE;
8158
8159 /* Copy .inf file to Inf\ directory (if needed) */
8160 Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
8161 if (!Result)
8162 goto cleanup;
8163 if (NeedtoCopyFile)
8164 {
8165 Result = SetupCopyOEMInfW(
8166 SelectedDriver->InfFileDetails->FullInfFileName,
8167 NULL,
8168 SPOST_NONE,
8169 SP_COPY_NOOVERWRITE,
8170 NULL, 0,
8171 NULL,
8172 NULL);
8173 if (!Result)
8174 goto cleanup;
8175 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
8176 * to release use of current InfFile */
8177 }
8178
8179 /* Open device registry key */
8180 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
8181 if (hKey == INVALID_HANDLE_VALUE)
8182 goto cleanup;
8183
8184 /* Install .HW section */
8185 DoAction = 0;
8186 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
8187 DoAction |= SPINST_REGISTRY;
8188 strcpyW(pSectionName, DotHW);
8189 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
8190 SelectedDriver->InfFileDetails->hInf, SectionName,
8191 DoAction, hKey, NULL, 0,
8192 NULL, NULL,
8193 DeviceInfoSet, DeviceInfoData);
8194 if (!Result)
8195 goto cleanup;
8196
8197 /* Write information to enum key */
8198 TRACE("Write information to enum key\n");
8199 TRACE("Class : '%s'\n", debugstr_w(ClassName));
8200 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString));
8201 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
8202 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName));
8203 rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
8204 if (rc == ERROR_SUCCESS)
8205 rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
8206 if (rc == ERROR_SUCCESS)
8207 rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
8208 if (rc == ERROR_SUCCESS)
8209 rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
8210 if (rc != ERROR_SUCCESS)
8211 {
8212 SetLastError(rc);
8213 goto cleanup;
8214 }
8215
8216 /* Start the device */
8217 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
8218 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
8219 else
8220 ret = TRUE;
8221
8222 cleanup:
8223 /* End of installation */
8224 if (hKey != INVALID_HANDLE_VALUE)
8225 RegCloseKey(hKey);
8226 if (lpGuidString)
8227 RpcStringFreeW(&lpGuidString);
8228 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
8229 if (Context)
8230 SetupTermDefaultQueueCallback(Context);
8231 TRACE("Returning %d\n", ret);
8232 return ret;
8233 }