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"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
44 #include "setupapi_private.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
49 /* Unicode constants */
50 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
51 static const WCHAR Class
[] = {'C','l','a','s','s',0};
52 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
53 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
54 static const WCHAR NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
55 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
56 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
57 static const WCHAR NtExtension
[] = {'.','N','T',0};
58 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
59 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
60 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
61 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
63 /* Registry key and value names */
64 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
65 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
66 'C','o','n','t','r','o','l','\\',
67 'C','l','a','s','s',0};
69 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
70 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
71 'C','o','n','t','r','o','l','\\',
72 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
74 static const WCHAR EnumKeyName
[] = {'S','y','s','t','e','m','\\',
75 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
79 /* FIXME: header mess */
80 DEFINE_GUID(GUID_NULL
,
81 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
83 (CALLBACK
* CLASS_INSTALL_PROC
) (
84 IN DI_FUNCTION InstallFunction
,
85 IN HDEVINFO DeviceInfoSet
,
86 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
88 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
89 IN HDEVINFO DeviceInfoSet
,
90 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
92 (CALLBACK
* COINSTALLER_PROC
) (
93 IN DI_FUNCTION InstallFunction
,
94 IN HDEVINFO DeviceInfoSet
,
95 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
96 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
98 #define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
100 struct CoInstallerElement
102 LIST_ENTRY ListEntry
;
104 COINSTALLER_PROC Function
;
105 BOOL DoPostProcessing
;
109 struct DeviceInterface
/* Element of DeviceInfoElement.InterfaceListHead */
111 LIST_ENTRY ListEntry
;
113 struct DeviceInfoElement
* DeviceInfo
;
114 GUID InterfaceClassGuid
;
117 /* SPINT_ACTIVE : the interface is active/enabled
118 * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
119 * SPINT_REMOVED: the interface is removed
123 WCHAR SymbolicLink
[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
126 struct DriverInfoElement
/* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
128 LIST_ENTRY ListEntry
;
130 SP_DRVINFO_DATA_V2_W Info
;
133 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
135 LIST_ENTRY ListEntry
;
137 /* Information about devnode:
139 * "Root\*PNP0501" for example.
140 * It doesn't contain the unique ID for the device
141 * (points into the Data field at the end of the structure)
142 * WARNING: no NULL char exist between DeviceName and UniqueId
145 * "5&1be2108e&0" or "0000"
146 * If DICD_GENERATE_ID is specified in creation flags,
147 * this unique ID is autogenerated using 4 digits, base 10
148 * (points into the Data field at the end of the structure)
149 * - DeviceDescription
150 * String which identifies the device. Can be NULL. If not NULL,
151 * points into the Data field at the end of the structure
153 * Identifies the class of this device. FIXME: can it be GUID_NULL?
155 * Is a combination of:
157 * the unique ID needs to be generated
158 * - DICD_INHERIT_CLASSDRVS
159 * inherit driver of the device info set (== same pointer)
161 * Used when doing device-specific actions. Can be NULL
165 PCWSTR DeviceDescription
;
170 /* Flags is a combination of:
172 * Set when the device driver list is created
173 * FlagsEx is a combination of:
178 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
179 /* If the driver is not searched/detected, this list is empty */
180 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
181 /* Points into DriverListHead list. The pointer is NULL if no driver is
182 * currently chosen. */
183 struct DriverInfoElement
*SelectedDriver
;
185 /* List of interfaces implemented by this device */
186 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
191 struct DeviceInfoSet
/* HDEVINFO */
193 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
194 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
195 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
196 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
198 /* Flags is a combination of:
200 * Set when the class driver list is created
201 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
202 * Forces SetupDiBuildDriverInfoList to build a class drivers list
203 * FlagsEx is a combination of:
208 /* If the driver is not searched/detected, this list is empty */
209 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
210 /* Points into DriverListHead list. The pointer is NULL if no driver is
211 * currently chosen. */
212 struct DriverInfoElement
*SelectedDriver
;
214 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
217 /***********************************************************************
218 * SetupDiBuildClassInfoList (SETUPAPI.@)
220 BOOL WINAPI
SetupDiBuildClassInfoList(
222 LPGUID ClassGuidList
,
223 DWORD ClassGuidListSize
,
227 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
228 ClassGuidListSize
, RequiredSize
,
232 /***********************************************************************
233 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
235 BOOL WINAPI
SetupDiBuildClassInfoListExA(
237 LPGUID ClassGuidList
,
238 DWORD ClassGuidListSize
,
243 LPWSTR MachineNameW
= NULL
;
250 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
251 if (MachineNameW
== NULL
) return FALSE
;
254 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
255 ClassGuidListSize
, RequiredSize
,
256 MachineNameW
, Reserved
);
259 MyFree(MachineNameW
);
264 /***********************************************************************
265 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
267 BOOL WINAPI
SetupDiBuildClassInfoListExW(
269 LPGUID ClassGuidList
,
270 DWORD ClassGuidListSize
,
275 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
281 DWORD dwGuidListIndex
= 0;
285 if (RequiredSize
!= NULL
)
288 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
293 if (hClassesKey
== INVALID_HANDLE_VALUE
)
298 for (dwIndex
= 0; ; dwIndex
++)
300 dwLength
= MAX_GUID_STRING_LEN
+ 1;
301 lError
= RegEnumKeyExW(hClassesKey
,
309 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
310 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
312 TRACE("Key name: %p\n", szKeyName
);
314 if (RegOpenKeyExW(hClassesKey
,
320 RegCloseKey(hClassesKey
);
324 if (!RegQueryValueExW(hClassKey
,
331 TRACE("'NoUseClass' value found!\n");
332 RegCloseKey(hClassKey
);
336 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
337 (!RegQueryValueExW(hClassKey
,
344 TRACE("'NoInstallClass' value found!\n");
345 RegCloseKey(hClassKey
);
349 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
350 (!RegQueryValueExW(hClassKey
,
357 TRACE("'NoDisplayClass' value found!\n");
358 RegCloseKey(hClassKey
);
362 RegCloseKey(hClassKey
);
364 TRACE("Guid: %p\n", szKeyName
);
365 if (dwGuidListIndex
< ClassGuidListSize
)
367 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
371 TRACE("Guid: %p\n", &szKeyName
[1]);
373 UuidFromStringW(&szKeyName
[1],
374 &ClassGuidList
[dwGuidListIndex
]);
380 if (lError
!= ERROR_SUCCESS
)
384 RegCloseKey(hClassesKey
);
386 if (RequiredSize
!= NULL
)
387 *RequiredSize
= dwGuidListIndex
;
389 if (ClassGuidListSize
< dwGuidListIndex
)
391 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
398 /***********************************************************************
399 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
401 BOOL WINAPI
SetupDiClassGuidsFromNameA(
403 LPGUID ClassGuidList
,
404 DWORD ClassGuidListSize
,
407 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
408 ClassGuidListSize
, RequiredSize
,
412 /***********************************************************************
413 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
415 BOOL WINAPI
SetupDiClassGuidsFromNameW(
417 LPGUID ClassGuidList
,
418 DWORD ClassGuidListSize
,
421 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
422 ClassGuidListSize
, RequiredSize
,
426 /***********************************************************************
427 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
429 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
431 LPGUID ClassGuidList
,
432 DWORD ClassGuidListSize
,
437 LPWSTR ClassNameW
= NULL
;
438 LPWSTR MachineNameW
= NULL
;
443 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
444 if (ClassNameW
== NULL
)
449 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
450 if (MachineNameW
== NULL
)
457 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
458 ClassGuidListSize
, RequiredSize
,
459 MachineNameW
, Reserved
);
462 MyFree(MachineNameW
);
469 /***********************************************************************
470 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
472 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
474 LPGUID ClassGuidList
,
475 DWORD ClassGuidListSize
,
480 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
481 WCHAR szClassName
[256];
487 DWORD dwGuidListIndex
= 0;
489 if (RequiredSize
!= NULL
)
492 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
493 KEY_ENUMERATE_SUB_KEYS
,
497 if (hClassesKey
== INVALID_HANDLE_VALUE
)
502 for (dwIndex
= 0; ; dwIndex
++)
504 dwLength
= MAX_GUID_STRING_LEN
+ 1;
505 lError
= RegEnumKeyExW(hClassesKey
,
513 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
514 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
516 TRACE("Key name: %p\n", szKeyName
);
518 if (RegOpenKeyExW(hClassesKey
,
524 RegCloseKey(hClassesKey
);
528 dwLength
= 256 * sizeof(WCHAR
);
529 if (!RegQueryValueExW(hClassKey
,
536 TRACE("Class name: %p\n", szClassName
);
538 if (strcmpiW(szClassName
, ClassName
) == 0)
540 TRACE("Found matching class name\n");
542 TRACE("Guid: %p\n", szKeyName
);
543 if (dwGuidListIndex
< ClassGuidListSize
)
545 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
549 TRACE("Guid: %p\n", &szKeyName
[1]);
551 UuidFromStringW(&szKeyName
[1],
552 &ClassGuidList
[dwGuidListIndex
]);
559 RegCloseKey(hClassKey
);
562 if (lError
!= ERROR_SUCCESS
)
566 RegCloseKey(hClassesKey
);
568 if (RequiredSize
!= NULL
)
569 *RequiredSize
= dwGuidListIndex
;
571 if (ClassGuidListSize
< dwGuidListIndex
)
573 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
580 /***********************************************************************
581 * SetupDiClassNameFromGuidA (SETUPAPI.@)
583 BOOL WINAPI
SetupDiClassNameFromGuidA(
584 const GUID
* ClassGuid
,
589 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
590 ClassNameSize
, RequiredSize
,
594 /***********************************************************************
595 * SetupDiClassNameFromGuidW (SETUPAPI.@)
597 BOOL WINAPI
SetupDiClassNameFromGuidW(
598 const GUID
* ClassGuid
,
603 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
604 ClassNameSize
, RequiredSize
,
608 /***********************************************************************
609 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
611 BOOL WINAPI
SetupDiClassNameFromGuidExA(
612 const GUID
* ClassGuid
,
619 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
620 LPWSTR MachineNameW
= NULL
;
624 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
625 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
626 NULL
, MachineNameW
, Reserved
);
629 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
630 ClassNameSize
, NULL
, NULL
);
632 if (!ClassNameSize
&& RequiredSize
)
635 MyFree(MachineNameW
);
639 /***********************************************************************
640 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
642 BOOL WINAPI
SetupDiClassNameFromGuidExW(
643 const GUID
* ClassGuid
,
654 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
659 if (hKey
== INVALID_HANDLE_VALUE
)
664 if (RequiredSize
!= NULL
)
667 rc
= RegQueryValueExW(hKey
,
673 if (rc
!= ERROR_SUCCESS
)
680 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
683 dwLength
= ClassNameSize
* sizeof(WCHAR
);
684 rc
= RegQueryValueExW(hKey
,
690 if (rc
!= ERROR_SUCCESS
)
702 /***********************************************************************
703 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
706 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
709 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
712 /***********************************************************************
713 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
716 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
721 LPWSTR MachineNameW
= NULL
;
724 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
728 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
729 if (MachineNameW
== NULL
)
730 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
733 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
734 MachineNameW
, Reserved
);
737 MyFree(MachineNameW
);
742 /***********************************************************************
743 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
746 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
751 struct DeviceInfoSet
*list
;
754 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
756 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
759 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
760 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
763 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
766 ClassGuid
? ClassGuid
: &GUID_NULL
,
767 sizeof(list
->ClassGuid
));
768 list
->hwndParent
= hwndParent
;
771 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
772 if (rc
!= ERROR_SUCCESS
)
775 HeapFree(GetProcessHeap(), 0, list
);
776 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
781 list
->HKLM
= HKEY_LOCAL_MACHINE
;
783 list
->Flags
= 0; /* FIXME */
784 list
->FlagsEx
= 0; /* FIXME */
785 InitializeListHead(&list
->DriverListHead
);
786 InitializeListHead(&list
->ListHead
);
787 return (HDEVINFO
)list
;
790 /***********************************************************************
791 * SetupDiEnumDeviceInfo (SETUPAPI.@)
793 BOOL WINAPI
SetupDiEnumDeviceInfo(
794 HDEVINFO DeviceInfoSet
,
796 PSP_DEVINFO_DATA DeviceInfoData
)
800 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
802 SetLastError(ERROR_INVALID_PARAMETER
);
803 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
805 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
807 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
808 SetLastError(ERROR_INVALID_HANDLE
);
809 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
810 SetLastError(ERROR_INVALID_USER_BUFFER
);
813 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
814 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
815 ItemList
= ItemList
->Flink
;
816 if (ItemList
== &list
->ListHead
)
817 SetLastError(ERROR_NO_MORE_ITEMS
);
820 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
821 memcpy(&DeviceInfoData
->ClassGuid
,
824 DeviceInfoData
->DevInst
= 0; /* FIXME */
825 /* Note: this appears to be dangerous, passing a private
826 * pointer a heap-allocated datum to the caller. However, the
827 * expected lifetime of the device data is the same as the
828 * HDEVINFO; once that is closed, the data are no longer valid.
830 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
836 SetLastError(ERROR_INVALID_HANDLE
);
840 /***********************************************************************
841 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
843 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
845 PCSTR InfSectionName
,
846 PSTR InfSectionWithExt
,
847 DWORD InfSectionWithExtSize
,
851 LPWSTR InfSectionNameW
= NULL
;
852 PWSTR InfSectionWithExtW
= NULL
;
854 BOOL bResult
= FALSE
;
860 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
861 if (InfSectionNameW
== NULL
) goto end
;
863 if (InfSectionWithExt
)
865 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
866 if (InfSectionWithExtW
== NULL
) goto end
;
869 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
870 InfSectionWithExt
? InfSectionNameW
: NULL
,
871 InfSectionWithExtSize
, RequiredSize
,
872 Extension
? &ExtensionW
: NULL
);
874 if (bResult
&& InfSectionWithExt
)
876 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
877 InfSectionWithExtSize
, NULL
, NULL
) != 0;
879 if (bResult
&& Extension
)
881 if (ExtensionW
== NULL
)
884 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
888 if (InfSectionNameW
) MyFree(InfSectionNameW
);
889 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
894 /***********************************************************************
895 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
897 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
899 PCWSTR InfSectionName
,
900 PWSTR InfSectionWithExt
,
901 DWORD InfSectionWithExtSize
,
905 WCHAR szBuffer
[MAX_PATH
];
908 LONG lLineCount
= -1;
910 lstrcpyW(szBuffer
, InfSectionName
);
911 dwLength
= lstrlenW(szBuffer
);
913 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
915 /* Test section name with '.NTx86' extension */
916 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
917 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
919 if (lLineCount
== -1)
921 /* Test section name with '.NT' extension */
922 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
923 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
928 /* Test section name with '.Win' extension */
929 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
930 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
933 if (lLineCount
== -1)
935 /* Test section name without extension */
936 szBuffer
[dwLength
] = 0;
937 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
940 if (lLineCount
== -1)
942 SetLastError(ERROR_INVALID_PARAMETER
);
946 dwFullLength
= lstrlenW(szBuffer
);
948 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
950 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
952 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
956 lstrcpyW(InfSectionWithExt
, szBuffer
);
957 if (Extension
!= NULL
)
959 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
963 if (RequiredSize
!= NULL
)
965 *RequiredSize
= dwFullLength
+ 1;
971 /***********************************************************************
972 * SetupDiGetClassDescriptionA (SETUPAPI.@)
974 BOOL WINAPI
SetupDiGetClassDescriptionA(
975 const GUID
* ClassGuid
,
976 PSTR ClassDescription
,
977 DWORD ClassDescriptionSize
,
980 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
981 ClassDescriptionSize
,
982 RequiredSize
, NULL
, NULL
);
985 /***********************************************************************
986 * SetupDiGetClassDescriptionW (SETUPAPI.@)
988 BOOL WINAPI
SetupDiGetClassDescriptionW(
989 const GUID
* ClassGuid
,
990 PWSTR ClassDescription
,
991 DWORD ClassDescriptionSize
,
994 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
995 ClassDescriptionSize
,
996 RequiredSize
, NULL
, NULL
);
999 /***********************************************************************
1000 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1002 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1003 const GUID
* ClassGuid
,
1004 PSTR ClassDescription
,
1005 DWORD ClassDescriptionSize
,
1006 PDWORD RequiredSize
,
1010 PWCHAR ClassDescriptionW
;
1011 LPWSTR MachineNameW
= NULL
;
1015 if (ClassDescriptionSize
> 0)
1017 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1018 if (!ClassDescriptionW
)
1020 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1026 ClassDescriptionW
= NULL
;
1030 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1033 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1039 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1040 NULL
, MachineNameW
, Reserved
);
1043 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1044 ClassDescriptionSize
, NULL
, NULL
);
1046 if (!ClassDescriptionSize
&& RequiredSize
)
1047 *RequiredSize
= len
;
1051 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1052 MyFree(MachineNameW
);
1056 /***********************************************************************
1057 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1059 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1060 const GUID
* ClassGuid
,
1061 PWSTR ClassDescription
,
1062 DWORD ClassDescriptionSize
,
1063 PDWORD RequiredSize
,
1070 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1075 if (hKey
== INVALID_HANDLE_VALUE
)
1077 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1081 if (RequiredSize
!= NULL
)
1084 if (RegQueryValueExW(hKey
,
1095 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1098 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1099 if (RegQueryValueExW(hKey
,
1103 (LPBYTE
)ClassDescription
,
1115 /***********************************************************************
1116 * SetupDiGetClassDevsA (SETUPAPI.@)
1118 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1124 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1125 flags
, NULL
, NULL
, NULL
);
1128 /***********************************************************************
1129 * SetupDiGetClassDevsW (SETUPAPI.@)
1131 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1137 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1138 flags
, NULL
, NULL
, NULL
);
1141 /***********************************************************************
1142 * SetupDiGetClassDevsExA (SETUPAPI.@)
1144 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1154 LPWSTR enumstrW
= NULL
;
1155 LPWSTR machineW
= NULL
;
1159 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1160 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1163 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1166 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1170 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1171 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1174 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1177 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1179 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1182 HeapFree(GetProcessHeap(), 0, enumstrW
);
1183 HeapFree(GetProcessHeap(), 0, machineW
);
1188 CreateDeviceInfoElement(
1189 IN LPCWSTR InstancePath
,
1191 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1193 struct DeviceInfoElement
*deviceInfo
;
1195 *pDeviceInfo
= NULL
;
1196 if (IsEqualIID(&pClassGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1198 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1201 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1204 wcscpy(deviceInfo
->Data
, InstancePath
);
1205 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1206 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1207 deviceInfo
->DeviceDescription
= NULL
;
1208 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1209 deviceInfo
->CreationFlags
= 0;
1210 deviceInfo
->hwndParent
= NULL
;
1211 deviceInfo
->Flags
= 0; /* FIXME */
1212 deviceInfo
->FlagsEx
= 0; /* FIXME */
1213 deviceInfo
->SelectedDriver
= NULL
;
1214 InitializeListHead(&deviceInfo
->DriverListHead
);
1215 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1217 *pDeviceInfo
= deviceInfo
;
1222 CreateDeviceInterface(
1223 IN
struct DeviceInfoElement
* deviceInfo
,
1224 IN LPCWSTR SymbolicLink
,
1225 IN LPCGUID pInterfaceGuid
,
1226 OUT
struct DeviceInterface
**pDeviceInterface
)
1228 struct DeviceInterface
*deviceInterface
;
1230 *pDeviceInterface
= NULL
;
1232 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1233 if (!deviceInterface
)
1235 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1238 deviceInterface
->DeviceInfo
= deviceInfo
;
1239 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1240 deviceInterface
->Flags
= 0; /* FIXME */
1241 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1243 *pDeviceInterface
= deviceInterface
;
1247 static LONG
SETUP_CreateDevListFromEnumerator(
1248 struct DeviceInfoSet
*list
,
1249 LPCGUID pClassGuid OPTIONAL
,
1251 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1253 HKEY hDeviceIdKey
, hInstanceIdKey
;
1254 WCHAR KeyBuffer
[MAX_PATH
];
1255 WCHAR InstancePath
[MAX_PATH
];
1256 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1257 struct DeviceInfoElement
*deviceInfo
;
1259 DWORD dwLength
, dwRegType
;
1262 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1265 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1266 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1267 if (rc
== ERROR_NO_MORE_ITEMS
)
1269 if (rc
!= ERROR_SUCCESS
)
1273 /* Open device id sub key */
1274 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1275 if (rc
!= ERROR_SUCCESS
)
1277 wcscpy(InstancePath
, Enumerator
);
1278 wcscat(InstancePath
, L
"\\");
1279 wcscat(InstancePath
, KeyBuffer
);
1280 wcscat(InstancePath
, L
"\\");
1281 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1283 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1289 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1290 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1291 if (rc
== ERROR_NO_MORE_ITEMS
)
1293 if (rc
!= ERROR_SUCCESS
)
1295 RegCloseKey(hDeviceIdKey
);
1300 /* Open instance id sub key */
1301 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1302 if (rc
!= ERROR_SUCCESS
)
1304 RegCloseKey(hDeviceIdKey
);
1307 *pEndOfInstancePath
= '\0';
1308 wcscat(InstancePath
, KeyBuffer
);
1310 /* Read ClassGUID value */
1311 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1312 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1313 RegCloseKey(hInstanceIdKey
);
1314 if (rc
== ERROR_FILE_NOT_FOUND
)
1317 /* Skip this bad entry as we can't verify it */
1320 else if (rc
!= ERROR_SUCCESS
)
1322 RegCloseKey(hDeviceIdKey
);
1325 else if (dwRegType
!= REG_SZ
)
1327 RegCloseKey(hDeviceIdKey
);
1328 return ERROR_GEN_FAILURE
;
1331 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1332 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1334 RegCloseKey(hDeviceIdKey
);
1335 return GetLastError();
1337 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1339 /* Skip this entry as it is not the right device class */
1343 /* Add the entry to the list */
1344 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1346 RegCloseKey(hDeviceIdKey
);
1347 return GetLastError();
1349 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1350 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1352 RegCloseKey(hDeviceIdKey
);
1355 return ERROR_SUCCESS
;
1358 static LONG
SETUP_CreateDevList(
1359 struct DeviceInfoSet
*list
,
1360 PCWSTR MachineName OPTIONAL
,
1361 LPGUID
class OPTIONAL
,
1362 PCWSTR Enumerator OPTIONAL
)
1364 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1365 WCHAR KeyBuffer
[MAX_PATH
];
1370 if (IsEqualIID(class, &GUID_NULL
))
1374 if (MachineName
!= NULL
)
1376 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1377 if (rc
!= ERROR_SUCCESS
)
1381 HKLM
= HKEY_LOCAL_MACHINE
;
1383 rc
= RegOpenKeyExW(HKLM
,
1386 KEY_ENUMERATE_SUB_KEYS
,
1388 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1389 if (rc
!= ERROR_SUCCESS
)
1392 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1393 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1402 KEY_ENUMERATE_SUB_KEYS
,
1404 RegCloseKey(hEnumKey
);
1405 if (rc
!= ERROR_SUCCESS
)
1407 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1408 RegCloseKey(hEnumeratorKey
);
1413 /* Enumerate enumerators */
1417 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1418 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1419 if (rc
== ERROR_NO_MORE_ITEMS
)
1421 if (rc
!= ERROR_SUCCESS
)
1423 RegCloseKey(hEnumKey
);
1429 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1430 if (rc
!= ERROR_SUCCESS
)
1432 RegCloseKey(hEnumKey
);
1436 /* Call SETUP_CreateDevListFromEnumerator */
1437 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1438 RegCloseKey(hEnumeratorKey
);
1439 if (rc
!= ERROR_SUCCESS
)
1441 RegCloseKey(hEnumKey
);
1445 RegCloseKey(hEnumKey
);
1446 return ERROR_SUCCESS
;
1451 static LONG
SETUP_CreateSerialDeviceList(
1452 struct DeviceInfoSet
*list
,
1454 LPGUID InterfaceGuid
,
1455 PCWSTR DeviceInstanceW
)
1457 static const size_t initialSize
= 100;
1459 WCHAR buf
[initialSize
];
1461 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1463 struct DeviceInfoElement
*deviceInfo
;
1466 WARN("'MachineName' is ignored on Wine!\n");
1467 if (DeviceInstanceW
)
1468 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1474 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1476 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1480 HeapFree(GetProcessHeap(), 0, devices
);
1481 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1483 return ERROR_NOT_ENOUGH_MEMORY
;
1489 HeapFree(GetProcessHeap(), 0, devices
);
1490 return GetLastError();
1494 /* 'devices' is a MULTI_SZ string */
1495 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1497 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1499 /* We have found a device */
1500 struct DeviceInterface
*interfaceInfo
;
1501 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1502 /* Step 1. Create a device info element */
1503 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1506 HeapFree(GetProcessHeap(), 0, devices
);
1507 return GetLastError();
1509 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1511 /* Step 2. Create an interface list for this element */
1512 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1515 HeapFree(GetProcessHeap(), 0, devices
);
1516 return GetLastError();
1518 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1522 HeapFree(GetProcessHeap(), 0, devices
);
1523 return ERROR_SUCCESS
;
1526 #else /* __REACTOS__ */
1528 static LONG
SETUP_CreateInterfaceList(
1529 struct DeviceInfoSet
*list
,
1531 LPGUID InterfaceGuid
,
1532 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1534 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1535 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1536 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1537 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1538 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1540 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1543 DWORD dwLength
, dwInstancePathLength
;
1546 struct DeviceInfoElement
*deviceInfo
;
1548 /* Open registry key related to this interface */
1549 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1550 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1551 return GetLastError();
1553 /* Enumerate sub keys of hInterfaceKey */
1557 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1558 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1559 if (rc
== ERROR_NO_MORE_ITEMS
)
1561 if (rc
!= ERROR_SUCCESS
)
1563 RegCloseKey(hInterfaceKey
);
1569 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1570 if (rc
!= ERROR_SUCCESS
)
1572 RegCloseKey(hInterfaceKey
);
1576 /* Read DeviceInstance */
1577 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1578 if (rc
!= ERROR_SUCCESS
)
1580 RegCloseKey(hDeviceInstanceKey
);
1581 RegCloseKey(hInterfaceKey
);
1584 if (dwRegType
!= REG_SZ
)
1586 RegCloseKey(hDeviceInstanceKey
);
1587 RegCloseKey(hInterfaceKey
);
1588 return ERROR_GEN_FAILURE
;
1590 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1593 RegCloseKey(hDeviceInstanceKey
);
1594 RegCloseKey(hInterfaceKey
);
1595 return ERROR_NOT_ENOUGH_MEMORY
;
1597 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1598 if (rc
!= ERROR_SUCCESS
)
1600 HeapFree(GetProcessHeap(), 0, InstancePath
);
1601 RegCloseKey(hDeviceInstanceKey
);
1602 RegCloseKey(hInterfaceKey
);
1605 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1606 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1608 if (DeviceInstanceW
)
1610 /* Check if device enumerator is not the right one */
1611 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1613 HeapFree(GetProcessHeap(), 0, InstancePath
);
1614 RegCloseKey(hDeviceInstanceKey
);
1619 /* Find class GUID associated to the device instance */
1624 KEY_ENUMERATE_SUB_KEYS
,
1626 if (rc
!= ERROR_SUCCESS
)
1628 HeapFree(GetProcessHeap(), 0, InstancePath
);
1629 RegCloseKey(hDeviceInstanceKey
);
1630 RegCloseKey(hInterfaceKey
);
1639 RegCloseKey(hEnumKey
);
1640 if (rc
!= ERROR_SUCCESS
)
1642 HeapFree(GetProcessHeap(), 0, InstancePath
);
1643 RegCloseKey(hDeviceInstanceKey
);
1644 RegCloseKey(hInterfaceKey
);
1647 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1648 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1650 if (rc
!= ERROR_SUCCESS
)
1652 HeapFree(GetProcessHeap(), 0, InstancePath
);
1653 RegCloseKey(hDeviceInstanceKey
);
1654 RegCloseKey(hInterfaceKey
);
1657 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1658 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1659 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1661 HeapFree(GetProcessHeap(), 0, InstancePath
);
1662 RegCloseKey(hDeviceInstanceKey
);
1663 RegCloseKey(hInterfaceKey
);
1664 return ERROR_GEN_FAILURE
;
1666 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1668 /* If current device doesn't match the list GUID (if any), skip this entry */
1669 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1671 HeapFree(GetProcessHeap(), 0, InstancePath
);
1672 RegCloseKey(hDeviceInstanceKey
);
1676 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1680 LPWSTR pSymbolicLink
;
1681 struct DeviceInterface
*interfaceInfo
;
1683 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1684 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1685 if (rc
== ERROR_NO_MORE_ITEMS
)
1687 if (rc
!= ERROR_SUCCESS
)
1689 HeapFree(GetProcessHeap(), 0, InstancePath
);
1690 RegCloseKey(hDeviceInstanceKey
);
1691 RegCloseKey(hInterfaceKey
);
1695 if (KeyBuffer
[0] != '#')
1696 /* This entry doesn't represent an interesting entry */
1700 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1701 if (rc
!= ERROR_SUCCESS
)
1703 RegCloseKey(hDeviceInstanceKey
);
1704 RegCloseKey(hInterfaceKey
);
1708 /* Read SymbolicLink value */
1709 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1710 if (rc
!= ERROR_SUCCESS
)
1712 RegCloseKey(hReferenceKey
);
1713 RegCloseKey(hDeviceInstanceKey
);
1714 RegCloseKey(hInterfaceKey
);
1717 if (dwRegType
!= REG_SZ
)
1719 RegCloseKey(hReferenceKey
);
1720 RegCloseKey(hDeviceInstanceKey
);
1721 RegCloseKey(hInterfaceKey
);
1722 return ERROR_GEN_FAILURE
;
1725 /* We have found a device */
1726 /* Step 1. Create a device info element */
1727 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1729 RegCloseKey(hReferenceKey
);
1730 RegCloseKey(hDeviceInstanceKey
);
1731 RegCloseKey(hInterfaceKey
);
1732 return GetLastError();
1734 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1735 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1737 /* Step 2. Create an interface list for this element */
1738 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1741 RegCloseKey(hReferenceKey
);
1742 RegCloseKey(hDeviceInstanceKey
);
1743 RegCloseKey(hInterfaceKey
);
1744 return ERROR_NOT_ENOUGH_MEMORY
;
1746 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1747 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1748 RegCloseKey(hReferenceKey
);
1749 if (rc
!= ERROR_SUCCESS
)
1751 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1752 RegCloseKey(hDeviceInstanceKey
);
1753 RegCloseKey(hInterfaceKey
);
1756 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1758 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1759 RegCloseKey(hDeviceInstanceKey
);
1760 RegCloseKey(hInterfaceKey
);
1761 return GetLastError();
1763 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1764 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1765 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1767 RegCloseKey(hDeviceInstanceKey
);
1769 RegCloseKey(hInterfaceKey
);
1770 return ERROR_SUCCESS
;
1772 #endif /* __REACTOS__ */
1774 /***********************************************************************
1775 * SetupDiGetClassDevsExW (SETUPAPI.@)
1777 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1786 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1787 struct DeviceInfoSet
*list
;
1791 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1792 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1794 /* Create the deviceset if not set */
1797 list
= (struct DeviceInfoSet
*)deviceset
;
1798 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1800 SetLastError(ERROR_INVALID_HANDLE
);
1801 return INVALID_HANDLE_VALUE
;
1803 hDeviceInfo
= deviceset
;
1807 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1808 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1809 NULL
, machine
, NULL
);
1810 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1811 return INVALID_HANDLE_VALUE
;
1812 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1815 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1818 pClassGuid
= &list
->ClassGuid
;
1820 if (flags
& DIGCF_PRESENT
)
1821 FIXME(": flag DIGCF_PRESENT ignored\n");
1822 if (flags
& DIGCF_PROFILE
)
1823 FIXME(": flag DIGCF_PROFILE ignored\n");
1825 if (flags
& DIGCF_ALLCLASSES
)
1827 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1828 if (rc
!= ERROR_SUCCESS
)
1832 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1833 return INVALID_HANDLE_VALUE
;
1837 else if (flags
& DIGCF_DEVICEINTERFACE
)
1841 SetLastError(ERROR_INVALID_PARAMETER
);
1843 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1844 return INVALID_HANDLE_VALUE
;
1848 /* Special case: find serial ports by calling QueryDosDevice */
1849 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1850 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1851 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1852 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1855 ERR("Wine can only enumerate serial devices at the moment!\n");
1856 rc
= ERROR_INVALID_PARAMETER
;
1858 #else /* __REACTOS__ */
1859 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1860 #endif /* __REACTOS__ */
1861 if (rc
!= ERROR_SUCCESS
)
1865 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1866 return INVALID_HANDLE_VALUE
;
1872 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1873 if (rc
!= ERROR_SUCCESS
)
1877 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1878 return INVALID_HANDLE_VALUE
;
1884 /***********************************************************************
1885 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1887 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1888 HDEVINFO DeviceInfoSet
,
1889 PSP_DEVINFO_DATA DeviceInfoData
,
1890 CONST GUID
* InterfaceClassGuid
,
1892 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1896 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1897 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1899 if (!DeviceInterfaceData
)
1900 SetLastError(ERROR_INVALID_PARAMETER
);
1901 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1902 SetLastError(ERROR_INVALID_USER_BUFFER
);
1903 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1905 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1907 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1909 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1911 while (ItemList
!= &list
->ListHead
&& !Found
)
1913 PLIST_ENTRY InterfaceListEntry
;
1914 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1915 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1917 /* We are not searching for this element */
1918 ItemList
= ItemList
->Flink
;
1921 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1922 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1924 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1925 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1927 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1930 if (MemberIndex
-- == 0)
1932 /* return this item */
1933 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1934 &DevItf
->InterfaceClassGuid
,
1936 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1937 /* Note: this appears to be dangerous, passing a private
1938 * pointer a heap-allocated datum to the caller. However, the
1939 * expected lifetime of the device data is the same as the
1940 * HDEVINFO; once that is closed, the data are no longer valid.
1942 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1945 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1947 ItemList
= ItemList
->Flink
;
1950 SetLastError(ERROR_NO_MORE_ITEMS
);
1955 SetLastError(ERROR_INVALID_HANDLE
);
1958 SetLastError(ERROR_INVALID_HANDLE
);
1962 /***********************************************************************
1963 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1965 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1969 TRACE("%p\n", devinfo
);
1970 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1972 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1974 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1976 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1977 struct DeviceInfoElement
*deviceInfo
;
1978 while (!IsListEmpty(&list
->ListHead
))
1980 ListEntry
= RemoveHeadList(&list
->ListHead
);
1981 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1982 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1984 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1985 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1987 HeapFree(GetProcessHeap(), 0, ListEntry
);
1989 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1990 RegCloseKey(list
->HKLM
);
1991 HeapFree(GetProcessHeap(), 0, list
);
1995 SetLastError(ERROR_INVALID_HANDLE
);
1998 SetLastError(ERROR_INVALID_HANDLE
);
2000 TRACE("Returning %d\n", ret
);
2004 /***********************************************************************
2005 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2007 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2008 HDEVINFO DeviceInfoSet
,
2009 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2010 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2011 DWORD DeviceInterfaceDetailDataSize
,
2012 PDWORD RequiredSize
,
2013 PSP_DEVINFO_DATA DeviceInfoData
)
2015 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2016 DWORD sizeW
= 0, sizeA
;
2019 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2020 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2021 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2023 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2024 SetLastError(ERROR_INVALID_USER_BUFFER
);
2025 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2026 SetLastError(ERROR_INVALID_PARAMETER
);
2027 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2028 SetLastError(ERROR_INVALID_PARAMETER
);
2031 if (DeviceInterfaceDetailData
!= NULL
)
2033 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2034 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2035 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2036 if (!DeviceInterfaceDetailDataW
)
2038 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2041 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2043 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2044 ret
= SetupDiGetDeviceInterfaceDetailW(
2046 DeviceInterfaceData
,
2047 DeviceInterfaceDetailDataW
,
2051 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2052 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2054 *RequiredSize
= sizeA
;
2055 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2057 if (!WideCharToMultiByte(
2059 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2060 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2067 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2070 TRACE("Returning %d\n", ret
);
2074 /***********************************************************************
2075 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2077 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2078 HDEVINFO DeviceInfoSet
,
2079 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2080 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2081 DWORD DeviceInterfaceDetailDataSize
,
2082 PDWORD RequiredSize
,
2083 PSP_DEVINFO_DATA DeviceInfoData
)
2087 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2088 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2089 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2091 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2092 SetLastError(ERROR_INVALID_PARAMETER
);
2093 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2094 SetLastError(ERROR_INVALID_HANDLE
);
2095 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2096 SetLastError(ERROR_INVALID_HANDLE
);
2097 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2098 SetLastError(ERROR_INVALID_USER_BUFFER
);
2099 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2100 SetLastError(ERROR_INVALID_USER_BUFFER
);
2101 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2102 SetLastError(ERROR_INVALID_USER_BUFFER
);
2103 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2104 SetLastError(ERROR_INVALID_PARAMETER
);
2105 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2106 SetLastError(ERROR_INVALID_PARAMETER
);
2109 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2110 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2111 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2112 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2114 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2116 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2118 *RequiredSize
= sizeRequired
;
2122 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2123 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2126 memcpy(&DeviceInfoData
->ClassGuid
,
2127 &deviceInterface
->DeviceInfo
->ClassGuid
,
2129 DeviceInfoData
->DevInst
= 0; /* FIXME */
2130 /* Note: this appears to be dangerous, passing a private
2131 * pointer a heap-allocated datum to the caller. However, the
2132 * expected lifetime of the device data is the same as the
2133 * HDEVINFO; once that is closed, the data are no longer valid.
2135 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2141 TRACE("Returning %d\n", ret
);
2145 /***********************************************************************
2146 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2148 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2150 PSP_DEVINFO_DATA DeviceInfoData
,
2152 PDWORD PropertyRegDataType
,
2153 PBYTE PropertyBuffer
,
2154 DWORD PropertyBufferSize
,
2155 PDWORD RequiredSize
)
2158 BOOL bIsStringProperty
;
2160 DWORD RequiredSizeA
, RequiredSizeW
;
2161 DWORD PropertyBufferSizeW
;
2162 PBYTE PropertyBufferW
;
2164 TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
2165 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2168 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2169 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2171 bResult
= SetupDiGetDeviceRegistryPropertyW(
2177 PropertyBufferSizeW
,
2182 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2186 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2188 if (bIsStringProperty
)
2189 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2191 RequiredSizeA
= RequiredSizeW
;
2193 if (RequiredSizeA
<= PropertyBufferSize
)
2195 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2197 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2199 /* Last error is already set by WideCharToMultiByte */
2204 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2208 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2212 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2213 if (PropertyRegDataType
)
2214 *PropertyRegDataType
= RegType
;
2216 *RequiredSize
= RequiredSizeA
;
2220 /***********************************************************************
2221 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2223 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2224 HDEVINFO DeviceInfoSet
,
2225 PSP_DEVINFO_DATA DeviceInfoData
,
2227 PDWORD PropertyRegDataType
,
2228 PBYTE PropertyBuffer
,
2229 DWORD PropertyBufferSize
,
2230 PDWORD RequiredSize
)
2232 HKEY hEnumKey
, hKey
;
2236 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2237 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2240 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2241 SetLastError(ERROR_INVALID_HANDLE
);
2242 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2243 SetLastError(ERROR_INVALID_HANDLE
);
2244 else if (!DeviceInfoData
)
2245 SetLastError(ERROR_INVALID_PARAMETER
);
2246 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2247 SetLastError(ERROR_INVALID_USER_BUFFER
);
2248 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2249 SetLastError(ERROR_INVALID_PARAMETER
);
2252 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2253 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2257 case SPDRP_CAPABILITIES
:
2259 case SPDRP_CLASSGUID
:
2260 case SPDRP_COMPATIBLEIDS
:
2261 case SPDRP_CONFIGFLAGS
:
2262 case SPDRP_DEVICEDESC
:
2264 case SPDRP_FRIENDLYNAME
:
2265 case SPDRP_HARDWAREID
:
2266 case SPDRP_LOCATION_INFORMATION
:
2267 case SPDRP_LOWERFILTERS
:
2269 case SPDRP_SECURITY
:
2271 case SPDRP_UI_NUMBER
:
2272 case SPDRP_UPPERFILTERS
:
2274 LPCWSTR RegistryPropertyName
;
2279 case SPDRP_CAPABILITIES
:
2280 RegistryPropertyName
= L
"Capabilities"; break;
2282 RegistryPropertyName
= L
"Class"; break;
2283 case SPDRP_CLASSGUID
:
2284 RegistryPropertyName
= L
"ClassGUID"; break;
2285 case SPDRP_COMPATIBLEIDS
:
2286 RegistryPropertyName
= L
"CompatibleIDs"; break;
2287 case SPDRP_CONFIGFLAGS
:
2288 RegistryPropertyName
= L
"ConfigFlags"; break;
2289 case SPDRP_DEVICEDESC
:
2290 RegistryPropertyName
= L
"DeviceDesc"; break;
2292 RegistryPropertyName
= L
"Driver"; break;
2293 case SPDRP_FRIENDLYNAME
:
2294 RegistryPropertyName
= L
"FriendlyName"; break;
2295 case SPDRP_HARDWAREID
:
2296 RegistryPropertyName
= L
"HardwareID"; break;
2297 case SPDRP_LOCATION_INFORMATION
:
2298 RegistryPropertyName
= L
"LocationInformation"; break;
2299 case SPDRP_LOWERFILTERS
:
2300 RegistryPropertyName
= L
"LowerFilters"; break;
2302 RegistryPropertyName
= L
"Mfg"; break;
2303 case SPDRP_SECURITY
:
2304 RegistryPropertyName
= L
"Security"; break;
2306 RegistryPropertyName
= L
"Service"; break;
2307 case SPDRP_UI_NUMBER
:
2308 RegistryPropertyName
= L
"UINumber"; break;
2309 case SPDRP_UPPERFILTERS
:
2310 RegistryPropertyName
= L
"UpperFilters"; break;
2312 /* Should not happen */
2313 RegistryPropertyName
= NULL
; break;
2316 /* Open registry key name */
2321 KEY_ENUMERATE_SUB_KEYS
,
2323 if (rc
!= ERROR_SUCCESS
)
2334 RegCloseKey(hEnumKey
);
2335 if (rc
!= ERROR_SUCCESS
)
2340 /* Read registry entry */
2341 BufferSize
= PropertyBufferSize
;
2342 rc
= RegQueryValueExW(
2344 RegistryPropertyName
,
2345 NULL
, /* Reserved */
2346 PropertyRegDataType
,
2350 *RequiredSize
= BufferSize
;
2351 if (rc
== ERROR_SUCCESS
)
2359 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2361 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2363 if (PropertyRegDataType
)
2364 *PropertyRegDataType
= REG_SZ
;
2366 *RequiredSize
= required
;
2367 if (PropertyBufferSize
>= required
)
2369 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2373 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2377 /*case SPDRP_BUSTYPEGUID:
2378 case SPDRP_LEGACYBUSTYPE:
2379 case SPDRP_BUSNUMBER:
2380 case SPDRP_ENUMERATOR_NAME:
2381 case SPDRP_SECURITY_SDS:
2383 case SPDRP_EXCLUSIVE:
2384 case SPDRP_CHARACTERISTICS:
2386 case SPDRP_UI_NUMBER_DESC_FORMAT:
2387 case SPDRP_DEVICE_POWER_DATA:*/
2388 #if (WINVER >= 0x501)
2389 /*case SPDRP_REMOVAL_POLICY:
2390 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2391 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2392 case SPDRP_INSTALL_STATE:*/
2397 FIXME("Property 0x%lx not implemented\n", Property
);
2398 SetLastError(ERROR_NOT_SUPPORTED
);
2403 TRACE("Returning %d\n", ret
);
2408 /***********************************************************************
2409 * SetupDiInstallClassA (SETUPAPI.@)
2411 BOOL WINAPI
SetupDiInstallClassA(
2417 UNICODE_STRING FileNameW
;
2420 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2422 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2426 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2428 RtlFreeUnicodeString(&FileNameW
);
2433 static HKEY
CreateClassKey(HINF hInf
)
2435 WCHAR FullBuffer
[MAX_PATH
];
2436 WCHAR Buffer
[MAX_PATH
];
2441 if (!SetupGetLineTextW(NULL
,
2449 return INVALID_HANDLE_VALUE
;
2452 lstrcpyW(FullBuffer
, ControlClass
);
2453 lstrcatW(FullBuffer
, Buffer
);
2456 if (!SetupGetLineTextW(NULL
,
2464 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2465 return INVALID_HANDLE_VALUE
;
2468 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2472 REG_OPTION_NON_VOLATILE
,
2478 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2479 return INVALID_HANDLE_VALUE
;
2482 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2487 RequiredSize
* sizeof(WCHAR
)))
2489 RegCloseKey(hClassKey
);
2490 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2491 return INVALID_HANDLE_VALUE
;
2497 /***********************************************************************
2498 * SetupDiInstallClassW (SETUPAPI.@)
2500 BOOL WINAPI
SetupDiInstallClassW(
2506 WCHAR SectionName
[MAX_PATH
];
2507 DWORD SectionNameLength
= 0;
2509 BOOL bFileQueueCreated
= FALSE
;
2512 FIXME("not fully implemented\n");
2514 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2516 SetLastError(ERROR_INVALID_PARAMETER
);
2520 /* Open the .inf file */
2521 hInf
= SetupOpenInfFileW(InfFileName
,
2525 if (hInf
== INVALID_HANDLE_VALUE
)
2531 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2532 hClassKey
= CreateClassKey(hInf
);
2533 if (hClassKey
== INVALID_HANDLE_VALUE
)
2535 SetupCloseInfFile(hInf
);
2541 /* Try to append a layout file */
2543 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2546 /* Retrieve the actual section name */
2547 SetupDiGetActualSectionToInstallW(hInf
,
2555 if (!(Flags
& DI_NOVCP
))
2557 FileQueue
= SetupOpenFileQueue();
2558 if (FileQueue
== INVALID_HANDLE_VALUE
)
2560 SetupCloseInfFile(hInf
);
2561 RegCloseKey(hClassKey
);
2565 bFileQueueCreated
= TRUE
;
2570 SetupInstallFromInfSectionW(NULL
,
2579 INVALID_HANDLE_VALUE
,
2582 /* FIXME: More code! */
2584 if (bFileQueueCreated
)
2585 SetupCloseFileQueue(FileQueue
);
2587 SetupCloseInfFile(hInf
);
2589 RegCloseKey(hClassKey
);
2594 /***********************************************************************
2595 * SetupDiOpenClassRegKey (SETUPAPI.@)
2597 HKEY WINAPI
SetupDiOpenClassRegKey(
2598 const GUID
* ClassGuid
,
2601 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2602 DIOCR_INSTALLER
, NULL
, NULL
);
2606 /***********************************************************************
2607 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2609 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2610 const GUID
* ClassGuid
,
2616 PWSTR MachineNameW
= NULL
;
2623 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2624 if (MachineNameW
== NULL
)
2625 return INVALID_HANDLE_VALUE
;
2628 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2629 Flags
, MachineNameW
, Reserved
);
2632 MyFree(MachineNameW
);
2638 /***********************************************************************
2639 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2641 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2642 const GUID
* ClassGuid
,
2648 LPWSTR lpGuidString
;
2649 LPWSTR lpFullGuidString
;
2657 if (Flags
== DIOCR_INSTALLER
)
2659 lpKeyName
= ControlClass
;
2661 else if (Flags
== DIOCR_INTERFACE
)
2663 lpKeyName
= DeviceClasses
;
2667 ERR("Invalid Flags parameter!\n");
2668 SetLastError(ERROR_INVALID_PARAMETER
);
2669 return INVALID_HANDLE_VALUE
;
2672 if (MachineName
!= NULL
)
2674 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2675 if (rc
!= ERROR_SUCCESS
)
2678 return INVALID_HANDLE_VALUE
;
2682 HKLM
= HKEY_LOCAL_MACHINE
;
2684 rc
= RegOpenKeyExW(HKLM
,
2689 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2690 if (rc
!= ERROR_SUCCESS
)
2693 return INVALID_HANDLE_VALUE
;
2696 if (ClassGuid
== NULL
)
2699 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2701 SetLastError(ERROR_GEN_FAILURE
);
2702 RegCloseKey(hClassesKey
);
2703 return INVALID_HANDLE_VALUE
;
2706 dwLength
= lstrlenW(lpGuidString
);
2707 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2708 if (!lpFullGuidString
)
2710 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2711 RpcStringFreeW(&lpGuidString
);
2712 return INVALID_HANDLE_VALUE
;
2714 lpFullGuidString
[0] = '{';
2715 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2716 lpFullGuidString
[dwLength
+ 1] = '}';
2717 lpFullGuidString
[dwLength
+ 2] = '\0';
2718 RpcStringFreeW(&lpGuidString
);
2720 rc
= RegOpenKeyExW(hClassesKey
,
2725 if (rc
!= ERROR_SUCCESS
)
2728 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2729 RegCloseKey(hClassesKey
);
2730 return INVALID_HANDLE_VALUE
;
2733 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2734 RegCloseKey(hClassesKey
);
2739 /***********************************************************************
2740 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2742 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2743 HDEVINFO DeviceInfoSet
,
2746 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2748 FIXME("%p %s %08lx %p\n",
2749 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2753 /***********************************************************************
2754 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2756 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2757 HDEVINFO DeviceInfoSet
,
2760 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2762 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
2763 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2767 /***********************************************************************
2768 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2770 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2771 HDEVINFO DeviceInfoSet
,
2772 PSP_DEVINFO_DATA DeviceInfoData
,
2773 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2774 DWORD ClassInstallParamsSize
)
2776 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2777 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2781 /***********************************************************************
2782 * SetupDiCallClassInstaller (SETUPAPI.@)
2784 BOOL WINAPI
SetupDiCallClassInstaller(
2785 IN DI_FUNCTION InstallFunction
,
2786 IN HDEVINFO DeviceInfoSet
,
2787 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2791 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2794 SetLastError(ERROR_INVALID_PARAMETER
);
2795 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2796 SetLastError(ERROR_INVALID_HANDLE
);
2797 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2798 SetLastError(ERROR_INVALID_HANDLE
);
2799 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2800 SetLastError(ERROR_INVALID_HANDLE
);
2801 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2802 SetLastError(ERROR_INVALID_USER_BUFFER
);
2805 #define CLASS_COINSTALLER 0x1
2806 #define DEVICE_COINSTALLER 0x2
2807 #define CLASS_INSTALLER 0x4
2808 UCHAR CanHandle
= 0;
2809 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2811 switch (InstallFunction
)
2813 case DIF_ALLOW_INSTALL
:
2814 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2816 case DIF_DESTROYPRIVATEDATA
:
2817 CanHandle
= CLASS_INSTALLER
;
2819 case DIF_INSTALLDEVICE
:
2820 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2821 DefaultHandler
= SetupDiInstallDevice
;
2823 case DIF_INSTALLDEVICEFILES
:
2824 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2825 DefaultHandler
= SetupDiInstallDriverFiles
;
2827 case DIF_INSTALLINTERFACES
:
2828 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2829 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2831 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2832 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2834 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2835 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2837 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2838 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2840 case DIF_REGISTER_COINSTALLERS
:
2841 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2842 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2844 case DIF_SELECTBESTCOMPATDRV
:
2845 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2846 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2849 FIXME("Install function %ld not implemented\n", InstallFunction
);
2850 SetLastError(ERROR_INVALID_PARAMETER
);
2855 LIST_ENTRY ClassCoInstallersListHead
;
2856 LIST_ENTRY DeviceCoInstallersListHead
;
2857 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2858 COINSTALLER_CONTEXT_DATA Context
;
2859 PLIST_ENTRY ListEntry
;
2861 DWORD dwRegType
, dwLength
;
2862 DWORD rc
= NO_ERROR
;
2864 InitializeListHead(&ClassCoInstallersListHead
);
2865 InitializeListHead(&DeviceCoInstallersListHead
);
2867 if (CanHandle
& CLASS_COINSTALLER
)
2869 FIXME("Doesn't use Class co-installers at the moment\n");
2871 if (CanHandle
& DEVICE_COINSTALLER
)
2875 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2879 if (rc
== ERROR_SUCCESS
)
2881 LPWSTR lpGuidString
;
2882 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2884 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2885 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2887 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2888 if (KeyBuffer
!= NULL
)
2890 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2891 if (rc
== ERROR_SUCCESS
)
2894 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2896 /* Add coinstaller to DeviceCoInstallersListHead list */
2897 FIXME("Device coinstaller is '%S'\n", ptr
);
2900 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2903 RpcStringFreeW(&lpGuidString
);
2908 if (CanHandle
& CLASS_INSTALLER
)
2910 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2911 if (hKey
!= INVALID_HANDLE_VALUE
)
2913 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2914 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2916 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2917 if (KeyBuffer
!= NULL
)
2919 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2920 if (rc
== ERROR_SUCCESS
)
2922 /* Set ClassInstaller function pointer */
2923 FIXME("Installer is '%S'\n", KeyBuffer
);
2925 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2932 /* Call Class co-installers */
2933 Context
.PostProcessing
= FALSE
;
2935 ListEntry
= ClassCoInstallersListHead
.Flink
;
2936 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
2938 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2939 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2940 coinstaller
->PrivateData
= Context
.PrivateData
;
2941 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2943 coinstaller
->DoPostProcessing
= TRUE
;
2946 ListEntry
= ListEntry
->Flink
;
2949 /* Call Device co-installers */
2950 ListEntry
= DeviceCoInstallersListHead
.Flink
;
2951 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
2953 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2954 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2955 coinstaller
->PrivateData
= Context
.PrivateData
;
2956 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2958 coinstaller
->DoPostProcessing
= TRUE
;
2961 ListEntry
= ListEntry
->Flink
;
2964 /* Call Class installer */
2966 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2968 rc
= ERROR_DI_DO_DEFAULT
;
2970 /* Call default handler */
2971 if (rc
== ERROR_DI_DO_DEFAULT
)
2973 if (DefaultHandler
/*FIXME && DI_NODI_DEFAULTACTION not set */)
2975 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
2978 rc
= GetLastError();
2984 /* Call Class co-installers that required postprocessing */
2985 Context
.PostProcessing
= TRUE
;
2986 ListEntry
= ClassCoInstallersListHead
.Flink
;
2987 while (ListEntry
!= &ClassCoInstallersListHead
)
2989 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2990 if (coinstaller
->DoPostProcessing
)
2992 Context
.InstallResult
= rc
;
2993 Context
.PrivateData
= coinstaller
->PrivateData
;
2994 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2996 ListEntry
= ListEntry
->Flink
;
2999 /* Call Device co-installers that required postprocessing */
3000 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3001 while (ListEntry
!= &DeviceCoInstallersListHead
)
3003 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3004 if (coinstaller
->DoPostProcessing
)
3006 Context
.InstallResult
= rc
;
3007 Context
.PrivateData
= coinstaller
->PrivateData
;
3008 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3010 ListEntry
= ListEntry
->Flink
;
3013 /* Free allocated memory */
3014 while (!IsListEmpty(&ClassCoInstallersListHead
))
3016 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3017 HeapFree(GetProcessHeap(), 0, ListEntry
);
3019 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3021 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3022 HeapFree(GetProcessHeap(), 0, ListEntry
);
3025 ret
= (rc
== NO_ERROR
);
3029 TRACE("Returning %d\n", ret
);
3033 /***********************************************************************
3034 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3036 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3037 IN HDEVINFO DeviceInfoSet
,
3038 IN PSP_DEVINFO_DATA DeviceInfoData
,
3039 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3041 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3044 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3046 if (DeviceInstallParams
== NULL
)
3047 SetLastError(ERROR_INVALID_PARAMETER
);
3048 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3049 SetLastError(ERROR_INVALID_USER_BUFFER
);
3052 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3053 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3057 /* Do W->A conversion */
3059 DeviceInstallParams
,
3060 &deviceInstallParamsW
,
3061 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3062 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3063 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3065 DeviceInstallParams
->DriverPath
[0] = '\0';
3071 TRACE("Returning %d\n", ret
);
3075 /***********************************************************************
3076 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3078 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3079 IN HDEVINFO DeviceInfoSet
,
3080 IN PSP_DEVINFO_DATA DeviceInfoData
,
3081 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3083 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3087 /***********************************************************************
3088 * SetupDiOpenDevRegKey (SETUPAPI.@)
3090 HKEY WINAPI
SetupDiOpenDevRegKey(
3091 HDEVINFO DeviceInfoSet
,
3092 PSP_DEVINFO_DATA DeviceInfoData
,
3098 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
3099 Scope
, HwProfile
, KeyType
, samDesired
);
3100 return INVALID_HANDLE_VALUE
;
3103 /***********************************************************************
3104 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3106 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3107 HDEVINFO DeviceInfoSet
,
3109 CONST GUID
*ClassGuid
,
3110 PCSTR DeviceDescription
,
3112 DWORD CreationFlags
,
3113 PSP_DEVINFO_DATA DeviceInfoData
)
3115 LPWSTR DeviceNameW
= NULL
;
3116 LPWSTR DeviceDescriptionW
= NULL
;
3123 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3124 if (DeviceNameW
== NULL
) return FALSE
;
3126 if (DeviceDescription
)
3128 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3129 if (DeviceDescriptionW
== NULL
)
3131 if (DeviceNameW
) MyFree(DeviceNameW
);
3136 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3137 ClassGuid
, DeviceDescriptionW
,
3138 hwndParent
, CreationFlags
,
3141 if (DeviceNameW
) MyFree(DeviceNameW
);
3142 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3147 /***********************************************************************
3148 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3150 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3151 HDEVINFO DeviceInfoSet
,
3153 CONST GUID
*ClassGuid
,
3154 PCWSTR DeviceDescription
,
3156 DWORD CreationFlags
,
3157 PSP_DEVINFO_DATA DeviceInfoData
)
3159 struct DeviceInfoSet
*list
;
3162 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3163 debugstr_guid(ClassGuid
), DeviceDescription
,
3164 hwndParent
, CreationFlags
, DeviceInfoData
);
3167 SetLastError(ERROR_INVALID_HANDLE
);
3168 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3169 SetLastError(ERROR_INVALID_HANDLE
);
3170 else if (!ClassGuid
)
3171 SetLastError(ERROR_INVALID_PARAMETER
);
3172 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3173 SetLastError(ERROR_CLASS_MISMATCH
);
3174 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3176 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3177 SetLastError(ERROR_INVALID_PARAMETER
);
3181 SP_DEVINFO_DATA DevInfo
;
3183 if (CreationFlags
& DICD_GENERATE_ID
)
3185 /* Generate a new unique ID for this device */
3186 SetLastError(ERROR_GEN_FAILURE
);
3187 FIXME("not implemented\n");
3191 /* Device name is fully qualified. Try to open it */
3194 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3195 rc
= SetupDiOpenDeviceInfoW(
3198 NULL
, /* hwndParent */
3199 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3204 /* SetupDiOpenDeviceInfoW has already added
3205 * the device info to the device info set
3207 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3209 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3211 struct DeviceInfoElement
*deviceInfo
;
3213 /* FIXME: ClassGuid can be NULL */
3214 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3216 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3218 if (!DeviceInfoData
)
3222 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3224 SetLastError(ERROR_INVALID_USER_BUFFER
);
3228 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3229 DeviceInfoData
->DevInst
= 0; /* FIXME */
3230 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3239 TRACE("Returning %d\n", ret
);
3243 /***********************************************************************
3244 * Helper functions for SetupDiBuildDriverInfoList
3248 IN PLIST_ENTRY DriverListHead
,
3249 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3250 IN INFCONTEXT ContextDevice
,
3252 IN LPCWSTR ProviderName
,
3253 IN LPCWSTR ManufacturerName
,
3254 FILETIME DriverDate
,
3255 DWORDLONG DriverVersion
,
3258 struct DriverInfoElement
*driverInfo
;
3259 DWORD RequiredSize
= 128; /* Initial buffer size */
3260 BOOL Result
= FALSE
;
3261 LPWSTR DeviceDescription
= NULL
;
3262 LPWSTR InfInstallSection
= NULL
;
3264 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3267 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3271 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3272 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3274 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3275 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3276 if (!DeviceDescription
)
3278 Result
= SetupGetStringFieldW(
3280 0, /* Field index */
3281 DeviceDescription
, RequiredSize
,
3286 HeapFree(GetProcessHeap(), 0, driverInfo
);
3287 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3292 RequiredSize
= 128; /* Initial buffer size */
3293 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3294 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3296 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3297 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3298 if (!InfInstallSection
)
3300 HeapFree(GetProcessHeap(), 0, driverInfo
);
3301 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3304 Result
= SetupGetStringFieldW(
3306 1, /* Field index */
3307 InfInstallSection
, RequiredSize
,
3312 HeapFree(GetProcessHeap(), 0, driverInfo
);
3313 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3314 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3318 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3319 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3321 driverInfo
->Info
.DriverType
= DriverType
;
3322 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3323 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3324 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3325 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3326 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3329 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3330 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3333 driverInfo
->Info
.ProviderName
[0] = '\0';
3334 driverInfo
->Info
.DriverDate
= DriverDate
;
3335 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3336 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3338 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3339 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3344 GetVersionInformationFromInfFile(
3346 OUT LPGUID ClassGuid
,
3347 OUT LPWSTR
* pProviderName
,
3348 OUT FILETIME
* DriverDate
,
3349 OUT DWORDLONG
* DriverVersion
)
3352 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3353 LPWSTR ProviderName
= NULL
;
3356 if (!SetupGetLineTextW(
3359 L
"Version", L
"ClassGUID",
3360 guidW
, sizeof(guidW
),
3361 NULL
/* Required size */))
3366 /* Get Provider name, driver date, and driver version */
3368 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3369 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3373 Result
= SetupGetLineTextW(
3375 hInf
, L
"Version", L
"Provider",
3378 if (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3380 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3383 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3386 Result
= SetupGetLineTextW(
3388 hInf
, L
"Version", L
"Provider",
3389 ProviderName
, RequiredSize
,
3392 //FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
3393 //FIXME: DriverVersion = Version.DriverVer => invalid = 0
3395 *pProviderName
= ProviderName
;
3399 /***********************************************************************
3400 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3403 SetupDiBuildDriverInfoList(
3404 IN HDEVINFO DeviceInfoSet
,
3405 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3406 IN DWORD DriverType
)
3408 struct DeviceInfoSet
*list
;
3409 PVOID Buffer
= NULL
;
3410 HINF hInf
= INVALID_HANDLE_VALUE
;
3411 LPWSTR ProviderName
= NULL
;
3412 LPWSTR ManufacturerName
= NULL
;
3413 LPWSTR ManufacturerSection
= NULL
;
3414 LPWSTR HardwareIDs
= NULL
;
3415 LPWSTR CompatibleIDs
= NULL
;
3416 FILETIME DriverDate
;
3417 DWORDLONG DriverVersion
;
3421 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3424 SetLastError(ERROR_INVALID_HANDLE
);
3425 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3426 SetLastError(ERROR_INVALID_HANDLE
);
3427 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3428 SetLastError(ERROR_INVALID_HANDLE
);
3429 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3430 SetLastError(ERROR_INVALID_PARAMETER
);
3431 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3432 SetLastError(ERROR_INVALID_PARAMETER
);
3433 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3434 SetLastError(ERROR_INVALID_PARAMETER
);
3435 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3436 SetLastError(ERROR_INVALID_USER_BUFFER
);
3439 BOOL Result
= FALSE
;
3441 if (DriverType
== SPDIT_COMPATDRIVER
)
3443 /* Get hardware IDs list */
3445 RequiredSize
= 512; /* Initial buffer size */
3446 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3447 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3449 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3450 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3453 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3456 Result
= SetupDiGetDeviceRegistryPropertyW(
3468 /* Get compatible IDs list */
3470 RequiredSize
= 512; /* Initial buffer size */
3471 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3472 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3474 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3475 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3478 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3481 Result
= SetupDiGetDeviceRegistryPropertyW(
3484 SPDRP_COMPATIBLEIDS
,
3486 (PBYTE
)CompatibleIDs
,
3489 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3491 /* No compatible ID for this device */
3492 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3493 CompatibleIDs
= NULL
;
3501 /* Enumerate .inf files */
3503 RequiredSize
= 32768; /* Initial buffer size */
3504 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3505 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3507 HeapFree(GetProcessHeap(), 0, Buffer
);
3508 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3512 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3515 Result
= SetupGetInfFileListW(
3516 NULL
, /* Directory path */
3518 Buffer
, RequiredSize
,
3525 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
3527 INFCONTEXT ContextManufacturer
, ContextDevice
;
3529 TRACE("Opening file %S\n", filename
);
3531 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
3532 if (hInf
== INVALID_HANDLE_VALUE
)
3535 if (!GetVersionInformationFromInfFile(
3542 SetupCloseInfFile(hInf
);
3543 hInf
= INVALID_HANDLE_VALUE
;
3547 if (DriverType
== SPDIT_CLASSDRIVER
)
3549 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3550 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
3552 SetupCloseInfFile(hInf
);
3553 hInf
= INVALID_HANDLE_VALUE
;
3558 /* Get the manufacturers list */
3559 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
3562 Result
= SetupGetStringFieldW(
3563 &ContextManufacturer
,
3564 0, /* Field index */
3569 /* We got the needed size for the buffer */
3570 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3571 if (!ManufacturerName
)
3573 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3576 Result
= SetupGetStringFieldW(
3577 &ContextManufacturer
,
3578 0, /* Field index */
3579 ManufacturerName
, RequiredSize
,
3582 Result
= SetupGetStringFieldW(
3583 &ContextManufacturer
,
3584 1, /* Field index */
3589 /* We got the needed size for the buffer */
3590 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3591 if (!ManufacturerSection
)
3593 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3596 Result
= SetupGetStringFieldW(
3597 &ContextManufacturer
,
3598 1, /* Field index */
3599 ManufacturerSection
, RequiredSize
,
3603 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
3604 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
3607 if (DriverType
== SPDIT_CLASSDRIVER
)
3609 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3610 if (!AddDriverToList(
3611 &list
->DriverListHead
,
3617 DriverDate
, DriverVersion
,
3623 else /* DriverType = SPDIT_COMPATDRIVER */
3625 /* 1. Get all fields */
3626 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
3630 BOOL DriverAlreadyAdded
;
3632 for (i
= 2; i
<= FieldCount
; i
++)
3634 LPWSTR DeviceId
= NULL
;
3636 RequiredSize
= 128; /* Initial buffer size */
3637 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3638 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3640 HeapFree(GetProcessHeap(), 0, DeviceId
);
3641 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3644 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3647 Result
= SetupGetStringFieldW(
3650 DeviceId
, RequiredSize
,
3655 HeapFree(GetProcessHeap(), 0, DeviceId
);
3658 DriverAlreadyAdded
= FALSE
;
3659 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3661 if (wcscmp(DeviceId
, currentId
) == 0)
3664 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3670 DriverDate
, DriverVersion
,
3671 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
3672 DriverAlreadyAdded
= TRUE
;
3677 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3679 if (wcscmp(DeviceId
, currentId
) == 0)
3682 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3688 DriverDate
, DriverVersion
,
3689 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
3690 DriverAlreadyAdded
= TRUE
;
3694 HeapFree(GetProcessHeap(), 0, DeviceId
);
3697 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
3700 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3701 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3702 ManufacturerName
= ManufacturerSection
= NULL
;
3703 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
3705 HeapFree(GetProcessHeap(), 0, ProviderName
);
3706 ProviderName
= NULL
;
3709 SetupCloseInfFile(hInf
);
3710 hInf
= INVALID_HANDLE_VALUE
;
3721 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
;
3722 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
3725 list
->Flags
|= DI_DIDCLASS
;
3728 HeapFree(GetProcessHeap(), 0, ProviderName
);
3729 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3730 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3731 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3732 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3733 if (hInf
!= INVALID_HANDLE_VALUE
)
3734 SetupCloseInfFile(hInf
);
3735 HeapFree(GetProcessHeap(), 0, Buffer
);
3737 TRACE("Returning %d\n", ret
);
3741 /***********************************************************************
3742 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3745 SetupDiDeleteDeviceInfo(
3746 IN HDEVINFO DeviceInfoSet
,
3747 IN PSP_DEVINFO_DATA DeviceInfoData
)
3749 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3751 FIXME("not implemented\n");
3752 SetLastError(ERROR_GEN_FAILURE
);
3757 /***********************************************************************
3758 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3761 SetupDiDestroyDriverInfoList(
3762 IN HDEVINFO DeviceInfoSet
,
3763 IN PSP_DEVINFO_DATA DeviceInfoData
,
3764 IN DWORD DriverType
)
3766 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3768 FIXME("not implemented\n");
3769 SetLastError(ERROR_GEN_FAILURE
);
3774 /***********************************************************************
3775 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3778 SetupDiOpenDeviceInfoA(
3779 IN HDEVINFO DeviceInfoSet
,
3780 IN PCSTR DeviceInstanceId
,
3781 IN HWND hwndParent OPTIONAL
,
3783 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3785 LPWSTR DeviceInstanceIdW
= NULL
;
3788 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3790 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
3791 if (DeviceInstanceIdW
== NULL
)
3794 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
3795 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
3797 MyFree(DeviceInstanceIdW
);
3803 /***********************************************************************
3804 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3807 SetupDiOpenDeviceInfoW(
3808 IN HDEVINFO DeviceInfoSet
,
3809 IN PCWSTR DeviceInstanceId
,
3810 IN HWND hwndParent OPTIONAL
,
3812 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3814 struct DeviceInfoSet
*list
;
3815 HKEY hEnumKey
, hKey
;
3819 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3821 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
3822 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3825 SetLastError(ERROR_INVALID_HANDLE
);
3826 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3827 SetLastError(ERROR_INVALID_HANDLE
);
3828 else if (!DeviceInstanceId
)
3829 SetLastError(ERROR_INVALID_PARAMETER
);
3830 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
3832 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
3833 SetLastError(ERROR_INVALID_PARAMETER
);
3835 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3836 SetLastError(ERROR_INVALID_USER_BUFFER
);
3839 struct DeviceInfoElement
*deviceInfo
= NULL
;
3840 /* Search if device already exists in DeviceInfoSet.
3841 * If yes, return the existing element
3842 * If no, create a new element using informations in registry
3844 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
3845 while (ItemList
!= &list
->ListHead
)
3850 FIXME("not implemented\n");
3851 ItemList
= ItemList
->Flink
;
3856 /* good one found */
3859 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
3860 DeviceInfoData
->DevInst
= 0; /* FIXME */
3861 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3867 /* Open supposed registry key */
3872 KEY_ENUMERATE_SUB_KEYS
,
3874 if (rc
!= ERROR_SUCCESS
)
3885 RegCloseKey(hEnumKey
);
3886 if (rc
!= ERROR_SUCCESS
)
3892 /* FIXME: GUID_NULL is not allowed */
3893 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
3898 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3904 if (ret
&& deviceInfo
&& DeviceInfoData
)
3906 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
3907 DeviceInfoData
->DevInst
= 0; /* FIXME */
3908 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3916 /***********************************************************************
3917 * SetupDiEnumDriverInfoA (SETUPAPI.@)
3920 SetupDiEnumDriverInfoA(
3921 IN HDEVINFO DeviceInfoSet
,
3922 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3923 IN DWORD DriverType
,
3924 IN DWORD MemberIndex
,
3925 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
3927 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
3930 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
3931 DriverType
, MemberIndex
, DriverInfoData
);
3933 if (DriverInfoData
== NULL
)
3934 SetLastError(ERROR_INVALID_PARAMETER
);
3935 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
3936 SetLastError(ERROR_INVALID_USER_BUFFER
);
3939 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
3940 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
3941 DriverType
, MemberIndex
, &driverInfoData2W
);
3945 /* Do W->A conversion */
3946 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
3947 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
3948 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
3949 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
3951 DriverInfoData
->Description
[0] = '\0';
3954 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
3955 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
3957 DriverInfoData
->MfgName
[0] = '\0';
3960 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
3961 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
3963 DriverInfoData
->ProviderName
[0] = '\0';
3966 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
3968 /* Copy more fields */
3969 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
3970 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
3975 TRACE("Returning %d\n", ret
);
3980 /***********************************************************************
3981 * SetupDiEnumDriverInfoW (SETUPAPI.@)
3984 SetupDiEnumDriverInfoW(
3985 IN HDEVINFO DeviceInfoSet
,
3986 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3987 IN DWORD DriverType
,
3988 IN DWORD MemberIndex
,
3989 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
3991 PLIST_ENTRY ListHead
;
3994 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
3995 DriverType
, MemberIndex
, DriverInfoData
);
3997 if (!DeviceInfoSet
|| !DriverInfoData
)
3998 SetLastError(ERROR_INVALID_PARAMETER
);
3999 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4000 SetLastError(ERROR_INVALID_HANDLE
);
4001 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4002 SetLastError(ERROR_INVALID_HANDLE
);
4003 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4004 SetLastError(ERROR_INVALID_PARAMETER
);
4005 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4006 SetLastError(ERROR_INVALID_PARAMETER
);
4007 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4008 SetLastError(ERROR_INVALID_PARAMETER
);
4009 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4010 SetLastError(ERROR_INVALID_USER_BUFFER
);
4013 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4014 PLIST_ENTRY ItemList
;
4015 if (DriverType
== SPDIT_CLASSDRIVER
||
4016 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4018 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4022 ListHead
= &devInfo
->DriverListHead
;
4025 ItemList
= ListHead
->Flink
;
4026 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4027 ItemList
= ItemList
->Flink
;
4028 if (ItemList
== ListHead
)
4029 SetLastError(ERROR_NO_MORE_ITEMS
);
4032 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4035 &DriverInfoData
->DriverType
,
4036 &DrvInfo
->Info
.DriverType
,
4037 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4042 TRACE("Returning %d\n", ret
);
4046 /***********************************************************************
4047 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4050 SetupDiGetSelectedDriverW(
4051 IN HDEVINFO DeviceInfoSet
,
4052 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4053 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4057 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4059 if (!DeviceInfoSet
|| !DriverInfoData
)
4060 SetLastError(ERROR_INVALID_PARAMETER
);
4061 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4062 SetLastError(ERROR_INVALID_HANDLE
);
4063 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4064 SetLastError(ERROR_INVALID_HANDLE
);
4065 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4066 SetLastError(ERROR_INVALID_USER_BUFFER
);
4067 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4068 SetLastError(ERROR_INVALID_USER_BUFFER
);
4071 struct DriverInfoElement
*driverInfo
;
4074 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4076 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4078 if (driverInfo
== NULL
)
4079 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4083 &DriverInfoData
->DriverType
,
4084 &driverInfo
->Info
.DriverType
,
4085 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4090 TRACE("Returning %d\n", ret
);
4094 /***********************************************************************
4095 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4098 SetupDiSetSelectedDriverW(
4099 IN HDEVINFO DeviceInfoSet
,
4100 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4101 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4105 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4108 SetLastError(ERROR_INVALID_PARAMETER
);
4109 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4110 SetLastError(ERROR_INVALID_HANDLE
);
4111 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4112 SetLastError(ERROR_INVALID_HANDLE
);
4113 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4114 SetLastError(ERROR_INVALID_USER_BUFFER
);
4115 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4116 SetLastError(ERROR_INVALID_USER_BUFFER
);
4119 struct DriverInfoElement
**pDriverInfo
;
4120 PLIST_ENTRY ListHead
, ItemList
;
4124 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4125 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4129 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4130 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4133 if (!DriverInfoData
)
4135 *pDriverInfo
= NULL
;
4140 /* Search selected driver in list */
4141 ItemList
= ListHead
->Flink
;
4142 while (ItemList
!= ListHead
)
4144 if (DriverInfoData
->Reserved
!= 0)
4146 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4151 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4152 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4153 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4154 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4155 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4161 if (ItemList
== ListHead
)
4162 SetLastError(ERROR_INVALID_PARAMETER
);
4165 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4166 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4172 TRACE("Returning %d\n", ret
);
4176 /***********************************************************************
4177 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4180 SetupDiSelectBestCompatDrv(
4181 IN HDEVINFO DeviceInfoSet
,
4182 IN PSP_DEVINFO_DATA DeviceInfoData
)
4184 SP_DRVINFO_DATA_W drvInfoData
;
4187 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4189 FIXME("SetupDiSelectBestCompatDrv() is selecting the 1st driver...\n");
4191 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4192 ret
= SetupDiEnumDriverInfoW(
4196 0, /* Member index */
4201 ret
= SetupDiSetSelectedDriverW(
4207 TRACE("Returning %d\n", ret
);
4211 /***********************************************************************
4212 * SetupDiInstallDriverFiles (SETUPAPI.@)
4215 SetupDiInstallDriverFiles(
4216 IN HDEVINFO DeviceInfoSet
,
4217 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4219 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4221 FIXME("SetupDiInstallDriverFiles not implemented. Doing nothing\n");
4222 //SetLastError(ERROR_GEN_FAILURE);
4227 /***********************************************************************
4228 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4231 SetupDiRegisterCoDeviceInstallers(
4232 IN HDEVINFO DeviceInfoSet
,
4233 IN PSP_DEVINFO_DATA DeviceInfoData
)
4235 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4237 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4238 //SetLastError(ERROR_GEN_FAILURE);
4243 /***********************************************************************
4244 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4247 SetupDiInstallDeviceInterfaces(
4248 IN HDEVINFO DeviceInfoSet
,
4249 IN PSP_DEVINFO_DATA DeviceInfoData
)
4251 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4253 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4254 //SetLastError(ERROR_GEN_FAILURE);
4259 /***********************************************************************
4260 * SetupDiInstallDevice (SETUPAPI.@)
4263 SetupDiInstallDevice(
4264 IN HDEVINFO DeviceInfoSet
,
4265 IN PSP_DEVINFO_DATA DeviceInfoData
)
4267 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4270 * 0. If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit
4271 * 1. Create driver key and write InfPath and ProviderName
4272 * 2a Process inf sections: {DDInstall}, {DDInstall}.HW [SetupDiOpenDevRegKey]
4273 * b Process {DDInstall}.LogConfigOverride if present [SetupDiOpenDevRegKey]
4274 * c Process {DDInstall}.Services [SetupDiOpenDevRegKey]
4275 * 3. Copy inf file to Inf\ directory [SetupCopyOEMInf]
4276 * 4. Install other waiting files
4277 * 5. Load the driver/Call AddDevice
4278 * 6. Send IRP_MN_START_DEVICE if DI_NEEDRESTART, DI_NEEDREBOOT and DI_DONOTCALLCONFIGMG are not set
4281 FIXME("SetupDiInstallDevice not implemented. Doing nothing\n");
4282 //SetLastError(ERROR_GEN_FAILURE);