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