2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
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.
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.
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
23 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
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 NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
33 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
34 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
35 static const WCHAR NtExtension
[] = {'.','N','T',0};
36 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
37 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
38 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
39 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
41 /* Registry key and value names */
42 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
43 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
44 'C','o','n','t','r','o','l','\\',
45 'C','l','a','s','s',0};
47 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
48 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
49 'C','o','n','t','r','o','l','\\',
50 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
52 static const WCHAR EnumKeyName
[] = {'S','y','s','t','e','m','\\',
53 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
57 /* FIXME: header mess */
58 DEFINE_GUID(GUID_NULL
,
59 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
61 (CALLBACK
* CLASS_INSTALL_PROC
) (
62 IN DI_FUNCTION InstallFunction
,
63 IN HDEVINFO DeviceInfoSet
,
64 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
66 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
67 IN HDEVINFO DeviceInfoSet
,
68 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
70 (CALLBACK
* COINSTALLER_PROC
) (
71 IN DI_FUNCTION InstallFunction
,
72 IN HDEVINFO DeviceInfoSet
,
73 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
74 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
76 struct CoInstallerElement
81 COINSTALLER_PROC Function
;
82 BOOL DoPostProcessing
;
86 /***********************************************************************
87 * SetupDiBuildClassInfoList (SETUPAPI.@)
89 BOOL WINAPI
SetupDiBuildClassInfoList(
92 DWORD ClassGuidListSize
,
96 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
97 ClassGuidListSize
, RequiredSize
,
101 /***********************************************************************
102 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
104 BOOL WINAPI
SetupDiBuildClassInfoListExA(
106 LPGUID ClassGuidList
,
107 DWORD ClassGuidListSize
,
112 LPWSTR MachineNameW
= NULL
;
119 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
120 if (MachineNameW
== NULL
) return FALSE
;
123 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
124 ClassGuidListSize
, RequiredSize
,
125 MachineNameW
, Reserved
);
128 MyFree(MachineNameW
);
133 /***********************************************************************
134 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
136 BOOL WINAPI
SetupDiBuildClassInfoListExW(
138 LPGUID ClassGuidList
,
139 DWORD ClassGuidListSize
,
144 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
150 DWORD dwGuidListIndex
= 0;
154 if (RequiredSize
!= NULL
)
157 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
162 if (hClassesKey
== INVALID_HANDLE_VALUE
)
167 for (dwIndex
= 0; ; dwIndex
++)
169 dwLength
= MAX_GUID_STRING_LEN
+ 1;
170 lError
= RegEnumKeyExW(hClassesKey
,
178 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
179 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
181 TRACE("Key name: %p\n", szKeyName
);
183 if (RegOpenKeyExW(hClassesKey
,
189 RegCloseKey(hClassesKey
);
193 if (!RegQueryValueExW(hClassKey
,
200 TRACE("'NoUseClass' value found!\n");
201 RegCloseKey(hClassKey
);
205 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
206 (!RegQueryValueExW(hClassKey
,
213 TRACE("'NoInstallClass' value found!\n");
214 RegCloseKey(hClassKey
);
218 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
219 (!RegQueryValueExW(hClassKey
,
226 TRACE("'NoDisplayClass' value found!\n");
227 RegCloseKey(hClassKey
);
231 RegCloseKey(hClassKey
);
233 TRACE("Guid: %p\n", szKeyName
);
234 if (dwGuidListIndex
< ClassGuidListSize
)
236 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
240 TRACE("Guid: %p\n", &szKeyName
[1]);
242 UuidFromStringW(&szKeyName
[1],
243 &ClassGuidList
[dwGuidListIndex
]);
249 if (lError
!= ERROR_SUCCESS
)
253 RegCloseKey(hClassesKey
);
255 if (RequiredSize
!= NULL
)
256 *RequiredSize
= dwGuidListIndex
;
258 if (ClassGuidListSize
< dwGuidListIndex
)
260 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
267 /***********************************************************************
268 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
270 BOOL WINAPI
SetupDiClassGuidsFromNameA(
272 LPGUID ClassGuidList
,
273 DWORD ClassGuidListSize
,
276 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
277 ClassGuidListSize
, RequiredSize
,
281 /***********************************************************************
282 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
284 BOOL WINAPI
SetupDiClassGuidsFromNameW(
286 LPGUID ClassGuidList
,
287 DWORD ClassGuidListSize
,
290 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
291 ClassGuidListSize
, RequiredSize
,
295 /***********************************************************************
296 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
298 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
300 LPGUID ClassGuidList
,
301 DWORD ClassGuidListSize
,
306 LPWSTR ClassNameW
= NULL
;
307 LPWSTR MachineNameW
= NULL
;
312 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
313 if (ClassNameW
== NULL
)
318 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
319 if (MachineNameW
== NULL
)
326 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
327 ClassGuidListSize
, RequiredSize
,
328 MachineNameW
, Reserved
);
331 MyFree(MachineNameW
);
338 /***********************************************************************
339 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
341 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
343 LPGUID ClassGuidList
,
344 DWORD ClassGuidListSize
,
349 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
350 WCHAR szClassName
[256];
356 DWORD dwGuidListIndex
= 0;
358 if (RequiredSize
!= NULL
)
361 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
362 KEY_ENUMERATE_SUB_KEYS
,
366 if (hClassesKey
== INVALID_HANDLE_VALUE
)
371 for (dwIndex
= 0; ; dwIndex
++)
373 dwLength
= MAX_GUID_STRING_LEN
+ 1;
374 lError
= RegEnumKeyExW(hClassesKey
,
382 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
383 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
385 TRACE("Key name: %p\n", szKeyName
);
387 if (RegOpenKeyExW(hClassesKey
,
393 RegCloseKey(hClassesKey
);
397 dwLength
= 256 * sizeof(WCHAR
);
398 if (!RegQueryValueExW(hClassKey
,
405 TRACE("Class name: %p\n", szClassName
);
407 if (strcmpiW(szClassName
, ClassName
) == 0)
409 TRACE("Found matching class name\n");
411 TRACE("Guid: %p\n", szKeyName
);
412 if (dwGuidListIndex
< ClassGuidListSize
)
414 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
418 TRACE("Guid: %p\n", &szKeyName
[1]);
420 UuidFromStringW(&szKeyName
[1],
421 &ClassGuidList
[dwGuidListIndex
]);
428 RegCloseKey(hClassKey
);
431 if (lError
!= ERROR_SUCCESS
)
435 RegCloseKey(hClassesKey
);
437 if (RequiredSize
!= NULL
)
438 *RequiredSize
= dwGuidListIndex
;
440 if (ClassGuidListSize
< dwGuidListIndex
)
442 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
449 /***********************************************************************
450 * SetupDiClassNameFromGuidA (SETUPAPI.@)
452 BOOL WINAPI
SetupDiClassNameFromGuidA(
453 const GUID
* ClassGuid
,
458 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
459 ClassNameSize
, RequiredSize
,
463 /***********************************************************************
464 * SetupDiClassNameFromGuidW (SETUPAPI.@)
466 BOOL WINAPI
SetupDiClassNameFromGuidW(
467 const GUID
* ClassGuid
,
472 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
473 ClassNameSize
, RequiredSize
,
477 /***********************************************************************
478 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
480 BOOL WINAPI
SetupDiClassNameFromGuidExA(
481 const GUID
* ClassGuid
,
488 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
489 LPWSTR MachineNameW
= NULL
;
493 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
494 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
495 NULL
, MachineNameW
, Reserved
);
498 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
499 ClassNameSize
, NULL
, NULL
);
501 if (!ClassNameSize
&& RequiredSize
)
504 MyFree(MachineNameW
);
508 /***********************************************************************
509 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
511 BOOL WINAPI
SetupDiClassNameFromGuidExW(
512 const GUID
* ClassGuid
,
523 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
528 if (hKey
== INVALID_HANDLE_VALUE
)
533 if (RequiredSize
!= NULL
)
536 rc
= RegQueryValueExW(hKey
,
542 if (rc
!= ERROR_SUCCESS
)
549 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
552 dwLength
= ClassNameSize
* sizeof(WCHAR
);
553 rc
= RegQueryValueExW(hKey
,
559 if (rc
!= ERROR_SUCCESS
)
571 /***********************************************************************
572 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
575 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
578 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
581 /***********************************************************************
582 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
585 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
590 LPWSTR MachineNameW
= NULL
;
593 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
597 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
598 if (MachineNameW
== NULL
)
599 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
602 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
603 MachineNameW
, Reserved
);
606 MyFree(MachineNameW
);
611 /***********************************************************************
612 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
615 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
620 struct DeviceInfoSet
*list
;
623 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
625 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
628 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
629 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
631 memset(list
, 0, sizeof(struct DeviceInfoSet
));
633 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
636 ClassGuid
? ClassGuid
: &GUID_NULL
,
637 sizeof(list
->ClassGuid
));
638 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
639 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
640 list
->InstallParams
.hwndParent
= hwndParent
;
643 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
644 if (rc
!= ERROR_SUCCESS
)
647 HeapFree(GetProcessHeap(), 0, list
);
648 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
653 list
->HKLM
= HKEY_LOCAL_MACHINE
;
655 InitializeListHead(&list
->DriverListHead
);
656 InitializeListHead(&list
->ListHead
);
657 return (HDEVINFO
)list
;
660 /***********************************************************************
661 * SetupDiEnumDeviceInfo (SETUPAPI.@)
663 BOOL WINAPI
SetupDiEnumDeviceInfo(
664 HDEVINFO DeviceInfoSet
,
666 PSP_DEVINFO_DATA DeviceInfoData
)
670 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
672 SetLastError(ERROR_INVALID_PARAMETER
);
673 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
675 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
677 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
678 SetLastError(ERROR_INVALID_HANDLE
);
679 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
680 SetLastError(ERROR_INVALID_USER_BUFFER
);
683 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
684 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
685 ItemList
= ItemList
->Flink
;
686 if (ItemList
== &list
->ListHead
)
687 SetLastError(ERROR_NO_MORE_ITEMS
);
690 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
691 memcpy(&DeviceInfoData
->ClassGuid
,
694 DeviceInfoData
->DevInst
= 0; /* FIXME */
695 /* Note: this appears to be dangerous, passing a private
696 * pointer a heap-allocated datum to the caller. However, the
697 * expected lifetime of the device data is the same as the
698 * HDEVINFO; once that is closed, the data are no longer valid.
700 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
706 SetLastError(ERROR_INVALID_HANDLE
);
710 /***********************************************************************
711 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
713 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
715 PCSTR InfSectionName
,
716 PSTR InfSectionWithExt
,
717 DWORD InfSectionWithExtSize
,
721 LPWSTR InfSectionNameW
= NULL
;
722 PWSTR InfSectionWithExtW
= NULL
;
724 BOOL bResult
= FALSE
;
730 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
731 if (InfSectionNameW
== NULL
) goto end
;
733 if (InfSectionWithExt
)
735 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
736 if (InfSectionWithExtW
== NULL
) goto end
;
739 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
740 InfSectionWithExt
? InfSectionNameW
: NULL
,
741 InfSectionWithExtSize
, RequiredSize
,
742 Extension
? &ExtensionW
: NULL
);
744 if (bResult
&& InfSectionWithExt
)
746 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
747 InfSectionWithExtSize
, NULL
, NULL
) != 0;
749 if (bResult
&& Extension
)
751 if (ExtensionW
== NULL
)
754 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
758 if (InfSectionNameW
) MyFree(InfSectionNameW
);
759 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
764 /***********************************************************************
765 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
767 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
769 PCWSTR InfSectionName
,
770 PWSTR InfSectionWithExt
,
771 DWORD InfSectionWithExtSize
,
775 WCHAR szBuffer
[MAX_PATH
];
778 LONG lLineCount
= -1;
780 lstrcpyW(szBuffer
, InfSectionName
);
781 dwLength
= lstrlenW(szBuffer
);
783 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
785 /* Test section name with '.NTx86' extension */
786 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
787 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
789 if (lLineCount
== -1)
791 /* Test section name with '.NT' extension */
792 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
793 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
798 /* Test section name with '.Win' extension */
799 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
800 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
803 if (lLineCount
== -1)
805 /* Test section name without extension */
806 szBuffer
[dwLength
] = 0;
807 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
810 if (lLineCount
== -1)
812 SetLastError(ERROR_INVALID_PARAMETER
);
816 dwFullLength
= lstrlenW(szBuffer
);
818 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
820 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
822 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
826 lstrcpyW(InfSectionWithExt
, szBuffer
);
827 if (Extension
!= NULL
)
829 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
833 if (RequiredSize
!= NULL
)
835 *RequiredSize
= dwFullLength
+ 1;
841 /***********************************************************************
842 * SetupDiGetClassDescriptionA (SETUPAPI.@)
844 BOOL WINAPI
SetupDiGetClassDescriptionA(
845 const GUID
* ClassGuid
,
846 PSTR ClassDescription
,
847 DWORD ClassDescriptionSize
,
850 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
851 ClassDescriptionSize
,
852 RequiredSize
, NULL
, NULL
);
855 /***********************************************************************
856 * SetupDiGetClassDescriptionW (SETUPAPI.@)
858 BOOL WINAPI
SetupDiGetClassDescriptionW(
859 const GUID
* ClassGuid
,
860 PWSTR ClassDescription
,
861 DWORD ClassDescriptionSize
,
864 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
865 ClassDescriptionSize
,
866 RequiredSize
, NULL
, NULL
);
869 /***********************************************************************
870 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
872 BOOL WINAPI
SetupDiGetClassDescriptionExA(
873 const GUID
* ClassGuid
,
874 PSTR ClassDescription
,
875 DWORD ClassDescriptionSize
,
880 PWCHAR ClassDescriptionW
;
881 LPWSTR MachineNameW
= NULL
;
885 if (ClassDescriptionSize
> 0)
887 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
888 if (!ClassDescriptionW
)
890 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
896 ClassDescriptionW
= NULL
;
900 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
903 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
909 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
910 NULL
, MachineNameW
, Reserved
);
913 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
914 ClassDescriptionSize
, NULL
, NULL
);
916 if (!ClassDescriptionSize
&& RequiredSize
)
921 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
922 MyFree(MachineNameW
);
926 /***********************************************************************
927 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
929 BOOL WINAPI
SetupDiGetClassDescriptionExW(
930 const GUID
* ClassGuid
,
931 PWSTR ClassDescription
,
932 DWORD ClassDescriptionSize
,
940 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
945 if (hKey
== INVALID_HANDLE_VALUE
)
947 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
951 if (RequiredSize
!= NULL
)
954 if (RegQueryValueExW(hKey
,
965 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
968 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
969 if (RegQueryValueExW(hKey
,
973 (LPBYTE
)ClassDescription
,
985 /***********************************************************************
986 * SetupDiGetClassDevsA (SETUPAPI.@)
988 HDEVINFO WINAPI
SetupDiGetClassDevsA(
994 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
995 flags
, NULL
, NULL
, NULL
);
998 /***********************************************************************
999 * SetupDiGetClassDevsW (SETUPAPI.@)
1001 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1007 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1008 flags
, NULL
, NULL
, NULL
);
1011 /***********************************************************************
1012 * SetupDiGetClassDevsExA (SETUPAPI.@)
1014 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1024 LPWSTR enumstrW
= NULL
;
1025 LPWSTR machineW
= NULL
;
1029 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1030 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1033 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1036 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1040 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1041 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1044 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1047 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1049 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1052 HeapFree(GetProcessHeap(), 0, enumstrW
);
1053 HeapFree(GetProcessHeap(), 0, machineW
);
1058 CreateDeviceInfoElement(
1059 IN LPCWSTR InstancePath
,
1060 IN LPCGUID pClassGuid
,
1061 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1064 struct DeviceInfoElement
*deviceInfo
;
1066 *pDeviceInfo
= NULL
;
1068 size
= sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1069 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1072 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1075 memset(deviceInfo
, 0, size
);
1076 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1077 wcscpy(deviceInfo
->Data
, InstancePath
);
1078 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1079 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1080 deviceInfo
->DeviceDescription
= NULL
;
1081 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1082 deviceInfo
->CreationFlags
= 0;
1083 InitializeListHead(&deviceInfo
->DriverListHead
);
1084 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1086 *pDeviceInfo
= deviceInfo
;
1091 CreateDeviceInterface(
1092 IN
struct DeviceInfoElement
* deviceInfo
,
1093 IN LPCWSTR SymbolicLink
,
1094 IN LPCGUID pInterfaceGuid
,
1095 OUT
struct DeviceInterface
**pDeviceInterface
)
1097 struct DeviceInterface
*deviceInterface
;
1099 *pDeviceInterface
= NULL
;
1101 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1102 if (!deviceInterface
)
1104 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1107 deviceInterface
->DeviceInfo
= deviceInfo
;
1108 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1109 deviceInterface
->Flags
= 0; /* FIXME */
1110 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1112 *pDeviceInterface
= deviceInterface
;
1116 static LONG
SETUP_CreateDevListFromEnumerator(
1117 struct DeviceInfoSet
*list
,
1118 LPCGUID pClassGuid OPTIONAL
,
1120 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1122 HKEY hDeviceIdKey
, hInstanceIdKey
;
1123 WCHAR KeyBuffer
[MAX_PATH
];
1124 WCHAR InstancePath
[MAX_PATH
];
1125 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1126 struct DeviceInfoElement
*deviceInfo
;
1128 DWORD dwLength
, dwRegType
;
1131 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1134 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1135 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1136 if (rc
== ERROR_NO_MORE_ITEMS
)
1138 if (rc
!= ERROR_SUCCESS
)
1142 /* Open device id sub key */
1143 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1144 if (rc
!= ERROR_SUCCESS
)
1146 wcscpy(InstancePath
, Enumerator
);
1147 wcscat(InstancePath
, L
"\\");
1148 wcscat(InstancePath
, KeyBuffer
);
1149 wcscat(InstancePath
, L
"\\");
1150 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1152 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1158 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1159 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1160 if (rc
== ERROR_NO_MORE_ITEMS
)
1162 if (rc
!= ERROR_SUCCESS
)
1164 RegCloseKey(hDeviceIdKey
);
1169 /* Open instance id sub key */
1170 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1171 if (rc
!= ERROR_SUCCESS
)
1173 RegCloseKey(hDeviceIdKey
);
1176 *pEndOfInstancePath
= '\0';
1177 wcscat(InstancePath
, KeyBuffer
);
1179 /* Read ClassGUID value */
1180 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1181 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1182 RegCloseKey(hInstanceIdKey
);
1183 if (rc
== ERROR_FILE_NOT_FOUND
)
1186 /* Skip this bad entry as we can't verify it */
1188 /* Set a default GUID for this device */
1189 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1191 else if (rc
!= ERROR_SUCCESS
)
1193 RegCloseKey(hDeviceIdKey
);
1196 else if (dwRegType
!= REG_SZ
)
1198 RegCloseKey(hDeviceIdKey
);
1199 return ERROR_GEN_FAILURE
;
1203 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1204 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1205 /* Bad GUID, skip the entry */
1209 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1211 /* Skip this entry as it is not the right device class */
1215 /* Add the entry to the list */
1216 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1218 RegCloseKey(hDeviceIdKey
);
1219 return GetLastError();
1221 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1222 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1224 RegCloseKey(hDeviceIdKey
);
1227 return ERROR_SUCCESS
;
1230 static LONG
SETUP_CreateDevList(
1231 struct DeviceInfoSet
*list
,
1232 PCWSTR MachineName OPTIONAL
,
1233 LPGUID
class OPTIONAL
,
1234 PCWSTR Enumerator OPTIONAL
)
1236 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1237 WCHAR KeyBuffer
[MAX_PATH
];
1242 if (class && IsEqualIID(class, &GUID_NULL
))
1246 if (MachineName
!= NULL
)
1248 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1249 if (rc
!= ERROR_SUCCESS
)
1253 HKLM
= HKEY_LOCAL_MACHINE
;
1255 rc
= RegOpenKeyExW(HKLM
,
1258 KEY_ENUMERATE_SUB_KEYS
,
1260 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1261 if (rc
!= ERROR_SUCCESS
)
1264 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1265 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1274 KEY_ENUMERATE_SUB_KEYS
,
1276 RegCloseKey(hEnumKey
);
1277 if (rc
!= ERROR_SUCCESS
)
1279 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1280 RegCloseKey(hEnumeratorKey
);
1285 /* Enumerate enumerators */
1289 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1290 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1291 if (rc
== ERROR_NO_MORE_ITEMS
)
1293 if (rc
!= ERROR_SUCCESS
)
1295 RegCloseKey(hEnumKey
);
1301 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1302 if (rc
!= ERROR_SUCCESS
)
1304 RegCloseKey(hEnumKey
);
1308 /* Call SETUP_CreateDevListFromEnumerator */
1309 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1310 RegCloseKey(hEnumeratorKey
);
1311 if (rc
!= ERROR_SUCCESS
)
1313 RegCloseKey(hEnumKey
);
1317 RegCloseKey(hEnumKey
);
1318 return ERROR_SUCCESS
;
1323 static LONG
SETUP_CreateSerialDeviceList(
1324 struct DeviceInfoSet
*list
,
1326 LPGUID InterfaceGuid
,
1327 PCWSTR DeviceInstanceW
)
1329 static const size_t initialSize
= 100;
1331 WCHAR buf
[initialSize
];
1333 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1335 struct DeviceInfoElement
*deviceInfo
;
1338 WARN("'MachineName' is ignored on Wine!\n");
1339 if (DeviceInstanceW
)
1340 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1346 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1348 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1352 HeapFree(GetProcessHeap(), 0, devices
);
1353 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1355 return ERROR_NOT_ENOUGH_MEMORY
;
1361 HeapFree(GetProcessHeap(), 0, devices
);
1362 return GetLastError();
1366 /* 'devices' is a MULTI_SZ string */
1367 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1369 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1371 /* We have found a device */
1372 struct DeviceInterface
*interfaceInfo
;
1373 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1374 /* Step 1. Create a device info element */
1375 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1378 HeapFree(GetProcessHeap(), 0, devices
);
1379 return GetLastError();
1381 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1383 /* Step 2. Create an interface list for this element */
1384 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1387 HeapFree(GetProcessHeap(), 0, devices
);
1388 return GetLastError();
1390 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1394 HeapFree(GetProcessHeap(), 0, devices
);
1395 return ERROR_SUCCESS
;
1398 #else /* __REACTOS__ */
1400 static LONG
SETUP_CreateInterfaceList(
1401 struct DeviceInfoSet
*list
,
1403 LPGUID InterfaceGuid
,
1404 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1406 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1407 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1408 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1409 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1410 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1412 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1415 DWORD dwLength
, dwInstancePathLength
;
1418 struct DeviceInfoElement
*deviceInfo
;
1420 /* Open registry key related to this interface */
1421 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1422 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1423 return GetLastError();
1425 /* Enumerate sub keys of hInterfaceKey */
1429 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1430 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1431 if (rc
== ERROR_NO_MORE_ITEMS
)
1433 if (rc
!= ERROR_SUCCESS
)
1435 RegCloseKey(hInterfaceKey
);
1441 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1442 if (rc
!= ERROR_SUCCESS
)
1444 RegCloseKey(hInterfaceKey
);
1448 /* Read DeviceInstance */
1449 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1450 if (rc
!= ERROR_SUCCESS
)
1452 RegCloseKey(hDeviceInstanceKey
);
1453 RegCloseKey(hInterfaceKey
);
1456 if (dwRegType
!= REG_SZ
)
1458 RegCloseKey(hDeviceInstanceKey
);
1459 RegCloseKey(hInterfaceKey
);
1460 return ERROR_GEN_FAILURE
;
1462 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1465 RegCloseKey(hDeviceInstanceKey
);
1466 RegCloseKey(hInterfaceKey
);
1467 return ERROR_NOT_ENOUGH_MEMORY
;
1469 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1470 if (rc
!= ERROR_SUCCESS
)
1472 HeapFree(GetProcessHeap(), 0, InstancePath
);
1473 RegCloseKey(hDeviceInstanceKey
);
1474 RegCloseKey(hInterfaceKey
);
1477 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1478 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1480 if (DeviceInstanceW
)
1482 /* Check if device enumerator is not the right one */
1483 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1485 HeapFree(GetProcessHeap(), 0, InstancePath
);
1486 RegCloseKey(hDeviceInstanceKey
);
1491 /* Find class GUID associated to the device instance */
1496 KEY_ENUMERATE_SUB_KEYS
,
1498 if (rc
!= ERROR_SUCCESS
)
1500 HeapFree(GetProcessHeap(), 0, InstancePath
);
1501 RegCloseKey(hDeviceInstanceKey
);
1502 RegCloseKey(hInterfaceKey
);
1511 RegCloseKey(hEnumKey
);
1512 if (rc
!= ERROR_SUCCESS
)
1514 HeapFree(GetProcessHeap(), 0, InstancePath
);
1515 RegCloseKey(hDeviceInstanceKey
);
1516 RegCloseKey(hInterfaceKey
);
1519 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1520 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1522 if (rc
!= ERROR_SUCCESS
)
1524 HeapFree(GetProcessHeap(), 0, InstancePath
);
1525 RegCloseKey(hDeviceInstanceKey
);
1526 RegCloseKey(hInterfaceKey
);
1529 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1530 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1531 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1533 HeapFree(GetProcessHeap(), 0, InstancePath
);
1534 RegCloseKey(hDeviceInstanceKey
);
1535 RegCloseKey(hInterfaceKey
);
1536 return ERROR_GEN_FAILURE
;
1538 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1540 /* If current device doesn't match the list GUID (if any), skip this entry */
1541 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1543 HeapFree(GetProcessHeap(), 0, InstancePath
);
1544 RegCloseKey(hDeviceInstanceKey
);
1548 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1552 LPWSTR pSymbolicLink
;
1553 struct DeviceInterface
*interfaceInfo
;
1555 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1556 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1557 if (rc
== ERROR_NO_MORE_ITEMS
)
1559 if (rc
!= ERROR_SUCCESS
)
1561 HeapFree(GetProcessHeap(), 0, InstancePath
);
1562 RegCloseKey(hDeviceInstanceKey
);
1563 RegCloseKey(hInterfaceKey
);
1567 if (KeyBuffer
[0] != '#')
1568 /* This entry doesn't represent an interesting entry */
1572 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1573 if (rc
!= ERROR_SUCCESS
)
1575 RegCloseKey(hDeviceInstanceKey
);
1576 RegCloseKey(hInterfaceKey
);
1580 /* Read SymbolicLink value */
1581 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1582 if (rc
!= ERROR_SUCCESS
)
1584 RegCloseKey(hReferenceKey
);
1585 RegCloseKey(hDeviceInstanceKey
);
1586 RegCloseKey(hInterfaceKey
);
1589 if (dwRegType
!= REG_SZ
)
1591 RegCloseKey(hReferenceKey
);
1592 RegCloseKey(hDeviceInstanceKey
);
1593 RegCloseKey(hInterfaceKey
);
1594 return ERROR_GEN_FAILURE
;
1597 /* We have found a device */
1598 /* Step 1. Create a device info element */
1599 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1601 RegCloseKey(hReferenceKey
);
1602 RegCloseKey(hDeviceInstanceKey
);
1603 RegCloseKey(hInterfaceKey
);
1604 return GetLastError();
1606 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1607 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1609 /* Step 2. Create an interface list for this element */
1610 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1613 RegCloseKey(hReferenceKey
);
1614 RegCloseKey(hDeviceInstanceKey
);
1615 RegCloseKey(hInterfaceKey
);
1616 return ERROR_NOT_ENOUGH_MEMORY
;
1618 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1619 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1620 RegCloseKey(hReferenceKey
);
1621 if (rc
!= ERROR_SUCCESS
)
1623 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1624 RegCloseKey(hDeviceInstanceKey
);
1625 RegCloseKey(hInterfaceKey
);
1628 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1630 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1631 RegCloseKey(hDeviceInstanceKey
);
1632 RegCloseKey(hInterfaceKey
);
1633 return GetLastError();
1635 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1636 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1637 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1639 RegCloseKey(hDeviceInstanceKey
);
1641 RegCloseKey(hInterfaceKey
);
1642 return ERROR_SUCCESS
;
1644 #endif /* __REACTOS__ */
1646 /***********************************************************************
1647 * SetupDiGetClassDevsExW (SETUPAPI.@)
1649 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1658 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1659 struct DeviceInfoSet
*list
;
1663 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1664 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1666 /* Create the deviceset if not set */
1669 list
= (struct DeviceInfoSet
*)deviceset
;
1670 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1672 SetLastError(ERROR_INVALID_HANDLE
);
1673 return INVALID_HANDLE_VALUE
;
1675 hDeviceInfo
= deviceset
;
1679 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1680 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1681 NULL
, machine
, NULL
);
1682 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1683 return INVALID_HANDLE_VALUE
;
1684 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1687 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1690 pClassGuid
= &list
->ClassGuid
;
1692 if (flags
& DIGCF_PRESENT
)
1693 FIXME(": flag DIGCF_PRESENT ignored\n");
1694 if (flags
& DIGCF_PROFILE
)
1695 FIXME(": flag DIGCF_PROFILE ignored\n");
1697 if (flags
& DIGCF_ALLCLASSES
)
1699 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1700 if (rc
!= ERROR_SUCCESS
)
1704 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1705 return INVALID_HANDLE_VALUE
;
1709 else if (flags
& DIGCF_DEVICEINTERFACE
)
1713 SetLastError(ERROR_INVALID_PARAMETER
);
1715 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1716 return INVALID_HANDLE_VALUE
;
1720 /* Special case: find serial ports by calling QueryDosDevice */
1721 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1722 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1723 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1724 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1727 ERR("Wine can only enumerate serial devices at the moment!\n");
1728 rc
= ERROR_INVALID_PARAMETER
;
1730 #else /* __REACTOS__ */
1731 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1732 #endif /* __REACTOS__ */
1733 if (rc
!= ERROR_SUCCESS
)
1737 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1738 return INVALID_HANDLE_VALUE
;
1744 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1745 if (rc
!= ERROR_SUCCESS
)
1749 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1750 return INVALID_HANDLE_VALUE
;
1756 /***********************************************************************
1757 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1759 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1760 HDEVINFO DeviceInfoSet
,
1761 PSP_DEVINFO_DATA DeviceInfoData
,
1762 CONST GUID
* InterfaceClassGuid
,
1764 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1768 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1769 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1771 if (!DeviceInterfaceData
)
1772 SetLastError(ERROR_INVALID_PARAMETER
);
1773 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1774 SetLastError(ERROR_INVALID_USER_BUFFER
);
1775 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1777 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1779 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1781 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1783 while (ItemList
!= &list
->ListHead
&& !Found
)
1785 PLIST_ENTRY InterfaceListEntry
;
1786 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1787 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1789 /* We are not searching for this element */
1790 ItemList
= ItemList
->Flink
;
1793 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1794 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1796 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1797 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1799 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1802 if (MemberIndex
-- == 0)
1804 /* return this item */
1805 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1806 &DevItf
->InterfaceClassGuid
,
1808 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1809 /* Note: this appears to be dangerous, passing a private
1810 * pointer a heap-allocated datum to the caller. However, the
1811 * expected lifetime of the device data is the same as the
1812 * HDEVINFO; once that is closed, the data are no longer valid.
1814 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1817 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1819 ItemList
= ItemList
->Flink
;
1822 SetLastError(ERROR_NO_MORE_ITEMS
);
1827 SetLastError(ERROR_INVALID_HANDLE
);
1830 SetLastError(ERROR_INVALID_HANDLE
);
1834 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
1836 InterlockedIncrement(&infFile
->References
);
1839 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
1841 if (InterlockedDecrement(&infFile
->References
) == 0)
1843 SetupCloseInfFile(infFile
->hInf
);
1844 HeapFree(GetProcessHeap(), 0, infFile
);
1848 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
1850 DereferenceInfFile(driverInfo
->InfFileDetails
);
1851 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
1852 HeapFree(GetProcessHeap(), 0, driverInfo
);
1856 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
1858 PLIST_ENTRY ListEntry
;
1859 struct DriverInfoElement
*driverInfo
;
1861 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1863 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1864 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
1865 if (!DestroyDriverInfoElement(driverInfo
))
1868 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1870 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1871 HeapFree(GetProcessHeap(), 0, ListEntry
);
1873 HeapFree(GetProcessHeap(), 0, deviceInfo
);
1877 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
1879 PLIST_ENTRY ListEntry
;
1880 struct DeviceInfoElement
*deviceInfo
;
1882 while (!IsListEmpty(&list
->ListHead
))
1884 ListEntry
= RemoveHeadList(&list
->ListHead
);
1885 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1886 if (!DestroyDeviceInfoElement(deviceInfo
))
1889 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1890 RegCloseKey(list
->HKLM
);
1891 HeapFree(GetProcessHeap(), 0, list
);
1895 /***********************************************************************
1896 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1898 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1902 TRACE("%p\n", devinfo
);
1903 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1905 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1907 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1908 ret
= DestroyDeviceInfoSet(list
);
1910 SetLastError(ERROR_INVALID_HANDLE
);
1913 SetLastError(ERROR_INVALID_HANDLE
);
1915 TRACE("Returning %d\n", ret
);
1919 /***********************************************************************
1920 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1922 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1923 HDEVINFO DeviceInfoSet
,
1924 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1925 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1926 DWORD DeviceInterfaceDetailDataSize
,
1927 PDWORD RequiredSize
,
1928 PSP_DEVINFO_DATA DeviceInfoData
)
1930 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
1931 DWORD sizeW
= 0, sizeA
;
1934 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
1935 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1936 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1938 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
1939 SetLastError(ERROR_INVALID_USER_BUFFER
);
1940 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
1941 SetLastError(ERROR_INVALID_PARAMETER
);
1942 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
1943 SetLastError(ERROR_INVALID_PARAMETER
);
1946 if (DeviceInterfaceDetailData
!= NULL
)
1948 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
1949 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
1950 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
1951 if (!DeviceInterfaceDetailDataW
)
1953 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1956 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
1958 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
1959 ret
= SetupDiGetDeviceInterfaceDetailW(
1961 DeviceInterfaceData
,
1962 DeviceInterfaceDetailDataW
,
1966 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
1967 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
1969 *RequiredSize
= sizeA
;
1970 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
1972 if (!WideCharToMultiByte(
1974 DeviceInterfaceDetailDataW
->DevicePath
, -1,
1975 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
1982 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
1985 TRACE("Returning %d\n", ret
);
1989 /***********************************************************************
1990 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1992 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
1993 HDEVINFO DeviceInfoSet
,
1994 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1995 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
1996 DWORD DeviceInterfaceDetailDataSize
,
1997 PDWORD RequiredSize
,
1998 PSP_DEVINFO_DATA DeviceInfoData
)
2002 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2003 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2004 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2006 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2007 SetLastError(ERROR_INVALID_PARAMETER
);
2008 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2009 SetLastError(ERROR_INVALID_HANDLE
);
2010 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2011 SetLastError(ERROR_INVALID_HANDLE
);
2012 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2013 SetLastError(ERROR_INVALID_USER_BUFFER
);
2014 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2015 SetLastError(ERROR_INVALID_USER_BUFFER
);
2016 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2017 SetLastError(ERROR_INVALID_USER_BUFFER
);
2018 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2019 SetLastError(ERROR_INVALID_PARAMETER
);
2020 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2021 SetLastError(ERROR_INVALID_PARAMETER
);
2024 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2025 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2026 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2027 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2029 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2031 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2033 *RequiredSize
= sizeRequired
;
2037 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2038 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2041 memcpy(&DeviceInfoData
->ClassGuid
,
2042 &deviceInterface
->DeviceInfo
->ClassGuid
,
2044 DeviceInfoData
->DevInst
= 0; /* FIXME */
2045 /* Note: this appears to be dangerous, passing a private
2046 * pointer a heap-allocated datum to the caller. However, the
2047 * expected lifetime of the device data is the same as the
2048 * HDEVINFO; once that is closed, the data are no longer valid.
2050 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2056 TRACE("Returning %d\n", ret
);
2060 /***********************************************************************
2061 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2063 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2065 PSP_DEVINFO_DATA DeviceInfoData
,
2067 PDWORD PropertyRegDataType
,
2068 PBYTE PropertyBuffer
,
2069 DWORD PropertyBufferSize
,
2070 PDWORD RequiredSize
)
2073 BOOL bIsStringProperty
;
2075 DWORD RequiredSizeA
, RequiredSizeW
;
2076 DWORD PropertyBufferSizeW
;
2077 PBYTE PropertyBufferW
;
2079 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2080 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2083 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2084 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2086 bResult
= SetupDiGetDeviceRegistryPropertyW(
2092 PropertyBufferSizeW
,
2095 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2097 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2099 if (bIsStringProperty
)
2100 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2102 RequiredSizeA
= RequiredSizeW
;
2104 *RequiredSize
= RequiredSizeA
;
2105 if (PropertyRegDataType
)
2106 *PropertyRegDataType
= RegType
;
2111 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2115 if (RequiredSizeA
<= PropertyBufferSize
)
2117 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2119 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2121 /* Last error is already set by WideCharToMultiByte */
2126 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2130 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2134 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2138 /***********************************************************************
2139 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2141 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2142 HDEVINFO DeviceInfoSet
,
2143 PSP_DEVINFO_DATA DeviceInfoData
,
2145 PDWORD PropertyRegDataType
,
2146 PBYTE PropertyBuffer
,
2147 DWORD PropertyBufferSize
,
2148 PDWORD RequiredSize
)
2150 HKEY hEnumKey
, hKey
;
2154 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2155 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2158 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2159 SetLastError(ERROR_INVALID_HANDLE
);
2160 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2161 SetLastError(ERROR_INVALID_HANDLE
);
2162 else if (!DeviceInfoData
)
2163 SetLastError(ERROR_INVALID_PARAMETER
);
2164 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2165 SetLastError(ERROR_INVALID_USER_BUFFER
);
2166 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2167 SetLastError(ERROR_INVALID_PARAMETER
);
2170 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2171 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2175 case SPDRP_CAPABILITIES
:
2177 case SPDRP_CLASSGUID
:
2178 case SPDRP_COMPATIBLEIDS
:
2179 case SPDRP_CONFIGFLAGS
:
2180 case SPDRP_DEVICEDESC
:
2182 case SPDRP_FRIENDLYNAME
:
2183 case SPDRP_HARDWAREID
:
2184 case SPDRP_LOCATION_INFORMATION
:
2185 case SPDRP_LOWERFILTERS
:
2187 case SPDRP_SECURITY
:
2189 case SPDRP_UI_NUMBER
:
2190 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2191 case SPDRP_UPPERFILTERS
:
2193 LPCWSTR RegistryPropertyName
;
2198 case SPDRP_CAPABILITIES
:
2199 RegistryPropertyName
= L
"Capabilities"; break;
2201 RegistryPropertyName
= L
"Class"; break;
2202 case SPDRP_CLASSGUID
:
2203 RegistryPropertyName
= L
"ClassGUID"; break;
2204 case SPDRP_COMPATIBLEIDS
:
2205 RegistryPropertyName
= L
"CompatibleIDs"; break;
2206 case SPDRP_CONFIGFLAGS
:
2207 RegistryPropertyName
= L
"ConfigFlags"; break;
2208 case SPDRP_DEVICEDESC
:
2209 RegistryPropertyName
= L
"DeviceDesc"; break;
2211 RegistryPropertyName
= L
"Driver"; break;
2212 case SPDRP_FRIENDLYNAME
:
2213 RegistryPropertyName
= L
"FriendlyName"; break;
2214 case SPDRP_HARDWAREID
:
2215 RegistryPropertyName
= L
"HardwareID"; break;
2216 case SPDRP_LOCATION_INFORMATION
:
2217 RegistryPropertyName
= L
"LocationInformation"; break;
2218 case SPDRP_LOWERFILTERS
:
2219 RegistryPropertyName
= L
"LowerFilters"; break;
2221 RegistryPropertyName
= L
"Mfg"; break;
2222 case SPDRP_SECURITY
:
2223 RegistryPropertyName
= L
"Security"; break;
2225 RegistryPropertyName
= L
"Service"; break;
2226 case SPDRP_UI_NUMBER
:
2227 RegistryPropertyName
= L
"UINumber"; break;
2228 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2229 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2230 case SPDRP_UPPERFILTERS
:
2231 RegistryPropertyName
= L
"UpperFilters"; break;
2233 /* Should not happen */
2234 RegistryPropertyName
= NULL
; break;
2237 /* Open registry key name */
2242 KEY_ENUMERATE_SUB_KEYS
,
2244 if (rc
!= ERROR_SUCCESS
)
2255 RegCloseKey(hEnumKey
);
2256 if (rc
!= ERROR_SUCCESS
)
2261 /* Read registry entry */
2262 BufferSize
= PropertyBufferSize
;
2263 rc
= RegQueryValueExW(
2265 RegistryPropertyName
,
2266 NULL
, /* Reserved */
2267 PropertyRegDataType
,
2271 *RequiredSize
= BufferSize
;
2274 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2277 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2279 case ERROR_MORE_DATA
:
2280 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2289 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2291 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2293 if (PropertyRegDataType
)
2294 *PropertyRegDataType
= REG_SZ
;
2296 *RequiredSize
= required
;
2297 if (PropertyBufferSize
>= required
)
2299 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2303 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2307 /*case SPDRP_BUSTYPEGUID:
2308 case SPDRP_LEGACYBUSTYPE:
2309 case SPDRP_BUSNUMBER:
2310 case SPDRP_ENUMERATOR_NAME:
2311 case SPDRP_SECURITY_SDS:
2313 case SPDRP_EXCLUSIVE:
2314 case SPDRP_CHARACTERISTICS:
2316 case SPDRP_DEVICE_POWER_DATA:*/
2317 #if (WINVER >= 0x501)
2318 /*case SPDRP_REMOVAL_POLICY:
2319 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2320 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2321 case SPDRP_INSTALL_STATE:*/
2326 FIXME("Property 0x%lx not implemented\n", Property
);
2327 SetLastError(ERROR_NOT_SUPPORTED
);
2332 TRACE("Returning %d\n", ret
);
2336 /***********************************************************************
2337 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2339 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2340 IN HDEVINFO DeviceInfoSet
,
2341 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2343 IN CONST BYTE
*PropertyBuffer
,
2344 IN DWORD PropertyBufferSize
)
2346 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2347 Property
, PropertyBuffer
, PropertyBufferSize
);
2348 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2352 /***********************************************************************
2353 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2355 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2356 IN HDEVINFO DeviceInfoSet
,
2357 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2359 IN
const BYTE
*PropertyBuffer
,
2360 IN DWORD PropertyBufferSize
)
2362 struct DeviceInfoSet
*list
;
2365 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2366 Property
, PropertyBuffer
, PropertyBufferSize
);
2369 SetLastError(ERROR_INVALID_HANDLE
);
2370 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2371 SetLastError(ERROR_INVALID_HANDLE
);
2372 else if (DeviceInfoData
)
2373 SetLastError(ERROR_INVALID_HANDLE
);
2374 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2375 SetLastError(ERROR_INVALID_USER_BUFFER
);
2380 case SPDRP_COMPATIBLEIDS
:
2381 case SPDRP_CONFIGFLAGS
:
2382 case SPDRP_FRIENDLYNAME
:
2383 case SPDRP_HARDWAREID
:
2384 case SPDRP_LOCATION_INFORMATION
:
2385 case SPDRP_LOWERFILTERS
:
2386 case SPDRP_SECURITY
:
2388 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2389 case SPDRP_UPPERFILTERS
:
2391 LPCWSTR RegistryPropertyName
;
2392 DWORD RegistryDataType
;
2398 case SPDRP_COMPATIBLEIDS
:
2399 RegistryPropertyName
= L
"CompatibleIDs";
2400 RegistryDataType
= REG_MULTI_SZ
;
2402 case SPDRP_CONFIGFLAGS
:
2403 RegistryPropertyName
= L
"ConfigFlags";
2404 RegistryDataType
= REG_DWORD
;
2406 case SPDRP_FRIENDLYNAME
:
2407 RegistryPropertyName
= L
"FriendlyName";
2408 RegistryDataType
= REG_SZ
;
2410 case SPDRP_HARDWAREID
:
2411 RegistryPropertyName
= L
"HardwareID";
2412 RegistryDataType
= REG_MULTI_SZ
;
2414 case SPDRP_LOCATION_INFORMATION
:
2415 RegistryPropertyName
= L
"LocationInformation";
2416 RegistryDataType
= REG_SZ
;
2418 case SPDRP_LOWERFILTERS
:
2419 RegistryPropertyName
= L
"LowerFilters";
2420 RegistryDataType
= REG_MULTI_SZ
;
2422 case SPDRP_SECURITY
:
2423 RegistryPropertyName
= L
"Security";
2424 RegistryDataType
= REG_BINARY
;
2427 RegistryPropertyName
= L
"Service";
2428 RegistryDataType
= REG_SZ
;
2430 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2431 RegistryPropertyName
= L
"UINumberDescFormat";
2432 RegistryDataType
= REG_SZ
;
2434 case SPDRP_UPPERFILTERS
:
2435 RegistryPropertyName
= L
"UpperFilters";
2436 RegistryDataType
= REG_MULTI_SZ
;
2439 /* Should not happen */
2440 RegistryPropertyName
= NULL
;
2441 RegistryDataType
= REG_BINARY
;
2444 /* Open device registry key */
2445 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2446 if (hKey
!= INVALID_HANDLE_VALUE
)
2448 /* Write new data */
2449 rc
= RegSetValueExW(
2451 RegistryPropertyName
,
2455 PropertyBufferSize
);
2456 if (rc
== ERROR_SUCCESS
)
2465 /*case SPDRP_CHARACTERISTICS:
2467 case SPDRP_EXCLUSIVE:*/
2468 #if (WINVER >= 0x501)
2469 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2471 //case SPDRP_SECURITY_SDS:
2475 FIXME("Property 0x%lx not implemented\n", Property
);
2476 SetLastError(ERROR_NOT_SUPPORTED
);
2481 TRACE("Returning %d\n", ret
);
2485 /***********************************************************************
2486 * SetupDiInstallClassA (SETUPAPI.@)
2488 BOOL WINAPI
SetupDiInstallClassA(
2494 UNICODE_STRING FileNameW
;
2497 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2499 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2503 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2505 RtlFreeUnicodeString(&FileNameW
);
2510 static HKEY
CreateClassKey(HINF hInf
)
2512 WCHAR FullBuffer
[MAX_PATH
];
2513 WCHAR Buffer
[MAX_PATH
];
2518 if (!SetupGetLineTextW(NULL
,
2526 return INVALID_HANDLE_VALUE
;
2529 lstrcpyW(FullBuffer
, ControlClass
);
2530 lstrcatW(FullBuffer
, Buffer
);
2533 if (!SetupGetLineTextW(NULL
,
2541 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2542 return INVALID_HANDLE_VALUE
;
2545 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2549 REG_OPTION_NON_VOLATILE
,
2555 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2556 return INVALID_HANDLE_VALUE
;
2559 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2564 RequiredSize
* sizeof(WCHAR
)))
2566 RegCloseKey(hClassKey
);
2567 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2568 return INVALID_HANDLE_VALUE
;
2574 /***********************************************************************
2575 * SetupDiInstallClassW (SETUPAPI.@)
2577 BOOL WINAPI
SetupDiInstallClassW(
2583 WCHAR SectionName
[MAX_PATH
];
2584 DWORD SectionNameLength
= 0;
2586 BOOL bFileQueueCreated
= FALSE
;
2589 FIXME("not fully implemented\n");
2591 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2593 SetLastError(ERROR_INVALID_PARAMETER
);
2597 /* Open the .inf file */
2598 hInf
= SetupOpenInfFileW(InfFileName
,
2602 if (hInf
== INVALID_HANDLE_VALUE
)
2608 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2609 hClassKey
= CreateClassKey(hInf
);
2610 if (hClassKey
== INVALID_HANDLE_VALUE
)
2612 SetupCloseInfFile(hInf
);
2618 /* Try to append a layout file */
2620 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2623 /* Retrieve the actual section name */
2624 SetupDiGetActualSectionToInstallW(hInf
,
2632 if (!(Flags
& DI_NOVCP
))
2634 FileQueue
= SetupOpenFileQueue();
2635 if (FileQueue
== INVALID_HANDLE_VALUE
)
2637 SetupCloseInfFile(hInf
);
2638 RegCloseKey(hClassKey
);
2642 bFileQueueCreated
= TRUE
;
2647 SetupInstallFromInfSectionW(NULL
,
2656 INVALID_HANDLE_VALUE
,
2659 /* FIXME: More code! */
2661 if (bFileQueueCreated
)
2662 SetupCloseFileQueue(FileQueue
);
2664 SetupCloseInfFile(hInf
);
2666 RegCloseKey(hClassKey
);
2671 /***********************************************************************
2672 * SetupDiOpenClassRegKey (SETUPAPI.@)
2674 HKEY WINAPI
SetupDiOpenClassRegKey(
2675 const GUID
* ClassGuid
,
2678 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2679 DIOCR_INSTALLER
, NULL
, NULL
);
2683 /***********************************************************************
2684 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2686 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2687 const GUID
* ClassGuid
,
2693 PWSTR MachineNameW
= NULL
;
2700 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2701 if (MachineNameW
== NULL
)
2702 return INVALID_HANDLE_VALUE
;
2705 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2706 Flags
, MachineNameW
, Reserved
);
2709 MyFree(MachineNameW
);
2715 /***********************************************************************
2716 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2718 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2719 const GUID
* ClassGuid
,
2725 LPWSTR lpGuidString
;
2726 LPWSTR lpFullGuidString
;
2734 if (Flags
== DIOCR_INSTALLER
)
2736 lpKeyName
= ControlClass
;
2738 else if (Flags
== DIOCR_INTERFACE
)
2740 lpKeyName
= DeviceClasses
;
2744 ERR("Invalid Flags parameter!\n");
2745 SetLastError(ERROR_INVALID_PARAMETER
);
2746 return INVALID_HANDLE_VALUE
;
2749 if (MachineName
!= NULL
)
2751 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2752 if (rc
!= ERROR_SUCCESS
)
2755 return INVALID_HANDLE_VALUE
;
2759 HKLM
= HKEY_LOCAL_MACHINE
;
2761 rc
= RegOpenKeyExW(HKLM
,
2766 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2767 if (rc
!= ERROR_SUCCESS
)
2770 return INVALID_HANDLE_VALUE
;
2773 if (ClassGuid
== NULL
)
2776 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2778 SetLastError(ERROR_GEN_FAILURE
);
2779 RegCloseKey(hClassesKey
);
2780 return INVALID_HANDLE_VALUE
;
2783 dwLength
= lstrlenW(lpGuidString
);
2784 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2785 if (!lpFullGuidString
)
2787 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2788 RpcStringFreeW(&lpGuidString
);
2789 return INVALID_HANDLE_VALUE
;
2791 lpFullGuidString
[0] = '{';
2792 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2793 lpFullGuidString
[dwLength
+ 1] = '}';
2794 lpFullGuidString
[dwLength
+ 2] = '\0';
2795 RpcStringFreeW(&lpGuidString
);
2797 rc
= RegOpenKeyExW(hClassesKey
,
2802 if (rc
!= ERROR_SUCCESS
)
2805 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2806 RegCloseKey(hClassesKey
);
2807 return INVALID_HANDLE_VALUE
;
2810 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2811 RegCloseKey(hClassesKey
);
2816 /***********************************************************************
2817 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2819 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2820 HDEVINFO DeviceInfoSet
,
2823 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2825 FIXME("%p %s %08lx %p\n",
2826 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2830 /***********************************************************************
2831 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2833 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2834 HDEVINFO DeviceInfoSet
,
2837 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2839 LPWSTR DevicePathW
= NULL
;
2842 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2844 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2845 if (DevicePathW
== NULL
)
2848 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2849 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2851 MyFree(DevicePathW
);
2856 /***********************************************************************
2857 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2859 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2860 HDEVINFO DeviceInfoSet
,
2861 PSP_DEVINFO_DATA DeviceInfoData
,
2862 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2863 DWORD ClassInstallParamsSize
)
2865 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2866 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2872 IN PWSTR InstallerName
,
2873 OUT HMODULE
* ModulePointer
,
2874 OUT PVOID
* FunctionPointer
)
2876 HMODULE hModule
= NULL
;
2877 LPSTR FunctionNameA
= NULL
;
2881 *ModulePointer
= NULL
;
2882 *FunctionPointer
= NULL
;
2884 Comma
= strchrW(InstallerName
, ',');
2887 rc
= ERROR_INVALID_PARAMETER
;
2893 hModule
= LoadLibraryW(InstallerName
);
2897 rc
= GetLastError();
2901 /* Skip comma spaces */
2902 while (*Comma
== ',' || isspaceW(*Comma
))
2905 /* W->A conversion for function name */
2906 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
2909 rc
= GetLastError();
2913 /* Search function */
2914 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
2915 if (!*FunctionPointer
)
2917 rc
= GetLastError();
2921 *ModulePointer
= hModule
;
2925 if (rc
!= ERROR_SUCCESS
&& hModule
)
2926 FreeLibrary(hModule
);
2927 MyFree(FunctionNameA
);
2932 FreeFunctionPointer(
2933 IN HMODULE ModulePointer
,
2934 IN PVOID FunctionPointer
)
2936 if (ModulePointer
== NULL
)
2937 return ERROR_SUCCESS
;
2938 if (FreeLibrary(ModulePointer
))
2939 return ERROR_SUCCESS
;
2941 return GetLastError();
2944 /***********************************************************************
2945 * SetupDiCallClassInstaller (SETUPAPI.@)
2947 BOOL WINAPI
SetupDiCallClassInstaller(
2948 IN DI_FUNCTION InstallFunction
,
2949 IN HDEVINFO DeviceInfoSet
,
2950 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2954 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2957 SetLastError(ERROR_INVALID_PARAMETER
);
2958 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2959 SetLastError(ERROR_INVALID_HANDLE
);
2960 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2961 SetLastError(ERROR_INVALID_HANDLE
);
2962 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2963 SetLastError(ERROR_INVALID_HANDLE
);
2964 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2965 SetLastError(ERROR_INVALID_USER_BUFFER
);
2968 SP_DEVINSTALL_PARAMS_W InstallParams
;
2969 #define CLASS_COINSTALLER 0x1
2970 #define DEVICE_COINSTALLER 0x2
2971 #define CLASS_INSTALLER 0x4
2972 UCHAR CanHandle
= 0;
2973 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2975 switch (InstallFunction
)
2977 case DIF_ALLOW_INSTALL
:
2978 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2980 case DIF_DESTROYPRIVATEDATA
:
2981 CanHandle
= CLASS_INSTALLER
;
2983 case DIF_INSTALLDEVICE
:
2984 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2985 DefaultHandler
= SetupDiInstallDevice
;
2987 case DIF_INSTALLDEVICEFILES
:
2988 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2989 DefaultHandler
= SetupDiInstallDriverFiles
;
2991 case DIF_INSTALLINTERFACES
:
2992 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2993 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2995 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2996 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2998 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2999 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3001 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3002 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3004 case DIF_REGISTER_COINSTALLERS
:
3005 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3006 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3008 case DIF_SELECTBESTCOMPATDRV
:
3009 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3010 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3013 FIXME("Install function %ld not implemented\n", InstallFunction
);
3014 SetLastError(ERROR_INVALID_PARAMETER
);
3017 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3018 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3019 /* Don't process this call, as a parameter is invalid */
3024 LIST_ENTRY ClassCoInstallersListHead
;
3025 LIST_ENTRY DeviceCoInstallersListHead
;
3026 HMODULE ClassInstallerLibrary
= NULL
;
3027 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3028 COINSTALLER_CONTEXT_DATA Context
;
3029 PLIST_ENTRY ListEntry
;
3031 DWORD dwRegType
, dwLength
;
3032 DWORD rc
= NO_ERROR
;
3034 InitializeListHead(&ClassCoInstallersListHead
);
3035 InitializeListHead(&DeviceCoInstallersListHead
);
3037 if (CanHandle
& DEVICE_COINSTALLER
)
3039 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3040 if (hKey
!= INVALID_HANDLE_VALUE
)
3042 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3043 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3045 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3046 if (KeyBuffer
!= NULL
)
3048 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3049 if (rc
== ERROR_SUCCESS
)
3052 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3054 /* Add coinstaller to DeviceCoInstallersListHead list */
3055 struct CoInstallerElement
*coinstaller
;
3056 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3057 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3060 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3061 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3062 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3064 HeapFree(GetProcessHeap(), 0, coinstaller
);
3067 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3073 if (CanHandle
& CLASS_COINSTALLER
)
3077 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3081 if (rc
== ERROR_SUCCESS
)
3083 LPWSTR lpGuidString
;
3084 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3086 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3087 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3089 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3090 if (KeyBuffer
!= NULL
)
3092 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3093 if (rc
== ERROR_SUCCESS
)
3096 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3098 /* Add coinstaller to ClassCoInstallersListHead list */
3099 struct CoInstallerElement
*coinstaller
;
3100 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3101 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3104 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3105 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3106 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3108 HeapFree(GetProcessHeap(), 0, coinstaller
);
3111 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3114 RpcStringFreeW(&lpGuidString
);
3119 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3121 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3122 if (hKey
!= INVALID_HANDLE_VALUE
)
3124 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3125 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3127 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3128 if (KeyBuffer
!= NULL
)
3130 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3131 if (rc
== ERROR_SUCCESS
)
3133 /* Get ClassInstaller function pointer */
3134 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3135 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3137 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3138 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3141 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3148 /* Call Class co-installers */
3149 Context
.PostProcessing
= FALSE
;
3151 ListEntry
= ClassCoInstallersListHead
.Flink
;
3152 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3154 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3155 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3156 coinstaller
->PrivateData
= Context
.PrivateData
;
3157 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3159 coinstaller
->DoPostProcessing
= TRUE
;
3162 ListEntry
= ListEntry
->Flink
;
3165 /* Call Device co-installers */
3166 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3167 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3169 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3170 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3171 coinstaller
->PrivateData
= Context
.PrivateData
;
3172 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3174 coinstaller
->DoPostProcessing
= TRUE
;
3177 ListEntry
= ListEntry
->Flink
;
3180 /* Call Class installer */
3183 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3184 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3187 rc
= ERROR_DI_DO_DEFAULT
;
3189 /* Call default handler */
3190 if (rc
== ERROR_DI_DO_DEFAULT
)
3192 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3194 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3197 rc
= GetLastError();
3203 /* Call Class co-installers that required postprocessing */
3204 Context
.PostProcessing
= TRUE
;
3205 ListEntry
= ClassCoInstallersListHead
.Flink
;
3206 while (ListEntry
!= &ClassCoInstallersListHead
)
3208 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3209 if (coinstaller
->DoPostProcessing
)
3211 Context
.InstallResult
= rc
;
3212 Context
.PrivateData
= coinstaller
->PrivateData
;
3213 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3215 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3216 ListEntry
= ListEntry
->Flink
;
3219 /* Call Device co-installers that required postprocessing */
3220 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3221 while (ListEntry
!= &DeviceCoInstallersListHead
)
3223 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3224 if (coinstaller
->DoPostProcessing
)
3226 Context
.InstallResult
= rc
;
3227 Context
.PrivateData
= coinstaller
->PrivateData
;
3228 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3230 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3231 ListEntry
= ListEntry
->Flink
;
3234 /* Free allocated memory */
3235 while (!IsListEmpty(&ClassCoInstallersListHead
))
3237 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3238 HeapFree(GetProcessHeap(), 0, ListEntry
);
3240 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3242 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3243 HeapFree(GetProcessHeap(), 0, ListEntry
);
3246 ret
= (rc
== NO_ERROR
);
3250 TRACE("Returning %d\n", ret
);
3254 /***********************************************************************
3255 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3257 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3258 IN HDEVINFO DeviceInfoSet
,
3259 IN PSP_DEVINFO_DATA DeviceInfoData
,
3260 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3262 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3265 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3267 if (DeviceInstallParams
== NULL
)
3268 SetLastError(ERROR_INVALID_PARAMETER
);
3269 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3270 SetLastError(ERROR_INVALID_USER_BUFFER
);
3273 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3274 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3278 /* Do W->A conversion */
3280 DeviceInstallParams
,
3281 &deviceInstallParamsW
,
3282 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3283 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3284 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3286 DeviceInstallParams
->DriverPath
[0] = '\0';
3292 TRACE("Returning %d\n", ret
);
3296 /***********************************************************************
3297 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3299 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3300 IN HDEVINFO DeviceInfoSet
,
3301 IN PSP_DEVINFO_DATA DeviceInfoData
,
3302 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3304 struct DeviceInfoSet
*list
;
3307 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3310 SetLastError(ERROR_INVALID_HANDLE
);
3311 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3312 SetLastError(ERROR_INVALID_HANDLE
);
3313 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3314 SetLastError(ERROR_INVALID_USER_BUFFER
);
3315 else if (!DeviceInstallParams
)
3316 SetLastError(ERROR_INVALID_PARAMETER
);
3317 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3318 SetLastError(ERROR_INVALID_USER_BUFFER
);
3321 PSP_DEVINSTALL_PARAMS_W Source
;
3324 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3326 Source
= &list
->InstallParams
;
3327 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3331 TRACE("Returning %d\n", ret
);
3335 /***********************************************************************
3336 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3338 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3339 IN HDEVINFO DeviceInfoSet
,
3340 IN PSP_DEVINFO_DATA DeviceInfoData
,
3341 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3343 struct DeviceInfoSet
*list
;
3346 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3349 SetLastError(ERROR_INVALID_HANDLE
);
3350 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3351 SetLastError(ERROR_INVALID_HANDLE
);
3352 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3353 SetLastError(ERROR_INVALID_USER_BUFFER
);
3354 else if (!DeviceInstallParams
)
3355 SetLastError(ERROR_INVALID_PARAMETER
);
3356 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3357 SetLastError(ERROR_INVALID_USER_BUFFER
);
3360 PSP_DEVINSTALL_PARAMS_W Destination
;
3362 /* FIXME: Validate parameters */
3365 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3367 Destination
= &list
->InstallParams
;
3368 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3372 TRACE("Returning %d\n", ret
);
3376 /***********************************************************************
3377 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3379 HKEY WINAPI
SetupDiCreateDevRegKeyA(
3380 IN HDEVINFO DeviceInfoSet
,
3381 IN PSP_DEVINFO_DATA DeviceInfoData
,
3385 IN HINF InfHandle OPTIONAL
,
3386 IN PCSTR InfSectionName OPTIONAL
)
3388 PCWSTR InfSectionNameW
= NULL
;
3389 HKEY ret
= INVALID_HANDLE_VALUE
;
3393 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
3394 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
3397 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
3405 if (InfSectionNameW
!= NULL
)
3406 MyFree((PVOID
)InfSectionNameW
);
3411 /***********************************************************************
3412 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3414 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3415 IN HDEVINFO DeviceInfoSet
,
3416 IN PSP_DEVINFO_DATA DeviceInfoData
,
3420 IN HINF InfHandle OPTIONAL
,
3421 IN PCWSTR InfSectionName OPTIONAL
)
3423 struct DeviceInfoSet
*list
;
3424 HKEY ret
= INVALID_HANDLE_VALUE
;
3426 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3427 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3430 SetLastError(ERROR_INVALID_HANDLE
);
3431 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3432 SetLastError(ERROR_INVALID_HANDLE
);
3433 else if (!DeviceInfoData
)
3434 SetLastError(ERROR_INVALID_PARAMETER
);
3435 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3436 SetLastError(ERROR_INVALID_USER_BUFFER
);
3437 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3438 SetLastError(ERROR_INVALID_PARAMETER
);
3439 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3440 SetLastError(ERROR_INVALID_PARAMETER
);
3441 else if (InfHandle
&& !InfSectionName
)
3442 SetLastError(ERROR_INVALID_PARAMETER
);
3443 else if (!InfHandle
&& InfSectionName
)
3444 SetLastError(ERROR_INVALID_PARAMETER
);
3447 LPWSTR lpGuidString
= NULL
;
3448 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3449 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3450 DWORD Index
; /* Index used in the DriverKey name */
3452 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3453 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3454 HKEY hKey
= INVALID_HANDLE_VALUE
;
3456 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3458 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3462 if (KeyType
== DIREG_DEV
)
3464 FIXME("DIREG_DEV case unimplemented\n");
3466 else /* KeyType == DIREG_DRV */
3468 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3470 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3471 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3474 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3477 wcscpy(DriverKey
, L
"{");
3478 wcscat(DriverKey
, lpGuidString
);
3479 wcscat(DriverKey
, L
"}\\");
3480 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3481 rc
= RegOpenKeyExW(list
->HKLM
,
3486 if (rc
!= ERROR_SUCCESS
)
3492 /* Try all values for Index between 0 and 9999 */
3494 while (Index
<= 9999)
3497 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3498 rc
= RegCreateKeyEx(hClassKey
,
3502 REG_OPTION_NON_VOLATILE
,
3503 #if _WIN32_WINNT >= 0x502
3504 KEY_READ
| KEY_WRITE
,
3511 if (rc
!= ERROR_SUCCESS
)
3516 if (Disposition
== REG_CREATED_NEW_KEY
)
3519 hKey
= INVALID_HANDLE_VALUE
;
3524 /* Unable to create more than 9999 devices within the same class */
3525 SetLastError(ERROR_GEN_FAILURE
);
3529 /* Open device key, to write Driver value */
3530 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3531 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3533 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3534 if (rc
!= ERROR_SUCCESS
)
3541 /* Do installation of the specified section */
3544 FIXME("Need to install section %s in file %p\n",
3545 debugstr_w(InfSectionName
), InfHandle
);
3551 RpcStringFreeW(&lpGuidString
);
3552 HeapFree(GetProcessHeap(), 0, DriverKey
);
3553 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3554 RegCloseKey(hClassKey
);
3555 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3556 RegCloseKey(hDeviceKey
);
3557 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3561 TRACE("Returning 0x%p\n", ret
);
3565 /***********************************************************************
3566 * SetupDiOpenDevRegKey (SETUPAPI.@)
3568 HKEY WINAPI
SetupDiOpenDevRegKey(
3569 HDEVINFO DeviceInfoSet
,
3570 PSP_DEVINFO_DATA DeviceInfoData
,
3576 struct DeviceInfoSet
*list
;
3577 HKEY ret
= INVALID_HANDLE_VALUE
;
3579 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3580 Scope
, HwProfile
, KeyType
, samDesired
);
3583 SetLastError(ERROR_INVALID_HANDLE
);
3584 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3585 SetLastError(ERROR_INVALID_HANDLE
);
3586 else if (!DeviceInfoData
)
3587 SetLastError(ERROR_INVALID_PARAMETER
);
3588 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3589 SetLastError(ERROR_INVALID_USER_BUFFER
);
3590 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3591 SetLastError(ERROR_INVALID_PARAMETER
);
3592 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3593 SetLastError(ERROR_INVALID_PARAMETER
);
3596 HKEY hKey
= INVALID_HANDLE_VALUE
;
3597 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3598 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3599 LPWSTR DriverKey
= NULL
;
3604 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3606 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3608 else /* Scope == DICS_FLAG_GLOBAL */
3614 KEY_ENUMERATE_SUB_KEYS
,
3616 if (rc
!= ERROR_SUCCESS
)
3623 deviceInfo
->DeviceName
,
3625 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3627 RegCloseKey(hRootKey
);
3628 hRootKey
= INVALID_HANDLE_VALUE
;
3629 if (rc
!= ERROR_SUCCESS
)
3634 if (KeyType
== DIREG_DEV
)
3636 /* We're done. Just return the hKey handle */
3640 /* Read the 'Driver' key */
3641 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3642 if (rc
!= ERROR_SUCCESS
)
3647 if (dwRegType
!= REG_SZ
)
3649 SetLastError(ERROR_GEN_FAILURE
);
3652 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3655 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3658 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3659 if (rc
!= ERROR_SUCCESS
)
3665 hKey
= INVALID_HANDLE_VALUE
;
3666 /* Need to open the driver key */
3671 KEY_ENUMERATE_SUB_KEYS
,
3673 if (rc
!= ERROR_SUCCESS
)
3684 if (rc
!= ERROR_SUCCESS
)
3692 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3693 RegCloseKey(hRootKey
);
3694 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3698 TRACE("Returning 0x%p\n", ret
);
3702 /***********************************************************************
3703 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3705 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3706 HDEVINFO DeviceInfoSet
,
3708 CONST GUID
*ClassGuid
,
3709 PCSTR DeviceDescription
,
3711 DWORD CreationFlags
,
3712 PSP_DEVINFO_DATA DeviceInfoData
)
3714 LPWSTR DeviceNameW
= NULL
;
3715 LPWSTR DeviceDescriptionW
= NULL
;
3722 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3723 if (DeviceNameW
== NULL
) return FALSE
;
3725 if (DeviceDescription
)
3727 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3728 if (DeviceDescriptionW
== NULL
)
3730 if (DeviceNameW
) MyFree(DeviceNameW
);
3735 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3736 ClassGuid
, DeviceDescriptionW
,
3737 hwndParent
, CreationFlags
,
3740 if (DeviceNameW
) MyFree(DeviceNameW
);
3741 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3746 /***********************************************************************
3747 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3749 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3750 HDEVINFO DeviceInfoSet
,
3752 CONST GUID
*ClassGuid
,
3753 PCWSTR DeviceDescription
,
3755 DWORD CreationFlags
,
3756 PSP_DEVINFO_DATA DeviceInfoData
)
3758 struct DeviceInfoSet
*list
;
3761 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3762 debugstr_guid(ClassGuid
), DeviceDescription
,
3763 hwndParent
, CreationFlags
, DeviceInfoData
);
3766 SetLastError(ERROR_INVALID_HANDLE
);
3767 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3768 SetLastError(ERROR_INVALID_HANDLE
);
3769 else if (!ClassGuid
)
3770 SetLastError(ERROR_INVALID_PARAMETER
);
3771 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3772 SetLastError(ERROR_CLASS_MISMATCH
);
3773 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3775 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3776 SetLastError(ERROR_INVALID_PARAMETER
);
3780 SP_DEVINFO_DATA DevInfo
;
3782 if (CreationFlags
& DICD_GENERATE_ID
)
3784 /* Generate a new unique ID for this device */
3785 SetLastError(ERROR_GEN_FAILURE
);
3786 FIXME("not implemented\n");
3790 /* Device name is fully qualified. Try to open it */
3793 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3794 rc
= SetupDiOpenDeviceInfoW(
3797 NULL
, /* hwndParent */
3798 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3803 /* SetupDiOpenDeviceInfoW has already added
3804 * the device info to the device info set
3806 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3808 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3810 struct DeviceInfoElement
*deviceInfo
;
3812 /* FIXME: ClassGuid can be NULL */
3813 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3815 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3817 if (!DeviceInfoData
)
3821 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3823 SetLastError(ERROR_INVALID_USER_BUFFER
);
3827 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3828 DeviceInfoData
->DevInst
= 0; /* FIXME */
3829 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3838 TRACE("Returning %d\n", ret
);
3842 /***********************************************************************
3843 * Helper functions for SetupDiBuildDriverInfoList
3847 IN PLIST_ENTRY DriverListHead
,
3848 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3849 IN LPGUID ClassGuid
,
3850 IN INFCONTEXT ContextDevice
,
3851 IN
struct InfFileDetails
*InfFileDetails
,
3853 IN LPCWSTR ProviderName
,
3854 IN LPCWSTR ManufacturerName
,
3855 IN LPCWSTR MatchingId
,
3856 FILETIME DriverDate
,
3857 DWORDLONG DriverVersion
,
3860 struct DriverInfoElement
*driverInfo
= NULL
;
3861 HANDLE hFile
= INVALID_HANDLE_VALUE
;
3862 DWORD RequiredSize
= 128; /* Initial buffer size */
3863 BOOL Result
= FALSE
;
3864 PLIST_ENTRY PreviousEntry
;
3865 LPWSTR InfInstallSection
= NULL
;
3868 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3871 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3874 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3876 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
3877 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
3879 /* Copy InfFileName field */
3880 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
3881 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
3883 /* Fill InfDate field */
3884 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3885 GENERIC_READ, FILE_SHARE_READ,
3886 NULL, OPEN_EXISTING, 0, NULL);
3887 if (hFile == INVALID_HANDLE_VALUE)
3889 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
3893 /* Fill SectionName field */
3894 Result
= SetupGetStringFieldW(
3897 driverInfo
->Details
.SectionName
, LINE_LEN
,
3902 /* Fill DrvDescription field */
3903 Result
= SetupGetStringFieldW(
3905 0, /* Field index */
3906 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
3909 /* Copy MatchingId information */
3910 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3911 if (!driverInfo
->MatchingId
)
3913 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3916 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3918 /* Get inf install section */
3920 RequiredSize
= 128; /* Initial buffer size */
3921 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3922 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3924 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3925 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3926 if (!InfInstallSection
)
3928 Result
= SetupGetStringFieldW(
3930 1, /* Field index */
3931 InfInstallSection
, RequiredSize
,
3937 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3938 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
3940 driverInfo
->DriverRank
= Rank
;
3941 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3942 driverInfo
->Info
.DriverType
= DriverType
;
3943 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3944 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
3945 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3946 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3947 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3950 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3951 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3954 driverInfo
->Info
.ProviderName
[0] = '\0';
3955 driverInfo
->Info
.DriverDate
= DriverDate
;
3956 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3957 ReferenceInfFile(InfFileDetails
);
3958 driverInfo
->InfFileDetails
= InfFileDetails
;
3960 /* Insert current driver in driver list, according to its rank */
3961 PreviousEntry
= DriverListHead
->Flink
;
3962 while (PreviousEntry
!= DriverListHead
)
3964 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3966 /* Insert before the current item */
3967 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3970 PreviousEntry
= PreviousEntry
->Flink
;
3972 if (PreviousEntry
== DriverListHead
)
3974 /* Insert at the end of the list */
3975 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3984 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
3985 HeapFree(GetProcessHeap(), 0, driverInfo
);
3987 if (hFile
!= INVALID_HANDLE_VALUE
)
3989 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3995 GetVersionInformationFromInfFile(
3997 OUT LPGUID ClassGuid
,
3998 OUT LPWSTR
* pProviderName
,
3999 OUT FILETIME
* DriverDate
,
4000 OUT DWORDLONG
* DriverVersion
)
4003 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4004 LPWSTR DriverVer
= NULL
;
4005 LPWSTR ProviderName
= NULL
;
4006 LPWSTR pComma
; /* Points into DriverVer */
4007 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4008 SYSTEMTIME SystemTime
;
4010 BOOL ret
= FALSE
; /* Final result */
4012 /* Get class Guid */
4013 if (!SetupGetLineTextW(
4016 L
"Version", L
"ClassGUID",
4017 guidW
, sizeof(guidW
),
4018 NULL
/* Required size */))
4022 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4023 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4025 SetLastError(ERROR_GEN_FAILURE
);
4029 /* Get provider name */
4030 Result
= SetupGetLineTextW(
4032 hInf
, L
"Version", L
"Provider",
4037 /* We know know the needed buffer size */
4038 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4041 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4044 Result
= SetupGetLineTextW(
4046 hInf
, L
"Version", L
"Provider",
4047 ProviderName
, RequiredSize
,
4052 *pProviderName
= ProviderName
;
4054 /* Read the "DriverVer" value */
4055 Result
= SetupGetLineTextW(
4057 hInf
, L
"Version", L
"DriverVer",
4062 /* We know know the needed buffer size */
4063 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4066 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4069 Result
= SetupGetLineTextW(
4071 hInf
, L
"Version", L
"DriverVer",
4072 DriverVer
, RequiredSize
,
4078 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4079 pComma
= wcschr(DriverVer
, ',');
4082 *pComma
= UNICODE_NULL
;
4083 pVersion
= pComma
+ 1;
4085 /* Get driver date version. Invalid date = 00/00/00 */
4086 memset(DriverDate
, 0, sizeof(FILETIME
));
4087 if (wcslen(DriverVer
) == 10
4088 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4089 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4091 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4092 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4093 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4094 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4095 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4096 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4098 /* Get driver version. Invalid version = 0.0.0.0 */
4100 /* FIXME: use pVersion to fill DriverVersion variable */
4106 HeapFree(GetProcessHeap(), 0, ProviderName
);
4107 HeapFree(GetProcessHeap(), 0, DriverVer
);
4109 TRACE("Returning %d\n", ret
);
4113 /***********************************************************************
4114 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4117 SetupDiBuildDriverInfoList(
4118 IN HDEVINFO DeviceInfoSet
,
4119 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4120 IN DWORD DriverType
)
4122 struct DeviceInfoSet
*list
;
4123 SP_DEVINSTALL_PARAMS_W InstallParams
;
4124 PVOID Buffer
= NULL
;
4125 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4126 LPWSTR ProviderName
= NULL
;
4127 LPWSTR ManufacturerName
= NULL
;
4128 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4129 LPWSTR HardwareIDs
= NULL
;
4130 LPWSTR CompatibleIDs
= NULL
;
4131 LPWSTR FullInfFileName
= NULL
;
4132 FILETIME DriverDate
;
4133 DWORDLONG DriverVersion
= 0;
4137 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4140 SetLastError(ERROR_INVALID_HANDLE
);
4141 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4142 SetLastError(ERROR_INVALID_HANDLE
);
4143 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4144 SetLastError(ERROR_INVALID_HANDLE
);
4145 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4146 SetLastError(ERROR_INVALID_PARAMETER
);
4147 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4148 SetLastError(ERROR_INVALID_PARAMETER
);
4149 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4150 SetLastError(ERROR_INVALID_PARAMETER
);
4151 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4152 SetLastError(ERROR_INVALID_USER_BUFFER
);
4157 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4158 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4162 if (DriverType
== SPDIT_COMPATDRIVER
)
4164 /* Get hardware IDs list */
4166 RequiredSize
= 512; /* Initial buffer size */
4167 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4168 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4170 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4171 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4174 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4177 Result
= SetupDiGetDeviceRegistryPropertyW(
4189 /* Get compatible IDs list */
4191 RequiredSize
= 512; /* Initial buffer size */
4192 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4193 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4195 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4196 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4199 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4202 Result
= SetupDiGetDeviceRegistryPropertyW(
4205 SPDRP_COMPATIBLEIDS
,
4207 (PBYTE
)CompatibleIDs
,
4210 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4212 /* No compatible ID for this device */
4213 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4214 CompatibleIDs
= NULL
;
4222 /* Enumerate .inf files */
4224 RequiredSize
= 32768; /* Initial buffer size */
4225 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4226 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4228 HeapFree(GetProcessHeap(), 0, Buffer
);
4229 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4233 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4236 Result
= SetupGetInfFileListW(
4237 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4239 Buffer
, RequiredSize
,
4242 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4244 /* No .inf file in specified directory. So, we should
4245 * success as we created an empty driver info list.
4253 LPWSTR pFullFilename
;
4255 if (*InstallParams
.DriverPath
)
4258 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
4261 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
4262 if (!FullInfFileName
)
4264 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
4267 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
4268 wcscat(FullInfFileName
, L
"\\");
4269 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
4273 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
4274 if (!FullInfFileName
)
4276 pFullFilename
= &FullInfFileName
[0];
4279 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4281 INFCONTEXT ContextManufacturer
, ContextDevice
;
4284 wcscpy(pFullFilename
, filename
);
4285 TRACE("Opening file %S\n", FullInfFileName
);
4287 currentInfFileDetails
= HeapAlloc(
4290 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
4291 if (!currentInfFileDetails
)
4293 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
4294 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
4296 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
4297 ReferenceInfFile(currentInfFileDetails
);
4298 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
4300 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
4301 currentInfFileDetails
= NULL
;
4305 if (!GetVersionInformationFromInfFile(
4306 currentInfFileDetails
->hInf
,
4312 SetupCloseInfFile(currentInfFileDetails
->hInf
);
4313 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
4314 currentInfFileDetails
= NULL
;
4318 if (DriverType
== SPDIT_CLASSDRIVER
)
4320 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4321 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4327 /* Get the manufacturers list */
4328 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4331 Result
= SetupGetStringFieldW(
4332 &ContextManufacturer
,
4333 0, /* Field index */
4338 /* We got the needed size for the buffer */
4339 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4340 if (!ManufacturerName
)
4342 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4345 Result
= SetupGetStringFieldW(
4346 &ContextManufacturer
,
4347 0, /* Field index */
4348 ManufacturerName
, RequiredSize
,
4351 /* Get manufacturer section name */
4352 Result
= SetupGetStringFieldW(
4353 &ContextManufacturer
,
4354 1, /* Field index */
4355 ManufacturerSection
, LINE_LEN
,
4359 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
4360 /* Add (possible) extension to manufacturer section name */
4361 Result
= SetupDiGetActualSectionToInstallW(
4362 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
4365 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4366 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4371 if (DriverType
== SPDIT_CLASSDRIVER
)
4373 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4374 if (!AddDriverToList(
4375 &list
->DriverListHead
,
4379 currentInfFileDetails
,
4384 DriverDate
, DriverVersion
,
4390 else /* DriverType = SPDIT_COMPATDRIVER */
4392 /* 1. Get all fields */
4393 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4397 BOOL DriverAlreadyAdded
;
4399 for (i
= 2; i
<= FieldCount
; i
++)
4401 LPWSTR DeviceId
= NULL
;
4403 RequiredSize
= 128; /* Initial buffer size */
4404 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4405 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4407 HeapFree(GetProcessHeap(), 0, DeviceId
);
4408 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4411 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4414 Result
= SetupGetStringFieldW(
4417 DeviceId
, RequiredSize
,
4422 HeapFree(GetProcessHeap(), 0, DeviceId
);
4425 DriverAlreadyAdded
= FALSE
;
4426 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4428 if (wcscmp(DeviceId
, currentId
) == 0)
4431 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4435 currentInfFileDetails
,
4440 DriverDate
, DriverVersion
,
4441 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4442 DriverAlreadyAdded
= TRUE
;
4447 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4449 if (wcscmp(DeviceId
, currentId
) == 0)
4452 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4456 currentInfFileDetails
,
4461 DriverDate
, DriverVersion
,
4462 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4463 DriverAlreadyAdded
= TRUE
;
4467 HeapFree(GetProcessHeap(), 0, DeviceId
);
4470 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4473 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4474 ManufacturerName
= NULL
;
4475 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4480 HeapFree(GetProcessHeap(), 0, ProviderName
);
4481 ProviderName
= NULL
;
4483 DereferenceInfFile(currentInfFileDetails
);
4484 currentInfFileDetails
= NULL
;
4495 InstallParams
.Flags
|= DI_DIDCOMPAT
;
4496 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
4500 InstallParams
.Flags
|= DI_DIDCLASS
;
4501 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
4503 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4506 HeapFree(GetProcessHeap(), 0, ProviderName
);
4507 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4508 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4509 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4510 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
4511 if (currentInfFileDetails
)
4512 DereferenceInfFile(currentInfFileDetails
);
4513 HeapFree(GetProcessHeap(), 0, Buffer
);
4515 TRACE("Returning %d\n", ret
);
4519 /***********************************************************************
4520 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4523 SetupDiDeleteDeviceInfo(
4524 IN HDEVINFO DeviceInfoSet
,
4525 IN PSP_DEVINFO_DATA DeviceInfoData
)
4527 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4529 FIXME("not implemented\n");
4530 SetLastError(ERROR_GEN_FAILURE
);
4535 /***********************************************************************
4536 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4539 SetupDiDestroyDriverInfoList(
4540 IN HDEVINFO DeviceInfoSet
,
4541 IN PSP_DEVINFO_DATA DeviceInfoData
,
4542 IN DWORD DriverType
)
4544 struct DeviceInfoSet
*list
;
4547 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4550 SetLastError(ERROR_INVALID_HANDLE
);
4551 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4552 SetLastError(ERROR_INVALID_HANDLE
);
4553 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4554 SetLastError(ERROR_INVALID_PARAMETER
);
4555 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4556 SetLastError(ERROR_INVALID_PARAMETER
);
4557 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4558 SetLastError(ERROR_INVALID_USER_BUFFER
);
4561 PLIST_ENTRY ListEntry
;
4562 struct DriverInfoElement
*driverInfo
;
4563 SP_DEVINSTALL_PARAMS_W InstallParams
;
4565 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4566 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4569 if (!DeviceInfoData
)
4570 /* Fall back to destroying class driver list */
4571 DriverType
= SPDIT_CLASSDRIVER
;
4573 if (DriverType
== SPDIT_CLASSDRIVER
)
4575 while (!IsListEmpty(&list
->DriverListHead
))
4577 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
4578 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4579 DestroyDriverInfoElement(driverInfo
);
4581 InstallParams
.Reserved
= 0;
4582 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
4583 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
4584 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
4588 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
4589 struct DeviceInfoElement
*deviceInfo
;
4591 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4592 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
4594 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4595 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
4597 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
4598 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4599 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
4601 InstallParamsSet
.Reserved
= 0;
4602 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
4604 DestroyDriverInfoElement(driverInfo
);
4606 InstallParams
.Reserved
= 0;
4607 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
4608 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
4609 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4614 TRACE("Returning %d\n", ret
);
4619 /***********************************************************************
4620 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4623 SetupDiOpenDeviceInfoA(
4624 IN HDEVINFO DeviceInfoSet
,
4625 IN PCSTR DeviceInstanceId
,
4626 IN HWND hwndParent OPTIONAL
,
4628 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4630 LPWSTR DeviceInstanceIdW
= NULL
;
4633 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4635 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4636 if (DeviceInstanceIdW
== NULL
)
4639 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4640 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4642 MyFree(DeviceInstanceIdW
);
4648 /***********************************************************************
4649 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4652 SetupDiOpenDeviceInfoW(
4653 IN HDEVINFO DeviceInfoSet
,
4654 IN PCWSTR DeviceInstanceId
,
4655 IN HWND hwndParent OPTIONAL
,
4657 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4659 struct DeviceInfoSet
*list
;
4660 HKEY hEnumKey
, hKey
;
4664 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4666 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4667 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4670 SetLastError(ERROR_INVALID_HANDLE
);
4671 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4672 SetLastError(ERROR_INVALID_HANDLE
);
4673 else if (!DeviceInstanceId
)
4674 SetLastError(ERROR_INVALID_PARAMETER
);
4675 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4677 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4678 SetLastError(ERROR_INVALID_PARAMETER
);
4680 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4681 SetLastError(ERROR_INVALID_USER_BUFFER
);
4684 struct DeviceInfoElement
*deviceInfo
= NULL
;
4685 /* Search if device already exists in DeviceInfoSet.
4686 * If yes, return the existing element
4687 * If no, create a new element using informations in registry
4689 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4690 while (ItemList
!= &list
->ListHead
)
4695 FIXME("not implemented\n");
4696 ItemList
= ItemList
->Flink
;
4701 /* good one found */
4706 /* Open supposed registry key */
4711 KEY_ENUMERATE_SUB_KEYS
,
4713 if (rc
!= ERROR_SUCCESS
)
4724 RegCloseKey(hEnumKey
);
4725 if (rc
!= ERROR_SUCCESS
)
4731 /* FIXME: GUID_NULL is not allowed */
4732 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
4737 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4743 if (ret
&& deviceInfo
&& DeviceInfoData
)
4745 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4746 DeviceInfoData
->DevInst
= 0; /* FIXME */
4747 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4755 /***********************************************************************
4756 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4759 SetupDiEnumDriverInfoA(
4760 IN HDEVINFO DeviceInfoSet
,
4761 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4762 IN DWORD DriverType
,
4763 IN DWORD MemberIndex
,
4764 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4766 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4769 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4770 DriverType
, MemberIndex
, DriverInfoData
);
4772 if (DriverInfoData
== NULL
)
4773 SetLastError(ERROR_INVALID_PARAMETER
);
4774 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4775 SetLastError(ERROR_INVALID_USER_BUFFER
);
4778 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4779 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4780 DriverType
, MemberIndex
, &driverInfoData2W
);
4784 /* Do W->A conversion */
4785 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4786 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4787 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4788 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4790 DriverInfoData
->Description
[0] = '\0';
4793 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4794 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4796 DriverInfoData
->MfgName
[0] = '\0';
4799 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4800 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4802 DriverInfoData
->ProviderName
[0] = '\0';
4805 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4807 /* Copy more fields */
4808 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4809 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4814 TRACE("Returning %d\n", ret
);
4819 /***********************************************************************
4820 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4823 SetupDiEnumDriverInfoW(
4824 IN HDEVINFO DeviceInfoSet
,
4825 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4826 IN DWORD DriverType
,
4827 IN DWORD MemberIndex
,
4828 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4830 PLIST_ENTRY ListHead
;
4833 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4834 DriverType
, MemberIndex
, DriverInfoData
);
4836 if (!DeviceInfoSet
|| !DriverInfoData
)
4837 SetLastError(ERROR_INVALID_PARAMETER
);
4838 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4839 SetLastError(ERROR_INVALID_HANDLE
);
4840 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4841 SetLastError(ERROR_INVALID_HANDLE
);
4842 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4843 SetLastError(ERROR_INVALID_PARAMETER
);
4844 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4845 SetLastError(ERROR_INVALID_PARAMETER
);
4846 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4847 SetLastError(ERROR_INVALID_PARAMETER
);
4848 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4849 SetLastError(ERROR_INVALID_USER_BUFFER
);
4852 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4853 PLIST_ENTRY ItemList
;
4854 if (DriverType
== SPDIT_CLASSDRIVER
||
4855 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4857 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4861 ListHead
= &devInfo
->DriverListHead
;
4864 ItemList
= ListHead
->Flink
;
4865 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4866 ItemList
= ItemList
->Flink
;
4867 if (ItemList
== ListHead
)
4868 SetLastError(ERROR_NO_MORE_ITEMS
);
4871 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4874 &DriverInfoData
->DriverType
,
4875 &DrvInfo
->Info
.DriverType
,
4876 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4881 TRACE("Returning %d\n", ret
);
4886 /***********************************************************************
4887 * SetupDiGetSelectedDriverA (SETUPAPI.@)
4890 SetupDiGetSelectedDriverA(
4891 IN HDEVINFO DeviceInfoSet
,
4892 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4893 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4895 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4898 if (DriverInfoData
== NULL
)
4899 SetLastError(ERROR_INVALID_PARAMETER
);
4900 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4901 SetLastError(ERROR_INVALID_USER_BUFFER
);
4904 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4906 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
4912 /* Do W->A conversion */
4913 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4914 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4915 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4916 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4918 DriverInfoData
->Description
[0] = '\0';
4921 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4922 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4924 DriverInfoData
->MfgName
[0] = '\0';
4927 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4928 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4930 DriverInfoData
->ProviderName
[0] = '\0';
4933 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4935 /* Copy more fields */
4936 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4937 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4946 /***********************************************************************
4947 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4950 SetupDiGetSelectedDriverW(
4951 IN HDEVINFO DeviceInfoSet
,
4952 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4953 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4957 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4959 if (!DeviceInfoSet
|| !DriverInfoData
)
4960 SetLastError(ERROR_INVALID_PARAMETER
);
4961 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4962 SetLastError(ERROR_INVALID_HANDLE
);
4963 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4964 SetLastError(ERROR_INVALID_HANDLE
);
4965 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4966 SetLastError(ERROR_INVALID_USER_BUFFER
);
4967 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4968 SetLastError(ERROR_INVALID_USER_BUFFER
);
4971 SP_DEVINSTALL_PARAMS InstallParams
;
4973 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4974 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4976 struct DriverInfoElement
*driverInfo
;
4977 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
4978 if (driverInfo
== NULL
)
4979 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4983 &DriverInfoData
->DriverType
,
4984 &driverInfo
->Info
.DriverType
,
4985 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4991 TRACE("Returning %d\n", ret
);
4996 /***********************************************************************
4997 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5000 SetupDiSetSelectedDriverA(
5001 IN HDEVINFO DeviceInfoSet
,
5002 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5003 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5005 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5006 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5009 if (DriverInfoData
!= NULL
)
5011 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5012 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5014 SetLastError(ERROR_INVALID_PARAMETER
);
5018 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5019 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5021 if (DriverInfoDataW
.Reserved
== 0)
5023 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5025 /* convert the strings to unicode */
5026 if (!MultiByteToWideChar(CP_ACP
,
5028 DriverInfoData
->Description
,
5030 DriverInfoDataW
.Description
,
5032 !MultiByteToWideChar(CP_ACP
,
5034 DriverInfoData
->ProviderName
,
5036 DriverInfoDataW
.ProviderName
,
5043 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5046 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5050 if (ret
&& pDriverInfoDataW
!= NULL
)
5052 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5059 /***********************************************************************
5060 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5063 SetupDiSetSelectedDriverW(
5064 IN HDEVINFO DeviceInfoSet
,
5065 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5066 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5070 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5073 SetLastError(ERROR_INVALID_PARAMETER
);
5074 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5075 SetLastError(ERROR_INVALID_HANDLE
);
5076 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5077 SetLastError(ERROR_INVALID_HANDLE
);
5078 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5079 SetLastError(ERROR_INVALID_USER_BUFFER
);
5080 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5081 SetLastError(ERROR_INVALID_USER_BUFFER
);
5084 struct DriverInfoElement
**pDriverInfo
;
5085 PLIST_ENTRY ListHead
, ItemList
;
5089 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5090 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5094 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5095 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5098 if (!DriverInfoData
)
5100 *pDriverInfo
= NULL
;
5105 /* Search selected driver in list */
5106 ItemList
= ListHead
->Flink
;
5107 while (ItemList
!= ListHead
)
5109 if (DriverInfoData
->Reserved
!= 0)
5111 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5116 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5117 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5118 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5119 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5120 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5126 if (ItemList
== ListHead
)
5127 SetLastError(ERROR_INVALID_PARAMETER
);
5130 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5131 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5133 TRACE("Choosing driver whose rank is 0x%lx\n",
5134 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5136 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5141 TRACE("Returning %d\n", ret
);
5145 /***********************************************************************
5146 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5149 SetupDiGetDriverInfoDetailA(
5150 IN HDEVINFO DeviceInfoSet
,
5151 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5152 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5153 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5154 IN DWORD DriverInfoDetailDataSize
,
5155 OUT PDWORD RequiredSize OPTIONAL
)
5157 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5158 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5160 DWORD HardwareIDLen
= 0;
5163 /* do some sanity checks, the unicode version might do more thorough checks */
5164 if (DriverInfoData
== NULL
||
5165 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5166 (DriverInfoDetailData
!= NULL
&&
5167 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5168 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5170 SetLastError(ERROR_INVALID_PARAMETER
);
5174 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5175 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5177 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5179 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5181 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5185 SetLastError(ERROR_INVALID_PARAMETER
);
5188 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5189 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5191 /* convert the strings to unicode */
5192 if (MultiByteToWideChar(CP_ACP
,
5194 DriverInfoData
->Description
,
5196 DriverInfoDataW
.Description
,
5198 MultiByteToWideChar(CP_ACP
,
5200 DriverInfoData
->MfgName
,
5202 DriverInfoDataW
.MfgName
,
5204 MultiByteToWideChar(CP_ACP
,
5206 DriverInfoData
->ProviderName
,
5208 DriverInfoDataW
.ProviderName
,
5211 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5213 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5214 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5217 if (DriverInfoDetailData
!= NULL
)
5219 /* calculate the unicode buffer size from the ansi buffer size */
5220 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5221 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5222 (HardwareIDLen
* sizeof(WCHAR
));
5224 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5225 if (DriverInfoDetailDataW
== NULL
)
5227 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5231 /* initialize the buffer */
5232 ZeroMemory(DriverInfoDetailDataW
,
5234 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5237 /* call the unicode version */
5238 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5241 DriverInfoDetailDataW
,
5247 if (DriverInfoDetailDataW
!= NULL
)
5249 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5250 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
5251 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
5252 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
5253 if (WideCharToMultiByte(CP_ACP
,
5255 DriverInfoDetailDataW
->SectionName
,
5257 DriverInfoDetailData
->SectionName
,
5261 WideCharToMultiByte(CP_ACP
,
5263 DriverInfoDetailDataW
->InfFileName
,
5265 DriverInfoDetailData
->InfFileName
,
5269 WideCharToMultiByte(CP_ACP
,
5271 DriverInfoDetailDataW
->DrvDescription
,
5273 DriverInfoDetailData
->DrvDescription
,
5277 WideCharToMultiByte(CP_ACP
,
5279 DriverInfoDetailDataW
->HardwareID
,
5281 DriverInfoDetailData
->HardwareID
,
5287 DWORD hwidlen
= HardwareIDLen
;
5288 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
5290 /* count the strings in the list */
5293 len
= lstrlenA(s
) + 1;
5302 /* looks like the string list wasn't terminated... */
5303 SetLastError(ERROR_INVALID_USER_BUFFER
);
5309 /* make sure CompatIDsOffset points to the second string in the
5313 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
5314 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
5315 DriverInfoDetailData
->CompatIDsOffset
+ 1;
5319 DriverInfoDetailData
->CompatIDsOffset
= 0;
5320 DriverInfoDetailData
->CompatIDsLength
= 0;
5329 if (RequiredSize
!= NULL
)
5331 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
5332 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
5338 if (DriverInfoDetailDataW
!= NULL
)
5340 MyFree(DriverInfoDetailDataW
);
5346 /***********************************************************************
5347 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5350 SetupDiGetDriverInfoDetailW(
5351 IN HDEVINFO DeviceInfoSet
,
5352 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5353 IN PSP_DRVINFO_DATA_W DriverInfoData
,
5354 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
5355 IN DWORD DriverInfoDetailDataSize
,
5356 OUT PDWORD RequiredSize OPTIONAL
)
5360 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
5361 DriverInfoData
, DriverInfoDetailData
,
5362 DriverInfoDetailDataSize
, RequiredSize
);
5365 SetLastError(ERROR_INVALID_PARAMETER
);
5366 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5367 SetLastError(ERROR_INVALID_HANDLE
);
5368 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5369 SetLastError(ERROR_INVALID_HANDLE
);
5370 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5371 SetLastError(ERROR_INVALID_USER_BUFFER
);
5372 else if (!DriverInfoData
)
5373 SetLastError(ERROR_INVALID_PARAMETER
);
5374 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
5375 SetLastError(ERROR_INVALID_PARAMETER
);
5376 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5377 SetLastError(ERROR_INVALID_PARAMETER
);
5378 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5379 SetLastError(ERROR_INVALID_USER_BUFFER
);
5380 else if (DriverInfoData
->Reserved
== 0)
5381 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5384 struct DriverInfoElement
*driverInfoElement
;
5385 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
5388 DriverInfoDetailData
,
5389 &driverInfoElement
->Details
,
5390 driverInfoElement
->Details
.cbSize
);
5391 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5392 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5397 TRACE("Returning %d\n", ret
);
5401 /***********************************************************************
5402 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5405 SetupDiSelectBestCompatDrv(
5406 IN HDEVINFO DeviceInfoSet
,
5407 IN PSP_DEVINFO_DATA DeviceInfoData
)
5409 SP_DRVINFO_DATA_W drvInfoData
;
5412 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5414 /* Drivers are sorted by rank in the driver list, so
5415 * the first driver in the list is the best one.
5417 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
5418 ret
= SetupDiEnumDriverInfoW(
5422 0, /* Member index */
5427 ret
= SetupDiSetSelectedDriverW(
5433 TRACE("Returning %d\n", ret
);
5437 /***********************************************************************
5438 * SetupDiInstallDriverFiles (SETUPAPI.@)
5441 SetupDiInstallDriverFiles(
5442 IN HDEVINFO DeviceInfoSet
,
5443 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5447 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5450 SetLastError(ERROR_INVALID_PARAMETER
);
5451 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5452 SetLastError(ERROR_INVALID_HANDLE
);
5453 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5454 SetLastError(ERROR_INVALID_HANDLE
);
5455 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5456 SetLastError(ERROR_INVALID_USER_BUFFER
);
5457 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
5458 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5459 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
5460 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5463 SP_DEVINSTALL_PARAMS_W InstallParams
;
5464 struct DriverInfoElement
*SelectedDriver
;
5465 WCHAR SectionName
[MAX_PATH
];
5466 DWORD SectionNameLength
= 0;
5468 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5469 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5473 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5474 if (!SelectedDriver
)
5476 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5480 ret
= SetupDiGetActualSectionToInstallW(
5481 SelectedDriver
->InfFileDetails
->hInf
,
5482 SelectedDriver
->Details
.SectionName
,
5483 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5487 if (!InstallParams
.InstallMsgHandler
)
5489 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5490 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5491 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5493 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5494 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5495 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
5496 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5497 DeviceInfoSet
, DeviceInfoData
);
5501 TRACE("Returning %d\n", ret
);
5505 /***********************************************************************
5506 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5509 SetupDiRegisterCoDeviceInstallers(
5510 IN HDEVINFO DeviceInfoSet
,
5511 IN PSP_DEVINFO_DATA DeviceInfoData
)
5513 BOOL ret
= FALSE
; /* Return value */
5515 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5518 SetLastError(ERROR_INVALID_PARAMETER
);
5519 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5520 SetLastError(ERROR_INVALID_HANDLE
);
5521 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5522 SetLastError(ERROR_INVALID_HANDLE
);
5523 else if (!DeviceInfoData
)
5524 SetLastError(ERROR_INVALID_PARAMETER
);
5525 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5526 SetLastError(ERROR_INVALID_USER_BUFFER
);
5529 SP_DEVINSTALL_PARAMS_W InstallParams
;
5530 struct DriverInfoElement
*SelectedDriver
;
5533 WCHAR SectionName
[MAX_PATH
];
5534 DWORD SectionNameLength
= 0;
5535 HKEY hKey
= INVALID_HANDLE_VALUE
;;
5537 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5538 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5542 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5543 if (SelectedDriver
== NULL
)
5545 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5549 /* Get .CoInstallers section name */
5550 Result
= SetupDiGetActualSectionToInstallW(
5551 SelectedDriver
->InfFileDetails
->hInf
,
5552 SelectedDriver
->Details
.SectionName
,
5553 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5554 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
5556 wcscat(SectionName
, L
".CoInstallers");
5558 /* Open/Create driver key information */
5559 #if _WIN32_WINNT >= 0x502
5560 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5562 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5564 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5565 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5566 if (hKey
== INVALID_HANDLE_VALUE
)
5569 /* Install .CoInstallers section */
5570 DoAction
= SPINST_REGISTRY
;
5571 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5573 DoAction
|= SPINST_FILES
;
5574 if (!InstallParams
.InstallMsgHandler
)
5576 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5577 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5578 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5581 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5582 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5583 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5584 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5585 DeviceInfoSet
, DeviceInfoData
);
5592 if (hKey
!= INVALID_HANDLE_VALUE
)
5596 TRACE("Returning %d\n", ret
);
5600 /***********************************************************************
5601 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5604 SetupDiInstallDeviceInterfaces(
5605 IN HDEVINFO DeviceInfoSet
,
5606 IN PSP_DEVINFO_DATA DeviceInfoData
)
5608 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5610 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5611 //SetLastError(ERROR_GEN_FAILURE);
5617 InfIsFromOEMLocation(
5619 OUT LPBOOL IsOEMLocation
)
5623 last
= strrchrW(FullName
, '\\');
5626 /* No directory specified */
5627 *IsOEMLocation
= FALSE
;
5631 WCHAR Windir
[MAX_PATH
];
5634 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
5635 if (ret
== 0 || ret
>= MAX_PATH
)
5637 SetLastError(ERROR_GEN_FAILURE
);
5641 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
5643 /* The path is %SYSTEMROOT%\Inf */
5644 *IsOEMLocation
= FALSE
;
5648 /* The file is in another place */
5649 *IsOEMLocation
= TRUE
;
5655 /***********************************************************************
5656 * SetupDiInstallDevice (SETUPAPI.@)
5659 SetupDiInstallDevice(
5660 IN HDEVINFO DeviceInfoSet
,
5661 IN PSP_DEVINFO_DATA DeviceInfoData
)
5663 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5664 SP_DEVINSTALL_PARAMS_W InstallParams
;
5665 struct DriverInfoElement
*SelectedDriver
;
5666 SYSTEMTIME DriverDate
;
5667 WCHAR SectionName
[MAX_PATH
];
5669 DWORD SectionNameLength
= 0;
5670 BOOL Result
= FALSE
;
5671 INFCONTEXT ContextService
;
5675 LPCWSTR AssociatedService
= NULL
;
5676 LPWSTR pSectionName
= NULL
;
5677 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5679 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5680 BOOL RebootRequired
= FALSE
;
5681 HKEY hKey
= INVALID_HANDLE_VALUE
;
5682 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
5683 BOOL NeedtoCopyFile
;
5685 BOOL ret
= FALSE
; /* Return value */
5687 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5690 SetLastError(ERROR_INVALID_PARAMETER
);
5691 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5692 SetLastError(ERROR_INVALID_HANDLE
);
5693 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5694 SetLastError(ERROR_INVALID_HANDLE
);
5695 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5696 SetLastError(ERROR_INVALID_USER_BUFFER
);
5702 /* One parameter is bad */
5706 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5707 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5711 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5713 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5717 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5718 if (SelectedDriver
== NULL
)
5720 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5724 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5726 Result
= SetupDiGetActualSectionToInstallW(
5727 SelectedDriver
->InfFileDetails
->hInf
,
5728 SelectedDriver
->Details
.SectionName
,
5729 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5730 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
5732 pSectionName
= &SectionName
[wcslen(SectionName
)];
5734 /* Get information from [Version] section */
5735 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5737 /* Format ClassGuid to a string */
5738 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5740 RequiredSize
= lstrlenW(lpGuidString
);
5741 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5742 if (!lpFullGuidString
)
5744 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5747 lpFullGuidString
[0] = '{';
5748 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5749 lpFullGuidString
[RequiredSize
+ 1] = '}';
5750 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5752 /* Open/Create driver key information */
5753 #if _WIN32_WINNT >= 0x502
5754 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5756 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5758 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5759 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5760 if (hKey
== INVALID_HANDLE_VALUE
)
5763 /* Install main section */
5764 DoAction
= SPINST_REGISTRY
;
5765 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5767 DoAction
|= SPINST_FILES
;
5768 if (!InstallParams
.InstallMsgHandler
)
5770 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5771 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5772 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5775 *pSectionName
= '\0';
5776 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5777 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5778 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5779 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5780 DeviceInfoSet
, DeviceInfoData
);
5783 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
5785 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
5787 /* Delete resources allocated by SetupInitDefaultQueueCallback */
5788 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
5791 InstallParams
.Flags
|= DI_NOFILECOPY
;
5792 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5794 /* Write information to driver key */
5795 *pSectionName
= UNICODE_NULL
;
5796 TRACE("Write information to driver key\n");
5797 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5798 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5799 TRACE("DriverVersion : '%u.%u.%u.%u'\n", SelectedDriver
->Info
.DriverVersion
& 0xff, (SelectedDriver
->Info
.DriverVersion
>> 8) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 16) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 24) & 0xff);
5800 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
5801 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
5802 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
5803 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
5804 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
5805 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5806 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5807 if (rc
== ERROR_SUCCESS
)
5808 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5809 if (rc
== ERROR_SUCCESS
)
5810 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5811 if (rc
== ERROR_SUCCESS
)
5813 swprintf(Buffer
, L
"%u.%u.%u.%u", SelectedDriver
->Info
.DriverVersion
& 0xff, (SelectedDriver
->Info
.DriverVersion
>> 8) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 16) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 24) & 0xff);
5814 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5816 if (rc
== ERROR_SUCCESS
)
5817 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
5818 if (rc
== ERROR_SUCCESS
)
5819 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5820 if (rc
== ERROR_SUCCESS
)
5821 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5822 if (rc
== ERROR_SUCCESS
)
5823 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5824 if (rc
== ERROR_SUCCESS
)
5825 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5826 if (rc
!= ERROR_SUCCESS
)
5832 hKey
= INVALID_HANDLE_VALUE
;
5834 /* FIXME: Process .LogConfigOverride section */
5836 /* Install .Services section */
5837 wcscpy(pSectionName
, L
".Services");
5838 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
5841 LPWSTR ServiceName
= NULL
;
5842 LPWSTR ServiceSection
= NULL
;
5844 Result
= SetupGetStringFieldW(
5846 1, /* Field index */
5851 if (RequiredSize
> 0)
5853 /* We got the needed size for the buffer */
5854 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5857 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5860 Result
= SetupGetStringFieldW(
5862 1, /* Field index */
5863 ServiceName
, RequiredSize
,
5868 Result
= SetupGetIntField(
5870 2, /* Field index */
5874 /* The field may be empty. Ignore the error */
5877 Result
= SetupGetStringFieldW(
5879 3, /* Field index */
5884 if (RequiredSize
> 0)
5886 /* We got the needed size for the buffer */
5887 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5888 if (!ServiceSection
)
5890 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5893 Result
= SetupGetStringFieldW(
5895 3, /* Field index */
5896 ServiceSection
, RequiredSize
,
5901 SetLastError(ERROR_SUCCESS
);
5902 Result
= SetupInstallServicesFromInfSectionExW(
5903 SelectedDriver
->InfFileDetails
->hInf
,
5904 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
5905 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
5907 AssociatedService
= ServiceName
;
5909 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5910 RebootRequired
= TRUE
;
5913 HeapFree(GetProcessHeap(), 0, ServiceName
);
5914 HeapFree(GetProcessHeap(), 0, ServiceSection
);
5917 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
5920 /* Copy .inf file to Inf\ directory (if needed) */
5921 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
5926 Result
= SetupCopyOEMInfW(
5927 SelectedDriver
->InfFileDetails
->FullInfFileName
,
5930 SP_COPY_NOOVERWRITE
,
5936 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
5937 * to release use of current InfFile */
5940 /* Open device registry key */
5941 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5942 if (hKey
== INVALID_HANDLE_VALUE
)
5945 /* Install .HW section */
5946 wcscpy(pSectionName
, L
".HW");
5947 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5948 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5949 SPINST_REGISTRY
, hKey
, NULL
, 0,
5950 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5951 DeviceInfoSet
, DeviceInfoData
);
5955 /* Write information to enum key */
5956 TRACE("Write information to enum key\n");
5957 TRACE("Service : '%S'\n", AssociatedService
);
5958 TRACE("Class : '%S'\n", ClassName
);
5959 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
5960 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5961 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
5962 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
5963 if (rc
== ERROR_SUCCESS
)
5964 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
5965 if (rc
== ERROR_SUCCESS
)
5966 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5967 if (rc
== ERROR_SUCCESS
)
5968 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5969 if (rc
== ERROR_SUCCESS
)
5970 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5971 if (rc
!= ERROR_SUCCESS
)
5977 /* Start the device */
5978 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5980 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
5982 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
5983 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
5984 ret
= NT_SUCCESS(Status
);
5990 /* End of installation */
5991 if (hClassKey
!= INVALID_HANDLE_VALUE
)
5992 RegCloseKey(hClassKey
);
5993 if (hKey
!= INVALID_HANDLE_VALUE
)
5996 RpcStringFreeW(&lpGuidString
);
5997 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
5998 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6000 TRACE("Returning %d\n", ret
);