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
96 COINSTALLER_PROC Function
;
97 BOOL DoPostProcessing
;
101 struct DeviceInterface
/* Element of DeviceInfoElement.InterfaceListHead */
103 LIST_ENTRY ListEntry
;
105 struct DeviceInfoElement
* DeviceInfo
;
106 GUID InterfaceClassGuid
;
109 /* SPINT_ACTIVE : the interface is active/enabled
110 * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
111 * SPINT_REMOVED: the interface is removed
115 WCHAR SymbolicLink
[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
118 struct DriverInfoElement
/* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
120 LIST_ENTRY ListEntry
;
123 SP_DRVINFO_DATA_V2_W Info
;
129 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
131 LIST_ENTRY ListEntry
;
133 /* Information about devnode:
135 * "Root\*PNP0501" for example.
136 * It doesn't contain the unique ID for the device
137 * (points into the Data field at the end of the structure)
138 * WARNING: no NULL char exist between DeviceName and UniqueId
141 * "5&1be2108e&0" or "0000"
142 * If DICD_GENERATE_ID is specified in creation flags,
143 * this unique ID is autogenerated using 4 digits, base 10
144 * (points into the Data field at the end of the structure)
145 * - DeviceDescription
146 * String which identifies the device. Can be NULL. If not NULL,
147 * points into the Data field at the end of the structure
149 * Identifies the class of this device. FIXME: can it be GUID_NULL?
151 * Is a combination of:
153 * the unique ID needs to be generated
154 * - DICD_INHERIT_CLASSDRVS
155 * inherit driver of the device info set (== same pointer)
157 * Used when doing device-specific actions. Can be NULL
161 PCWSTR DeviceDescription
;
166 /* Flags is a combination of:
168 * Set when the device driver list is created
169 * FlagsEx is a combination of:
174 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
175 /* If the driver is not searched/detected, this list is empty */
176 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
177 /* Points into DriverListHead list. The pointer is NULL if no driver is
178 * currently chosen. */
179 struct DriverInfoElement
*SelectedDriver
;
181 /* List of interfaces implemented by this device */
182 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
187 struct DeviceInfoSet
/* HDEVINFO */
189 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
190 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
191 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
192 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
194 /* Flags is a combination of:
196 * Set when the class driver list is created
197 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
198 * Forces SetupDiBuildDriverInfoList to build a class drivers list
199 * FlagsEx is a combination of:
204 /* If the driver is not searched/detected, this list is empty */
205 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
206 /* Points into DriverListHead list. The pointer is NULL if no driver is
207 * currently chosen. */
208 struct DriverInfoElement
*SelectedDriver
;
210 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
213 /***********************************************************************
214 * SetupDiBuildClassInfoList (SETUPAPI.@)
216 BOOL WINAPI
SetupDiBuildClassInfoList(
218 LPGUID ClassGuidList
,
219 DWORD ClassGuidListSize
,
223 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
224 ClassGuidListSize
, RequiredSize
,
228 /***********************************************************************
229 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
231 BOOL WINAPI
SetupDiBuildClassInfoListExA(
233 LPGUID ClassGuidList
,
234 DWORD ClassGuidListSize
,
239 LPWSTR MachineNameW
= NULL
;
246 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
247 if (MachineNameW
== NULL
) return FALSE
;
250 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
251 ClassGuidListSize
, RequiredSize
,
252 MachineNameW
, Reserved
);
255 MyFree(MachineNameW
);
260 /***********************************************************************
261 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
263 BOOL WINAPI
SetupDiBuildClassInfoListExW(
265 LPGUID ClassGuidList
,
266 DWORD ClassGuidListSize
,
271 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
277 DWORD dwGuidListIndex
= 0;
281 if (RequiredSize
!= NULL
)
284 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
289 if (hClassesKey
== INVALID_HANDLE_VALUE
)
294 for (dwIndex
= 0; ; dwIndex
++)
296 dwLength
= MAX_GUID_STRING_LEN
+ 1;
297 lError
= RegEnumKeyExW(hClassesKey
,
305 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
306 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
308 TRACE("Key name: %p\n", szKeyName
);
310 if (RegOpenKeyExW(hClassesKey
,
316 RegCloseKey(hClassesKey
);
320 if (!RegQueryValueExW(hClassKey
,
327 TRACE("'NoUseClass' value found!\n");
328 RegCloseKey(hClassKey
);
332 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
333 (!RegQueryValueExW(hClassKey
,
340 TRACE("'NoInstallClass' value found!\n");
341 RegCloseKey(hClassKey
);
345 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
346 (!RegQueryValueExW(hClassKey
,
353 TRACE("'NoDisplayClass' value found!\n");
354 RegCloseKey(hClassKey
);
358 RegCloseKey(hClassKey
);
360 TRACE("Guid: %p\n", szKeyName
);
361 if (dwGuidListIndex
< ClassGuidListSize
)
363 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
367 TRACE("Guid: %p\n", &szKeyName
[1]);
369 UuidFromStringW(&szKeyName
[1],
370 &ClassGuidList
[dwGuidListIndex
]);
376 if (lError
!= ERROR_SUCCESS
)
380 RegCloseKey(hClassesKey
);
382 if (RequiredSize
!= NULL
)
383 *RequiredSize
= dwGuidListIndex
;
385 if (ClassGuidListSize
< dwGuidListIndex
)
387 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
394 /***********************************************************************
395 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
397 BOOL WINAPI
SetupDiClassGuidsFromNameA(
399 LPGUID ClassGuidList
,
400 DWORD ClassGuidListSize
,
403 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
404 ClassGuidListSize
, RequiredSize
,
408 /***********************************************************************
409 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
411 BOOL WINAPI
SetupDiClassGuidsFromNameW(
413 LPGUID ClassGuidList
,
414 DWORD ClassGuidListSize
,
417 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
418 ClassGuidListSize
, RequiredSize
,
422 /***********************************************************************
423 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
425 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
427 LPGUID ClassGuidList
,
428 DWORD ClassGuidListSize
,
433 LPWSTR ClassNameW
= NULL
;
434 LPWSTR MachineNameW
= NULL
;
439 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
440 if (ClassNameW
== NULL
)
445 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
446 if (MachineNameW
== NULL
)
453 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
454 ClassGuidListSize
, RequiredSize
,
455 MachineNameW
, Reserved
);
458 MyFree(MachineNameW
);
465 /***********************************************************************
466 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
468 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
470 LPGUID ClassGuidList
,
471 DWORD ClassGuidListSize
,
476 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
477 WCHAR szClassName
[256];
483 DWORD dwGuidListIndex
= 0;
485 if (RequiredSize
!= NULL
)
488 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
489 KEY_ENUMERATE_SUB_KEYS
,
493 if (hClassesKey
== INVALID_HANDLE_VALUE
)
498 for (dwIndex
= 0; ; dwIndex
++)
500 dwLength
= MAX_GUID_STRING_LEN
+ 1;
501 lError
= RegEnumKeyExW(hClassesKey
,
509 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
510 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
512 TRACE("Key name: %p\n", szKeyName
);
514 if (RegOpenKeyExW(hClassesKey
,
520 RegCloseKey(hClassesKey
);
524 dwLength
= 256 * sizeof(WCHAR
);
525 if (!RegQueryValueExW(hClassKey
,
532 TRACE("Class name: %p\n", szClassName
);
534 if (strcmpiW(szClassName
, ClassName
) == 0)
536 TRACE("Found matching class name\n");
538 TRACE("Guid: %p\n", szKeyName
);
539 if (dwGuidListIndex
< ClassGuidListSize
)
541 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
545 TRACE("Guid: %p\n", &szKeyName
[1]);
547 UuidFromStringW(&szKeyName
[1],
548 &ClassGuidList
[dwGuidListIndex
]);
555 RegCloseKey(hClassKey
);
558 if (lError
!= ERROR_SUCCESS
)
562 RegCloseKey(hClassesKey
);
564 if (RequiredSize
!= NULL
)
565 *RequiredSize
= dwGuidListIndex
;
567 if (ClassGuidListSize
< dwGuidListIndex
)
569 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
576 /***********************************************************************
577 * SetupDiClassNameFromGuidA (SETUPAPI.@)
579 BOOL WINAPI
SetupDiClassNameFromGuidA(
580 const GUID
* ClassGuid
,
585 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
586 ClassNameSize
, RequiredSize
,
590 /***********************************************************************
591 * SetupDiClassNameFromGuidW (SETUPAPI.@)
593 BOOL WINAPI
SetupDiClassNameFromGuidW(
594 const GUID
* ClassGuid
,
599 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
600 ClassNameSize
, RequiredSize
,
604 /***********************************************************************
605 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
607 BOOL WINAPI
SetupDiClassNameFromGuidExA(
608 const GUID
* ClassGuid
,
615 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
616 LPWSTR MachineNameW
= NULL
;
620 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
621 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
622 NULL
, MachineNameW
, Reserved
);
625 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
626 ClassNameSize
, NULL
, NULL
);
628 if (!ClassNameSize
&& RequiredSize
)
631 MyFree(MachineNameW
);
635 /***********************************************************************
636 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
638 BOOL WINAPI
SetupDiClassNameFromGuidExW(
639 const GUID
* ClassGuid
,
650 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
655 if (hKey
== INVALID_HANDLE_VALUE
)
660 if (RequiredSize
!= NULL
)
663 rc
= RegQueryValueExW(hKey
,
669 if (rc
!= ERROR_SUCCESS
)
676 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
679 dwLength
= ClassNameSize
* sizeof(WCHAR
);
680 rc
= RegQueryValueExW(hKey
,
686 if (rc
!= ERROR_SUCCESS
)
698 /***********************************************************************
699 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
702 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
705 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
708 /***********************************************************************
709 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
712 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
717 LPWSTR MachineNameW
= NULL
;
720 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
724 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
725 if (MachineNameW
== NULL
)
726 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
729 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
730 MachineNameW
, Reserved
);
733 MyFree(MachineNameW
);
738 /***********************************************************************
739 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
742 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
747 struct DeviceInfoSet
*list
;
750 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
752 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
755 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
756 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
759 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
762 ClassGuid
? ClassGuid
: &GUID_NULL
,
763 sizeof(list
->ClassGuid
));
764 list
->hwndParent
= hwndParent
;
767 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
768 if (rc
!= ERROR_SUCCESS
)
771 HeapFree(GetProcessHeap(), 0, list
);
772 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
777 list
->HKLM
= HKEY_LOCAL_MACHINE
;
779 list
->Flags
= 0; /* FIXME */
780 list
->FlagsEx
= 0; /* FIXME */
781 InitializeListHead(&list
->DriverListHead
);
782 InitializeListHead(&list
->ListHead
);
783 return (HDEVINFO
)list
;
786 /***********************************************************************
787 * SetupDiEnumDeviceInfo (SETUPAPI.@)
789 BOOL WINAPI
SetupDiEnumDeviceInfo(
790 HDEVINFO DeviceInfoSet
,
792 PSP_DEVINFO_DATA DeviceInfoData
)
796 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
798 SetLastError(ERROR_INVALID_PARAMETER
);
799 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
801 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
803 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
804 SetLastError(ERROR_INVALID_HANDLE
);
805 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
806 SetLastError(ERROR_INVALID_USER_BUFFER
);
809 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
810 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
811 ItemList
= ItemList
->Flink
;
812 if (ItemList
== &list
->ListHead
)
813 SetLastError(ERROR_NO_MORE_ITEMS
);
816 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
817 memcpy(&DeviceInfoData
->ClassGuid
,
820 DeviceInfoData
->DevInst
= 0; /* FIXME */
821 /* Note: this appears to be dangerous, passing a private
822 * pointer a heap-allocated datum to the caller. However, the
823 * expected lifetime of the device data is the same as the
824 * HDEVINFO; once that is closed, the data are no longer valid.
826 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
832 SetLastError(ERROR_INVALID_HANDLE
);
836 /***********************************************************************
837 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
839 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
841 PCSTR InfSectionName
,
842 PSTR InfSectionWithExt
,
843 DWORD InfSectionWithExtSize
,
847 LPWSTR InfSectionNameW
= NULL
;
848 PWSTR InfSectionWithExtW
= NULL
;
850 BOOL bResult
= FALSE
;
856 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
857 if (InfSectionNameW
== NULL
) goto end
;
859 if (InfSectionWithExt
)
861 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
862 if (InfSectionWithExtW
== NULL
) goto end
;
865 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
866 InfSectionWithExt
? InfSectionNameW
: NULL
,
867 InfSectionWithExtSize
, RequiredSize
,
868 Extension
? &ExtensionW
: NULL
);
870 if (bResult
&& InfSectionWithExt
)
872 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
873 InfSectionWithExtSize
, NULL
, NULL
) != 0;
875 if (bResult
&& Extension
)
877 if (ExtensionW
== NULL
)
880 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
884 if (InfSectionNameW
) MyFree(InfSectionNameW
);
885 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
890 /***********************************************************************
891 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
893 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
895 PCWSTR InfSectionName
,
896 PWSTR InfSectionWithExt
,
897 DWORD InfSectionWithExtSize
,
901 WCHAR szBuffer
[MAX_PATH
];
904 LONG lLineCount
= -1;
906 lstrcpyW(szBuffer
, InfSectionName
);
907 dwLength
= lstrlenW(szBuffer
);
909 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
911 /* Test section name with '.NTx86' extension */
912 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
913 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
915 if (lLineCount
== -1)
917 /* Test section name with '.NT' extension */
918 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
919 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
924 /* Test section name with '.Win' extension */
925 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
926 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
929 if (lLineCount
== -1)
931 /* Test section name without extension */
932 szBuffer
[dwLength
] = 0;
933 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
936 if (lLineCount
== -1)
938 SetLastError(ERROR_INVALID_PARAMETER
);
942 dwFullLength
= lstrlenW(szBuffer
);
944 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
946 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
948 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
952 lstrcpyW(InfSectionWithExt
, szBuffer
);
953 if (Extension
!= NULL
)
955 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
959 if (RequiredSize
!= NULL
)
961 *RequiredSize
= dwFullLength
+ 1;
967 /***********************************************************************
968 * SetupDiGetClassDescriptionA (SETUPAPI.@)
970 BOOL WINAPI
SetupDiGetClassDescriptionA(
971 const GUID
* ClassGuid
,
972 PSTR ClassDescription
,
973 DWORD ClassDescriptionSize
,
976 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
977 ClassDescriptionSize
,
978 RequiredSize
, NULL
, NULL
);
981 /***********************************************************************
982 * SetupDiGetClassDescriptionW (SETUPAPI.@)
984 BOOL WINAPI
SetupDiGetClassDescriptionW(
985 const GUID
* ClassGuid
,
986 PWSTR ClassDescription
,
987 DWORD ClassDescriptionSize
,
990 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
991 ClassDescriptionSize
,
992 RequiredSize
, NULL
, NULL
);
995 /***********************************************************************
996 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
998 BOOL WINAPI
SetupDiGetClassDescriptionExA(
999 const GUID
* ClassGuid
,
1000 PSTR ClassDescription
,
1001 DWORD ClassDescriptionSize
,
1002 PDWORD RequiredSize
,
1006 PWCHAR ClassDescriptionW
;
1007 LPWSTR MachineNameW
= NULL
;
1011 if (ClassDescriptionSize
> 0)
1013 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1014 if (!ClassDescriptionW
)
1016 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1022 ClassDescriptionW
= NULL
;
1026 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1029 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1035 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1036 NULL
, MachineNameW
, Reserved
);
1039 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1040 ClassDescriptionSize
, NULL
, NULL
);
1042 if (!ClassDescriptionSize
&& RequiredSize
)
1043 *RequiredSize
= len
;
1047 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1048 MyFree(MachineNameW
);
1052 /***********************************************************************
1053 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1055 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1056 const GUID
* ClassGuid
,
1057 PWSTR ClassDescription
,
1058 DWORD ClassDescriptionSize
,
1059 PDWORD RequiredSize
,
1066 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1071 if (hKey
== INVALID_HANDLE_VALUE
)
1073 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1077 if (RequiredSize
!= NULL
)
1080 if (RegQueryValueExW(hKey
,
1091 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1094 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1095 if (RegQueryValueExW(hKey
,
1099 (LPBYTE
)ClassDescription
,
1111 /***********************************************************************
1112 * SetupDiGetClassDevsA (SETUPAPI.@)
1114 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1120 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1121 flags
, NULL
, NULL
, NULL
);
1124 /***********************************************************************
1125 * SetupDiGetClassDevsW (SETUPAPI.@)
1127 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1133 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1134 flags
, NULL
, NULL
, NULL
);
1137 /***********************************************************************
1138 * SetupDiGetClassDevsExA (SETUPAPI.@)
1140 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1150 LPWSTR enumstrW
= NULL
;
1151 LPWSTR machineW
= NULL
;
1155 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1156 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1159 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1162 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1166 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1167 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1170 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1173 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1175 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1178 HeapFree(GetProcessHeap(), 0, enumstrW
);
1179 HeapFree(GetProcessHeap(), 0, machineW
);
1184 CreateDeviceInfoElement(
1185 IN LPCWSTR InstancePath
,
1187 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1189 struct DeviceInfoElement
*deviceInfo
;
1191 *pDeviceInfo
= NULL
;
1192 if (IsEqualIID(&pClassGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1194 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1197 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1200 wcscpy(deviceInfo
->Data
, InstancePath
);
1201 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1202 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1203 deviceInfo
->DeviceDescription
= NULL
;
1204 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1205 deviceInfo
->CreationFlags
= 0;
1206 deviceInfo
->hwndParent
= NULL
;
1207 deviceInfo
->Flags
= 0; /* FIXME */
1208 deviceInfo
->FlagsEx
= 0; /* FIXME */
1209 deviceInfo
->SelectedDriver
= NULL
;
1210 InitializeListHead(&deviceInfo
->DriverListHead
);
1211 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1213 *pDeviceInfo
= deviceInfo
;
1218 CreateDeviceInterface(
1219 IN
struct DeviceInfoElement
* deviceInfo
,
1220 IN LPCWSTR SymbolicLink
,
1221 IN LPCGUID pInterfaceGuid
,
1222 OUT
struct DeviceInterface
**pDeviceInterface
)
1224 struct DeviceInterface
*deviceInterface
;
1226 *pDeviceInterface
= NULL
;
1228 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1229 if (!deviceInterface
)
1231 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1234 deviceInterface
->DeviceInfo
= deviceInfo
;
1235 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1236 deviceInterface
->Flags
= 0; /* FIXME */
1237 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1239 *pDeviceInterface
= deviceInterface
;
1243 static LONG
SETUP_CreateDevListFromEnumerator(
1244 struct DeviceInfoSet
*list
,
1245 LPCGUID pClassGuid OPTIONAL
,
1247 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1249 HKEY hDeviceIdKey
, hInstanceIdKey
;
1250 WCHAR KeyBuffer
[MAX_PATH
];
1251 WCHAR InstancePath
[MAX_PATH
];
1252 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1253 struct DeviceInfoElement
*deviceInfo
;
1255 DWORD dwLength
, dwRegType
;
1258 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1261 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1262 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1263 if (rc
== ERROR_NO_MORE_ITEMS
)
1265 if (rc
!= ERROR_SUCCESS
)
1269 /* Open device id sub key */
1270 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1271 if (rc
!= ERROR_SUCCESS
)
1273 wcscpy(InstancePath
, Enumerator
);
1274 wcscat(InstancePath
, L
"\\");
1275 wcscat(InstancePath
, KeyBuffer
);
1276 wcscat(InstancePath
, L
"\\");
1277 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1279 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1285 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1286 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1287 if (rc
== ERROR_NO_MORE_ITEMS
)
1289 if (rc
!= ERROR_SUCCESS
)
1291 RegCloseKey(hDeviceIdKey
);
1296 /* Open instance id sub key */
1297 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1298 if (rc
!= ERROR_SUCCESS
)
1300 RegCloseKey(hDeviceIdKey
);
1303 *pEndOfInstancePath
= '\0';
1304 wcscat(InstancePath
, KeyBuffer
);
1306 /* Read ClassGUID value */
1307 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1308 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1309 RegCloseKey(hInstanceIdKey
);
1310 if (rc
== ERROR_FILE_NOT_FOUND
)
1313 /* Skip this bad entry as we can't verify it */
1316 else if (rc
!= ERROR_SUCCESS
)
1318 RegCloseKey(hDeviceIdKey
);
1321 else if (dwRegType
!= REG_SZ
)
1323 RegCloseKey(hDeviceIdKey
);
1324 return ERROR_GEN_FAILURE
;
1327 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1328 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1330 RegCloseKey(hDeviceIdKey
);
1331 return GetLastError();
1333 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1335 /* Skip this entry as it is not the right device class */
1339 /* Add the entry to the list */
1340 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1342 RegCloseKey(hDeviceIdKey
);
1343 return GetLastError();
1345 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1346 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1348 RegCloseKey(hDeviceIdKey
);
1351 return ERROR_SUCCESS
;
1354 static LONG
SETUP_CreateDevList(
1355 struct DeviceInfoSet
*list
,
1356 PCWSTR MachineName OPTIONAL
,
1357 LPGUID
class OPTIONAL
,
1358 PCWSTR Enumerator OPTIONAL
)
1360 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1361 WCHAR KeyBuffer
[MAX_PATH
];
1366 if (IsEqualIID(class, &GUID_NULL
))
1370 if (MachineName
!= NULL
)
1372 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1373 if (rc
!= ERROR_SUCCESS
)
1377 HKLM
= HKEY_LOCAL_MACHINE
;
1379 rc
= RegOpenKeyExW(HKLM
,
1382 KEY_ENUMERATE_SUB_KEYS
,
1384 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1385 if (rc
!= ERROR_SUCCESS
)
1388 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1389 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1398 KEY_ENUMERATE_SUB_KEYS
,
1400 RegCloseKey(hEnumKey
);
1401 if (rc
!= ERROR_SUCCESS
)
1403 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1404 RegCloseKey(hEnumeratorKey
);
1409 /* Enumerate enumerators */
1413 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1414 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1415 if (rc
== ERROR_NO_MORE_ITEMS
)
1417 if (rc
!= ERROR_SUCCESS
)
1419 RegCloseKey(hEnumKey
);
1425 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1426 if (rc
!= ERROR_SUCCESS
)
1428 RegCloseKey(hEnumKey
);
1432 /* Call SETUP_CreateDevListFromEnumerator */
1433 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1434 RegCloseKey(hEnumeratorKey
);
1435 if (rc
!= ERROR_SUCCESS
)
1437 RegCloseKey(hEnumKey
);
1441 RegCloseKey(hEnumKey
);
1442 return ERROR_SUCCESS
;
1447 static LONG
SETUP_CreateSerialDeviceList(
1448 struct DeviceInfoSet
*list
,
1450 LPGUID InterfaceGuid
,
1451 PCWSTR DeviceInstanceW
)
1453 static const size_t initialSize
= 100;
1455 WCHAR buf
[initialSize
];
1457 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1459 struct DeviceInfoElement
*deviceInfo
;
1462 WARN("'MachineName' is ignored on Wine!\n");
1463 if (DeviceInstanceW
)
1464 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1470 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1472 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1476 HeapFree(GetProcessHeap(), 0, devices
);
1477 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1479 return ERROR_NOT_ENOUGH_MEMORY
;
1485 HeapFree(GetProcessHeap(), 0, devices
);
1486 return GetLastError();
1490 /* 'devices' is a MULTI_SZ string */
1491 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1493 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1495 /* We have found a device */
1496 struct DeviceInterface
*interfaceInfo
;
1497 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1498 /* Step 1. Create a device info element */
1499 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1502 HeapFree(GetProcessHeap(), 0, devices
);
1503 return GetLastError();
1505 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1507 /* Step 2. Create an interface list for this element */
1508 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1511 HeapFree(GetProcessHeap(), 0, devices
);
1512 return GetLastError();
1514 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1518 HeapFree(GetProcessHeap(), 0, devices
);
1519 return ERROR_SUCCESS
;
1522 #else /* __REACTOS__ */
1524 static LONG
SETUP_CreateInterfaceList(
1525 struct DeviceInfoSet
*list
,
1527 LPGUID InterfaceGuid
,
1528 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1530 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1531 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1532 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1533 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1534 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1536 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1539 DWORD dwLength
, dwInstancePathLength
;
1542 struct DeviceInfoElement
*deviceInfo
;
1544 /* Open registry key related to this interface */
1545 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1546 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1547 return GetLastError();
1549 /* Enumerate sub keys of hInterfaceKey */
1553 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1554 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1555 if (rc
== ERROR_NO_MORE_ITEMS
)
1557 if (rc
!= ERROR_SUCCESS
)
1559 RegCloseKey(hInterfaceKey
);
1565 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1566 if (rc
!= ERROR_SUCCESS
)
1568 RegCloseKey(hInterfaceKey
);
1572 /* Read DeviceInstance */
1573 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1574 if (rc
!= ERROR_SUCCESS
)
1576 RegCloseKey(hDeviceInstanceKey
);
1577 RegCloseKey(hInterfaceKey
);
1580 if (dwRegType
!= REG_SZ
)
1582 RegCloseKey(hDeviceInstanceKey
);
1583 RegCloseKey(hInterfaceKey
);
1584 return ERROR_GEN_FAILURE
;
1586 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1589 RegCloseKey(hDeviceInstanceKey
);
1590 RegCloseKey(hInterfaceKey
);
1591 return ERROR_NOT_ENOUGH_MEMORY
;
1593 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1594 if (rc
!= ERROR_SUCCESS
)
1596 HeapFree(GetProcessHeap(), 0, InstancePath
);
1597 RegCloseKey(hDeviceInstanceKey
);
1598 RegCloseKey(hInterfaceKey
);
1601 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1602 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1604 if (DeviceInstanceW
)
1606 /* Check if device enumerator is not the right one */
1607 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1609 HeapFree(GetProcessHeap(), 0, InstancePath
);
1610 RegCloseKey(hDeviceInstanceKey
);
1615 /* Find class GUID associated to the device instance */
1620 KEY_ENUMERATE_SUB_KEYS
,
1622 if (rc
!= ERROR_SUCCESS
)
1624 HeapFree(GetProcessHeap(), 0, InstancePath
);
1625 RegCloseKey(hDeviceInstanceKey
);
1626 RegCloseKey(hInterfaceKey
);
1635 RegCloseKey(hEnumKey
);
1636 if (rc
!= ERROR_SUCCESS
)
1638 HeapFree(GetProcessHeap(), 0, InstancePath
);
1639 RegCloseKey(hDeviceInstanceKey
);
1640 RegCloseKey(hInterfaceKey
);
1643 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1644 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1646 if (rc
!= ERROR_SUCCESS
)
1648 HeapFree(GetProcessHeap(), 0, InstancePath
);
1649 RegCloseKey(hDeviceInstanceKey
);
1650 RegCloseKey(hInterfaceKey
);
1653 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1654 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1655 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1657 HeapFree(GetProcessHeap(), 0, InstancePath
);
1658 RegCloseKey(hDeviceInstanceKey
);
1659 RegCloseKey(hInterfaceKey
);
1660 return ERROR_GEN_FAILURE
;
1662 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1664 /* If current device doesn't match the list GUID (if any), skip this entry */
1665 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1667 HeapFree(GetProcessHeap(), 0, InstancePath
);
1668 RegCloseKey(hDeviceInstanceKey
);
1672 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1676 LPWSTR pSymbolicLink
;
1677 struct DeviceInterface
*interfaceInfo
;
1679 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1680 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1681 if (rc
== ERROR_NO_MORE_ITEMS
)
1683 if (rc
!= ERROR_SUCCESS
)
1685 HeapFree(GetProcessHeap(), 0, InstancePath
);
1686 RegCloseKey(hDeviceInstanceKey
);
1687 RegCloseKey(hInterfaceKey
);
1691 if (KeyBuffer
[0] != '#')
1692 /* This entry doesn't represent an interesting entry */
1696 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1697 if (rc
!= ERROR_SUCCESS
)
1699 RegCloseKey(hDeviceInstanceKey
);
1700 RegCloseKey(hInterfaceKey
);
1704 /* Read SymbolicLink value */
1705 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1706 if (rc
!= ERROR_SUCCESS
)
1708 RegCloseKey(hReferenceKey
);
1709 RegCloseKey(hDeviceInstanceKey
);
1710 RegCloseKey(hInterfaceKey
);
1713 if (dwRegType
!= REG_SZ
)
1715 RegCloseKey(hReferenceKey
);
1716 RegCloseKey(hDeviceInstanceKey
);
1717 RegCloseKey(hInterfaceKey
);
1718 return ERROR_GEN_FAILURE
;
1721 /* We have found a device */
1722 /* Step 1. Create a device info element */
1723 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1725 RegCloseKey(hReferenceKey
);
1726 RegCloseKey(hDeviceInstanceKey
);
1727 RegCloseKey(hInterfaceKey
);
1728 return GetLastError();
1730 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1731 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1733 /* Step 2. Create an interface list for this element */
1734 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1737 RegCloseKey(hReferenceKey
);
1738 RegCloseKey(hDeviceInstanceKey
);
1739 RegCloseKey(hInterfaceKey
);
1740 return ERROR_NOT_ENOUGH_MEMORY
;
1742 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1743 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1744 RegCloseKey(hReferenceKey
);
1745 if (rc
!= ERROR_SUCCESS
)
1747 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1748 RegCloseKey(hDeviceInstanceKey
);
1749 RegCloseKey(hInterfaceKey
);
1752 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1754 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1755 RegCloseKey(hDeviceInstanceKey
);
1756 RegCloseKey(hInterfaceKey
);
1757 return GetLastError();
1759 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1760 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1761 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1763 RegCloseKey(hDeviceInstanceKey
);
1765 RegCloseKey(hInterfaceKey
);
1766 return ERROR_SUCCESS
;
1768 #endif /* __REACTOS__ */
1770 /***********************************************************************
1771 * SetupDiGetClassDevsExW (SETUPAPI.@)
1773 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1782 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1783 struct DeviceInfoSet
*list
;
1787 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1788 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1790 /* Create the deviceset if not set */
1793 list
= (struct DeviceInfoSet
*)deviceset
;
1794 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1796 SetLastError(ERROR_INVALID_HANDLE
);
1797 return INVALID_HANDLE_VALUE
;
1799 hDeviceInfo
= deviceset
;
1803 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1804 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1805 NULL
, machine
, NULL
);
1806 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1807 return INVALID_HANDLE_VALUE
;
1808 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1811 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1814 pClassGuid
= &list
->ClassGuid
;
1816 if (flags
& DIGCF_PRESENT
)
1817 FIXME(": flag DIGCF_PRESENT ignored\n");
1818 if (flags
& DIGCF_PROFILE
)
1819 FIXME(": flag DIGCF_PROFILE ignored\n");
1821 if (flags
& DIGCF_ALLCLASSES
)
1823 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1824 if (rc
!= ERROR_SUCCESS
)
1828 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1829 return INVALID_HANDLE_VALUE
;
1833 else if (flags
& DIGCF_DEVICEINTERFACE
)
1837 SetLastError(ERROR_INVALID_PARAMETER
);
1839 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1840 return INVALID_HANDLE_VALUE
;
1844 /* Special case: find serial ports by calling QueryDosDevice */
1845 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1846 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1847 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1848 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1851 ERR("Wine can only enumerate serial devices at the moment!\n");
1852 rc
= ERROR_INVALID_PARAMETER
;
1854 #else /* __REACTOS__ */
1855 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1856 #endif /* __REACTOS__ */
1857 if (rc
!= ERROR_SUCCESS
)
1861 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1862 return INVALID_HANDLE_VALUE
;
1868 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1869 if (rc
!= ERROR_SUCCESS
)
1873 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1874 return INVALID_HANDLE_VALUE
;
1880 /***********************************************************************
1881 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1883 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1884 HDEVINFO DeviceInfoSet
,
1885 PSP_DEVINFO_DATA DeviceInfoData
,
1886 CONST GUID
* InterfaceClassGuid
,
1888 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1892 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1893 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1895 if (!DeviceInterfaceData
)
1896 SetLastError(ERROR_INVALID_PARAMETER
);
1897 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1898 SetLastError(ERROR_INVALID_USER_BUFFER
);
1899 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1901 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1903 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1905 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1907 while (ItemList
!= &list
->ListHead
&& !Found
)
1909 PLIST_ENTRY InterfaceListEntry
;
1910 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1911 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1913 /* We are not searching for this element */
1914 ItemList
= ItemList
->Flink
;
1917 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1918 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1920 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1921 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1923 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1926 if (MemberIndex
-- == 0)
1928 /* return this item */
1929 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1930 &DevItf
->InterfaceClassGuid
,
1932 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1933 /* Note: this appears to be dangerous, passing a private
1934 * pointer a heap-allocated datum to the caller. However, the
1935 * expected lifetime of the device data is the same as the
1936 * HDEVINFO; once that is closed, the data are no longer valid.
1938 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1941 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1943 ItemList
= ItemList
->Flink
;
1946 SetLastError(ERROR_NO_MORE_ITEMS
);
1951 SetLastError(ERROR_INVALID_HANDLE
);
1954 SetLastError(ERROR_INVALID_HANDLE
);
1958 /***********************************************************************
1959 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1961 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1965 TRACE("%p\n", devinfo
);
1966 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1968 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1970 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1972 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1973 struct DeviceInfoElement
*deviceInfo
;
1974 while (!IsListEmpty(&list
->ListHead
))
1976 ListEntry
= RemoveHeadList(&list
->ListHead
);
1977 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1978 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1980 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1981 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1983 HeapFree(GetProcessHeap(), 0, ListEntry
);
1985 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1986 RegCloseKey(list
->HKLM
);
1987 HeapFree(GetProcessHeap(), 0, list
);
1991 SetLastError(ERROR_INVALID_HANDLE
);
1994 SetLastError(ERROR_INVALID_HANDLE
);
1996 TRACE("Returning %d\n", ret
);
2000 /***********************************************************************
2001 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2003 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2004 HDEVINFO DeviceInfoSet
,
2005 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2006 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2007 DWORD DeviceInterfaceDetailDataSize
,
2008 PDWORD RequiredSize
,
2009 PSP_DEVINFO_DATA DeviceInfoData
)
2011 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2012 DWORD sizeW
= 0, sizeA
;
2015 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2016 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2017 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2019 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2020 SetLastError(ERROR_INVALID_USER_BUFFER
);
2021 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2022 SetLastError(ERROR_INVALID_PARAMETER
);
2023 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2024 SetLastError(ERROR_INVALID_PARAMETER
);
2027 if (DeviceInterfaceDetailData
!= NULL
)
2029 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2030 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2031 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2032 if (!DeviceInterfaceDetailDataW
)
2034 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2037 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2039 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2040 ret
= SetupDiGetDeviceInterfaceDetailW(
2042 DeviceInterfaceData
,
2043 DeviceInterfaceDetailDataW
,
2047 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2048 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2050 *RequiredSize
= sizeA
;
2051 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2053 if (!WideCharToMultiByte(
2055 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2056 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2063 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2066 TRACE("Returning %d\n", ret
);
2070 /***********************************************************************
2071 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2073 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2074 HDEVINFO DeviceInfoSet
,
2075 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2076 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2077 DWORD DeviceInterfaceDetailDataSize
,
2078 PDWORD RequiredSize
,
2079 PSP_DEVINFO_DATA DeviceInfoData
)
2083 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2084 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2085 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2087 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2088 SetLastError(ERROR_INVALID_PARAMETER
);
2089 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2090 SetLastError(ERROR_INVALID_HANDLE
);
2091 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2092 SetLastError(ERROR_INVALID_HANDLE
);
2093 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2094 SetLastError(ERROR_INVALID_USER_BUFFER
);
2095 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2096 SetLastError(ERROR_INVALID_USER_BUFFER
);
2097 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2098 SetLastError(ERROR_INVALID_USER_BUFFER
);
2099 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2100 SetLastError(ERROR_INVALID_PARAMETER
);
2101 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2102 SetLastError(ERROR_INVALID_PARAMETER
);
2105 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2106 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2107 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2108 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2110 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2112 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2114 *RequiredSize
= sizeRequired
;
2118 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2119 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2122 memcpy(&DeviceInfoData
->ClassGuid
,
2123 &deviceInterface
->DeviceInfo
->ClassGuid
,
2125 DeviceInfoData
->DevInst
= 0; /* FIXME */
2126 /* Note: this appears to be dangerous, passing a private
2127 * pointer a heap-allocated datum to the caller. However, the
2128 * expected lifetime of the device data is the same as the
2129 * HDEVINFO; once that is closed, the data are no longer valid.
2131 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2137 TRACE("Returning %d\n", ret
);
2141 /***********************************************************************
2142 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2144 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2146 PSP_DEVINFO_DATA DeviceInfoData
,
2148 PDWORD PropertyRegDataType
,
2149 PBYTE PropertyBuffer
,
2150 DWORD PropertyBufferSize
,
2151 PDWORD RequiredSize
)
2154 BOOL bIsStringProperty
;
2156 DWORD RequiredSizeA
, RequiredSizeW
;
2157 DWORD PropertyBufferSizeW
;
2158 PBYTE PropertyBufferW
;
2160 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2161 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2164 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2165 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2167 bResult
= SetupDiGetDeviceRegistryPropertyW(
2173 PropertyBufferSizeW
,
2176 if (bResult
|| GetLastError() == ERROR_MORE_DATA
)
2178 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2180 if (bIsStringProperty
)
2181 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2183 RequiredSizeA
= RequiredSizeW
;
2185 *RequiredSize
= RequiredSizeA
;
2186 if (PropertyRegDataType
)
2187 *PropertyRegDataType
= RegType
;
2192 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2196 if (RequiredSizeA
<= PropertyBufferSize
)
2198 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2200 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2202 /* Last error is already set by WideCharToMultiByte */
2207 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2211 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2215 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2219 /***********************************************************************
2220 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2222 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2223 HDEVINFO DeviceInfoSet
,
2224 PSP_DEVINFO_DATA DeviceInfoData
,
2226 PDWORD PropertyRegDataType
,
2227 PBYTE PropertyBuffer
,
2228 DWORD PropertyBufferSize
,
2229 PDWORD RequiredSize
)
2231 HKEY hEnumKey
, hKey
;
2235 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2236 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2239 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2240 SetLastError(ERROR_INVALID_HANDLE
);
2241 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2242 SetLastError(ERROR_INVALID_HANDLE
);
2243 else if (!DeviceInfoData
)
2244 SetLastError(ERROR_INVALID_PARAMETER
);
2245 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2246 SetLastError(ERROR_INVALID_USER_BUFFER
);
2247 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2248 SetLastError(ERROR_INVALID_PARAMETER
);
2251 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2252 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2256 case SPDRP_CAPABILITIES
:
2258 case SPDRP_CLASSGUID
:
2259 case SPDRP_COMPATIBLEIDS
:
2260 case SPDRP_CONFIGFLAGS
:
2261 case SPDRP_DEVICEDESC
:
2263 case SPDRP_FRIENDLYNAME
:
2264 case SPDRP_HARDWAREID
:
2265 case SPDRP_LOCATION_INFORMATION
:
2266 case SPDRP_LOWERFILTERS
:
2268 case SPDRP_SECURITY
:
2270 case SPDRP_UI_NUMBER
:
2271 case SPDRP_UPPERFILTERS
:
2273 LPCWSTR RegistryPropertyName
;
2278 case SPDRP_CAPABILITIES
:
2279 RegistryPropertyName
= L
"Capabilities"; break;
2281 RegistryPropertyName
= L
"Class"; break;
2282 case SPDRP_CLASSGUID
:
2283 RegistryPropertyName
= L
"ClassGUID"; break;
2284 case SPDRP_COMPATIBLEIDS
:
2285 RegistryPropertyName
= L
"CompatibleIDs"; break;
2286 case SPDRP_CONFIGFLAGS
:
2287 RegistryPropertyName
= L
"ConfigFlags"; break;
2288 case SPDRP_DEVICEDESC
:
2289 RegistryPropertyName
= L
"DeviceDesc"; break;
2291 RegistryPropertyName
= L
"Driver"; break;
2292 case SPDRP_FRIENDLYNAME
:
2293 RegistryPropertyName
= L
"FriendlyName"; break;
2294 case SPDRP_HARDWAREID
:
2295 RegistryPropertyName
= L
"HardwareID"; break;
2296 case SPDRP_LOCATION_INFORMATION
:
2297 RegistryPropertyName
= L
"LocationInformation"; break;
2298 case SPDRP_LOWERFILTERS
:
2299 RegistryPropertyName
= L
"LowerFilters"; break;
2301 RegistryPropertyName
= L
"Mfg"; break;
2302 case SPDRP_SECURITY
:
2303 RegistryPropertyName
= L
"Security"; break;
2305 RegistryPropertyName
= L
"Service"; break;
2306 case SPDRP_UI_NUMBER
:
2307 RegistryPropertyName
= L
"UINumber"; break;
2308 case SPDRP_UPPERFILTERS
:
2309 RegistryPropertyName
= L
"UpperFilters"; break;
2311 /* Should not happen */
2312 RegistryPropertyName
= NULL
; break;
2315 /* Open registry key name */
2320 KEY_ENUMERATE_SUB_KEYS
,
2322 if (rc
!= ERROR_SUCCESS
)
2333 RegCloseKey(hEnumKey
);
2334 if (rc
!= ERROR_SUCCESS
)
2339 /* Read registry entry */
2340 BufferSize
= PropertyBufferSize
;
2341 rc
= RegQueryValueExW(
2343 RegistryPropertyName
,
2344 NULL
, /* Reserved */
2345 PropertyRegDataType
,
2349 *RequiredSize
= BufferSize
;
2350 if (rc
== ERROR_SUCCESS
)
2358 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2360 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2362 if (PropertyRegDataType
)
2363 *PropertyRegDataType
= REG_SZ
;
2365 *RequiredSize
= required
;
2366 if (PropertyBufferSize
>= required
)
2368 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2372 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2376 /*case SPDRP_BUSTYPEGUID:
2377 case SPDRP_LEGACYBUSTYPE:
2378 case SPDRP_BUSNUMBER:
2379 case SPDRP_ENUMERATOR_NAME:
2380 case SPDRP_SECURITY_SDS:
2382 case SPDRP_EXCLUSIVE:
2383 case SPDRP_CHARACTERISTICS:
2385 case SPDRP_UI_NUMBER_DESC_FORMAT:
2386 case SPDRP_DEVICE_POWER_DATA:*/
2387 #if (WINVER >= 0x501)
2388 /*case SPDRP_REMOVAL_POLICY:
2389 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2390 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2391 case SPDRP_INSTALL_STATE:*/
2396 FIXME("Property 0x%lx not implemented\n", Property
);
2397 SetLastError(ERROR_NOT_SUPPORTED
);
2402 TRACE("Returning %d\n", ret
);
2407 /***********************************************************************
2408 * SetupDiInstallClassA (SETUPAPI.@)
2410 BOOL WINAPI
SetupDiInstallClassA(
2416 UNICODE_STRING FileNameW
;
2419 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2421 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2425 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2427 RtlFreeUnicodeString(&FileNameW
);
2432 static HKEY
CreateClassKey(HINF hInf
)
2434 WCHAR FullBuffer
[MAX_PATH
];
2435 WCHAR Buffer
[MAX_PATH
];
2440 if (!SetupGetLineTextW(NULL
,
2448 return INVALID_HANDLE_VALUE
;
2451 lstrcpyW(FullBuffer
, ControlClass
);
2452 lstrcatW(FullBuffer
, Buffer
);
2455 if (!SetupGetLineTextW(NULL
,
2463 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2464 return INVALID_HANDLE_VALUE
;
2467 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2471 REG_OPTION_NON_VOLATILE
,
2477 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2478 return INVALID_HANDLE_VALUE
;
2481 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2486 RequiredSize
* sizeof(WCHAR
)))
2488 RegCloseKey(hClassKey
);
2489 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2490 return INVALID_HANDLE_VALUE
;
2496 /***********************************************************************
2497 * SetupDiInstallClassW (SETUPAPI.@)
2499 BOOL WINAPI
SetupDiInstallClassW(
2505 WCHAR SectionName
[MAX_PATH
];
2506 DWORD SectionNameLength
= 0;
2508 BOOL bFileQueueCreated
= FALSE
;
2511 FIXME("not fully implemented\n");
2513 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2515 SetLastError(ERROR_INVALID_PARAMETER
);
2519 /* Open the .inf file */
2520 hInf
= SetupOpenInfFileW(InfFileName
,
2524 if (hInf
== INVALID_HANDLE_VALUE
)
2530 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2531 hClassKey
= CreateClassKey(hInf
);
2532 if (hClassKey
== INVALID_HANDLE_VALUE
)
2534 SetupCloseInfFile(hInf
);
2540 /* Try to append a layout file */
2542 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2545 /* Retrieve the actual section name */
2546 SetupDiGetActualSectionToInstallW(hInf
,
2554 if (!(Flags
& DI_NOVCP
))
2556 FileQueue
= SetupOpenFileQueue();
2557 if (FileQueue
== INVALID_HANDLE_VALUE
)
2559 SetupCloseInfFile(hInf
);
2560 RegCloseKey(hClassKey
);
2564 bFileQueueCreated
= TRUE
;
2569 SetupInstallFromInfSectionW(NULL
,
2578 INVALID_HANDLE_VALUE
,
2581 /* FIXME: More code! */
2583 if (bFileQueueCreated
)
2584 SetupCloseFileQueue(FileQueue
);
2586 SetupCloseInfFile(hInf
);
2588 RegCloseKey(hClassKey
);
2593 /***********************************************************************
2594 * SetupDiOpenClassRegKey (SETUPAPI.@)
2596 HKEY WINAPI
SetupDiOpenClassRegKey(
2597 const GUID
* ClassGuid
,
2600 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2601 DIOCR_INSTALLER
, NULL
, NULL
);
2605 /***********************************************************************
2606 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2608 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2609 const GUID
* ClassGuid
,
2615 PWSTR MachineNameW
= NULL
;
2622 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2623 if (MachineNameW
== NULL
)
2624 return INVALID_HANDLE_VALUE
;
2627 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2628 Flags
, MachineNameW
, Reserved
);
2631 MyFree(MachineNameW
);
2637 /***********************************************************************
2638 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2640 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2641 const GUID
* ClassGuid
,
2647 LPWSTR lpGuidString
;
2648 LPWSTR lpFullGuidString
;
2656 if (Flags
== DIOCR_INSTALLER
)
2658 lpKeyName
= ControlClass
;
2660 else if (Flags
== DIOCR_INTERFACE
)
2662 lpKeyName
= DeviceClasses
;
2666 ERR("Invalid Flags parameter!\n");
2667 SetLastError(ERROR_INVALID_PARAMETER
);
2668 return INVALID_HANDLE_VALUE
;
2671 if (MachineName
!= NULL
)
2673 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2674 if (rc
!= ERROR_SUCCESS
)
2677 return INVALID_HANDLE_VALUE
;
2681 HKLM
= HKEY_LOCAL_MACHINE
;
2683 rc
= RegOpenKeyExW(HKLM
,
2688 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2689 if (rc
!= ERROR_SUCCESS
)
2692 return INVALID_HANDLE_VALUE
;
2695 if (ClassGuid
== NULL
)
2698 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2700 SetLastError(ERROR_GEN_FAILURE
);
2701 RegCloseKey(hClassesKey
);
2702 return INVALID_HANDLE_VALUE
;
2705 dwLength
= lstrlenW(lpGuidString
);
2706 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2707 if (!lpFullGuidString
)
2709 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2710 RpcStringFreeW(&lpGuidString
);
2711 return INVALID_HANDLE_VALUE
;
2713 lpFullGuidString
[0] = '{';
2714 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2715 lpFullGuidString
[dwLength
+ 1] = '}';
2716 lpFullGuidString
[dwLength
+ 2] = '\0';
2717 RpcStringFreeW(&lpGuidString
);
2719 rc
= RegOpenKeyExW(hClassesKey
,
2724 if (rc
!= ERROR_SUCCESS
)
2727 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2728 RegCloseKey(hClassesKey
);
2729 return INVALID_HANDLE_VALUE
;
2732 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2733 RegCloseKey(hClassesKey
);
2738 /***********************************************************************
2739 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2741 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2742 HDEVINFO DeviceInfoSet
,
2745 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2747 FIXME("%p %s %08lx %p\n",
2748 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2752 /***********************************************************************
2753 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2755 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2756 HDEVINFO DeviceInfoSet
,
2759 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2761 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
2762 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2766 /***********************************************************************
2767 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2769 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2770 HDEVINFO DeviceInfoSet
,
2771 PSP_DEVINFO_DATA DeviceInfoData
,
2772 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2773 DWORD ClassInstallParamsSize
)
2775 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2776 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2780 /***********************************************************************
2781 * SetupDiCallClassInstaller (SETUPAPI.@)
2783 BOOL WINAPI
SetupDiCallClassInstaller(
2784 IN DI_FUNCTION InstallFunction
,
2785 IN HDEVINFO DeviceInfoSet
,
2786 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2790 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2793 SetLastError(ERROR_INVALID_PARAMETER
);
2794 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2795 SetLastError(ERROR_INVALID_HANDLE
);
2796 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2797 SetLastError(ERROR_INVALID_HANDLE
);
2798 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2799 SetLastError(ERROR_INVALID_HANDLE
);
2800 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2801 SetLastError(ERROR_INVALID_USER_BUFFER
);
2804 #define CLASS_COINSTALLER 0x1
2805 #define DEVICE_COINSTALLER 0x2
2806 #define CLASS_INSTALLER 0x4
2807 UCHAR CanHandle
= 0;
2808 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2810 switch (InstallFunction
)
2812 case DIF_ALLOW_INSTALL
:
2813 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2815 case DIF_DESTROYPRIVATEDATA
:
2816 CanHandle
= CLASS_INSTALLER
;
2818 case DIF_INSTALLDEVICE
:
2819 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2820 DefaultHandler
= SetupDiInstallDevice
;
2822 case DIF_INSTALLDEVICEFILES
:
2823 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2824 DefaultHandler
= SetupDiInstallDriverFiles
;
2826 case DIF_INSTALLINTERFACES
:
2827 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2828 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2830 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2831 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2833 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2834 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2836 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2837 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2839 case DIF_REGISTER_COINSTALLERS
:
2840 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2841 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2843 case DIF_SELECTBESTCOMPATDRV
:
2844 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2845 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2848 FIXME("Install function %ld not implemented\n", InstallFunction
);
2849 SetLastError(ERROR_INVALID_PARAMETER
);
2854 LIST_ENTRY ClassCoInstallersListHead
;
2855 LIST_ENTRY DeviceCoInstallersListHead
;
2856 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2857 COINSTALLER_CONTEXT_DATA Context
;
2858 PLIST_ENTRY ListEntry
;
2860 DWORD dwRegType
, dwLength
;
2861 DWORD rc
= NO_ERROR
;
2863 InitializeListHead(&ClassCoInstallersListHead
);
2864 InitializeListHead(&DeviceCoInstallersListHead
);
2866 if (CanHandle
& DEVICE_COINSTALLER
)
2868 FIXME("Doesn't use Device co-installers at the moment\n");
2870 if (CanHandle
& CLASS_COINSTALLER
)
2874 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2878 if (rc
== ERROR_SUCCESS
)
2880 LPWSTR lpGuidString
;
2881 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2883 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
2884 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2886 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2887 if (KeyBuffer
!= NULL
)
2889 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2890 if (rc
== ERROR_SUCCESS
)
2893 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2895 /* Add coinstaller to ClassCoInstallersListHead list */
2896 FIXME("Class coinstaller is '%S'. UNIMPLEMENTED!\n", ptr
);
2899 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2902 RpcStringFreeW(&lpGuidString
);
2907 if (CanHandle
& CLASS_INSTALLER
)
2909 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2910 if (hKey
!= INVALID_HANDLE_VALUE
)
2912 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2913 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2915 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2916 if (KeyBuffer
!= NULL
)
2918 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2919 if (rc
== ERROR_SUCCESS
)
2921 /* Set ClassInstaller function pointer */
2922 FIXME("Installer is '%S'\n", KeyBuffer
);
2924 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2931 /* Call Class co-installers */
2932 Context
.PostProcessing
= FALSE
;
2934 ListEntry
= ClassCoInstallersListHead
.Flink
;
2935 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
2937 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2938 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2939 coinstaller
->PrivateData
= Context
.PrivateData
;
2940 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2942 coinstaller
->DoPostProcessing
= TRUE
;
2945 ListEntry
= ListEntry
->Flink
;
2948 /* Call Device co-installers */
2949 ListEntry
= DeviceCoInstallersListHead
.Flink
;
2950 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
2952 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2953 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2954 coinstaller
->PrivateData
= Context
.PrivateData
;
2955 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2957 coinstaller
->DoPostProcessing
= TRUE
;
2960 ListEntry
= ListEntry
->Flink
;
2963 /* Call Class installer */
2965 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2967 rc
= ERROR_DI_DO_DEFAULT
;
2969 /* Call default handler */
2970 if (rc
== ERROR_DI_DO_DEFAULT
)
2972 if (DefaultHandler
/*FIXME && DI_NODI_DEFAULTACTION not set */)
2974 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
2977 rc
= GetLastError();
2983 /* Call Class co-installers that required postprocessing */
2984 Context
.PostProcessing
= TRUE
;
2985 ListEntry
= ClassCoInstallersListHead
.Flink
;
2986 while (ListEntry
!= &ClassCoInstallersListHead
)
2988 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2989 if (coinstaller
->DoPostProcessing
)
2991 Context
.InstallResult
= rc
;
2992 Context
.PrivateData
= coinstaller
->PrivateData
;
2993 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2995 ListEntry
= ListEntry
->Flink
;
2998 /* Call Device co-installers that required postprocessing */
2999 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3000 while (ListEntry
!= &DeviceCoInstallersListHead
)
3002 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3003 if (coinstaller
->DoPostProcessing
)
3005 Context
.InstallResult
= rc
;
3006 Context
.PrivateData
= coinstaller
->PrivateData
;
3007 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3009 ListEntry
= ListEntry
->Flink
;
3012 /* Free allocated memory */
3013 while (!IsListEmpty(&ClassCoInstallersListHead
))
3015 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3016 HeapFree(GetProcessHeap(), 0, ListEntry
);
3018 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3020 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3021 HeapFree(GetProcessHeap(), 0, ListEntry
);
3024 ret
= (rc
== NO_ERROR
);
3028 TRACE("Returning %d\n", ret
);
3032 /***********************************************************************
3033 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3035 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3036 IN HDEVINFO DeviceInfoSet
,
3037 IN PSP_DEVINFO_DATA DeviceInfoData
,
3038 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3040 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3043 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3045 if (DeviceInstallParams
== NULL
)
3046 SetLastError(ERROR_INVALID_PARAMETER
);
3047 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3048 SetLastError(ERROR_INVALID_USER_BUFFER
);
3051 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3052 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3056 /* Do W->A conversion */
3058 DeviceInstallParams
,
3059 &deviceInstallParamsW
,
3060 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3061 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3062 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3064 DeviceInstallParams
->DriverPath
[0] = '\0';
3070 TRACE("Returning %d\n", ret
);
3074 /***********************************************************************
3075 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3077 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3078 IN HDEVINFO DeviceInfoSet
,
3079 IN PSP_DEVINFO_DATA DeviceInfoData
,
3080 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3082 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3086 /***********************************************************************
3087 * SetupDiOpenDevRegKey (SETUPAPI.@)
3089 HKEY WINAPI
SetupDiOpenDevRegKey(
3090 HDEVINFO DeviceInfoSet
,
3091 PSP_DEVINFO_DATA DeviceInfoData
,
3097 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
3098 Scope
, HwProfile
, KeyType
, samDesired
);
3099 return INVALID_HANDLE_VALUE
;
3102 /***********************************************************************
3103 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3105 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3106 HDEVINFO DeviceInfoSet
,
3108 CONST GUID
*ClassGuid
,
3109 PCSTR DeviceDescription
,
3111 DWORD CreationFlags
,
3112 PSP_DEVINFO_DATA DeviceInfoData
)
3114 LPWSTR DeviceNameW
= NULL
;
3115 LPWSTR DeviceDescriptionW
= NULL
;
3122 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3123 if (DeviceNameW
== NULL
) return FALSE
;
3125 if (DeviceDescription
)
3127 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3128 if (DeviceDescriptionW
== NULL
)
3130 if (DeviceNameW
) MyFree(DeviceNameW
);
3135 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3136 ClassGuid
, DeviceDescriptionW
,
3137 hwndParent
, CreationFlags
,
3140 if (DeviceNameW
) MyFree(DeviceNameW
);
3141 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3146 /***********************************************************************
3147 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3149 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3150 HDEVINFO DeviceInfoSet
,
3152 CONST GUID
*ClassGuid
,
3153 PCWSTR DeviceDescription
,
3155 DWORD CreationFlags
,
3156 PSP_DEVINFO_DATA DeviceInfoData
)
3158 struct DeviceInfoSet
*list
;
3161 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3162 debugstr_guid(ClassGuid
), DeviceDescription
,
3163 hwndParent
, CreationFlags
, DeviceInfoData
);
3166 SetLastError(ERROR_INVALID_HANDLE
);
3167 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3168 SetLastError(ERROR_INVALID_HANDLE
);
3169 else if (!ClassGuid
)
3170 SetLastError(ERROR_INVALID_PARAMETER
);
3171 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3172 SetLastError(ERROR_CLASS_MISMATCH
);
3173 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3175 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3176 SetLastError(ERROR_INVALID_PARAMETER
);
3180 SP_DEVINFO_DATA DevInfo
;
3182 if (CreationFlags
& DICD_GENERATE_ID
)
3184 /* Generate a new unique ID for this device */
3185 SetLastError(ERROR_GEN_FAILURE
);
3186 FIXME("not implemented\n");
3190 /* Device name is fully qualified. Try to open it */
3193 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3194 rc
= SetupDiOpenDeviceInfoW(
3197 NULL
, /* hwndParent */
3198 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3203 /* SetupDiOpenDeviceInfoW has already added
3204 * the device info to the device info set
3206 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3208 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3210 struct DeviceInfoElement
*deviceInfo
;
3212 /* FIXME: ClassGuid can be NULL */
3213 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3215 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3217 if (!DeviceInfoData
)
3221 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3223 SetLastError(ERROR_INVALID_USER_BUFFER
);
3227 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3228 DeviceInfoData
->DevInst
= 0; /* FIXME */
3229 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3238 TRACE("Returning %d\n", ret
);
3242 /***********************************************************************
3243 * Helper functions for SetupDiBuildDriverInfoList
3247 IN PLIST_ENTRY DriverListHead
,
3248 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3249 IN INFCONTEXT ContextDevice
,
3251 IN LPCWSTR ProviderName
,
3252 IN LPCWSTR ManufacturerName
,
3253 IN LPCWSTR MatchingId
,
3254 FILETIME DriverDate
,
3255 DWORDLONG DriverVersion
,
3258 struct DriverInfoElement
*driverInfo
= NULL
;
3259 DWORD RequiredSize
= 128; /* Initial buffer size */
3260 BOOL Result
= FALSE
;
3261 PLIST_ENTRY PreviousEntry
;
3262 LPWSTR DeviceDescription
= NULL
;
3263 LPWSTR InfInstallSection
= NULL
;
3266 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3269 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3272 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3274 /* Fill InfSection field */
3275 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3276 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3278 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3279 driverInfo
->InfSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3280 if (!driverInfo
->InfSection
)
3282 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3285 Result
= SetupGetStringFieldW(
3288 driverInfo
->InfSection
, RequiredSize
,
3294 /* Copy InfFile information */
3295 driverInfo
->InfPath
= HeapAlloc(GetProcessHeap(), 0, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3296 if (!driverInfo
->InfPath
)
3298 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3301 RtlCopyMemory(driverInfo
->InfPath
, InfFile
, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3303 /* Copy MatchingId information */
3304 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3305 if (!driverInfo
->MatchingId
)
3307 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3310 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3312 /* Get device description */
3314 RequiredSize
= 128; /* Initial buffer size */
3315 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3316 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3318 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3319 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3320 if (!DeviceDescription
)
3322 Result
= SetupGetStringFieldW(
3324 0, /* Field index */
3325 DeviceDescription
, RequiredSize
,
3331 /* Get inf install section */
3333 RequiredSize
= 128; /* Initial buffer size */
3334 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3335 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3337 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3338 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3339 if (!InfInstallSection
)
3341 Result
= SetupGetStringFieldW(
3343 1, /* Field index */
3344 InfInstallSection
, RequiredSize
,
3350 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3351 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3353 driverInfo
->DriverRank
= Rank
;
3354 driverInfo
->Info
.DriverType
= DriverType
;
3355 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3356 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3357 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3358 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3359 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3362 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3363 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3366 driverInfo
->Info
.ProviderName
[0] = '\0';
3367 driverInfo
->Info
.DriverDate
= DriverDate
;
3368 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3370 /* Insert current driver in driver list, according to its rank */
3371 PreviousEntry
= DriverListHead
->Flink
;
3372 while (PreviousEntry
!= DriverListHead
)
3374 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3376 /* Insert before the current item */
3377 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3381 if (PreviousEntry
== DriverListHead
)
3383 /* Insert at the end of the list */
3384 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3394 HeapFree(GetProcessHeap(), 0, driverInfo
->InfPath
);
3395 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3396 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
3398 HeapFree(GetProcessHeap(), 0, driverInfo
);
3400 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3401 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3407 GetVersionInformationFromInfFile(
3409 OUT LPGUID ClassGuid
,
3410 OUT LPWSTR
* pProviderName
,
3411 OUT FILETIME
* DriverDate
,
3412 OUT DWORDLONG
* DriverVersion
)
3415 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3416 LPWSTR DriverVer
= NULL
;
3417 LPWSTR ProviderName
= NULL
;
3418 LPWSTR pComma
; /* Points into DriverVer */
3419 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
3420 SYSTEMTIME SystemTime
;
3422 BOOL ret
= FALSE
; /* Final result */
3424 /* Get class Guid */
3425 if (!SetupGetLineTextW(
3428 L
"Version", L
"ClassGUID",
3429 guidW
, sizeof(guidW
),
3430 NULL
/* Required size */))
3434 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3435 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3437 SetLastError(ERROR_GEN_FAILURE
);
3441 /* Get provider name */
3442 Result
= SetupGetLineTextW(
3444 hInf
, L
"Version", L
"Provider",
3449 /* We know know the needed buffer size */
3450 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3453 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3456 Result
= SetupGetLineTextW(
3458 hInf
, L
"Version", L
"Provider",
3459 ProviderName
, RequiredSize
,
3464 *pProviderName
= ProviderName
;
3466 /* Read the "DriverVer" value */
3467 Result
= SetupGetLineTextW(
3469 hInf
, L
"Version", L
"DriverVer",
3474 /* We know know the needed buffer size */
3475 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3478 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3481 Result
= SetupGetLineTextW(
3483 hInf
, L
"Version", L
"DriverVer",
3484 DriverVer
, RequiredSize
,
3490 /* Get driver date and driver version, by analyzing the "DriverVer" value */
3491 pComma
= wcschr(DriverVer
, ',');
3494 *pComma
= UNICODE_NULL
;
3495 pVersion
= pComma
+ 1;
3497 /* Get driver date version. Invalid date = 00/00/00 */
3498 memset(DriverDate
, 0, sizeof(FILETIME
));
3499 if (wcslen(DriverVer
) == 10
3500 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
3501 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
3503 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
3504 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
3505 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
3506 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
3507 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
3508 SystemTimeToFileTime(&SystemTime
, DriverDate
);
3510 /* Get driver version. Invalid version = 0.0.0.0 */
3512 /* FIXME: use pVersion to fill DriverVersion variable */
3518 HeapFree(GetProcessHeap(), 0, ProviderName
);
3519 HeapFree(GetProcessHeap(), 0, DriverVer
);
3521 TRACE("Returning %d\n", ret
);
3525 /***********************************************************************
3526 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3529 SetupDiBuildDriverInfoList(
3530 IN HDEVINFO DeviceInfoSet
,
3531 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3532 IN DWORD DriverType
)
3534 struct DeviceInfoSet
*list
;
3535 PVOID Buffer
= NULL
;
3536 HINF hInf
= INVALID_HANDLE_VALUE
;
3537 LPWSTR ProviderName
= NULL
;
3538 LPWSTR ManufacturerName
= NULL
;
3539 LPWSTR ManufacturerSection
= NULL
;
3540 LPWSTR HardwareIDs
= NULL
;
3541 LPWSTR CompatibleIDs
= NULL
;
3542 FILETIME DriverDate
;
3543 DWORDLONG DriverVersion
= 0;
3547 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3550 SetLastError(ERROR_INVALID_HANDLE
);
3551 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3552 SetLastError(ERROR_INVALID_HANDLE
);
3553 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3554 SetLastError(ERROR_INVALID_HANDLE
);
3555 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3556 SetLastError(ERROR_INVALID_PARAMETER
);
3557 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3558 SetLastError(ERROR_INVALID_PARAMETER
);
3559 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3560 SetLastError(ERROR_INVALID_PARAMETER
);
3561 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3562 SetLastError(ERROR_INVALID_USER_BUFFER
);
3565 BOOL Result
= FALSE
;
3567 if (DriverType
== SPDIT_COMPATDRIVER
)
3569 /* Get hardware IDs list */
3571 RequiredSize
= 512; /* Initial buffer size */
3572 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3573 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3575 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3576 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3579 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3582 Result
= SetupDiGetDeviceRegistryPropertyW(
3594 /* Get compatible IDs list */
3596 RequiredSize
= 512; /* Initial buffer size */
3597 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3598 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3600 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3601 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3604 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3607 Result
= SetupDiGetDeviceRegistryPropertyW(
3610 SPDRP_COMPATIBLEIDS
,
3612 (PBYTE
)CompatibleIDs
,
3615 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3617 /* No compatible ID for this device */
3618 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3619 CompatibleIDs
= NULL
;
3627 /* Enumerate .inf files */
3629 RequiredSize
= 32768; /* Initial buffer size */
3630 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3631 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3633 HeapFree(GetProcessHeap(), 0, Buffer
);
3634 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3638 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3641 Result
= SetupGetInfFileListW(
3642 NULL
, /* Directory path */
3644 Buffer
, RequiredSize
,
3651 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
3653 INFCONTEXT ContextManufacturer
, ContextDevice
;
3655 TRACE("Opening file %S\n", filename
);
3657 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
3658 if (hInf
== INVALID_HANDLE_VALUE
)
3661 if (!GetVersionInformationFromInfFile(
3668 SetupCloseInfFile(hInf
);
3669 hInf
= INVALID_HANDLE_VALUE
;
3673 if (DriverType
== SPDIT_CLASSDRIVER
)
3675 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3676 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
3682 /* Get the manufacturers list */
3683 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
3686 Result
= SetupGetStringFieldW(
3687 &ContextManufacturer
,
3688 0, /* Field index */
3693 /* We got the needed size for the buffer */
3694 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3695 if (!ManufacturerName
)
3697 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3700 Result
= SetupGetStringFieldW(
3701 &ContextManufacturer
,
3702 0, /* Field index */
3703 ManufacturerName
, RequiredSize
,
3706 Result
= SetupGetStringFieldW(
3707 &ContextManufacturer
,
3708 1, /* Field index */
3713 /* We got the needed size for the buffer */
3714 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3715 if (!ManufacturerSection
)
3717 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3720 Result
= SetupGetStringFieldW(
3721 &ContextManufacturer
,
3722 1, /* Field index */
3723 ManufacturerSection
, RequiredSize
,
3727 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
3728 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
3731 if (DriverType
== SPDIT_CLASSDRIVER
)
3733 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3734 if (!AddDriverToList(
3735 &list
->DriverListHead
,
3742 DriverDate
, DriverVersion
,
3748 else /* DriverType = SPDIT_COMPATDRIVER */
3750 /* 1. Get all fields */
3751 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
3755 BOOL DriverAlreadyAdded
;
3757 for (i
= 2; i
<= FieldCount
; i
++)
3759 LPWSTR DeviceId
= NULL
;
3761 RequiredSize
= 128; /* Initial buffer size */
3762 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3763 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3765 HeapFree(GetProcessHeap(), 0, DeviceId
);
3766 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3769 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3772 Result
= SetupGetStringFieldW(
3775 DeviceId
, RequiredSize
,
3780 HeapFree(GetProcessHeap(), 0, DeviceId
);
3783 DriverAlreadyAdded
= FALSE
;
3784 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3786 if (wcscmp(DeviceId
, currentId
) == 0)
3789 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3796 DriverDate
, DriverVersion
,
3797 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
3798 DriverAlreadyAdded
= TRUE
;
3803 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3805 if (wcscmp(DeviceId
, currentId
) == 0)
3808 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3815 DriverDate
, DriverVersion
,
3816 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
3817 DriverAlreadyAdded
= TRUE
;
3821 HeapFree(GetProcessHeap(), 0, DeviceId
);
3824 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
3827 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3828 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3829 ManufacturerName
= ManufacturerSection
= NULL
;
3830 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
3835 HeapFree(GetProcessHeap(), 0, ProviderName
);
3836 ProviderName
= NULL
;
3838 SetupCloseInfFile(hInf
);
3839 hInf
= INVALID_HANDLE_VALUE
;
3850 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3851 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
3854 list
->Flags
|= DI_DIDCLASS
;
3857 HeapFree(GetProcessHeap(), 0, ProviderName
);
3858 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3859 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3860 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3861 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3862 if (hInf
!= INVALID_HANDLE_VALUE
)
3863 SetupCloseInfFile(hInf
);
3864 HeapFree(GetProcessHeap(), 0, Buffer
);
3866 TRACE("Returning %d\n", ret
);
3870 /***********************************************************************
3871 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3874 SetupDiDeleteDeviceInfo(
3875 IN HDEVINFO DeviceInfoSet
,
3876 IN PSP_DEVINFO_DATA DeviceInfoData
)
3878 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3880 FIXME("not implemented\n");
3881 SetLastError(ERROR_GEN_FAILURE
);
3886 /***********************************************************************
3887 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3890 SetupDiDestroyDriverInfoList(
3891 IN HDEVINFO DeviceInfoSet
,
3892 IN PSP_DEVINFO_DATA DeviceInfoData
,
3893 IN DWORD DriverType
)
3895 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3897 FIXME("not implemented\n");
3898 SetLastError(ERROR_GEN_FAILURE
);
3903 /***********************************************************************
3904 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3907 SetupDiOpenDeviceInfoA(
3908 IN HDEVINFO DeviceInfoSet
,
3909 IN PCSTR DeviceInstanceId
,
3910 IN HWND hwndParent OPTIONAL
,
3912 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3914 LPWSTR DeviceInstanceIdW
= NULL
;
3917 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3919 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
3920 if (DeviceInstanceIdW
== NULL
)
3923 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
3924 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
3926 MyFree(DeviceInstanceIdW
);
3932 /***********************************************************************
3933 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3936 SetupDiOpenDeviceInfoW(
3937 IN HDEVINFO DeviceInfoSet
,
3938 IN PCWSTR DeviceInstanceId
,
3939 IN HWND hwndParent OPTIONAL
,
3941 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3943 struct DeviceInfoSet
*list
;
3944 HKEY hEnumKey
, hKey
;
3948 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3950 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
3951 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3954 SetLastError(ERROR_INVALID_HANDLE
);
3955 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3956 SetLastError(ERROR_INVALID_HANDLE
);
3957 else if (!DeviceInstanceId
)
3958 SetLastError(ERROR_INVALID_PARAMETER
);
3959 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
3961 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
3962 SetLastError(ERROR_INVALID_PARAMETER
);
3964 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3965 SetLastError(ERROR_INVALID_USER_BUFFER
);
3968 struct DeviceInfoElement
*deviceInfo
= NULL
;
3969 /* Search if device already exists in DeviceInfoSet.
3970 * If yes, return the existing element
3971 * If no, create a new element using informations in registry
3973 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
3974 while (ItemList
!= &list
->ListHead
)
3979 FIXME("not implemented\n");
3980 ItemList
= ItemList
->Flink
;
3985 /* good one found */
3990 /* Open supposed registry key */
3995 KEY_ENUMERATE_SUB_KEYS
,
3997 if (rc
!= ERROR_SUCCESS
)
4008 RegCloseKey(hEnumKey
);
4009 if (rc
!= ERROR_SUCCESS
)
4015 /* FIXME: GUID_NULL is not allowed */
4016 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
4021 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4027 if (ret
&& deviceInfo
&& DeviceInfoData
)
4029 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4030 DeviceInfoData
->DevInst
= 0; /* FIXME */
4031 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4039 /***********************************************************************
4040 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4043 SetupDiEnumDriverInfoA(
4044 IN HDEVINFO DeviceInfoSet
,
4045 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4046 IN DWORD DriverType
,
4047 IN DWORD MemberIndex
,
4048 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4050 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4053 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4054 DriverType
, MemberIndex
, DriverInfoData
);
4056 if (DriverInfoData
== NULL
)
4057 SetLastError(ERROR_INVALID_PARAMETER
);
4058 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4059 SetLastError(ERROR_INVALID_USER_BUFFER
);
4062 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4063 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4064 DriverType
, MemberIndex
, &driverInfoData2W
);
4068 /* Do W->A conversion */
4069 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4070 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4071 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4072 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4074 DriverInfoData
->Description
[0] = '\0';
4077 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4078 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4080 DriverInfoData
->MfgName
[0] = '\0';
4083 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4084 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4086 DriverInfoData
->ProviderName
[0] = '\0';
4089 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4091 /* Copy more fields */
4092 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4093 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4098 TRACE("Returning %d\n", ret
);
4103 /***********************************************************************
4104 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4107 SetupDiEnumDriverInfoW(
4108 IN HDEVINFO DeviceInfoSet
,
4109 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4110 IN DWORD DriverType
,
4111 IN DWORD MemberIndex
,
4112 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4114 PLIST_ENTRY ListHead
;
4117 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4118 DriverType
, MemberIndex
, DriverInfoData
);
4120 if (!DeviceInfoSet
|| !DriverInfoData
)
4121 SetLastError(ERROR_INVALID_PARAMETER
);
4122 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4123 SetLastError(ERROR_INVALID_HANDLE
);
4124 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4125 SetLastError(ERROR_INVALID_HANDLE
);
4126 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4127 SetLastError(ERROR_INVALID_PARAMETER
);
4128 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4129 SetLastError(ERROR_INVALID_PARAMETER
);
4130 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4131 SetLastError(ERROR_INVALID_PARAMETER
);
4132 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4133 SetLastError(ERROR_INVALID_USER_BUFFER
);
4136 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4137 PLIST_ENTRY ItemList
;
4138 if (DriverType
== SPDIT_CLASSDRIVER
||
4139 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4141 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4145 ListHead
= &devInfo
->DriverListHead
;
4148 ItemList
= ListHead
->Flink
;
4149 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4150 ItemList
= ItemList
->Flink
;
4151 if (ItemList
== ListHead
)
4152 SetLastError(ERROR_NO_MORE_ITEMS
);
4155 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4158 &DriverInfoData
->DriverType
,
4159 &DrvInfo
->Info
.DriverType
,
4160 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4165 TRACE("Returning %d\n", ret
);
4169 /***********************************************************************
4170 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4173 SetupDiGetSelectedDriverW(
4174 IN HDEVINFO DeviceInfoSet
,
4175 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4176 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4180 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4182 if (!DeviceInfoSet
|| !DriverInfoData
)
4183 SetLastError(ERROR_INVALID_PARAMETER
);
4184 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4185 SetLastError(ERROR_INVALID_HANDLE
);
4186 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4187 SetLastError(ERROR_INVALID_HANDLE
);
4188 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4189 SetLastError(ERROR_INVALID_USER_BUFFER
);
4190 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4191 SetLastError(ERROR_INVALID_USER_BUFFER
);
4194 struct DriverInfoElement
*driverInfo
;
4197 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4199 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4201 if (driverInfo
== NULL
)
4202 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4206 &DriverInfoData
->DriverType
,
4207 &driverInfo
->Info
.DriverType
,
4208 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4213 TRACE("Returning %d\n", ret
);
4217 /***********************************************************************
4218 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4221 SetupDiSetSelectedDriverW(
4222 IN HDEVINFO DeviceInfoSet
,
4223 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4224 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4228 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4231 SetLastError(ERROR_INVALID_PARAMETER
);
4232 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4233 SetLastError(ERROR_INVALID_HANDLE
);
4234 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4235 SetLastError(ERROR_INVALID_HANDLE
);
4236 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4237 SetLastError(ERROR_INVALID_USER_BUFFER
);
4238 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4239 SetLastError(ERROR_INVALID_USER_BUFFER
);
4242 struct DriverInfoElement
**pDriverInfo
;
4243 PLIST_ENTRY ListHead
, ItemList
;
4247 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4248 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4252 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4253 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4256 if (!DriverInfoData
)
4258 *pDriverInfo
= NULL
;
4263 /* Search selected driver in list */
4264 ItemList
= ListHead
->Flink
;
4265 while (ItemList
!= ListHead
)
4267 if (DriverInfoData
->Reserved
!= 0)
4269 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4274 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4275 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4276 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4277 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4278 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4284 if (ItemList
== ListHead
)
4285 SetLastError(ERROR_INVALID_PARAMETER
);
4288 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4289 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4291 TRACE("Choosing driver whose rank is 0x%lx\n",
4292 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
4297 TRACE("Returning %d\n", ret
);
4301 /***********************************************************************
4302 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4305 SetupDiSelectBestCompatDrv(
4306 IN HDEVINFO DeviceInfoSet
,
4307 IN PSP_DEVINFO_DATA DeviceInfoData
)
4309 SP_DRVINFO_DATA_W drvInfoData
;
4312 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4314 /* Drivers are sorted by rank in the driver list, so
4315 * the first driver in the list is the best one.
4317 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4318 ret
= SetupDiEnumDriverInfoW(
4322 0, /* Member index */
4327 ret
= SetupDiSetSelectedDriverW(
4333 TRACE("Returning %d\n", ret
);
4337 /***********************************************************************
4338 * SetupDiInstallDriverFiles (SETUPAPI.@)
4341 SetupDiInstallDriverFiles(
4342 IN HDEVINFO DeviceInfoSet
,
4343 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4347 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4350 SetLastError(ERROR_INVALID_PARAMETER
);
4351 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4352 SetLastError(ERROR_INVALID_HANDLE
);
4353 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4354 SetLastError(ERROR_INVALID_HANDLE
);
4355 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4356 SetLastError(ERROR_INVALID_USER_BUFFER
);
4357 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4358 SetLastError(ERROR_INVALID_PARAMETER
);
4359 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4360 SetLastError(ERROR_INVALID_PARAMETER
);
4363 struct DriverInfoElement
*DriverInfo
;
4369 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4370 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4374 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4375 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4378 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4379 if (hInf
!= INVALID_HANDLE_VALUE
)
4381 WCHAR SectionName
[MAX_PATH
];
4382 DWORD SectionNameLength
= 0;
4384 ret
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4385 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4388 PVOID callback_context
= SetupInitDefaultQueueCallback(hWnd
);
4389 ret
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4390 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
4391 SetupDefaultQueueCallbackW
, callback_context
,
4393 SetupTermDefaultQueueCallback(callback_context
);
4395 SetupCloseInfFile(hInf
);
4399 TRACE("Returning %d\n", ret
);
4403 /***********************************************************************
4404 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4407 SetupDiRegisterCoDeviceInstallers(
4408 IN HDEVINFO DeviceInfoSet
,
4409 IN PSP_DEVINFO_DATA DeviceInfoData
)
4411 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4413 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4414 //SetLastError(ERROR_GEN_FAILURE);
4419 /***********************************************************************
4420 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4423 SetupDiInstallDeviceInterfaces(
4424 IN HDEVINFO DeviceInfoSet
,
4425 IN PSP_DEVINFO_DATA DeviceInfoData
)
4427 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4429 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4430 //SetLastError(ERROR_GEN_FAILURE);
4435 /***********************************************************************
4436 * SetupDiInstallDevice (SETUPAPI.@)
4439 SetupDiInstallDevice(
4440 IN HDEVINFO DeviceInfoSet
,
4441 IN PSP_DEVINFO_DATA DeviceInfoData
)
4443 struct DriverInfoElement
*DriverInfo
;
4444 struct DeviceInfoSet
*DevInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
;
4445 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4446 SYSTEMTIME DriverDate
;
4447 WCHAR SectionName
[MAX_PATH
];
4449 DWORD SectionNameLength
= 0;
4450 BOOL Result
= FALSE
;
4451 INFCONTEXT ContextService
;
4454 HINF hInf
= INVALID_HANDLE_VALUE
;
4455 LPCWSTR AssociatedService
= NULL
;
4456 LPWSTR pSectionName
= NULL
;
4457 LPWSTR ClassName
= NULL
;
4459 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
4460 BOOL RebootRequired
= FALSE
;
4461 HKEY hEnumKey
, hKey
= INVALID_HANDLE_VALUE
;
4462 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4463 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4464 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4465 DWORD Index
; /* Index used in the DriverKey name */
4468 PVOID callback_context
;
4469 BOOL ret
= FALSE
; /* Return value */
4471 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4474 SetLastError(ERROR_INVALID_PARAMETER
);
4475 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4476 SetLastError(ERROR_INVALID_HANDLE
);
4477 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4478 SetLastError(ERROR_INVALID_HANDLE
);
4479 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4480 SetLastError(ERROR_INVALID_USER_BUFFER
);
4481 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4482 SetLastError(ERROR_INVALID_PARAMETER
);
4483 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4484 SetLastError(ERROR_INVALID_PARAMETER
);
4490 /* One parameter is bad */
4494 /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
4498 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4499 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4503 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4504 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4506 FileTimeToSystemTime(&DriverInfo
->Info
.DriverDate
, &DriverDate
);
4508 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4509 if (hInf
== INVALID_HANDLE_VALUE
)
4512 Result
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4513 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4514 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
4516 pSectionName
= &SectionName
[wcslen(SectionName
)];
4518 /* Get information from [Version] section */
4521 if (!SetupDiGetINFClassW(DriverInfo
->InfPath
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
4523 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
4525 ClassName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4528 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4531 if (!SetupDiGetINFClassW(DriverInfo
->InfPath
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
4534 /* Format ClassGuid to a string */
4535 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4537 RequiredSize
= lstrlenW(lpGuidString
);
4538 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
4539 if (!lpFullGuidString
)
4541 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4544 lpFullGuidString
[0] = '{';
4545 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
4546 lpFullGuidString
[RequiredSize
+ 1] = '}';
4547 lpFullGuidString
[RequiredSize
+ 2] = '\0';
4549 /* Create driver key information */
4550 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\{#ID} */
4551 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpFullGuidString
) + 6) * sizeof(WCHAR
));
4554 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4557 wcscpy(DriverKey
, lpFullGuidString
);
4558 wcscat(DriverKey
, L
"\\");
4559 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4560 rc
= RegOpenKeyExW(DevInfoSet
->HKLM
,
4565 if (rc
!= ERROR_SUCCESS
)
4570 /* Try all values for Index between 0 and 9999 */
4572 while (Index
<= 9999)
4575 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4576 rc
= RegCreateKeyEx(hClassKey
,
4580 REG_OPTION_NON_VOLATILE
,
4585 if (rc
!= ERROR_SUCCESS
)
4590 if (Disposition
== REG_CREATED_NEW_KEY
)
4593 hKey
= INVALID_HANDLE_VALUE
;
4598 /* Unable to create more than 9999 devices within the same class */
4599 SetLastError(ERROR_GEN_FAILURE
);
4603 /* Write information to driver key */
4604 *pSectionName
= UNICODE_NULL
;
4605 TRACE("Write information to driver key\n");
4606 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4607 TRACE("DriverDesc : '%S'\n", DriverInfo
->Info
.Description
);
4608 TRACE("DriverVersion : '%u.%u.%u.%u'\n", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4609 TRACE("InfPath : '%S'\n", DriverInfo
->InfPath
);
4610 TRACE("InfSection : '%S'\n", DriverInfo
->InfSection
);
4611 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(DriverInfo
->InfSection
)]); /* FIXME */
4612 TRACE("MatchingDeviceId: '%S'\n", DriverInfo
->MatchingId
);
4613 TRACE("ProviderName : '%S'\n", DriverInfo
->Info
.ProviderName
);
4614 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4615 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
4616 if (rc
== ERROR_SUCCESS
)
4617 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&DriverInfo
->Info
.DriverDate
, sizeof(FILETIME
));
4618 if (rc
== ERROR_SUCCESS
)
4619 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
4620 if (rc
== ERROR_SUCCESS
)
4622 swprintf(Buffer
, L
"%u.%u.%u.%u", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4623 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
4625 if (rc
== ERROR_SUCCESS
)
4626 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)DriverInfo
->InfPath
, (wcslen(DriverInfo
->InfPath
) + 1) * sizeof(WCHAR
));
4627 if (rc
== ERROR_SUCCESS
)
4628 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)DriverInfo
->InfSection
, (wcslen(DriverInfo
->InfSection
) + 1) * sizeof(WCHAR
));
4629 if (rc
== ERROR_SUCCESS
)
4630 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(DriverInfo
->InfSection
)], (wcslen(SectionName
) - wcslen(DriverInfo
->InfSection
) + 1) * sizeof(WCHAR
));
4631 if (rc
== ERROR_SUCCESS
)
4632 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)DriverInfo
->MatchingId
, (wcslen(DriverInfo
->MatchingId
) + 1) * sizeof(WCHAR
));
4633 if (rc
== ERROR_SUCCESS
)
4634 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.ProviderName
, (wcslen(DriverInfo
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
4635 if (rc
!= ERROR_SUCCESS
)
4641 hKey
= INVALID_HANDLE_VALUE
;
4643 /* Install .Services section */
4644 wcscpy(pSectionName
, L
".Services");
4645 Result
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
4648 LPWSTR ServiceName
= NULL
;
4649 LPWSTR ServiceSection
= NULL
;
4651 Result
= SetupGetStringFieldW(
4653 1, /* Field index */
4658 if (RequiredSize
> 0)
4660 /* We got the needed size for the buffer */
4661 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4664 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4667 Result
= SetupGetStringFieldW(
4669 1, /* Field index */
4670 ServiceName
, RequiredSize
,
4675 Result
= SetupGetIntField(
4677 2, /* Field index */
4681 /* The field may be empty. Ignore the error */
4684 Result
= SetupGetStringFieldW(
4686 3, /* Field index */
4691 if (RequiredSize
> 0)
4693 /* We got the needed size for the buffer */
4694 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4695 if (!ServiceSection
)
4697 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4700 Result
= SetupGetStringFieldW(
4702 3, /* Field index */
4703 ServiceSection
, RequiredSize
,
4708 SetLastError(ERROR_SUCCESS
);
4709 Result
= SetupInstallServicesFromInfSectionExW(hInf
, ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
4710 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
4712 AssociatedService
= ServiceName
;
4714 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
4715 RebootRequired
= TRUE
;
4718 HeapFree(GetProcessHeap(), 0, ServiceName
);
4719 HeapFree(GetProcessHeap(), 0, ServiceSection
);
4722 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
4725 /* Copy .inf file to Inf\ directory */
4726 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
4729 rc
= RegOpenKeyExW(DevInfoSet
->HKLM
,
4732 KEY_ENUMERATE_SUB_KEYS
,
4734 if (rc
!= ERROR_SUCCESS
)
4741 DevInfo
->DeviceName
,
4745 RegCloseKey(hEnumKey
);
4746 if (rc
!= ERROR_SUCCESS
)
4752 /* Install .HW section */
4753 wcscpy(pSectionName
, L
".HW");
4754 callback_context
= SetupInitDefaultQueueCallback(hWnd
);
4755 Result
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4756 SPINST_REGISTRY
, hKey
, NULL
, 0,
4757 SetupDefaultQueueCallbackW
, callback_context
,
4759 SetupTermDefaultQueueCallback(callback_context
);
4763 /* Write information to enum key */
4764 TRACE("Write information to enum key\n");
4765 TRACE("Service : '%S'\n", AssociatedService
);
4766 TRACE("Class : '%S'\n", ClassName
);
4767 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
4768 TRACE("DeviceDesc : '%S'\n", DriverInfo
->Info
.Description
);
4769 TRACE("Driver : '%S'\n", DriverKey
);
4770 TRACE("Mfg : '%S'\n", DriverInfo
->Info
.MfgName
);
4771 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
4772 if (rc
== ERROR_SUCCESS
)
4773 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
4774 if (rc
== ERROR_SUCCESS
)
4775 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
4776 if (rc
== ERROR_SUCCESS
)
4777 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
4778 if (rc
== ERROR_SUCCESS
)
4779 rc
= RegSetValueEx(hKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4780 if (rc
== ERROR_SUCCESS
)
4781 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.MfgName
, (wcslen(DriverInfo
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
4782 if (rc
!= ERROR_SUCCESS
)
4788 /* Start the device */
4789 if (!RebootRequired
&& !(Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
4791 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
4793 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
4794 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
4795 ret
= NT_SUCCESS(Status
);
4801 /* End of installation */
4802 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4803 RegCloseKey(hClassKey
);
4804 if (hKey
!= INVALID_HANDLE_VALUE
)
4807 RpcStringFreeW(&lpGuidString
);
4808 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4809 HeapFree(GetProcessHeap(), 0, DriverKey
);
4810 HeapFree(GetProcessHeap(), 0, ClassName
);
4811 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
4812 if (hInf
!= INVALID_HANDLE_VALUE
)
4813 SetupCloseInfFile(hInf
);
4815 TRACE("Returning %d\n", ret
);