2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.com)
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 "wine/port.h"
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
33 #define NTOS_MODE_USER
34 #include <ndk/ntndk.h>
36 #include "setupapi_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
41 /* Unicode constants */
42 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
43 static const WCHAR Class
[] = {'C','l','a','s','s',0};
44 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
45 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
46 static const WCHAR NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
47 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
48 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
49 static const WCHAR NtExtension
[] = {'.','N','T',0};
50 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
51 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
52 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
53 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
55 /* Registry key and value names */
56 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
57 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
58 'C','o','n','t','r','o','l','\\',
59 'C','l','a','s','s',0};
61 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
62 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
63 'C','o','n','t','r','o','l','\\',
64 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
66 static const WCHAR EnumKeyName
[] = {'S','y','s','t','e','m','\\',
67 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
71 /* FIXME: header mess */
72 DEFINE_GUID(GUID_NULL
,
73 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
75 (CALLBACK
* CLASS_INSTALL_PROC
) (
76 IN DI_FUNCTION InstallFunction
,
77 IN HDEVINFO DeviceInfoSet
,
78 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
80 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
81 IN HDEVINFO DeviceInfoSet
,
82 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
84 (CALLBACK
* COINSTALLER_PROC
) (
85 IN DI_FUNCTION InstallFunction
,
86 IN HDEVINFO DeviceInfoSet
,
87 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
88 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
90 #define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
92 struct CoInstallerElement
97 COINSTALLER_PROC Function
;
98 BOOL DoPostProcessing
;
102 struct DeviceInterface
/* Element of DeviceInfoElement.InterfaceListHead */
104 LIST_ENTRY ListEntry
;
106 struct DeviceInfoElement
* DeviceInfo
;
107 GUID InterfaceClassGuid
;
110 /* SPINT_ACTIVE : the interface is active/enabled
111 * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
112 * SPINT_REMOVED: the interface is removed
116 WCHAR SymbolicLink
[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
119 /* We don't want to open the .inf file to read only one information in it, so keep a handle to it once it
120 * has been already loaded once. Keep also a reference counter */
121 struct InfFileDetails
127 struct DriverInfoElement
/* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
129 LIST_ENTRY ListEntry
;
132 SP_DRVINFO_DATA_V2_W Info
;
133 SP_DRVINFO_DETAIL_DATA_W Details
;
136 struct InfFileDetails
*InfFileDetails
;
139 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
141 LIST_ENTRY ListEntry
;
143 /* Reserved Field points to a struct DriverInfoElement */
144 SP_DEVINSTALL_PARAMS_W InstallParams
;
146 /* Information about devnode:
148 * "Root\*PNP0501" for example.
149 * It doesn't contain the unique ID for the device
150 * (points into the Data field at the end of the structure)
151 * WARNING: no NULL char exist between DeviceName and UniqueId
154 * "5&1be2108e&0" or "0000"
155 * If DICD_GENERATE_ID is specified in creation flags,
156 * this unique ID is autogenerated using 4 digits, base 10
157 * (points into the Data field at the end of the structure)
158 * - DeviceDescription
159 * String which identifies the device. Can be NULL. If not NULL,
160 * points into the Data field at the end of the structure
162 * Identifies the class of this device. FIXME: can it be GUID_NULL?
164 * Is a combination of:
166 * the unique ID needs to be generated
167 * - DICD_INHERIT_CLASSDRVS
168 * inherit driver of the device info set (== same pointer)
172 PCWSTR DeviceDescription
;
176 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
177 /* If the driver is not searched/detected, this list is empty */
178 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
180 /* List of interfaces implemented by this device */
181 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
186 struct DeviceInfoSet
/* HDEVINFO */
188 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
189 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
190 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
192 /* Reserved Field points to a struct DriverInfoElement */
193 SP_DEVINSTALL_PARAMS_W InstallParams
;
195 /* If the driver is not searched/detected, this list is empty */
196 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
198 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
201 /***********************************************************************
202 * SetupDiBuildClassInfoList (SETUPAPI.@)
204 BOOL WINAPI
SetupDiBuildClassInfoList(
206 LPGUID ClassGuidList
,
207 DWORD ClassGuidListSize
,
211 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
212 ClassGuidListSize
, RequiredSize
,
216 /***********************************************************************
217 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
219 BOOL WINAPI
SetupDiBuildClassInfoListExA(
221 LPGUID ClassGuidList
,
222 DWORD ClassGuidListSize
,
227 LPWSTR MachineNameW
= NULL
;
234 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
235 if (MachineNameW
== NULL
) return FALSE
;
238 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
239 ClassGuidListSize
, RequiredSize
,
240 MachineNameW
, Reserved
);
243 MyFree(MachineNameW
);
248 /***********************************************************************
249 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
251 BOOL WINAPI
SetupDiBuildClassInfoListExW(
253 LPGUID ClassGuidList
,
254 DWORD ClassGuidListSize
,
259 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
265 DWORD dwGuidListIndex
= 0;
269 if (RequiredSize
!= NULL
)
272 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
277 if (hClassesKey
== INVALID_HANDLE_VALUE
)
282 for (dwIndex
= 0; ; dwIndex
++)
284 dwLength
= MAX_GUID_STRING_LEN
+ 1;
285 lError
= RegEnumKeyExW(hClassesKey
,
293 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
294 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
296 TRACE("Key name: %p\n", szKeyName
);
298 if (RegOpenKeyExW(hClassesKey
,
304 RegCloseKey(hClassesKey
);
308 if (!RegQueryValueExW(hClassKey
,
315 TRACE("'NoUseClass' value found!\n");
316 RegCloseKey(hClassKey
);
320 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
321 (!RegQueryValueExW(hClassKey
,
328 TRACE("'NoInstallClass' value found!\n");
329 RegCloseKey(hClassKey
);
333 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
334 (!RegQueryValueExW(hClassKey
,
341 TRACE("'NoDisplayClass' value found!\n");
342 RegCloseKey(hClassKey
);
346 RegCloseKey(hClassKey
);
348 TRACE("Guid: %p\n", szKeyName
);
349 if (dwGuidListIndex
< ClassGuidListSize
)
351 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
355 TRACE("Guid: %p\n", &szKeyName
[1]);
357 UuidFromStringW(&szKeyName
[1],
358 &ClassGuidList
[dwGuidListIndex
]);
364 if (lError
!= ERROR_SUCCESS
)
368 RegCloseKey(hClassesKey
);
370 if (RequiredSize
!= NULL
)
371 *RequiredSize
= dwGuidListIndex
;
373 if (ClassGuidListSize
< dwGuidListIndex
)
375 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
382 /***********************************************************************
383 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
385 BOOL WINAPI
SetupDiClassGuidsFromNameA(
387 LPGUID ClassGuidList
,
388 DWORD ClassGuidListSize
,
391 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
392 ClassGuidListSize
, RequiredSize
,
396 /***********************************************************************
397 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
399 BOOL WINAPI
SetupDiClassGuidsFromNameW(
401 LPGUID ClassGuidList
,
402 DWORD ClassGuidListSize
,
405 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
406 ClassGuidListSize
, RequiredSize
,
410 /***********************************************************************
411 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
413 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
415 LPGUID ClassGuidList
,
416 DWORD ClassGuidListSize
,
421 LPWSTR ClassNameW
= NULL
;
422 LPWSTR MachineNameW
= NULL
;
427 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
428 if (ClassNameW
== NULL
)
433 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
434 if (MachineNameW
== NULL
)
441 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
442 ClassGuidListSize
, RequiredSize
,
443 MachineNameW
, Reserved
);
446 MyFree(MachineNameW
);
453 /***********************************************************************
454 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
456 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
458 LPGUID ClassGuidList
,
459 DWORD ClassGuidListSize
,
464 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
465 WCHAR szClassName
[256];
471 DWORD dwGuidListIndex
= 0;
473 if (RequiredSize
!= NULL
)
476 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
477 KEY_ENUMERATE_SUB_KEYS
,
481 if (hClassesKey
== INVALID_HANDLE_VALUE
)
486 for (dwIndex
= 0; ; dwIndex
++)
488 dwLength
= MAX_GUID_STRING_LEN
+ 1;
489 lError
= RegEnumKeyExW(hClassesKey
,
497 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
498 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
500 TRACE("Key name: %p\n", szKeyName
);
502 if (RegOpenKeyExW(hClassesKey
,
508 RegCloseKey(hClassesKey
);
512 dwLength
= 256 * sizeof(WCHAR
);
513 if (!RegQueryValueExW(hClassKey
,
520 TRACE("Class name: %p\n", szClassName
);
522 if (strcmpiW(szClassName
, ClassName
) == 0)
524 TRACE("Found matching class name\n");
526 TRACE("Guid: %p\n", szKeyName
);
527 if (dwGuidListIndex
< ClassGuidListSize
)
529 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
533 TRACE("Guid: %p\n", &szKeyName
[1]);
535 UuidFromStringW(&szKeyName
[1],
536 &ClassGuidList
[dwGuidListIndex
]);
543 RegCloseKey(hClassKey
);
546 if (lError
!= ERROR_SUCCESS
)
550 RegCloseKey(hClassesKey
);
552 if (RequiredSize
!= NULL
)
553 *RequiredSize
= dwGuidListIndex
;
555 if (ClassGuidListSize
< dwGuidListIndex
)
557 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
564 /***********************************************************************
565 * SetupDiClassNameFromGuidA (SETUPAPI.@)
567 BOOL WINAPI
SetupDiClassNameFromGuidA(
568 const GUID
* ClassGuid
,
573 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
574 ClassNameSize
, RequiredSize
,
578 /***********************************************************************
579 * SetupDiClassNameFromGuidW (SETUPAPI.@)
581 BOOL WINAPI
SetupDiClassNameFromGuidW(
582 const GUID
* ClassGuid
,
587 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
588 ClassNameSize
, RequiredSize
,
592 /***********************************************************************
593 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
595 BOOL WINAPI
SetupDiClassNameFromGuidExA(
596 const GUID
* ClassGuid
,
603 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
604 LPWSTR MachineNameW
= NULL
;
608 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
609 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
610 NULL
, MachineNameW
, Reserved
);
613 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
614 ClassNameSize
, NULL
, NULL
);
616 if (!ClassNameSize
&& RequiredSize
)
619 MyFree(MachineNameW
);
623 /***********************************************************************
624 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
626 BOOL WINAPI
SetupDiClassNameFromGuidExW(
627 const GUID
* ClassGuid
,
638 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
643 if (hKey
== INVALID_HANDLE_VALUE
)
648 if (RequiredSize
!= NULL
)
651 rc
= RegQueryValueExW(hKey
,
657 if (rc
!= ERROR_SUCCESS
)
664 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
667 dwLength
= ClassNameSize
* sizeof(WCHAR
);
668 rc
= RegQueryValueExW(hKey
,
674 if (rc
!= ERROR_SUCCESS
)
686 /***********************************************************************
687 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
690 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
693 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
696 /***********************************************************************
697 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
700 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
705 LPWSTR MachineNameW
= NULL
;
708 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
712 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
713 if (MachineNameW
== NULL
)
714 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
717 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
718 MachineNameW
, Reserved
);
721 MyFree(MachineNameW
);
726 /***********************************************************************
727 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
730 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
735 struct DeviceInfoSet
*list
;
738 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
740 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
743 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
744 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
746 memset(list
, 0, sizeof(struct DeviceInfoSet
));
748 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
751 ClassGuid
? ClassGuid
: &GUID_NULL
,
752 sizeof(list
->ClassGuid
));
753 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
754 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
755 list
->InstallParams
.hwndParent
= hwndParent
;
758 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
759 if (rc
!= ERROR_SUCCESS
)
762 HeapFree(GetProcessHeap(), 0, list
);
763 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
768 list
->HKLM
= HKEY_LOCAL_MACHINE
;
770 InitializeListHead(&list
->DriverListHead
);
771 InitializeListHead(&list
->ListHead
);
772 return (HDEVINFO
)list
;
775 /***********************************************************************
776 * SetupDiEnumDeviceInfo (SETUPAPI.@)
778 BOOL WINAPI
SetupDiEnumDeviceInfo(
779 HDEVINFO DeviceInfoSet
,
781 PSP_DEVINFO_DATA DeviceInfoData
)
785 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
787 SetLastError(ERROR_INVALID_PARAMETER
);
788 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
790 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
792 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
793 SetLastError(ERROR_INVALID_HANDLE
);
794 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
795 SetLastError(ERROR_INVALID_USER_BUFFER
);
798 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
799 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
800 ItemList
= ItemList
->Flink
;
801 if (ItemList
== &list
->ListHead
)
802 SetLastError(ERROR_NO_MORE_ITEMS
);
805 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
806 memcpy(&DeviceInfoData
->ClassGuid
,
809 DeviceInfoData
->DevInst
= 0; /* FIXME */
810 /* Note: this appears to be dangerous, passing a private
811 * pointer a heap-allocated datum to the caller. However, the
812 * expected lifetime of the device data is the same as the
813 * HDEVINFO; once that is closed, the data are no longer valid.
815 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
821 SetLastError(ERROR_INVALID_HANDLE
);
825 /***********************************************************************
826 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
828 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
830 PCSTR InfSectionName
,
831 PSTR InfSectionWithExt
,
832 DWORD InfSectionWithExtSize
,
836 LPWSTR InfSectionNameW
= NULL
;
837 PWSTR InfSectionWithExtW
= NULL
;
839 BOOL bResult
= FALSE
;
845 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
846 if (InfSectionNameW
== NULL
) goto end
;
848 if (InfSectionWithExt
)
850 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
851 if (InfSectionWithExtW
== NULL
) goto end
;
854 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
855 InfSectionWithExt
? InfSectionNameW
: NULL
,
856 InfSectionWithExtSize
, RequiredSize
,
857 Extension
? &ExtensionW
: NULL
);
859 if (bResult
&& InfSectionWithExt
)
861 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
862 InfSectionWithExtSize
, NULL
, NULL
) != 0;
864 if (bResult
&& Extension
)
866 if (ExtensionW
== NULL
)
869 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
873 if (InfSectionNameW
) MyFree(InfSectionNameW
);
874 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
879 /***********************************************************************
880 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
882 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
884 PCWSTR InfSectionName
,
885 PWSTR InfSectionWithExt
,
886 DWORD InfSectionWithExtSize
,
890 WCHAR szBuffer
[MAX_PATH
];
893 LONG lLineCount
= -1;
895 lstrcpyW(szBuffer
, InfSectionName
);
896 dwLength
= lstrlenW(szBuffer
);
898 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
900 /* Test section name with '.NTx86' extension */
901 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
902 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
904 if (lLineCount
== -1)
906 /* Test section name with '.NT' extension */
907 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
908 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
913 /* Test section name with '.Win' extension */
914 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
915 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
918 if (lLineCount
== -1)
920 /* Test section name without extension */
921 szBuffer
[dwLength
] = 0;
922 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
925 if (lLineCount
== -1)
927 SetLastError(ERROR_INVALID_PARAMETER
);
931 dwFullLength
= lstrlenW(szBuffer
);
933 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
935 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
937 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
941 lstrcpyW(InfSectionWithExt
, szBuffer
);
942 if (Extension
!= NULL
)
944 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
948 if (RequiredSize
!= NULL
)
950 *RequiredSize
= dwFullLength
+ 1;
956 /***********************************************************************
957 * SetupDiGetClassDescriptionA (SETUPAPI.@)
959 BOOL WINAPI
SetupDiGetClassDescriptionA(
960 const GUID
* ClassGuid
,
961 PSTR ClassDescription
,
962 DWORD ClassDescriptionSize
,
965 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
966 ClassDescriptionSize
,
967 RequiredSize
, NULL
, NULL
);
970 /***********************************************************************
971 * SetupDiGetClassDescriptionW (SETUPAPI.@)
973 BOOL WINAPI
SetupDiGetClassDescriptionW(
974 const GUID
* ClassGuid
,
975 PWSTR ClassDescription
,
976 DWORD ClassDescriptionSize
,
979 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
980 ClassDescriptionSize
,
981 RequiredSize
, NULL
, NULL
);
984 /***********************************************************************
985 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
987 BOOL WINAPI
SetupDiGetClassDescriptionExA(
988 const GUID
* ClassGuid
,
989 PSTR ClassDescription
,
990 DWORD ClassDescriptionSize
,
995 PWCHAR ClassDescriptionW
;
996 LPWSTR MachineNameW
= NULL
;
1000 if (ClassDescriptionSize
> 0)
1002 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1003 if (!ClassDescriptionW
)
1005 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1011 ClassDescriptionW
= NULL
;
1015 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1018 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1024 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1025 NULL
, MachineNameW
, Reserved
);
1028 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1029 ClassDescriptionSize
, NULL
, NULL
);
1031 if (!ClassDescriptionSize
&& RequiredSize
)
1032 *RequiredSize
= len
;
1036 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1037 MyFree(MachineNameW
);
1041 /***********************************************************************
1042 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1044 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1045 const GUID
* ClassGuid
,
1046 PWSTR ClassDescription
,
1047 DWORD ClassDescriptionSize
,
1048 PDWORD RequiredSize
,
1055 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1060 if (hKey
== INVALID_HANDLE_VALUE
)
1062 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1066 if (RequiredSize
!= NULL
)
1069 if (RegQueryValueExW(hKey
,
1080 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1083 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1084 if (RegQueryValueExW(hKey
,
1088 (LPBYTE
)ClassDescription
,
1100 /***********************************************************************
1101 * SetupDiGetClassDevsA (SETUPAPI.@)
1103 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1109 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1110 flags
, NULL
, NULL
, NULL
);
1113 /***********************************************************************
1114 * SetupDiGetClassDevsW (SETUPAPI.@)
1116 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1122 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1123 flags
, NULL
, NULL
, NULL
);
1126 /***********************************************************************
1127 * SetupDiGetClassDevsExA (SETUPAPI.@)
1129 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1139 LPWSTR enumstrW
= NULL
;
1140 LPWSTR machineW
= NULL
;
1144 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1145 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1148 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1151 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1155 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1156 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1159 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1162 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1164 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1167 HeapFree(GetProcessHeap(), 0, enumstrW
);
1168 HeapFree(GetProcessHeap(), 0, machineW
);
1173 CreateDeviceInfoElement(
1174 IN LPCWSTR InstancePath
,
1175 IN LPCGUID pClassGuid
,
1176 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1179 struct DeviceInfoElement
*deviceInfo
;
1181 *pDeviceInfo
= NULL
;
1183 size
= sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1184 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1187 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1190 memset(deviceInfo
, 0, size
);
1191 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1192 wcscpy(deviceInfo
->Data
, InstancePath
);
1193 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1194 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1195 deviceInfo
->DeviceDescription
= NULL
;
1196 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1197 deviceInfo
->CreationFlags
= 0;
1198 InitializeListHead(&deviceInfo
->DriverListHead
);
1199 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1201 *pDeviceInfo
= deviceInfo
;
1206 CreateDeviceInterface(
1207 IN
struct DeviceInfoElement
* deviceInfo
,
1208 IN LPCWSTR SymbolicLink
,
1209 IN LPCGUID pInterfaceGuid
,
1210 OUT
struct DeviceInterface
**pDeviceInterface
)
1212 struct DeviceInterface
*deviceInterface
;
1214 *pDeviceInterface
= NULL
;
1216 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1217 if (!deviceInterface
)
1219 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1222 deviceInterface
->DeviceInfo
= deviceInfo
;
1223 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1224 deviceInterface
->Flags
= 0; /* FIXME */
1225 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1227 *pDeviceInterface
= deviceInterface
;
1231 static LONG
SETUP_CreateDevListFromEnumerator(
1232 struct DeviceInfoSet
*list
,
1233 LPCGUID pClassGuid OPTIONAL
,
1235 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1237 HKEY hDeviceIdKey
, hInstanceIdKey
;
1238 WCHAR KeyBuffer
[MAX_PATH
];
1239 WCHAR InstancePath
[MAX_PATH
];
1240 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1241 struct DeviceInfoElement
*deviceInfo
;
1243 DWORD dwLength
, dwRegType
;
1246 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1249 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1250 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1251 if (rc
== ERROR_NO_MORE_ITEMS
)
1253 if (rc
!= ERROR_SUCCESS
)
1257 /* Open device id sub key */
1258 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1259 if (rc
!= ERROR_SUCCESS
)
1261 wcscpy(InstancePath
, Enumerator
);
1262 wcscat(InstancePath
, L
"\\");
1263 wcscat(InstancePath
, KeyBuffer
);
1264 wcscat(InstancePath
, L
"\\");
1265 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1267 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1273 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1274 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1275 if (rc
== ERROR_NO_MORE_ITEMS
)
1277 if (rc
!= ERROR_SUCCESS
)
1279 RegCloseKey(hDeviceIdKey
);
1284 /* Open instance id sub key */
1285 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1286 if (rc
!= ERROR_SUCCESS
)
1288 RegCloseKey(hDeviceIdKey
);
1291 *pEndOfInstancePath
= '\0';
1292 wcscat(InstancePath
, KeyBuffer
);
1294 /* Read ClassGUID value */
1295 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1296 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1297 RegCloseKey(hInstanceIdKey
);
1298 if (rc
== ERROR_FILE_NOT_FOUND
)
1301 /* Skip this bad entry as we can't verify it */
1304 else if (rc
!= ERROR_SUCCESS
)
1306 RegCloseKey(hDeviceIdKey
);
1309 else if (dwRegType
!= REG_SZ
)
1311 RegCloseKey(hDeviceIdKey
);
1312 return ERROR_GEN_FAILURE
;
1315 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1316 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1318 RegCloseKey(hDeviceIdKey
);
1319 return GetLastError();
1321 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1323 /* Skip this entry as it is not the right device class */
1327 /* Add the entry to the list */
1328 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1330 RegCloseKey(hDeviceIdKey
);
1331 return GetLastError();
1333 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1334 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1336 RegCloseKey(hDeviceIdKey
);
1339 return ERROR_SUCCESS
;
1342 static LONG
SETUP_CreateDevList(
1343 struct DeviceInfoSet
*list
,
1344 PCWSTR MachineName OPTIONAL
,
1345 LPGUID
class OPTIONAL
,
1346 PCWSTR Enumerator OPTIONAL
)
1348 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1349 WCHAR KeyBuffer
[MAX_PATH
];
1354 if (IsEqualIID(class, &GUID_NULL
))
1358 if (MachineName
!= NULL
)
1360 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1361 if (rc
!= ERROR_SUCCESS
)
1365 HKLM
= HKEY_LOCAL_MACHINE
;
1367 rc
= RegOpenKeyExW(HKLM
,
1370 KEY_ENUMERATE_SUB_KEYS
,
1372 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1373 if (rc
!= ERROR_SUCCESS
)
1376 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1377 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1386 KEY_ENUMERATE_SUB_KEYS
,
1388 RegCloseKey(hEnumKey
);
1389 if (rc
!= ERROR_SUCCESS
)
1391 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1392 RegCloseKey(hEnumeratorKey
);
1397 /* Enumerate enumerators */
1401 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1402 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1403 if (rc
== ERROR_NO_MORE_ITEMS
)
1405 if (rc
!= ERROR_SUCCESS
)
1407 RegCloseKey(hEnumKey
);
1413 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1414 if (rc
!= ERROR_SUCCESS
)
1416 RegCloseKey(hEnumKey
);
1420 /* Call SETUP_CreateDevListFromEnumerator */
1421 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1422 RegCloseKey(hEnumeratorKey
);
1423 if (rc
!= ERROR_SUCCESS
)
1425 RegCloseKey(hEnumKey
);
1429 RegCloseKey(hEnumKey
);
1430 return ERROR_SUCCESS
;
1435 static LONG
SETUP_CreateSerialDeviceList(
1436 struct DeviceInfoSet
*list
,
1438 LPGUID InterfaceGuid
,
1439 PCWSTR DeviceInstanceW
)
1441 static const size_t initialSize
= 100;
1443 WCHAR buf
[initialSize
];
1445 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1447 struct DeviceInfoElement
*deviceInfo
;
1450 WARN("'MachineName' is ignored on Wine!\n");
1451 if (DeviceInstanceW
)
1452 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1458 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1460 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1464 HeapFree(GetProcessHeap(), 0, devices
);
1465 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1467 return ERROR_NOT_ENOUGH_MEMORY
;
1473 HeapFree(GetProcessHeap(), 0, devices
);
1474 return GetLastError();
1478 /* 'devices' is a MULTI_SZ string */
1479 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1481 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1483 /* We have found a device */
1484 struct DeviceInterface
*interfaceInfo
;
1485 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1486 /* Step 1. Create a device info element */
1487 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1490 HeapFree(GetProcessHeap(), 0, devices
);
1491 return GetLastError();
1493 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1495 /* Step 2. Create an interface list for this element */
1496 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1499 HeapFree(GetProcessHeap(), 0, devices
);
1500 return GetLastError();
1502 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1506 HeapFree(GetProcessHeap(), 0, devices
);
1507 return ERROR_SUCCESS
;
1510 #else /* __REACTOS__ */
1512 static LONG
SETUP_CreateInterfaceList(
1513 struct DeviceInfoSet
*list
,
1515 LPGUID InterfaceGuid
,
1516 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1518 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1519 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1520 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1521 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1522 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1524 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1527 DWORD dwLength
, dwInstancePathLength
;
1530 struct DeviceInfoElement
*deviceInfo
;
1532 /* Open registry key related to this interface */
1533 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1534 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1535 return GetLastError();
1537 /* Enumerate sub keys of hInterfaceKey */
1541 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1542 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1543 if (rc
== ERROR_NO_MORE_ITEMS
)
1545 if (rc
!= ERROR_SUCCESS
)
1547 RegCloseKey(hInterfaceKey
);
1553 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1554 if (rc
!= ERROR_SUCCESS
)
1556 RegCloseKey(hInterfaceKey
);
1560 /* Read DeviceInstance */
1561 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1562 if (rc
!= ERROR_SUCCESS
)
1564 RegCloseKey(hDeviceInstanceKey
);
1565 RegCloseKey(hInterfaceKey
);
1568 if (dwRegType
!= REG_SZ
)
1570 RegCloseKey(hDeviceInstanceKey
);
1571 RegCloseKey(hInterfaceKey
);
1572 return ERROR_GEN_FAILURE
;
1574 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1577 RegCloseKey(hDeviceInstanceKey
);
1578 RegCloseKey(hInterfaceKey
);
1579 return ERROR_NOT_ENOUGH_MEMORY
;
1581 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1582 if (rc
!= ERROR_SUCCESS
)
1584 HeapFree(GetProcessHeap(), 0, InstancePath
);
1585 RegCloseKey(hDeviceInstanceKey
);
1586 RegCloseKey(hInterfaceKey
);
1589 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1590 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1592 if (DeviceInstanceW
)
1594 /* Check if device enumerator is not the right one */
1595 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1597 HeapFree(GetProcessHeap(), 0, InstancePath
);
1598 RegCloseKey(hDeviceInstanceKey
);
1603 /* Find class GUID associated to the device instance */
1608 KEY_ENUMERATE_SUB_KEYS
,
1610 if (rc
!= ERROR_SUCCESS
)
1612 HeapFree(GetProcessHeap(), 0, InstancePath
);
1613 RegCloseKey(hDeviceInstanceKey
);
1614 RegCloseKey(hInterfaceKey
);
1623 RegCloseKey(hEnumKey
);
1624 if (rc
!= ERROR_SUCCESS
)
1626 HeapFree(GetProcessHeap(), 0, InstancePath
);
1627 RegCloseKey(hDeviceInstanceKey
);
1628 RegCloseKey(hInterfaceKey
);
1631 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1632 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1634 if (rc
!= ERROR_SUCCESS
)
1636 HeapFree(GetProcessHeap(), 0, InstancePath
);
1637 RegCloseKey(hDeviceInstanceKey
);
1638 RegCloseKey(hInterfaceKey
);
1641 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1642 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1643 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1645 HeapFree(GetProcessHeap(), 0, InstancePath
);
1646 RegCloseKey(hDeviceInstanceKey
);
1647 RegCloseKey(hInterfaceKey
);
1648 return ERROR_GEN_FAILURE
;
1650 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1652 /* If current device doesn't match the list GUID (if any), skip this entry */
1653 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1655 HeapFree(GetProcessHeap(), 0, InstancePath
);
1656 RegCloseKey(hDeviceInstanceKey
);
1660 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1664 LPWSTR pSymbolicLink
;
1665 struct DeviceInterface
*interfaceInfo
;
1667 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1668 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1669 if (rc
== ERROR_NO_MORE_ITEMS
)
1671 if (rc
!= ERROR_SUCCESS
)
1673 HeapFree(GetProcessHeap(), 0, InstancePath
);
1674 RegCloseKey(hDeviceInstanceKey
);
1675 RegCloseKey(hInterfaceKey
);
1679 if (KeyBuffer
[0] != '#')
1680 /* This entry doesn't represent an interesting entry */
1684 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1685 if (rc
!= ERROR_SUCCESS
)
1687 RegCloseKey(hDeviceInstanceKey
);
1688 RegCloseKey(hInterfaceKey
);
1692 /* Read SymbolicLink value */
1693 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1694 if (rc
!= ERROR_SUCCESS
)
1696 RegCloseKey(hReferenceKey
);
1697 RegCloseKey(hDeviceInstanceKey
);
1698 RegCloseKey(hInterfaceKey
);
1701 if (dwRegType
!= REG_SZ
)
1703 RegCloseKey(hReferenceKey
);
1704 RegCloseKey(hDeviceInstanceKey
);
1705 RegCloseKey(hInterfaceKey
);
1706 return ERROR_GEN_FAILURE
;
1709 /* We have found a device */
1710 /* Step 1. Create a device info element */
1711 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1713 RegCloseKey(hReferenceKey
);
1714 RegCloseKey(hDeviceInstanceKey
);
1715 RegCloseKey(hInterfaceKey
);
1716 return GetLastError();
1718 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1719 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1721 /* Step 2. Create an interface list for this element */
1722 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1725 RegCloseKey(hReferenceKey
);
1726 RegCloseKey(hDeviceInstanceKey
);
1727 RegCloseKey(hInterfaceKey
);
1728 return ERROR_NOT_ENOUGH_MEMORY
;
1730 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1731 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1732 RegCloseKey(hReferenceKey
);
1733 if (rc
!= ERROR_SUCCESS
)
1735 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1736 RegCloseKey(hDeviceInstanceKey
);
1737 RegCloseKey(hInterfaceKey
);
1740 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1742 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1743 RegCloseKey(hDeviceInstanceKey
);
1744 RegCloseKey(hInterfaceKey
);
1745 return GetLastError();
1747 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1748 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1749 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1751 RegCloseKey(hDeviceInstanceKey
);
1753 RegCloseKey(hInterfaceKey
);
1754 return ERROR_SUCCESS
;
1756 #endif /* __REACTOS__ */
1758 /***********************************************************************
1759 * SetupDiGetClassDevsExW (SETUPAPI.@)
1761 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1770 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1771 struct DeviceInfoSet
*list
;
1775 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1776 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1778 /* Create the deviceset if not set */
1781 list
= (struct DeviceInfoSet
*)deviceset
;
1782 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1784 SetLastError(ERROR_INVALID_HANDLE
);
1785 return INVALID_HANDLE_VALUE
;
1787 hDeviceInfo
= deviceset
;
1791 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1792 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1793 NULL
, machine
, NULL
);
1794 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1795 return INVALID_HANDLE_VALUE
;
1796 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1799 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1802 pClassGuid
= &list
->ClassGuid
;
1804 if (flags
& DIGCF_PRESENT
)
1805 FIXME(": flag DIGCF_PRESENT ignored\n");
1806 if (flags
& DIGCF_PROFILE
)
1807 FIXME(": flag DIGCF_PROFILE ignored\n");
1809 if (flags
& DIGCF_ALLCLASSES
)
1811 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1812 if (rc
!= ERROR_SUCCESS
)
1816 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1817 return INVALID_HANDLE_VALUE
;
1821 else if (flags
& DIGCF_DEVICEINTERFACE
)
1825 SetLastError(ERROR_INVALID_PARAMETER
);
1827 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1828 return INVALID_HANDLE_VALUE
;
1832 /* Special case: find serial ports by calling QueryDosDevice */
1833 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1834 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1835 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1836 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1839 ERR("Wine can only enumerate serial devices at the moment!\n");
1840 rc
= ERROR_INVALID_PARAMETER
;
1842 #else /* __REACTOS__ */
1843 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1844 #endif /* __REACTOS__ */
1845 if (rc
!= ERROR_SUCCESS
)
1849 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1850 return INVALID_HANDLE_VALUE
;
1856 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1857 if (rc
!= ERROR_SUCCESS
)
1861 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1862 return INVALID_HANDLE_VALUE
;
1868 /***********************************************************************
1869 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1871 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1872 HDEVINFO DeviceInfoSet
,
1873 PSP_DEVINFO_DATA DeviceInfoData
,
1874 CONST GUID
* InterfaceClassGuid
,
1876 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1880 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1881 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1883 if (!DeviceInterfaceData
)
1884 SetLastError(ERROR_INVALID_PARAMETER
);
1885 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1886 SetLastError(ERROR_INVALID_USER_BUFFER
);
1887 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1889 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1891 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1893 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1895 while (ItemList
!= &list
->ListHead
&& !Found
)
1897 PLIST_ENTRY InterfaceListEntry
;
1898 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1899 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1901 /* We are not searching for this element */
1902 ItemList
= ItemList
->Flink
;
1905 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1906 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1908 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1909 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1911 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1914 if (MemberIndex
-- == 0)
1916 /* return this item */
1917 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1918 &DevItf
->InterfaceClassGuid
,
1920 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1921 /* Note: this appears to be dangerous, passing a private
1922 * pointer a heap-allocated datum to the caller. However, the
1923 * expected lifetime of the device data is the same as the
1924 * HDEVINFO; once that is closed, the data are no longer valid.
1926 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1929 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1931 ItemList
= ItemList
->Flink
;
1934 SetLastError(ERROR_NO_MORE_ITEMS
);
1939 SetLastError(ERROR_INVALID_HANDLE
);
1942 SetLastError(ERROR_INVALID_HANDLE
);
1946 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
1948 InterlockedIncrement(&infFile
->References
);
1951 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
1953 if (InterlockedDecrement(&infFile
->References
) == 0)
1955 SetupCloseInfFile(infFile
->hInf
);
1956 HeapFree(GetProcessHeap(), 0, infFile
);
1960 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
1962 DereferenceInfFile(driverInfo
->InfFileDetails
);
1963 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
1964 HeapFree(GetProcessHeap(), 0, driverInfo
);
1968 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
1970 PLIST_ENTRY ListEntry
;
1971 struct DriverInfoElement
*driverInfo
;
1973 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1975 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1976 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
1977 if (!DestroyDriverInfoElement(driverInfo
))
1980 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1982 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1983 HeapFree(GetProcessHeap(), 0, ListEntry
);
1985 HeapFree(GetProcessHeap(), 0, deviceInfo
);
1989 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
1991 PLIST_ENTRY ListEntry
;
1992 struct DeviceInfoElement
*deviceInfo
;
1994 while (!IsListEmpty(&list
->ListHead
))
1996 ListEntry
= RemoveHeadList(&list
->ListHead
);
1997 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1998 if (!DestroyDeviceInfoElement(deviceInfo
))
2001 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2002 RegCloseKey(list
->HKLM
);
2003 HeapFree(GetProcessHeap(), 0, list
);
2007 /***********************************************************************
2008 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2010 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2014 TRACE("%p\n", devinfo
);
2015 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2017 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2019 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2020 ret
= DestroyDeviceInfoSet(list
);
2022 SetLastError(ERROR_INVALID_HANDLE
);
2025 SetLastError(ERROR_INVALID_HANDLE
);
2027 TRACE("Returning %d\n", ret
);
2031 /***********************************************************************
2032 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2034 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2035 HDEVINFO DeviceInfoSet
,
2036 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2037 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2038 DWORD DeviceInterfaceDetailDataSize
,
2039 PDWORD RequiredSize
,
2040 PSP_DEVINFO_DATA DeviceInfoData
)
2042 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2043 DWORD sizeW
= 0, sizeA
;
2046 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2047 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2048 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2050 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2051 SetLastError(ERROR_INVALID_USER_BUFFER
);
2052 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2053 SetLastError(ERROR_INVALID_PARAMETER
);
2054 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2055 SetLastError(ERROR_INVALID_PARAMETER
);
2058 if (DeviceInterfaceDetailData
!= NULL
)
2060 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2061 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2062 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2063 if (!DeviceInterfaceDetailDataW
)
2065 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2068 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2070 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2071 ret
= SetupDiGetDeviceInterfaceDetailW(
2073 DeviceInterfaceData
,
2074 DeviceInterfaceDetailDataW
,
2078 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2079 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2081 *RequiredSize
= sizeA
;
2082 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2084 if (!WideCharToMultiByte(
2086 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2087 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2094 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2097 TRACE("Returning %d\n", ret
);
2101 /***********************************************************************
2102 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2104 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2105 HDEVINFO DeviceInfoSet
,
2106 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2107 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2108 DWORD DeviceInterfaceDetailDataSize
,
2109 PDWORD RequiredSize
,
2110 PSP_DEVINFO_DATA DeviceInfoData
)
2114 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2115 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2116 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2118 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2119 SetLastError(ERROR_INVALID_PARAMETER
);
2120 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2121 SetLastError(ERROR_INVALID_HANDLE
);
2122 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2123 SetLastError(ERROR_INVALID_HANDLE
);
2124 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2125 SetLastError(ERROR_INVALID_USER_BUFFER
);
2126 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2127 SetLastError(ERROR_INVALID_USER_BUFFER
);
2128 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2129 SetLastError(ERROR_INVALID_USER_BUFFER
);
2130 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2131 SetLastError(ERROR_INVALID_PARAMETER
);
2132 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2133 SetLastError(ERROR_INVALID_PARAMETER
);
2136 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2137 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2138 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2139 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2141 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2143 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2145 *RequiredSize
= sizeRequired
;
2149 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2150 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2153 memcpy(&DeviceInfoData
->ClassGuid
,
2154 &deviceInterface
->DeviceInfo
->ClassGuid
,
2156 DeviceInfoData
->DevInst
= 0; /* FIXME */
2157 /* Note: this appears to be dangerous, passing a private
2158 * pointer a heap-allocated datum to the caller. However, the
2159 * expected lifetime of the device data is the same as the
2160 * HDEVINFO; once that is closed, the data are no longer valid.
2162 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2168 TRACE("Returning %d\n", ret
);
2172 /***********************************************************************
2173 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2175 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2177 PSP_DEVINFO_DATA DeviceInfoData
,
2179 PDWORD PropertyRegDataType
,
2180 PBYTE PropertyBuffer
,
2181 DWORD PropertyBufferSize
,
2182 PDWORD RequiredSize
)
2185 BOOL bIsStringProperty
;
2187 DWORD RequiredSizeA
, RequiredSizeW
;
2188 DWORD PropertyBufferSizeW
;
2189 PBYTE PropertyBufferW
;
2191 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2192 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2195 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2196 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2198 bResult
= SetupDiGetDeviceRegistryPropertyW(
2204 PropertyBufferSizeW
,
2207 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2209 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2211 if (bIsStringProperty
)
2212 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2214 RequiredSizeA
= RequiredSizeW
;
2216 *RequiredSize
= RequiredSizeA
;
2217 if (PropertyRegDataType
)
2218 *PropertyRegDataType
= RegType
;
2223 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2227 if (RequiredSizeA
<= PropertyBufferSize
)
2229 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2231 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2233 /* Last error is already set by WideCharToMultiByte */
2238 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2242 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2246 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2250 /***********************************************************************
2251 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2253 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2254 HDEVINFO DeviceInfoSet
,
2255 PSP_DEVINFO_DATA DeviceInfoData
,
2257 PDWORD PropertyRegDataType
,
2258 PBYTE PropertyBuffer
,
2259 DWORD PropertyBufferSize
,
2260 PDWORD RequiredSize
)
2262 HKEY hEnumKey
, hKey
;
2266 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2267 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2270 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2271 SetLastError(ERROR_INVALID_HANDLE
);
2272 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2273 SetLastError(ERROR_INVALID_HANDLE
);
2274 else if (!DeviceInfoData
)
2275 SetLastError(ERROR_INVALID_PARAMETER
);
2276 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2277 SetLastError(ERROR_INVALID_USER_BUFFER
);
2278 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2279 SetLastError(ERROR_INVALID_PARAMETER
);
2282 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2283 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2287 case SPDRP_CAPABILITIES
:
2289 case SPDRP_CLASSGUID
:
2290 case SPDRP_COMPATIBLEIDS
:
2291 case SPDRP_CONFIGFLAGS
:
2292 case SPDRP_DEVICEDESC
:
2294 case SPDRP_FRIENDLYNAME
:
2295 case SPDRP_HARDWAREID
:
2296 case SPDRP_LOCATION_INFORMATION
:
2297 case SPDRP_LOWERFILTERS
:
2299 case SPDRP_SECURITY
:
2301 case SPDRP_UI_NUMBER
:
2302 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2303 case SPDRP_UPPERFILTERS
:
2305 LPCWSTR RegistryPropertyName
;
2310 case SPDRP_CAPABILITIES
:
2311 RegistryPropertyName
= L
"Capabilities"; break;
2313 RegistryPropertyName
= L
"Class"; break;
2314 case SPDRP_CLASSGUID
:
2315 RegistryPropertyName
= L
"ClassGUID"; break;
2316 case SPDRP_COMPATIBLEIDS
:
2317 RegistryPropertyName
= L
"CompatibleIDs"; break;
2318 case SPDRP_CONFIGFLAGS
:
2319 RegistryPropertyName
= L
"ConfigFlags"; break;
2320 case SPDRP_DEVICEDESC
:
2321 RegistryPropertyName
= L
"DeviceDesc"; break;
2323 RegistryPropertyName
= L
"Driver"; break;
2324 case SPDRP_FRIENDLYNAME
:
2325 RegistryPropertyName
= L
"FriendlyName"; break;
2326 case SPDRP_HARDWAREID
:
2327 RegistryPropertyName
= L
"HardwareID"; break;
2328 case SPDRP_LOCATION_INFORMATION
:
2329 RegistryPropertyName
= L
"LocationInformation"; break;
2330 case SPDRP_LOWERFILTERS
:
2331 RegistryPropertyName
= L
"LowerFilters"; break;
2333 RegistryPropertyName
= L
"Mfg"; break;
2334 case SPDRP_SECURITY
:
2335 RegistryPropertyName
= L
"Security"; break;
2337 RegistryPropertyName
= L
"Service"; break;
2338 case SPDRP_UI_NUMBER
:
2339 RegistryPropertyName
= L
"UINumber"; break;
2340 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2341 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2342 case SPDRP_UPPERFILTERS
:
2343 RegistryPropertyName
= L
"UpperFilters"; break;
2345 /* Should not happen */
2346 RegistryPropertyName
= NULL
; break;
2349 /* Open registry key name */
2354 KEY_ENUMERATE_SUB_KEYS
,
2356 if (rc
!= ERROR_SUCCESS
)
2367 RegCloseKey(hEnumKey
);
2368 if (rc
!= ERROR_SUCCESS
)
2373 /* Read registry entry */
2374 BufferSize
= PropertyBufferSize
;
2375 rc
= RegQueryValueExW(
2377 RegistryPropertyName
,
2378 NULL
, /* Reserved */
2379 PropertyRegDataType
,
2383 *RequiredSize
= BufferSize
;
2386 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2389 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2391 case ERROR_MORE_DATA
:
2392 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2401 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2403 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2405 if (PropertyRegDataType
)
2406 *PropertyRegDataType
= REG_SZ
;
2408 *RequiredSize
= required
;
2409 if (PropertyBufferSize
>= required
)
2411 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2415 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2419 /*case SPDRP_BUSTYPEGUID:
2420 case SPDRP_LEGACYBUSTYPE:
2421 case SPDRP_BUSNUMBER:
2422 case SPDRP_ENUMERATOR_NAME:
2423 case SPDRP_SECURITY_SDS:
2425 case SPDRP_EXCLUSIVE:
2426 case SPDRP_CHARACTERISTICS:
2428 case SPDRP_DEVICE_POWER_DATA:*/
2429 #if (WINVER >= 0x501)
2430 /*case SPDRP_REMOVAL_POLICY:
2431 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2432 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2433 case SPDRP_INSTALL_STATE:*/
2438 FIXME("Property 0x%lx not implemented\n", Property
);
2439 SetLastError(ERROR_NOT_SUPPORTED
);
2444 TRACE("Returning %d\n", ret
);
2448 /***********************************************************************
2449 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2451 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2452 IN HDEVINFO DeviceInfoSet
,
2453 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2455 IN CONST BYTE
*PropertyBuffer
,
2456 IN DWORD PropertyBufferSize
)
2458 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2459 Property
, PropertyBuffer
, PropertyBufferSize
);
2460 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2464 /***********************************************************************
2465 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2467 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2468 IN HDEVINFO DeviceInfoSet
,
2469 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2471 IN
const BYTE
*PropertyBuffer
,
2472 IN DWORD PropertyBufferSize
)
2474 struct DeviceInfoSet
*list
;
2477 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2478 Property
, PropertyBuffer
, PropertyBufferSize
);
2481 SetLastError(ERROR_INVALID_HANDLE
);
2482 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2483 SetLastError(ERROR_INVALID_HANDLE
);
2484 else if (DeviceInfoData
)
2485 SetLastError(ERROR_INVALID_HANDLE
);
2486 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2487 SetLastError(ERROR_INVALID_USER_BUFFER
);
2492 case SPDRP_COMPATIBLEIDS
:
2493 case SPDRP_CONFIGFLAGS
:
2494 case SPDRP_FRIENDLYNAME
:
2495 case SPDRP_HARDWAREID
:
2496 case SPDRP_LOCATION_INFORMATION
:
2497 case SPDRP_LOWERFILTERS
:
2498 case SPDRP_SECURITY
:
2500 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2501 case SPDRP_UPPERFILTERS
:
2503 LPCWSTR RegistryPropertyName
;
2504 DWORD RegistryDataType
;
2510 case SPDRP_COMPATIBLEIDS
:
2511 RegistryPropertyName
= L
"CompatibleIDs";
2512 RegistryDataType
= REG_MULTI_SZ
;
2514 case SPDRP_CONFIGFLAGS
:
2515 RegistryPropertyName
= L
"ConfigFlags";
2516 RegistryDataType
= REG_DWORD
;
2518 case SPDRP_FRIENDLYNAME
:
2519 RegistryPropertyName
= L
"FriendlyName";
2520 RegistryDataType
= REG_SZ
;
2522 case SPDRP_HARDWAREID
:
2523 RegistryPropertyName
= L
"HardwareID";
2524 RegistryDataType
= REG_MULTI_SZ
;
2526 case SPDRP_LOCATION_INFORMATION
:
2527 RegistryPropertyName
= L
"LocationInformation";
2528 RegistryDataType
= REG_SZ
;
2530 case SPDRP_LOWERFILTERS
:
2531 RegistryPropertyName
= L
"LowerFilters";
2532 RegistryDataType
= REG_MULTI_SZ
;
2534 case SPDRP_SECURITY
:
2535 RegistryPropertyName
= L
"Security";
2536 RegistryDataType
= REG_BINARY
;
2539 RegistryPropertyName
= L
"Service";
2540 RegistryDataType
= REG_SZ
;
2542 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2543 RegistryPropertyName
= L
"UINumberDescFormat";
2544 RegistryDataType
= REG_SZ
;
2546 case SPDRP_UPPERFILTERS
:
2547 RegistryPropertyName
= L
"UpperFilters";
2548 RegistryDataType
= REG_MULTI_SZ
;
2551 /* Should not happen */
2552 RegistryPropertyName
= NULL
;
2553 RegistryDataType
= REG_BINARY
;
2556 /* Open device registry key */
2557 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2558 if (hKey
!= INVALID_HANDLE_VALUE
)
2560 /* Write new data */
2561 rc
= RegSetValueExW(
2563 RegistryPropertyName
,
2567 PropertyBufferSize
);
2568 if (rc
== ERROR_SUCCESS
)
2577 /*case SPDRP_CHARACTERISTICS:
2579 case SPDRP_EXCLUSIVE:*/
2580 #if (WINVER >= 0x501)
2581 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2583 //case SPDRP_SECURITY_SDS:
2587 FIXME("Property 0x%lx not implemented\n", Property
);
2588 SetLastError(ERROR_NOT_SUPPORTED
);
2593 TRACE("Returning %d\n", ret
);
2597 /***********************************************************************
2598 * SetupDiInstallClassA (SETUPAPI.@)
2600 BOOL WINAPI
SetupDiInstallClassA(
2606 UNICODE_STRING FileNameW
;
2609 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2611 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2615 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2617 RtlFreeUnicodeString(&FileNameW
);
2622 static HKEY
CreateClassKey(HINF hInf
)
2624 WCHAR FullBuffer
[MAX_PATH
];
2625 WCHAR Buffer
[MAX_PATH
];
2630 if (!SetupGetLineTextW(NULL
,
2638 return INVALID_HANDLE_VALUE
;
2641 lstrcpyW(FullBuffer
, ControlClass
);
2642 lstrcatW(FullBuffer
, Buffer
);
2645 if (!SetupGetLineTextW(NULL
,
2653 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2654 return INVALID_HANDLE_VALUE
;
2657 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2661 REG_OPTION_NON_VOLATILE
,
2667 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2668 return INVALID_HANDLE_VALUE
;
2671 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2676 RequiredSize
* sizeof(WCHAR
)))
2678 RegCloseKey(hClassKey
);
2679 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2680 return INVALID_HANDLE_VALUE
;
2686 /***********************************************************************
2687 * SetupDiInstallClassW (SETUPAPI.@)
2689 BOOL WINAPI
SetupDiInstallClassW(
2695 WCHAR SectionName
[MAX_PATH
];
2696 DWORD SectionNameLength
= 0;
2698 BOOL bFileQueueCreated
= FALSE
;
2701 FIXME("not fully implemented\n");
2703 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2705 SetLastError(ERROR_INVALID_PARAMETER
);
2709 /* Open the .inf file */
2710 hInf
= SetupOpenInfFileW(InfFileName
,
2714 if (hInf
== INVALID_HANDLE_VALUE
)
2720 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2721 hClassKey
= CreateClassKey(hInf
);
2722 if (hClassKey
== INVALID_HANDLE_VALUE
)
2724 SetupCloseInfFile(hInf
);
2730 /* Try to append a layout file */
2732 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2735 /* Retrieve the actual section name */
2736 SetupDiGetActualSectionToInstallW(hInf
,
2744 if (!(Flags
& DI_NOVCP
))
2746 FileQueue
= SetupOpenFileQueue();
2747 if (FileQueue
== INVALID_HANDLE_VALUE
)
2749 SetupCloseInfFile(hInf
);
2750 RegCloseKey(hClassKey
);
2754 bFileQueueCreated
= TRUE
;
2759 SetupInstallFromInfSectionW(NULL
,
2768 INVALID_HANDLE_VALUE
,
2771 /* FIXME: More code! */
2773 if (bFileQueueCreated
)
2774 SetupCloseFileQueue(FileQueue
);
2776 SetupCloseInfFile(hInf
);
2778 RegCloseKey(hClassKey
);
2783 /***********************************************************************
2784 * SetupDiOpenClassRegKey (SETUPAPI.@)
2786 HKEY WINAPI
SetupDiOpenClassRegKey(
2787 const GUID
* ClassGuid
,
2790 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2791 DIOCR_INSTALLER
, NULL
, NULL
);
2795 /***********************************************************************
2796 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2798 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2799 const GUID
* ClassGuid
,
2805 PWSTR MachineNameW
= NULL
;
2812 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2813 if (MachineNameW
== NULL
)
2814 return INVALID_HANDLE_VALUE
;
2817 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2818 Flags
, MachineNameW
, Reserved
);
2821 MyFree(MachineNameW
);
2827 /***********************************************************************
2828 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2830 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2831 const GUID
* ClassGuid
,
2837 LPWSTR lpGuidString
;
2838 LPWSTR lpFullGuidString
;
2846 if (Flags
== DIOCR_INSTALLER
)
2848 lpKeyName
= ControlClass
;
2850 else if (Flags
== DIOCR_INTERFACE
)
2852 lpKeyName
= DeviceClasses
;
2856 ERR("Invalid Flags parameter!\n");
2857 SetLastError(ERROR_INVALID_PARAMETER
);
2858 return INVALID_HANDLE_VALUE
;
2861 if (MachineName
!= NULL
)
2863 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2864 if (rc
!= ERROR_SUCCESS
)
2867 return INVALID_HANDLE_VALUE
;
2871 HKLM
= HKEY_LOCAL_MACHINE
;
2873 rc
= RegOpenKeyExW(HKLM
,
2878 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2879 if (rc
!= ERROR_SUCCESS
)
2882 return INVALID_HANDLE_VALUE
;
2885 if (ClassGuid
== NULL
)
2888 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2890 SetLastError(ERROR_GEN_FAILURE
);
2891 RegCloseKey(hClassesKey
);
2892 return INVALID_HANDLE_VALUE
;
2895 dwLength
= lstrlenW(lpGuidString
);
2896 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2897 if (!lpFullGuidString
)
2899 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2900 RpcStringFreeW(&lpGuidString
);
2901 return INVALID_HANDLE_VALUE
;
2903 lpFullGuidString
[0] = '{';
2904 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2905 lpFullGuidString
[dwLength
+ 1] = '}';
2906 lpFullGuidString
[dwLength
+ 2] = '\0';
2907 RpcStringFreeW(&lpGuidString
);
2909 rc
= RegOpenKeyExW(hClassesKey
,
2914 if (rc
!= ERROR_SUCCESS
)
2917 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2918 RegCloseKey(hClassesKey
);
2919 return INVALID_HANDLE_VALUE
;
2922 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2923 RegCloseKey(hClassesKey
);
2928 /***********************************************************************
2929 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2931 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2932 HDEVINFO DeviceInfoSet
,
2935 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2937 FIXME("%p %s %08lx %p\n",
2938 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2942 /***********************************************************************
2943 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2945 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2946 HDEVINFO DeviceInfoSet
,
2949 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2951 LPWSTR DevicePathW
= NULL
;
2954 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2956 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2957 if (DevicePathW
== NULL
)
2960 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2961 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2963 MyFree(DevicePathW
);
2968 /***********************************************************************
2969 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2971 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2972 HDEVINFO DeviceInfoSet
,
2973 PSP_DEVINFO_DATA DeviceInfoData
,
2974 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2975 DWORD ClassInstallParamsSize
)
2977 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2978 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2984 IN PWSTR InstallerName
,
2985 OUT HMODULE
* ModulePointer
,
2986 OUT PVOID
* FunctionPointer
)
2988 HMODULE hModule
= NULL
;
2989 LPSTR FunctionNameA
= NULL
;
2993 *ModulePointer
= NULL
;
2994 *FunctionPointer
= NULL
;
2996 Comma
= strchrW(InstallerName
, ',');
2999 rc
= ERROR_INVALID_PARAMETER
;
3005 hModule
= LoadLibraryW(InstallerName
);
3009 rc
= GetLastError();
3013 /* Skip comma spaces */
3014 while (*Comma
== ',' || isspaceW(*Comma
))
3017 /* W->A conversion for function name */
3018 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3021 rc
= GetLastError();
3025 /* Search function */
3026 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3027 if (!*FunctionPointer
)
3029 rc
= GetLastError();
3033 *ModulePointer
= hModule
;
3037 if (rc
!= ERROR_SUCCESS
&& hModule
)
3038 FreeLibrary(hModule
);
3039 MyFree(FunctionNameA
);
3044 FreeFunctionPointer(
3045 IN HMODULE ModulePointer
,
3046 IN PVOID FunctionPointer
)
3048 if (ModulePointer
== NULL
)
3049 return ERROR_SUCCESS
;
3050 if (FreeLibrary(ModulePointer
))
3051 return ERROR_SUCCESS
;
3053 return GetLastError();
3056 /***********************************************************************
3057 * SetupDiCallClassInstaller (SETUPAPI.@)
3059 BOOL WINAPI
SetupDiCallClassInstaller(
3060 IN DI_FUNCTION InstallFunction
,
3061 IN HDEVINFO DeviceInfoSet
,
3062 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3066 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3069 SetLastError(ERROR_INVALID_PARAMETER
);
3070 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3071 SetLastError(ERROR_INVALID_HANDLE
);
3072 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3073 SetLastError(ERROR_INVALID_HANDLE
);
3074 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3075 SetLastError(ERROR_INVALID_HANDLE
);
3076 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3077 SetLastError(ERROR_INVALID_USER_BUFFER
);
3080 SP_DEVINSTALL_PARAMS_W InstallParams
;
3081 #define CLASS_COINSTALLER 0x1
3082 #define DEVICE_COINSTALLER 0x2
3083 #define CLASS_INSTALLER 0x4
3084 UCHAR CanHandle
= 0;
3085 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3087 switch (InstallFunction
)
3089 case DIF_ALLOW_INSTALL
:
3090 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3092 case DIF_DESTROYPRIVATEDATA
:
3093 CanHandle
= CLASS_INSTALLER
;
3095 case DIF_INSTALLDEVICE
:
3096 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3097 DefaultHandler
= SetupDiInstallDevice
;
3099 case DIF_INSTALLDEVICEFILES
:
3100 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3101 DefaultHandler
= SetupDiInstallDriverFiles
;
3103 case DIF_INSTALLINTERFACES
:
3104 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3105 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3107 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3108 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3110 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3111 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3113 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3114 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3116 case DIF_REGISTER_COINSTALLERS
:
3117 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3118 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3120 case DIF_SELECTBESTCOMPATDRV
:
3121 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3122 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3125 FIXME("Install function %ld not implemented\n", InstallFunction
);
3126 SetLastError(ERROR_INVALID_PARAMETER
);
3129 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3130 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3131 /* Don't process this call, as a parameter is invalid */
3136 LIST_ENTRY ClassCoInstallersListHead
;
3137 LIST_ENTRY DeviceCoInstallersListHead
;
3138 HMODULE ClassInstallerLibrary
= NULL
;
3139 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3140 COINSTALLER_CONTEXT_DATA Context
;
3141 PLIST_ENTRY ListEntry
;
3143 DWORD dwRegType
, dwLength
;
3144 DWORD rc
= NO_ERROR
;
3146 InitializeListHead(&ClassCoInstallersListHead
);
3147 InitializeListHead(&DeviceCoInstallersListHead
);
3149 if (CanHandle
& DEVICE_COINSTALLER
)
3151 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3152 if (hKey
!= INVALID_HANDLE_VALUE
)
3154 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3155 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3157 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3158 if (KeyBuffer
!= NULL
)
3160 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3161 if (rc
== ERROR_SUCCESS
)
3164 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3166 /* Add coinstaller to DeviceCoInstallersListHead list */
3167 struct CoInstallerElement
*coinstaller
;
3168 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3169 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3172 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3173 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3174 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3176 HeapFree(GetProcessHeap(), 0, coinstaller
);
3179 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3185 if (CanHandle
& CLASS_COINSTALLER
)
3189 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3193 if (rc
== ERROR_SUCCESS
)
3195 LPWSTR lpGuidString
;
3196 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3198 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3199 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3201 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3202 if (KeyBuffer
!= NULL
)
3204 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3205 if (rc
== ERROR_SUCCESS
)
3208 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3210 /* Add coinstaller to ClassCoInstallersListHead list */
3211 struct CoInstallerElement
*coinstaller
;
3212 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3213 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3216 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3217 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3218 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3220 HeapFree(GetProcessHeap(), 0, coinstaller
);
3223 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3226 RpcStringFreeW(&lpGuidString
);
3231 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3233 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3234 if (hKey
!= INVALID_HANDLE_VALUE
)
3236 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3237 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3239 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3240 if (KeyBuffer
!= NULL
)
3242 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3243 if (rc
== ERROR_SUCCESS
)
3245 /* Get ClassInstaller function pointer */
3246 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3247 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3249 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3250 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3253 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3260 /* Call Class co-installers */
3261 Context
.PostProcessing
= FALSE
;
3263 ListEntry
= ClassCoInstallersListHead
.Flink
;
3264 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3266 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3267 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3268 coinstaller
->PrivateData
= Context
.PrivateData
;
3269 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3271 coinstaller
->DoPostProcessing
= TRUE
;
3274 ListEntry
= ListEntry
->Flink
;
3277 /* Call Device co-installers */
3278 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3279 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3281 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3282 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3283 coinstaller
->PrivateData
= Context
.PrivateData
;
3284 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3286 coinstaller
->DoPostProcessing
= TRUE
;
3289 ListEntry
= ListEntry
->Flink
;
3292 /* Call Class installer */
3295 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3296 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3299 rc
= ERROR_DI_DO_DEFAULT
;
3301 /* Call default handler */
3302 if (rc
== ERROR_DI_DO_DEFAULT
)
3304 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3306 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3309 rc
= GetLastError();
3315 /* Call Class co-installers that required postprocessing */
3316 Context
.PostProcessing
= TRUE
;
3317 ListEntry
= ClassCoInstallersListHead
.Flink
;
3318 while (ListEntry
!= &ClassCoInstallersListHead
)
3320 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3321 if (coinstaller
->DoPostProcessing
)
3323 Context
.InstallResult
= rc
;
3324 Context
.PrivateData
= coinstaller
->PrivateData
;
3325 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3327 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3328 ListEntry
= ListEntry
->Flink
;
3331 /* Call Device co-installers that required postprocessing */
3332 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3333 while (ListEntry
!= &DeviceCoInstallersListHead
)
3335 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3336 if (coinstaller
->DoPostProcessing
)
3338 Context
.InstallResult
= rc
;
3339 Context
.PrivateData
= coinstaller
->PrivateData
;
3340 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3342 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3343 ListEntry
= ListEntry
->Flink
;
3346 /* Free allocated memory */
3347 while (!IsListEmpty(&ClassCoInstallersListHead
))
3349 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3350 HeapFree(GetProcessHeap(), 0, ListEntry
);
3352 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3354 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3355 HeapFree(GetProcessHeap(), 0, ListEntry
);
3358 ret
= (rc
== NO_ERROR
);
3362 TRACE("Returning %d\n", ret
);
3366 /***********************************************************************
3367 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3369 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3370 IN HDEVINFO DeviceInfoSet
,
3371 IN PSP_DEVINFO_DATA DeviceInfoData
,
3372 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3374 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3377 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3379 if (DeviceInstallParams
== NULL
)
3380 SetLastError(ERROR_INVALID_PARAMETER
);
3381 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3382 SetLastError(ERROR_INVALID_USER_BUFFER
);
3385 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3386 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3390 /* Do W->A conversion */
3392 DeviceInstallParams
,
3393 &deviceInstallParamsW
,
3394 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3395 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3396 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3398 DeviceInstallParams
->DriverPath
[0] = '\0';
3404 TRACE("Returning %d\n", ret
);
3408 /***********************************************************************
3409 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3411 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3412 IN HDEVINFO DeviceInfoSet
,
3413 IN PSP_DEVINFO_DATA DeviceInfoData
,
3414 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3416 struct DeviceInfoSet
*list
;
3419 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3422 SetLastError(ERROR_INVALID_HANDLE
);
3423 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3424 SetLastError(ERROR_INVALID_HANDLE
);
3425 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3426 SetLastError(ERROR_INVALID_USER_BUFFER
);
3427 else if (!DeviceInstallParams
)
3428 SetLastError(ERROR_INVALID_PARAMETER
);
3429 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3430 SetLastError(ERROR_INVALID_USER_BUFFER
);
3433 PSP_DEVINSTALL_PARAMS_W Source
;
3436 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3438 Source
= &list
->InstallParams
;
3439 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3443 TRACE("Returning %d\n", ret
);
3447 /***********************************************************************
3448 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3450 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3451 IN HDEVINFO DeviceInfoSet
,
3452 IN PSP_DEVINFO_DATA DeviceInfoData
,
3453 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3455 struct DeviceInfoSet
*list
;
3458 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3461 SetLastError(ERROR_INVALID_HANDLE
);
3462 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3463 SetLastError(ERROR_INVALID_HANDLE
);
3464 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3465 SetLastError(ERROR_INVALID_USER_BUFFER
);
3466 else if (!DeviceInstallParams
)
3467 SetLastError(ERROR_INVALID_PARAMETER
);
3468 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3469 SetLastError(ERROR_INVALID_USER_BUFFER
);
3472 PSP_DEVINSTALL_PARAMS_W Destination
;
3474 /* FIXME: Validate parameters */
3477 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3479 Destination
= &list
->InstallParams
;
3480 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3484 TRACE("Returning %d\n", ret
);
3488 /***********************************************************************
3489 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3491 HKEY WINAPI
SetupDiCreateDevRegKeyA(
3492 IN HDEVINFO DeviceInfoSet
,
3493 IN PSP_DEVINFO_DATA DeviceInfoData
,
3497 IN HINF InfHandle OPTIONAL
,
3498 IN PCSTR InfSectionName OPTIONAL
)
3500 PCWSTR InfSectionNameW
= NULL
;
3501 HKEY ret
= INVALID_HANDLE_VALUE
;
3505 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
3506 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
3509 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
3517 if (InfSectionNameW
!= NULL
)
3518 MyFree((PVOID
)InfSectionNameW
);
3523 /***********************************************************************
3524 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3526 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3527 IN HDEVINFO DeviceInfoSet
,
3528 IN PSP_DEVINFO_DATA DeviceInfoData
,
3532 IN HINF InfHandle OPTIONAL
,
3533 IN PCWSTR InfSectionName OPTIONAL
)
3535 struct DeviceInfoSet
*list
;
3536 HKEY ret
= INVALID_HANDLE_VALUE
;
3538 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3539 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3542 SetLastError(ERROR_INVALID_HANDLE
);
3543 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3544 SetLastError(ERROR_INVALID_HANDLE
);
3545 else if (!DeviceInfoData
)
3546 SetLastError(ERROR_INVALID_PARAMETER
);
3547 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3548 SetLastError(ERROR_INVALID_USER_BUFFER
);
3549 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3550 SetLastError(ERROR_INVALID_PARAMETER
);
3551 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3552 SetLastError(ERROR_INVALID_PARAMETER
);
3553 else if (InfHandle
&& !InfSectionName
)
3554 SetLastError(ERROR_INVALID_PARAMETER
);
3555 else if (!InfHandle
&& InfSectionName
)
3556 SetLastError(ERROR_INVALID_PARAMETER
);
3559 LPWSTR lpGuidString
= NULL
;
3560 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3561 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3562 DWORD Index
; /* Index used in the DriverKey name */
3564 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3565 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3566 HKEY hKey
= INVALID_HANDLE_VALUE
;
3568 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3570 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3574 if (KeyType
== DIREG_DEV
)
3576 FIXME("DIREG_DEV case unimplemented\n");
3578 else /* KeyType == DIREG_DRV */
3580 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3582 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3583 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3586 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3589 wcscpy(DriverKey
, L
"{");
3590 wcscat(DriverKey
, lpGuidString
);
3591 wcscat(DriverKey
, L
"}\\");
3592 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3593 rc
= RegOpenKeyExW(list
->HKLM
,
3598 if (rc
!= ERROR_SUCCESS
)
3604 /* Try all values for Index between 0 and 9999 */
3606 while (Index
<= 9999)
3609 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3610 rc
= RegCreateKeyEx(hClassKey
,
3614 REG_OPTION_NON_VOLATILE
,
3615 #if _WIN32_WINNT >= 0x502
3616 KEY_READ
| KEY_WRITE
,
3623 if (rc
!= ERROR_SUCCESS
)
3628 if (Disposition
== REG_CREATED_NEW_KEY
)
3631 hKey
= INVALID_HANDLE_VALUE
;
3636 /* Unable to create more than 9999 devices within the same class */
3637 SetLastError(ERROR_GEN_FAILURE
);
3641 /* Open device key, to write Driver value */
3642 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3643 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3645 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3646 if (rc
!= ERROR_SUCCESS
)
3653 /* Do installation of the specified section */
3656 FIXME("Need to install section %s in file %p\n",
3657 debugstr_w(InfSectionName
), InfHandle
);
3663 RpcStringFreeW(&lpGuidString
);
3664 HeapFree(GetProcessHeap(), 0, DriverKey
);
3665 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3666 RegCloseKey(hClassKey
);
3667 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3668 RegCloseKey(hDeviceKey
);
3669 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3673 TRACE("Returning 0x%p\n", ret
);
3677 /***********************************************************************
3678 * SetupDiOpenDevRegKey (SETUPAPI.@)
3680 HKEY WINAPI
SetupDiOpenDevRegKey(
3681 HDEVINFO DeviceInfoSet
,
3682 PSP_DEVINFO_DATA DeviceInfoData
,
3688 struct DeviceInfoSet
*list
;
3689 HKEY ret
= INVALID_HANDLE_VALUE
;
3691 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3692 Scope
, HwProfile
, KeyType
, samDesired
);
3695 SetLastError(ERROR_INVALID_HANDLE
);
3696 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3697 SetLastError(ERROR_INVALID_HANDLE
);
3698 else if (!DeviceInfoData
)
3699 SetLastError(ERROR_INVALID_PARAMETER
);
3700 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3701 SetLastError(ERROR_INVALID_USER_BUFFER
);
3702 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3703 SetLastError(ERROR_INVALID_PARAMETER
);
3704 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3705 SetLastError(ERROR_INVALID_PARAMETER
);
3708 HKEY hKey
= INVALID_HANDLE_VALUE
;
3709 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3710 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3711 LPWSTR DriverKey
= NULL
;
3716 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3718 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3720 else /* Scope == DICS_FLAG_GLOBAL */
3726 KEY_ENUMERATE_SUB_KEYS
,
3728 if (rc
!= ERROR_SUCCESS
)
3735 deviceInfo
->DeviceName
,
3737 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3739 RegCloseKey(hRootKey
);
3740 hRootKey
= INVALID_HANDLE_VALUE
;
3741 if (rc
!= ERROR_SUCCESS
)
3746 if (KeyType
== DIREG_DEV
)
3748 /* We're done. Just return the hKey handle */
3752 /* Read the 'Driver' key */
3753 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3754 if (rc
!= ERROR_SUCCESS
)
3759 if (dwRegType
!= REG_SZ
)
3761 SetLastError(ERROR_GEN_FAILURE
);
3764 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3767 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3770 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3771 if (rc
!= ERROR_SUCCESS
)
3777 hKey
= INVALID_HANDLE_VALUE
;
3778 /* Need to open the driver key */
3783 KEY_ENUMERATE_SUB_KEYS
,
3785 if (rc
!= ERROR_SUCCESS
)
3796 if (rc
!= ERROR_SUCCESS
)
3804 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3805 RegCloseKey(hRootKey
);
3806 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3810 TRACE("Returning 0x%p\n", ret
);
3814 /***********************************************************************
3815 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3817 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3818 HDEVINFO DeviceInfoSet
,
3820 CONST GUID
*ClassGuid
,
3821 PCSTR DeviceDescription
,
3823 DWORD CreationFlags
,
3824 PSP_DEVINFO_DATA DeviceInfoData
)
3826 LPWSTR DeviceNameW
= NULL
;
3827 LPWSTR DeviceDescriptionW
= NULL
;
3834 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3835 if (DeviceNameW
== NULL
) return FALSE
;
3837 if (DeviceDescription
)
3839 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3840 if (DeviceDescriptionW
== NULL
)
3842 if (DeviceNameW
) MyFree(DeviceNameW
);
3847 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3848 ClassGuid
, DeviceDescriptionW
,
3849 hwndParent
, CreationFlags
,
3852 if (DeviceNameW
) MyFree(DeviceNameW
);
3853 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3858 /***********************************************************************
3859 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3861 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3862 HDEVINFO DeviceInfoSet
,
3864 CONST GUID
*ClassGuid
,
3865 PCWSTR DeviceDescription
,
3867 DWORD CreationFlags
,
3868 PSP_DEVINFO_DATA DeviceInfoData
)
3870 struct DeviceInfoSet
*list
;
3873 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3874 debugstr_guid(ClassGuid
), DeviceDescription
,
3875 hwndParent
, CreationFlags
, DeviceInfoData
);
3878 SetLastError(ERROR_INVALID_HANDLE
);
3879 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3880 SetLastError(ERROR_INVALID_HANDLE
);
3881 else if (!ClassGuid
)
3882 SetLastError(ERROR_INVALID_PARAMETER
);
3883 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3884 SetLastError(ERROR_CLASS_MISMATCH
);
3885 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3887 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3888 SetLastError(ERROR_INVALID_PARAMETER
);
3892 SP_DEVINFO_DATA DevInfo
;
3894 if (CreationFlags
& DICD_GENERATE_ID
)
3896 /* Generate a new unique ID for this device */
3897 SetLastError(ERROR_GEN_FAILURE
);
3898 FIXME("not implemented\n");
3902 /* Device name is fully qualified. Try to open it */
3905 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3906 rc
= SetupDiOpenDeviceInfoW(
3909 NULL
, /* hwndParent */
3910 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3915 /* SetupDiOpenDeviceInfoW has already added
3916 * the device info to the device info set
3918 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3920 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3922 struct DeviceInfoElement
*deviceInfo
;
3924 /* FIXME: ClassGuid can be NULL */
3925 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3927 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3929 if (!DeviceInfoData
)
3933 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3935 SetLastError(ERROR_INVALID_USER_BUFFER
);
3939 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3940 DeviceInfoData
->DevInst
= 0; /* FIXME */
3941 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3950 TRACE("Returning %d\n", ret
);
3954 /***********************************************************************
3955 * Helper functions for SetupDiBuildDriverInfoList
3959 IN PLIST_ENTRY DriverListHead
,
3960 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3961 IN LPGUID ClassGuid
,
3962 IN INFCONTEXT ContextDevice
,
3963 IN
struct InfFileDetails
*InfFileDetails
,
3965 IN LPCWSTR ProviderName
,
3966 IN LPCWSTR ManufacturerName
,
3967 IN LPCWSTR MatchingId
,
3968 FILETIME DriverDate
,
3969 DWORDLONG DriverVersion
,
3972 struct DriverInfoElement
*driverInfo
= NULL
;
3973 HANDLE hFile
= INVALID_HANDLE_VALUE
;
3974 DWORD RequiredSize
= 128; /* Initial buffer size */
3975 BOOL Result
= FALSE
;
3976 PLIST_ENTRY PreviousEntry
;
3977 LPWSTR InfInstallSection
= NULL
;
3980 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3983 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3986 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3988 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
3989 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
3991 /* Copy InfFileName field */
3992 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
3993 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
3995 /* Fill InfDate field */
3996 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3997 GENERIC_READ, FILE_SHARE_READ,
3998 NULL, OPEN_EXISTING, 0, NULL);
3999 if (hFile == INVALID_HANDLE_VALUE)
4001 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4005 /* Fill SectionName field */
4006 Result
= SetupGetStringFieldW(
4009 driverInfo
->Details
.SectionName
, LINE_LEN
,
4014 /* Fill DrvDescription field */
4015 Result
= SetupGetStringFieldW(
4017 0, /* Field index */
4018 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
4021 /* Copy MatchingId information */
4022 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4023 if (!driverInfo
->MatchingId
)
4025 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4028 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4030 /* Get inf install section */
4032 RequiredSize
= 128; /* Initial buffer size */
4033 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4034 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4036 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4037 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4038 if (!InfInstallSection
)
4040 Result
= SetupGetStringFieldW(
4042 1, /* Field index */
4043 InfInstallSection
, RequiredSize
,
4049 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4050 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4052 driverInfo
->DriverRank
= Rank
;
4053 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4054 driverInfo
->Info
.DriverType
= DriverType
;
4055 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4056 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4057 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4058 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4059 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4062 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4063 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4066 driverInfo
->Info
.ProviderName
[0] = '\0';
4067 driverInfo
->Info
.DriverDate
= DriverDate
;
4068 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4069 ReferenceInfFile(InfFileDetails
);
4070 driverInfo
->InfFileDetails
= InfFileDetails
;
4072 /* Insert current driver in driver list, according to its rank */
4073 PreviousEntry
= DriverListHead
->Flink
;
4074 while (PreviousEntry
!= DriverListHead
)
4076 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
4078 /* Insert before the current item */
4079 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4082 PreviousEntry
= PreviousEntry
->Flink
;
4084 if (PreviousEntry
== DriverListHead
)
4086 /* Insert at the end of the list */
4087 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4096 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4097 HeapFree(GetProcessHeap(), 0, driverInfo
);
4099 if (hFile
!= INVALID_HANDLE_VALUE
)
4101 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4107 GetVersionInformationFromInfFile(
4109 OUT LPGUID ClassGuid
,
4110 OUT LPWSTR
* pProviderName
,
4111 OUT FILETIME
* DriverDate
,
4112 OUT DWORDLONG
* DriverVersion
)
4115 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4116 LPWSTR DriverVer
= NULL
;
4117 LPWSTR ProviderName
= NULL
;
4118 LPWSTR pComma
; /* Points into DriverVer */
4119 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4120 SYSTEMTIME SystemTime
;
4122 BOOL ret
= FALSE
; /* Final result */
4124 /* Get class Guid */
4125 if (!SetupGetLineTextW(
4128 L
"Version", L
"ClassGUID",
4129 guidW
, sizeof(guidW
),
4130 NULL
/* Required size */))
4134 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4135 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4137 SetLastError(ERROR_GEN_FAILURE
);
4141 /* Get provider name */
4142 Result
= SetupGetLineTextW(
4144 hInf
, L
"Version", L
"Provider",
4149 /* We know know the needed buffer size */
4150 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4153 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4156 Result
= SetupGetLineTextW(
4158 hInf
, L
"Version", L
"Provider",
4159 ProviderName
, RequiredSize
,
4164 *pProviderName
= ProviderName
;
4166 /* Read the "DriverVer" value */
4167 Result
= SetupGetLineTextW(
4169 hInf
, L
"Version", L
"DriverVer",
4174 /* We know know the needed buffer size */
4175 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4178 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4181 Result
= SetupGetLineTextW(
4183 hInf
, L
"Version", L
"DriverVer",
4184 DriverVer
, RequiredSize
,
4190 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4191 pComma
= wcschr(DriverVer
, ',');
4194 *pComma
= UNICODE_NULL
;
4195 pVersion
= pComma
+ 1;
4197 /* Get driver date version. Invalid date = 00/00/00 */
4198 memset(DriverDate
, 0, sizeof(FILETIME
));
4199 if (wcslen(DriverVer
) == 10
4200 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4201 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4203 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4204 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4205 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4206 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4207 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4208 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4210 /* Get driver version. Invalid version = 0.0.0.0 */
4212 /* FIXME: use pVersion to fill DriverVersion variable */
4218 HeapFree(GetProcessHeap(), 0, ProviderName
);
4219 HeapFree(GetProcessHeap(), 0, DriverVer
);
4221 TRACE("Returning %d\n", ret
);
4225 /***********************************************************************
4226 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4229 SetupDiBuildDriverInfoList(
4230 IN HDEVINFO DeviceInfoSet
,
4231 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4232 IN DWORD DriverType
)
4234 struct DeviceInfoSet
*list
;
4235 SP_DEVINSTALL_PARAMS_W InstallParams
;
4236 PVOID Buffer
= NULL
;
4237 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4238 LPWSTR ProviderName
= NULL
;
4239 LPWSTR ManufacturerName
= NULL
;
4240 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4241 LPWSTR HardwareIDs
= NULL
;
4242 LPWSTR CompatibleIDs
= NULL
;
4243 LPWSTR FullInfFileName
= NULL
;
4244 FILETIME DriverDate
;
4245 DWORDLONG DriverVersion
= 0;
4249 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4252 SetLastError(ERROR_INVALID_HANDLE
);
4253 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4254 SetLastError(ERROR_INVALID_HANDLE
);
4255 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4256 SetLastError(ERROR_INVALID_HANDLE
);
4257 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4258 SetLastError(ERROR_INVALID_PARAMETER
);
4259 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4260 SetLastError(ERROR_INVALID_PARAMETER
);
4261 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4262 SetLastError(ERROR_INVALID_PARAMETER
);
4263 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4264 SetLastError(ERROR_INVALID_USER_BUFFER
);
4269 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4270 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4274 if (DriverType
== SPDIT_COMPATDRIVER
)
4276 /* Get hardware IDs list */
4278 RequiredSize
= 512; /* Initial buffer size */
4279 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4280 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4282 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4283 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4286 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4289 Result
= SetupDiGetDeviceRegistryPropertyW(
4301 /* Get compatible IDs list */
4303 RequiredSize
= 512; /* Initial buffer size */
4304 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4305 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4307 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4308 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4311 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4314 Result
= SetupDiGetDeviceRegistryPropertyW(
4317 SPDRP_COMPATIBLEIDS
,
4319 (PBYTE
)CompatibleIDs
,
4322 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4324 /* No compatible ID for this device */
4325 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4326 CompatibleIDs
= NULL
;
4334 /* Enumerate .inf files */
4336 RequiredSize
= 32768; /* Initial buffer size */
4337 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4338 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4340 HeapFree(GetProcessHeap(), 0, Buffer
);
4341 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4345 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4348 Result
= SetupGetInfFileListW(
4349 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4351 Buffer
, RequiredSize
,
4354 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4356 /* No .inf file in specified directory. So, we should
4357 * success as we created an empty driver info list.
4365 LPWSTR pFullFilename
;
4367 if (*InstallParams
.DriverPath
)
4370 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
4373 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
4374 if (!FullInfFileName
)
4376 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
4379 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
4380 wcscat(FullInfFileName
, L
"\\");
4381 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
4385 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
4386 if (!FullInfFileName
)
4388 pFullFilename
= &FullInfFileName
[0];
4391 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4393 INFCONTEXT ContextManufacturer
, ContextDevice
;
4396 wcscpy(pFullFilename
, filename
);
4397 TRACE("Opening file %S\n", FullInfFileName
);
4399 currentInfFileDetails
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct InfFileDetails
));
4400 if (!currentInfFileDetails
)
4402 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
4404 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
4405 ReferenceInfFile(currentInfFileDetails
);
4406 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
4408 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
4409 currentInfFileDetails
= NULL
;
4413 if (!GetVersionInformationFromInfFile(
4414 currentInfFileDetails
->hInf
,
4420 SetupCloseInfFile(currentInfFileDetails
->hInf
);
4421 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
4422 currentInfFileDetails
= NULL
;
4426 if (DriverType
== SPDIT_CLASSDRIVER
)
4428 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4429 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4435 /* Get the manufacturers list */
4436 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4439 Result
= SetupGetStringFieldW(
4440 &ContextManufacturer
,
4441 0, /* Field index */
4446 /* We got the needed size for the buffer */
4447 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4448 if (!ManufacturerName
)
4450 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4453 Result
= SetupGetStringFieldW(
4454 &ContextManufacturer
,
4455 0, /* Field index */
4456 ManufacturerName
, RequiredSize
,
4459 /* Get manufacturer section name */
4460 Result
= SetupGetStringFieldW(
4461 &ContextManufacturer
,
4462 1, /* Field index */
4463 ManufacturerSection
, LINE_LEN
,
4467 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
4468 /* Add (possible) extension to manufacturer section name */
4469 Result
= SetupDiGetActualSectionToInstallW(
4470 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
4473 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4474 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4479 if (DriverType
== SPDIT_CLASSDRIVER
)
4481 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4482 if (!AddDriverToList(
4483 &list
->DriverListHead
,
4487 currentInfFileDetails
,
4492 DriverDate
, DriverVersion
,
4498 else /* DriverType = SPDIT_COMPATDRIVER */
4500 /* 1. Get all fields */
4501 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4505 BOOL DriverAlreadyAdded
;
4507 for (i
= 2; i
<= FieldCount
; i
++)
4509 LPWSTR DeviceId
= NULL
;
4511 RequiredSize
= 128; /* Initial buffer size */
4512 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4513 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4515 HeapFree(GetProcessHeap(), 0, DeviceId
);
4516 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4519 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4522 Result
= SetupGetStringFieldW(
4525 DeviceId
, RequiredSize
,
4530 HeapFree(GetProcessHeap(), 0, DeviceId
);
4533 DriverAlreadyAdded
= FALSE
;
4534 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4536 if (wcscmp(DeviceId
, currentId
) == 0)
4539 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4543 currentInfFileDetails
,
4548 DriverDate
, DriverVersion
,
4549 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4550 DriverAlreadyAdded
= TRUE
;
4555 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4557 if (wcscmp(DeviceId
, currentId
) == 0)
4560 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4564 currentInfFileDetails
,
4569 DriverDate
, DriverVersion
,
4570 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4571 DriverAlreadyAdded
= TRUE
;
4575 HeapFree(GetProcessHeap(), 0, DeviceId
);
4578 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4581 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4582 ManufacturerName
= NULL
;
4583 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4588 HeapFree(GetProcessHeap(), 0, ProviderName
);
4589 ProviderName
= NULL
;
4591 DereferenceInfFile(currentInfFileDetails
);
4592 currentInfFileDetails
= NULL
;
4603 InstallParams
.Flags
|= DI_DIDCOMPAT
;
4604 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
4608 InstallParams
.Flags
|= DI_DIDCLASS
;
4609 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
4611 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4614 HeapFree(GetProcessHeap(), 0, ProviderName
);
4615 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4616 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4617 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4618 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
4619 if (currentInfFileDetails
)
4620 DereferenceInfFile(currentInfFileDetails
);
4621 HeapFree(GetProcessHeap(), 0, Buffer
);
4623 TRACE("Returning %d\n", ret
);
4627 /***********************************************************************
4628 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4631 SetupDiDeleteDeviceInfo(
4632 IN HDEVINFO DeviceInfoSet
,
4633 IN PSP_DEVINFO_DATA DeviceInfoData
)
4635 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4637 FIXME("not implemented\n");
4638 SetLastError(ERROR_GEN_FAILURE
);
4643 /***********************************************************************
4644 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4647 SetupDiDestroyDriverInfoList(
4648 IN HDEVINFO DeviceInfoSet
,
4649 IN PSP_DEVINFO_DATA DeviceInfoData
,
4650 IN DWORD DriverType
)
4652 struct DeviceInfoSet
*list
;
4655 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4658 SetLastError(ERROR_INVALID_HANDLE
);
4659 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4660 SetLastError(ERROR_INVALID_HANDLE
);
4661 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4662 SetLastError(ERROR_INVALID_PARAMETER
);
4663 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4664 SetLastError(ERROR_INVALID_PARAMETER
);
4665 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4666 SetLastError(ERROR_INVALID_USER_BUFFER
);
4669 PLIST_ENTRY ListEntry
;
4670 struct DriverInfoElement
*driverInfo
;
4671 SP_DEVINSTALL_PARAMS_W InstallParams
;
4673 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4674 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4677 if (!DeviceInfoData
)
4678 /* Fall back to destroying class driver list */
4679 DriverType
= SPDIT_CLASSDRIVER
;
4681 if (DriverType
== SPDIT_CLASSDRIVER
)
4683 while (!IsListEmpty(&list
->DriverListHead
))
4685 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
4686 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4687 DestroyDriverInfoElement(driverInfo
);
4689 InstallParams
.Reserved
= 0;
4690 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
4691 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
4692 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
4696 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
4697 struct DeviceInfoElement
*deviceInfo
;
4699 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4700 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
4702 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4703 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
4705 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
4706 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4707 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
4709 InstallParamsSet
.Reserved
= 0;
4710 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
4712 DestroyDriverInfoElement(driverInfo
);
4714 InstallParams
.Reserved
= 0;
4715 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
4716 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
4717 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4722 TRACE("Returning %d\n", ret
);
4727 /***********************************************************************
4728 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4731 SetupDiOpenDeviceInfoA(
4732 IN HDEVINFO DeviceInfoSet
,
4733 IN PCSTR DeviceInstanceId
,
4734 IN HWND hwndParent OPTIONAL
,
4736 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4738 LPWSTR DeviceInstanceIdW
= NULL
;
4741 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4743 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4744 if (DeviceInstanceIdW
== NULL
)
4747 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4748 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4750 MyFree(DeviceInstanceIdW
);
4756 /***********************************************************************
4757 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4760 SetupDiOpenDeviceInfoW(
4761 IN HDEVINFO DeviceInfoSet
,
4762 IN PCWSTR DeviceInstanceId
,
4763 IN HWND hwndParent OPTIONAL
,
4765 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4767 struct DeviceInfoSet
*list
;
4768 HKEY hEnumKey
, hKey
;
4772 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4774 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4775 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4778 SetLastError(ERROR_INVALID_HANDLE
);
4779 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4780 SetLastError(ERROR_INVALID_HANDLE
);
4781 else if (!DeviceInstanceId
)
4782 SetLastError(ERROR_INVALID_PARAMETER
);
4783 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4785 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4786 SetLastError(ERROR_INVALID_PARAMETER
);
4788 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4789 SetLastError(ERROR_INVALID_USER_BUFFER
);
4792 struct DeviceInfoElement
*deviceInfo
= NULL
;
4793 /* Search if device already exists in DeviceInfoSet.
4794 * If yes, return the existing element
4795 * If no, create a new element using informations in registry
4797 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4798 while (ItemList
!= &list
->ListHead
)
4803 FIXME("not implemented\n");
4804 ItemList
= ItemList
->Flink
;
4809 /* good one found */
4814 /* Open supposed registry key */
4819 KEY_ENUMERATE_SUB_KEYS
,
4821 if (rc
!= ERROR_SUCCESS
)
4832 RegCloseKey(hEnumKey
);
4833 if (rc
!= ERROR_SUCCESS
)
4839 /* FIXME: GUID_NULL is not allowed */
4840 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
4845 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4851 if (ret
&& deviceInfo
&& DeviceInfoData
)
4853 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4854 DeviceInfoData
->DevInst
= 0; /* FIXME */
4855 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4863 /***********************************************************************
4864 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4867 SetupDiEnumDriverInfoA(
4868 IN HDEVINFO DeviceInfoSet
,
4869 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4870 IN DWORD DriverType
,
4871 IN DWORD MemberIndex
,
4872 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4874 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4877 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4878 DriverType
, MemberIndex
, DriverInfoData
);
4880 if (DriverInfoData
== NULL
)
4881 SetLastError(ERROR_INVALID_PARAMETER
);
4882 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4883 SetLastError(ERROR_INVALID_USER_BUFFER
);
4886 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4887 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4888 DriverType
, MemberIndex
, &driverInfoData2W
);
4892 /* Do W->A conversion */
4893 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4894 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4895 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4896 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4898 DriverInfoData
->Description
[0] = '\0';
4901 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4902 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4904 DriverInfoData
->MfgName
[0] = '\0';
4907 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4908 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4910 DriverInfoData
->ProviderName
[0] = '\0';
4913 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4915 /* Copy more fields */
4916 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4917 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4922 TRACE("Returning %d\n", ret
);
4927 /***********************************************************************
4928 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4931 SetupDiEnumDriverInfoW(
4932 IN HDEVINFO DeviceInfoSet
,
4933 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4934 IN DWORD DriverType
,
4935 IN DWORD MemberIndex
,
4936 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4938 PLIST_ENTRY ListHead
;
4941 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4942 DriverType
, MemberIndex
, DriverInfoData
);
4944 if (!DeviceInfoSet
|| !DriverInfoData
)
4945 SetLastError(ERROR_INVALID_PARAMETER
);
4946 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4947 SetLastError(ERROR_INVALID_HANDLE
);
4948 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4949 SetLastError(ERROR_INVALID_HANDLE
);
4950 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4951 SetLastError(ERROR_INVALID_PARAMETER
);
4952 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4953 SetLastError(ERROR_INVALID_PARAMETER
);
4954 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4955 SetLastError(ERROR_INVALID_PARAMETER
);
4956 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4957 SetLastError(ERROR_INVALID_USER_BUFFER
);
4960 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4961 PLIST_ENTRY ItemList
;
4962 if (DriverType
== SPDIT_CLASSDRIVER
||
4963 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4965 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4969 ListHead
= &devInfo
->DriverListHead
;
4972 ItemList
= ListHead
->Flink
;
4973 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4974 ItemList
= ItemList
->Flink
;
4975 if (ItemList
== ListHead
)
4976 SetLastError(ERROR_NO_MORE_ITEMS
);
4979 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4982 &DriverInfoData
->DriverType
,
4983 &DrvInfo
->Info
.DriverType
,
4984 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4989 TRACE("Returning %d\n", ret
);
4994 /***********************************************************************
4995 * SetupDiGetSelectedDriverA (SETUPAPI.@)
4998 SetupDiGetSelectedDriverA(
4999 IN HDEVINFO DeviceInfoSet
,
5000 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5001 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5003 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5006 if (DriverInfoData
== NULL
)
5007 SetLastError(ERROR_INVALID_PARAMETER
);
5008 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5009 SetLastError(ERROR_INVALID_USER_BUFFER
);
5012 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5014 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5020 /* Do W->A conversion */
5021 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5022 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5023 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5024 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5026 DriverInfoData
->Description
[0] = '\0';
5029 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5030 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5032 DriverInfoData
->MfgName
[0] = '\0';
5035 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5036 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5038 DriverInfoData
->ProviderName
[0] = '\0';
5041 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5043 /* Copy more fields */
5044 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5045 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5054 /***********************************************************************
5055 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5058 SetupDiGetSelectedDriverW(
5059 IN HDEVINFO DeviceInfoSet
,
5060 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5061 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5065 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5067 if (!DeviceInfoSet
|| !DriverInfoData
)
5068 SetLastError(ERROR_INVALID_PARAMETER
);
5069 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5070 SetLastError(ERROR_INVALID_HANDLE
);
5071 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5072 SetLastError(ERROR_INVALID_HANDLE
);
5073 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5074 SetLastError(ERROR_INVALID_USER_BUFFER
);
5075 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5076 SetLastError(ERROR_INVALID_USER_BUFFER
);
5079 SP_DEVINSTALL_PARAMS InstallParams
;
5081 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5082 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5084 struct DriverInfoElement
*driverInfo
;
5085 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5086 if (driverInfo
== NULL
)
5087 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5091 &DriverInfoData
->DriverType
,
5092 &driverInfo
->Info
.DriverType
,
5093 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5099 TRACE("Returning %d\n", ret
);
5104 /***********************************************************************
5105 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5108 SetupDiSetSelectedDriverA(
5109 IN HDEVINFO DeviceInfoSet
,
5110 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5111 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5113 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5114 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5117 if (DriverInfoData
!= NULL
)
5119 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5120 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5122 SetLastError(ERROR_INVALID_PARAMETER
);
5126 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5127 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5129 if (DriverInfoDataW
.Reserved
== 0)
5131 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5133 /* convert the strings to unicode */
5134 if (!MultiByteToWideChar(CP_ACP
,
5136 DriverInfoData
->Description
,
5138 DriverInfoDataW
.Description
,
5140 !MultiByteToWideChar(CP_ACP
,
5142 DriverInfoData
->ProviderName
,
5144 DriverInfoDataW
.ProviderName
,
5151 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5154 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5158 if (ret
&& pDriverInfoDataW
!= NULL
)
5160 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5167 /***********************************************************************
5168 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5171 SetupDiSetSelectedDriverW(
5172 IN HDEVINFO DeviceInfoSet
,
5173 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5174 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5178 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5181 SetLastError(ERROR_INVALID_PARAMETER
);
5182 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5183 SetLastError(ERROR_INVALID_HANDLE
);
5184 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5185 SetLastError(ERROR_INVALID_HANDLE
);
5186 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5187 SetLastError(ERROR_INVALID_USER_BUFFER
);
5188 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5189 SetLastError(ERROR_INVALID_USER_BUFFER
);
5192 struct DriverInfoElement
**pDriverInfo
;
5193 PLIST_ENTRY ListHead
, ItemList
;
5197 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5198 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5202 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5203 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5206 if (!DriverInfoData
)
5208 *pDriverInfo
= NULL
;
5213 /* Search selected driver in list */
5214 ItemList
= ListHead
->Flink
;
5215 while (ItemList
!= ListHead
)
5217 if (DriverInfoData
->Reserved
!= 0)
5219 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5224 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5225 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5226 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5227 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5228 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5234 if (ItemList
== ListHead
)
5235 SetLastError(ERROR_INVALID_PARAMETER
);
5238 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5239 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5241 TRACE("Choosing driver whose rank is 0x%lx\n",
5242 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5244 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5249 TRACE("Returning %d\n", ret
);
5253 /***********************************************************************
5254 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5257 SetupDiGetDriverInfoDetailA(
5258 IN HDEVINFO DeviceInfoSet
,
5259 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5260 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5261 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5262 IN DWORD DriverInfoDetailDataSize
,
5263 OUT PDWORD RequiredSize OPTIONAL
)
5265 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5266 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5268 DWORD HardwareIDLen
= 0;
5271 /* do some sanity checks, the unicode version might do more thorough checks */
5272 if (DriverInfoData
== NULL
||
5273 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5274 (DriverInfoDetailData
!= NULL
&&
5275 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5276 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5278 SetLastError(ERROR_INVALID_PARAMETER
);
5282 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5283 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5285 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5287 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5289 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5293 SetLastError(ERROR_INVALID_PARAMETER
);
5296 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5297 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5299 /* convert the strings to unicode */
5300 if (MultiByteToWideChar(CP_ACP
,
5302 DriverInfoData
->Description
,
5304 DriverInfoDataW
.Description
,
5306 MultiByteToWideChar(CP_ACP
,
5308 DriverInfoData
->MfgName
,
5310 DriverInfoDataW
.MfgName
,
5312 MultiByteToWideChar(CP_ACP
,
5314 DriverInfoData
->ProviderName
,
5316 DriverInfoDataW
.ProviderName
,
5319 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5321 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5322 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5325 if (DriverInfoDetailData
!= NULL
)
5327 /* calculate the unicode buffer size from the ansi buffer size */
5328 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5329 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5330 (HardwareIDLen
* sizeof(WCHAR
));
5332 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5333 if (DriverInfoDetailDataW
== NULL
)
5335 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5339 /* initialize the buffer */
5340 ZeroMemory(DriverInfoDetailDataW
,
5342 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5345 /* call the unicode version */
5346 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5349 DriverInfoDetailDataW
,
5355 if (DriverInfoDetailDataW
!= NULL
)
5357 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5358 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
5359 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
5360 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
5361 if (WideCharToMultiByte(CP_ACP
,
5363 DriverInfoDetailDataW
->SectionName
,
5365 DriverInfoDetailData
->SectionName
,
5369 WideCharToMultiByte(CP_ACP
,
5371 DriverInfoDetailDataW
->InfFileName
,
5373 DriverInfoDetailData
->InfFileName
,
5377 WideCharToMultiByte(CP_ACP
,
5379 DriverInfoDetailDataW
->DrvDescription
,
5381 DriverInfoDetailData
->DrvDescription
,
5385 WideCharToMultiByte(CP_ACP
,
5387 DriverInfoDetailDataW
->HardwareID
,
5389 DriverInfoDetailData
->HardwareID
,
5395 DWORD hwidlen
= HardwareIDLen
;
5396 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
5398 /* count the strings in the list */
5401 len
= lstrlenA(s
) + 1;
5410 /* looks like the string list wasn't terminated... */
5411 SetLastError(ERROR_INVALID_USER_BUFFER
);
5417 /* make sure CompatIDsOffset points to the second string in the
5421 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
5422 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
5423 DriverInfoDetailData
->CompatIDsOffset
+ 1;
5427 DriverInfoDetailData
->CompatIDsOffset
= 0;
5428 DriverInfoDetailData
->CompatIDsLength
= 0;
5437 if (RequiredSize
!= NULL
)
5439 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
5440 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
5446 if (DriverInfoDetailDataW
!= NULL
)
5448 MyFree(DriverInfoDetailDataW
);
5454 /***********************************************************************
5455 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5458 SetupDiGetDriverInfoDetailW(
5459 IN HDEVINFO DeviceInfoSet
,
5460 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5461 IN PSP_DRVINFO_DATA_W DriverInfoData
,
5462 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
5463 IN DWORD DriverInfoDetailDataSize
,
5464 OUT PDWORD RequiredSize OPTIONAL
)
5469 SetLastError(ERROR_INVALID_PARAMETER
);
5470 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5471 SetLastError(ERROR_INVALID_HANDLE
);
5472 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5473 SetLastError(ERROR_INVALID_HANDLE
);
5474 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5475 SetLastError(ERROR_INVALID_USER_BUFFER
);
5476 else if (!DriverInfoData
)
5477 SetLastError(ERROR_INVALID_PARAMETER
);
5478 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
5479 SetLastError(ERROR_INVALID_PARAMETER
);
5480 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5481 SetLastError(ERROR_INVALID_PARAMETER
);
5482 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5483 SetLastError(ERROR_INVALID_USER_BUFFER
);
5484 else if (DriverInfoDetailData
&& DriverInfoDetailData
->Reserved
== 0)
5485 SetLastError(ERROR_INVALID_PARAMETER
);
5488 struct DriverInfoElement
*driverInfoElement
;
5489 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
5492 DriverInfoDetailData
,
5493 &driverInfoElement
->Details
,
5494 driverInfoElement
->Details
.cbSize
);
5495 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5496 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5501 TRACE("Returning %d\n", ret
);
5505 /***********************************************************************
5506 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5509 SetupDiSelectBestCompatDrv(
5510 IN HDEVINFO DeviceInfoSet
,
5511 IN PSP_DEVINFO_DATA DeviceInfoData
)
5513 SP_DRVINFO_DATA_W drvInfoData
;
5516 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5518 /* Drivers are sorted by rank in the driver list, so
5519 * the first driver in the list is the best one.
5521 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
5522 ret
= SetupDiEnumDriverInfoW(
5526 0, /* Member index */
5531 ret
= SetupDiSetSelectedDriverW(
5537 TRACE("Returning %d\n", ret
);
5541 /***********************************************************************
5542 * SetupDiInstallDriverFiles (SETUPAPI.@)
5545 SetupDiInstallDriverFiles(
5546 IN HDEVINFO DeviceInfoSet
,
5547 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5551 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5554 SetLastError(ERROR_INVALID_PARAMETER
);
5555 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5556 SetLastError(ERROR_INVALID_HANDLE
);
5557 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5558 SetLastError(ERROR_INVALID_HANDLE
);
5559 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5560 SetLastError(ERROR_INVALID_USER_BUFFER
);
5561 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
5562 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5563 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
5564 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5567 SP_DEVINSTALL_PARAMS_W InstallParams
;
5568 struct DriverInfoElement
*SelectedDriver
;
5569 WCHAR SectionName
[MAX_PATH
];
5570 DWORD SectionNameLength
= 0;
5572 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5573 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5577 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5578 if (!SelectedDriver
)
5580 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5584 ret
= SetupDiGetActualSectionToInstallW(
5585 SelectedDriver
->InfFileDetails
->hInf
,
5586 SelectedDriver
->Details
.SectionName
,
5587 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5591 if (!InstallParams
.InstallMsgHandler
)
5593 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5594 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5595 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5597 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5598 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5599 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
5600 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5601 DeviceInfoSet
, DeviceInfoData
);
5605 TRACE("Returning %d\n", ret
);
5609 /***********************************************************************
5610 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5613 SetupDiRegisterCoDeviceInstallers(
5614 IN HDEVINFO DeviceInfoSet
,
5615 IN PSP_DEVINFO_DATA DeviceInfoData
)
5617 BOOL ret
= FALSE
; /* Return value */
5619 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5622 SetLastError(ERROR_INVALID_PARAMETER
);
5623 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5624 SetLastError(ERROR_INVALID_HANDLE
);
5625 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5626 SetLastError(ERROR_INVALID_HANDLE
);
5627 else if (!DeviceInfoData
)
5628 SetLastError(ERROR_INVALID_PARAMETER
);
5629 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5630 SetLastError(ERROR_INVALID_USER_BUFFER
);
5633 SP_DEVINSTALL_PARAMS_W InstallParams
;
5634 struct DriverInfoElement
*SelectedDriver
;
5637 WCHAR SectionName
[MAX_PATH
];
5638 DWORD SectionNameLength
= 0;
5639 HKEY hKey
= INVALID_HANDLE_VALUE
;;
5641 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5642 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5646 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5647 if (SelectedDriver
== NULL
)
5649 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5653 /* Get .CoInstallers section name */
5654 Result
= SetupDiGetActualSectionToInstallW(
5655 SelectedDriver
->InfFileDetails
->hInf
,
5656 SelectedDriver
->Details
.SectionName
,
5657 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5658 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
5660 wcscat(SectionName
, L
".CoInstallers");
5662 /* Open/Create driver key information */
5663 #if _WIN32_WINNT >= 0x502
5664 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5666 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5668 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5669 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5670 if (hKey
== INVALID_HANDLE_VALUE
)
5673 /* Install .CoInstallers section */
5674 DoAction
= SPINST_REGISTRY
;
5675 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5677 DoAction
|= SPINST_FILES
;
5678 if (!InstallParams
.InstallMsgHandler
)
5680 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5681 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5682 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5685 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5686 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5687 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5688 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5689 DeviceInfoSet
, DeviceInfoData
);
5696 if (hKey
!= INVALID_HANDLE_VALUE
)
5700 TRACE("Returning %d\n", ret
);
5704 /***********************************************************************
5705 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5708 SetupDiInstallDeviceInterfaces(
5709 IN HDEVINFO DeviceInfoSet
,
5710 IN PSP_DEVINFO_DATA DeviceInfoData
)
5712 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5714 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5715 //SetLastError(ERROR_GEN_FAILURE);
5720 /***********************************************************************
5721 * SetupDiInstallDevice (SETUPAPI.@)
5724 SetupDiInstallDevice(
5725 IN HDEVINFO DeviceInfoSet
,
5726 IN PSP_DEVINFO_DATA DeviceInfoData
)
5728 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5729 SP_DEVINSTALL_PARAMS_W InstallParams
;
5730 struct DriverInfoElement
*SelectedDriver
;
5731 SYSTEMTIME DriverDate
;
5732 WCHAR SectionName
[MAX_PATH
];
5734 DWORD SectionNameLength
= 0;
5735 BOOL Result
= FALSE
;
5736 INFCONTEXT ContextService
;
5740 LPCWSTR AssociatedService
= NULL
;
5741 LPWSTR pSectionName
= NULL
;
5742 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5744 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5745 BOOL RebootRequired
= FALSE
;
5746 HKEY hKey
= INVALID_HANDLE_VALUE
;
5747 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
5749 BOOL ret
= FALSE
; /* Return value */
5751 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5754 SetLastError(ERROR_INVALID_PARAMETER
);
5755 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5756 SetLastError(ERROR_INVALID_HANDLE
);
5757 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5758 SetLastError(ERROR_INVALID_HANDLE
);
5759 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5760 SetLastError(ERROR_INVALID_USER_BUFFER
);
5766 /* One parameter is bad */
5770 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5771 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5775 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5777 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5781 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5782 if (SelectedDriver
== NULL
)
5784 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5788 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5790 Result
= SetupDiGetActualSectionToInstallW(
5791 SelectedDriver
->InfFileDetails
->hInf
,
5792 SelectedDriver
->Details
.SectionName
,
5793 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5794 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
5796 pSectionName
= &SectionName
[wcslen(SectionName
)];
5798 /* Get information from [Version] section */
5799 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5801 /* Format ClassGuid to a string */
5802 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5804 RequiredSize
= lstrlenW(lpGuidString
);
5805 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5806 if (!lpFullGuidString
)
5808 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5811 lpFullGuidString
[0] = '{';
5812 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5813 lpFullGuidString
[RequiredSize
+ 1] = '}';
5814 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5816 /* Open/Create driver key information */
5817 #if _WIN32_WINNT >= 0x502
5818 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5820 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5822 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5823 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5824 if (hKey
== INVALID_HANDLE_VALUE
)
5827 /* Install main section */
5828 DoAction
= SPINST_REGISTRY
;
5829 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5831 DoAction
|= SPINST_FILES
;
5832 if (!InstallParams
.InstallMsgHandler
)
5834 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5835 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5836 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5839 *pSectionName
= '\0';
5840 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5841 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5842 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5843 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5844 DeviceInfoSet
, DeviceInfoData
);
5847 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
5849 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
5851 /* Delete resources allocated by SetupInitDefaultQueueCallback */
5852 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
5855 InstallParams
.Flags
|= DI_NOFILECOPY
;
5856 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5858 /* Write information to driver key */
5859 *pSectionName
= UNICODE_NULL
;
5860 TRACE("Write information to driver key\n");
5861 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5862 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5863 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);
5864 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
5865 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
5866 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
5867 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
5868 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
5869 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5870 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5871 if (rc
== ERROR_SUCCESS
)
5872 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5873 if (rc
== ERROR_SUCCESS
)
5874 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5875 if (rc
== ERROR_SUCCESS
)
5877 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);
5878 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5880 if (rc
== ERROR_SUCCESS
)
5881 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
5882 if (rc
== ERROR_SUCCESS
)
5883 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5884 if (rc
== ERROR_SUCCESS
)
5885 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5886 if (rc
== ERROR_SUCCESS
)
5887 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5888 if (rc
== ERROR_SUCCESS
)
5889 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5890 if (rc
!= ERROR_SUCCESS
)
5896 hKey
= INVALID_HANDLE_VALUE
;
5898 /* FIXME: Process .LogConfigOverride section */
5900 /* Install .Services section */
5901 wcscpy(pSectionName
, L
".Services");
5902 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
5905 LPWSTR ServiceName
= NULL
;
5906 LPWSTR ServiceSection
= NULL
;
5908 Result
= SetupGetStringFieldW(
5910 1, /* Field index */
5915 if (RequiredSize
> 0)
5917 /* We got the needed size for the buffer */
5918 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5921 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5924 Result
= SetupGetStringFieldW(
5926 1, /* Field index */
5927 ServiceName
, RequiredSize
,
5932 Result
= SetupGetIntField(
5934 2, /* Field index */
5938 /* The field may be empty. Ignore the error */
5941 Result
= SetupGetStringFieldW(
5943 3, /* Field index */
5948 if (RequiredSize
> 0)
5950 /* We got the needed size for the buffer */
5951 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5952 if (!ServiceSection
)
5954 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5957 Result
= SetupGetStringFieldW(
5959 3, /* Field index */
5960 ServiceSection
, RequiredSize
,
5965 SetLastError(ERROR_SUCCESS
);
5966 Result
= SetupInstallServicesFromInfSectionExW(
5967 SelectedDriver
->InfFileDetails
->hInf
,
5968 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
5969 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
5971 AssociatedService
= ServiceName
;
5973 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5974 RebootRequired
= TRUE
;
5977 HeapFree(GetProcessHeap(), 0, ServiceName
);
5978 HeapFree(GetProcessHeap(), 0, ServiceSection
);
5981 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
5984 /* Copy .inf file to Inf\ directory */
5985 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
5987 /* Open device registry key */
5988 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5989 if (hKey
== INVALID_HANDLE_VALUE
)
5992 /* Install .HW section */
5993 wcscpy(pSectionName
, L
".HW");
5994 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5995 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5996 SPINST_REGISTRY
, hKey
, NULL
, 0,
5997 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5998 DeviceInfoSet
, DeviceInfoData
);
6002 /* Write information to enum key */
6003 TRACE("Write information to enum key\n");
6004 TRACE("Service : '%S'\n", AssociatedService
);
6005 TRACE("Class : '%S'\n", ClassName
);
6006 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
6007 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6008 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
6009 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
6010 if (rc
== ERROR_SUCCESS
)
6011 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
6012 if (rc
== ERROR_SUCCESS
)
6013 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
6014 if (rc
== ERROR_SUCCESS
)
6015 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6016 if (rc
== ERROR_SUCCESS
)
6017 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
6018 if (rc
!= ERROR_SUCCESS
)
6024 /* Start the device */
6025 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
6027 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6029 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
6030 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6031 ret
= NT_SUCCESS(Status
);
6037 /* End of installation */
6038 if (hClassKey
!= INVALID_HANDLE_VALUE
)
6039 RegCloseKey(hClassKey
);
6040 if (hKey
!= INVALID_HANDLE_VALUE
)
6043 RpcStringFreeW(&lpGuidString
);
6044 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
6045 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6047 TRACE("Returning %d\n", ret
);