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