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
;
131 SP_DRVINFO_DATA_V2_W Info
;
136 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
138 LIST_ENTRY ListEntry
;
140 /* Information about devnode:
142 * "Root\*PNP0501" for example.
143 * It doesn't contain the unique ID for the device
144 * (points into the Data field at the end of the structure)
145 * WARNING: no NULL char exist between DeviceName and UniqueId
148 * "5&1be2108e&0" or "0000"
149 * If DICD_GENERATE_ID is specified in creation flags,
150 * this unique ID is autogenerated using 4 digits, base 10
151 * (points into the Data field at the end of the structure)
152 * - DeviceDescription
153 * String which identifies the device. Can be NULL. If not NULL,
154 * points into the Data field at the end of the structure
156 * Identifies the class of this device. FIXME: can it be GUID_NULL?
158 * Is a combination of:
160 * the unique ID needs to be generated
161 * - DICD_INHERIT_CLASSDRVS
162 * inherit driver of the device info set (== same pointer)
164 * Used when doing device-specific actions. Can be NULL
168 PCWSTR DeviceDescription
;
173 /* Flags is a combination of:
175 * Set when the device driver list is created
176 * FlagsEx is a combination of:
181 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
182 /* If the driver is not searched/detected, this list is empty */
183 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
184 /* Points into DriverListHead list. The pointer is NULL if no driver is
185 * currently chosen. */
186 struct DriverInfoElement
*SelectedDriver
;
188 /* List of interfaces implemented by this device */
189 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
194 struct DeviceInfoSet
/* HDEVINFO */
196 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
197 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
198 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
199 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
201 /* Flags is a combination of:
203 * Set when the class driver list is created
204 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
205 * Forces SetupDiBuildDriverInfoList to build a class drivers list
206 * FlagsEx is a combination of:
211 /* If the driver is not searched/detected, this list is empty */
212 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
213 /* Points into DriverListHead list. The pointer is NULL if no driver is
214 * currently chosen. */
215 struct DriverInfoElement
*SelectedDriver
;
217 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
220 /***********************************************************************
221 * SetupDiBuildClassInfoList (SETUPAPI.@)
223 BOOL WINAPI
SetupDiBuildClassInfoList(
225 LPGUID ClassGuidList
,
226 DWORD ClassGuidListSize
,
230 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
231 ClassGuidListSize
, RequiredSize
,
235 /***********************************************************************
236 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
238 BOOL WINAPI
SetupDiBuildClassInfoListExA(
240 LPGUID ClassGuidList
,
241 DWORD ClassGuidListSize
,
246 LPWSTR MachineNameW
= NULL
;
253 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
254 if (MachineNameW
== NULL
) return FALSE
;
257 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
258 ClassGuidListSize
, RequiredSize
,
259 MachineNameW
, Reserved
);
262 MyFree(MachineNameW
);
267 /***********************************************************************
268 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
270 BOOL WINAPI
SetupDiBuildClassInfoListExW(
272 LPGUID ClassGuidList
,
273 DWORD ClassGuidListSize
,
278 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
284 DWORD dwGuidListIndex
= 0;
288 if (RequiredSize
!= NULL
)
291 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
296 if (hClassesKey
== INVALID_HANDLE_VALUE
)
301 for (dwIndex
= 0; ; dwIndex
++)
303 dwLength
= MAX_GUID_STRING_LEN
+ 1;
304 lError
= RegEnumKeyExW(hClassesKey
,
312 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
313 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
315 TRACE("Key name: %p\n", szKeyName
);
317 if (RegOpenKeyExW(hClassesKey
,
323 RegCloseKey(hClassesKey
);
327 if (!RegQueryValueExW(hClassKey
,
334 TRACE("'NoUseClass' value found!\n");
335 RegCloseKey(hClassKey
);
339 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
340 (!RegQueryValueExW(hClassKey
,
347 TRACE("'NoInstallClass' value found!\n");
348 RegCloseKey(hClassKey
);
352 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
353 (!RegQueryValueExW(hClassKey
,
360 TRACE("'NoDisplayClass' value found!\n");
361 RegCloseKey(hClassKey
);
365 RegCloseKey(hClassKey
);
367 TRACE("Guid: %p\n", szKeyName
);
368 if (dwGuidListIndex
< ClassGuidListSize
)
370 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
374 TRACE("Guid: %p\n", &szKeyName
[1]);
376 UuidFromStringW(&szKeyName
[1],
377 &ClassGuidList
[dwGuidListIndex
]);
383 if (lError
!= ERROR_SUCCESS
)
387 RegCloseKey(hClassesKey
);
389 if (RequiredSize
!= NULL
)
390 *RequiredSize
= dwGuidListIndex
;
392 if (ClassGuidListSize
< dwGuidListIndex
)
394 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
401 /***********************************************************************
402 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
404 BOOL WINAPI
SetupDiClassGuidsFromNameA(
406 LPGUID ClassGuidList
,
407 DWORD ClassGuidListSize
,
410 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
411 ClassGuidListSize
, RequiredSize
,
415 /***********************************************************************
416 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
418 BOOL WINAPI
SetupDiClassGuidsFromNameW(
420 LPGUID ClassGuidList
,
421 DWORD ClassGuidListSize
,
424 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
425 ClassGuidListSize
, RequiredSize
,
429 /***********************************************************************
430 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
432 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
434 LPGUID ClassGuidList
,
435 DWORD ClassGuidListSize
,
440 LPWSTR ClassNameW
= NULL
;
441 LPWSTR MachineNameW
= NULL
;
446 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
447 if (ClassNameW
== NULL
)
452 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
453 if (MachineNameW
== NULL
)
460 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
461 ClassGuidListSize
, RequiredSize
,
462 MachineNameW
, Reserved
);
465 MyFree(MachineNameW
);
472 /***********************************************************************
473 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
475 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
477 LPGUID ClassGuidList
,
478 DWORD ClassGuidListSize
,
483 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
484 WCHAR szClassName
[256];
490 DWORD dwGuidListIndex
= 0;
492 if (RequiredSize
!= NULL
)
495 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
496 KEY_ENUMERATE_SUB_KEYS
,
500 if (hClassesKey
== INVALID_HANDLE_VALUE
)
505 for (dwIndex
= 0; ; dwIndex
++)
507 dwLength
= MAX_GUID_STRING_LEN
+ 1;
508 lError
= RegEnumKeyExW(hClassesKey
,
516 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
517 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
519 TRACE("Key name: %p\n", szKeyName
);
521 if (RegOpenKeyExW(hClassesKey
,
527 RegCloseKey(hClassesKey
);
531 dwLength
= 256 * sizeof(WCHAR
);
532 if (!RegQueryValueExW(hClassKey
,
539 TRACE("Class name: %p\n", szClassName
);
541 if (strcmpiW(szClassName
, ClassName
) == 0)
543 TRACE("Found matching class name\n");
545 TRACE("Guid: %p\n", szKeyName
);
546 if (dwGuidListIndex
< ClassGuidListSize
)
548 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
552 TRACE("Guid: %p\n", &szKeyName
[1]);
554 UuidFromStringW(&szKeyName
[1],
555 &ClassGuidList
[dwGuidListIndex
]);
562 RegCloseKey(hClassKey
);
565 if (lError
!= ERROR_SUCCESS
)
569 RegCloseKey(hClassesKey
);
571 if (RequiredSize
!= NULL
)
572 *RequiredSize
= dwGuidListIndex
;
574 if (ClassGuidListSize
< dwGuidListIndex
)
576 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
583 /***********************************************************************
584 * SetupDiClassNameFromGuidA (SETUPAPI.@)
586 BOOL WINAPI
SetupDiClassNameFromGuidA(
587 const GUID
* ClassGuid
,
592 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
593 ClassNameSize
, RequiredSize
,
597 /***********************************************************************
598 * SetupDiClassNameFromGuidW (SETUPAPI.@)
600 BOOL WINAPI
SetupDiClassNameFromGuidW(
601 const GUID
* ClassGuid
,
606 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
607 ClassNameSize
, RequiredSize
,
611 /***********************************************************************
612 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
614 BOOL WINAPI
SetupDiClassNameFromGuidExA(
615 const GUID
* ClassGuid
,
622 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
623 LPWSTR MachineNameW
= NULL
;
627 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
628 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
629 NULL
, MachineNameW
, Reserved
);
632 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
633 ClassNameSize
, NULL
, NULL
);
635 if (!ClassNameSize
&& RequiredSize
)
638 MyFree(MachineNameW
);
642 /***********************************************************************
643 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
645 BOOL WINAPI
SetupDiClassNameFromGuidExW(
646 const GUID
* ClassGuid
,
657 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
662 if (hKey
== INVALID_HANDLE_VALUE
)
667 if (RequiredSize
!= NULL
)
670 rc
= RegQueryValueExW(hKey
,
676 if (rc
!= ERROR_SUCCESS
)
683 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
686 dwLength
= ClassNameSize
* sizeof(WCHAR
);
687 rc
= RegQueryValueExW(hKey
,
693 if (rc
!= ERROR_SUCCESS
)
705 /***********************************************************************
706 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
709 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
712 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
715 /***********************************************************************
716 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
719 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
724 LPWSTR MachineNameW
= NULL
;
727 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
731 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
732 if (MachineNameW
== NULL
)
733 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
736 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
737 MachineNameW
, Reserved
);
740 MyFree(MachineNameW
);
745 /***********************************************************************
746 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
749 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
754 struct DeviceInfoSet
*list
;
757 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
759 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
762 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
763 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
766 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
769 ClassGuid
? ClassGuid
: &GUID_NULL
,
770 sizeof(list
->ClassGuid
));
771 list
->hwndParent
= hwndParent
;
774 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
775 if (rc
!= ERROR_SUCCESS
)
778 HeapFree(GetProcessHeap(), 0, list
);
779 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
784 list
->HKLM
= HKEY_LOCAL_MACHINE
;
786 list
->Flags
= 0; /* FIXME */
787 list
->FlagsEx
= 0; /* FIXME */
788 InitializeListHead(&list
->DriverListHead
);
789 InitializeListHead(&list
->ListHead
);
790 return (HDEVINFO
)list
;
793 /***********************************************************************
794 * SetupDiEnumDeviceInfo (SETUPAPI.@)
796 BOOL WINAPI
SetupDiEnumDeviceInfo(
797 HDEVINFO DeviceInfoSet
,
799 PSP_DEVINFO_DATA DeviceInfoData
)
803 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
805 SetLastError(ERROR_INVALID_PARAMETER
);
806 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
808 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
810 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
811 SetLastError(ERROR_INVALID_HANDLE
);
812 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
813 SetLastError(ERROR_INVALID_USER_BUFFER
);
816 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
817 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
818 ItemList
= ItemList
->Flink
;
819 if (ItemList
== &list
->ListHead
)
820 SetLastError(ERROR_NO_MORE_ITEMS
);
823 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
824 memcpy(&DeviceInfoData
->ClassGuid
,
827 DeviceInfoData
->DevInst
= 0; /* FIXME */
828 /* Note: this appears to be dangerous, passing a private
829 * pointer a heap-allocated datum to the caller. However, the
830 * expected lifetime of the device data is the same as the
831 * HDEVINFO; once that is closed, the data are no longer valid.
833 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
839 SetLastError(ERROR_INVALID_HANDLE
);
843 /***********************************************************************
844 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
846 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
848 PCSTR InfSectionName
,
849 PSTR InfSectionWithExt
,
850 DWORD InfSectionWithExtSize
,
854 LPWSTR InfSectionNameW
= NULL
;
855 PWSTR InfSectionWithExtW
= NULL
;
857 BOOL bResult
= FALSE
;
863 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
864 if (InfSectionNameW
== NULL
) goto end
;
866 if (InfSectionWithExt
)
868 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
869 if (InfSectionWithExtW
== NULL
) goto end
;
872 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
873 InfSectionWithExt
? InfSectionNameW
: NULL
,
874 InfSectionWithExtSize
, RequiredSize
,
875 Extension
? &ExtensionW
: NULL
);
877 if (bResult
&& InfSectionWithExt
)
879 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
880 InfSectionWithExtSize
, NULL
, NULL
) != 0;
882 if (bResult
&& Extension
)
884 if (ExtensionW
== NULL
)
887 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
891 if (InfSectionNameW
) MyFree(InfSectionNameW
);
892 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
897 /***********************************************************************
898 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
900 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
902 PCWSTR InfSectionName
,
903 PWSTR InfSectionWithExt
,
904 DWORD InfSectionWithExtSize
,
908 WCHAR szBuffer
[MAX_PATH
];
911 LONG lLineCount
= -1;
913 lstrcpyW(szBuffer
, InfSectionName
);
914 dwLength
= lstrlenW(szBuffer
);
916 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
918 /* Test section name with '.NTx86' extension */
919 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
920 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
922 if (lLineCount
== -1)
924 /* Test section name with '.NT' extension */
925 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
926 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
931 /* Test section name with '.Win' extension */
932 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
933 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
936 if (lLineCount
== -1)
938 /* Test section name without extension */
939 szBuffer
[dwLength
] = 0;
940 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
943 if (lLineCount
== -1)
945 SetLastError(ERROR_INVALID_PARAMETER
);
949 dwFullLength
= lstrlenW(szBuffer
);
951 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
953 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
955 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
959 lstrcpyW(InfSectionWithExt
, szBuffer
);
960 if (Extension
!= NULL
)
962 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
966 if (RequiredSize
!= NULL
)
968 *RequiredSize
= dwFullLength
+ 1;
974 /***********************************************************************
975 * SetupDiGetClassDescriptionA (SETUPAPI.@)
977 BOOL WINAPI
SetupDiGetClassDescriptionA(
978 const GUID
* ClassGuid
,
979 PSTR ClassDescription
,
980 DWORD ClassDescriptionSize
,
983 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
984 ClassDescriptionSize
,
985 RequiredSize
, NULL
, NULL
);
988 /***********************************************************************
989 * SetupDiGetClassDescriptionW (SETUPAPI.@)
991 BOOL WINAPI
SetupDiGetClassDescriptionW(
992 const GUID
* ClassGuid
,
993 PWSTR ClassDescription
,
994 DWORD ClassDescriptionSize
,
997 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
998 ClassDescriptionSize
,
999 RequiredSize
, NULL
, NULL
);
1002 /***********************************************************************
1003 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1005 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1006 const GUID
* ClassGuid
,
1007 PSTR ClassDescription
,
1008 DWORD ClassDescriptionSize
,
1009 PDWORD RequiredSize
,
1013 PWCHAR ClassDescriptionW
;
1014 LPWSTR MachineNameW
= NULL
;
1018 if (ClassDescriptionSize
> 0)
1020 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1021 if (!ClassDescriptionW
)
1023 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1029 ClassDescriptionW
= NULL
;
1033 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1036 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1042 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1043 NULL
, MachineNameW
, Reserved
);
1046 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1047 ClassDescriptionSize
, NULL
, NULL
);
1049 if (!ClassDescriptionSize
&& RequiredSize
)
1050 *RequiredSize
= len
;
1054 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1055 MyFree(MachineNameW
);
1059 /***********************************************************************
1060 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1062 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1063 const GUID
* ClassGuid
,
1064 PWSTR ClassDescription
,
1065 DWORD ClassDescriptionSize
,
1066 PDWORD RequiredSize
,
1073 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1078 if (hKey
== INVALID_HANDLE_VALUE
)
1080 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1084 if (RequiredSize
!= NULL
)
1087 if (RegQueryValueExW(hKey
,
1098 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1101 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1102 if (RegQueryValueExW(hKey
,
1106 (LPBYTE
)ClassDescription
,
1118 /***********************************************************************
1119 * SetupDiGetClassDevsA (SETUPAPI.@)
1121 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1127 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1128 flags
, NULL
, NULL
, NULL
);
1131 /***********************************************************************
1132 * SetupDiGetClassDevsW (SETUPAPI.@)
1134 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1140 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1141 flags
, NULL
, NULL
, NULL
);
1144 /***********************************************************************
1145 * SetupDiGetClassDevsExA (SETUPAPI.@)
1147 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1157 LPWSTR enumstrW
= NULL
;
1158 LPWSTR machineW
= NULL
;
1162 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1163 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1166 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1169 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1173 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1174 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1177 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1180 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1182 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1185 HeapFree(GetProcessHeap(), 0, enumstrW
);
1186 HeapFree(GetProcessHeap(), 0, machineW
);
1191 CreateDeviceInfoElement(
1192 IN LPCWSTR InstancePath
,
1194 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1196 struct DeviceInfoElement
*deviceInfo
;
1198 *pDeviceInfo
= NULL
;
1199 if (IsEqualIID(&pClassGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1201 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1204 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1207 wcscpy(deviceInfo
->Data
, InstancePath
);
1208 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1209 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1210 deviceInfo
->DeviceDescription
= NULL
;
1211 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1212 deviceInfo
->CreationFlags
= 0;
1213 deviceInfo
->hwndParent
= NULL
;
1214 deviceInfo
->Flags
= 0; /* FIXME */
1215 deviceInfo
->FlagsEx
= 0; /* FIXME */
1216 deviceInfo
->SelectedDriver
= NULL
;
1217 InitializeListHead(&deviceInfo
->DriverListHead
);
1218 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1220 *pDeviceInfo
= deviceInfo
;
1225 CreateDeviceInterface(
1226 IN
struct DeviceInfoElement
* deviceInfo
,
1227 IN LPCWSTR SymbolicLink
,
1228 IN LPCGUID pInterfaceGuid
,
1229 OUT
struct DeviceInterface
**pDeviceInterface
)
1231 struct DeviceInterface
*deviceInterface
;
1233 *pDeviceInterface
= NULL
;
1235 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1236 if (!deviceInterface
)
1238 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1241 deviceInterface
->DeviceInfo
= deviceInfo
;
1242 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1243 deviceInterface
->Flags
= 0; /* FIXME */
1244 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1246 *pDeviceInterface
= deviceInterface
;
1250 static LONG
SETUP_CreateDevListFromEnumerator(
1251 struct DeviceInfoSet
*list
,
1252 LPCGUID pClassGuid OPTIONAL
,
1254 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1256 HKEY hDeviceIdKey
, hInstanceIdKey
;
1257 WCHAR KeyBuffer
[MAX_PATH
];
1258 WCHAR InstancePath
[MAX_PATH
];
1259 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1260 struct DeviceInfoElement
*deviceInfo
;
1262 DWORD dwLength
, dwRegType
;
1265 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1268 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1269 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1270 if (rc
== ERROR_NO_MORE_ITEMS
)
1272 if (rc
!= ERROR_SUCCESS
)
1276 /* Open device id sub key */
1277 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1278 if (rc
!= ERROR_SUCCESS
)
1280 wcscpy(InstancePath
, Enumerator
);
1281 wcscat(InstancePath
, L
"\\");
1282 wcscat(InstancePath
, KeyBuffer
);
1283 wcscat(InstancePath
, L
"\\");
1284 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1286 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1292 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1293 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1294 if (rc
== ERROR_NO_MORE_ITEMS
)
1296 if (rc
!= ERROR_SUCCESS
)
1298 RegCloseKey(hDeviceIdKey
);
1303 /* Open instance id sub key */
1304 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1305 if (rc
!= ERROR_SUCCESS
)
1307 RegCloseKey(hDeviceIdKey
);
1310 *pEndOfInstancePath
= '\0';
1311 wcscat(InstancePath
, KeyBuffer
);
1313 /* Read ClassGUID value */
1314 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1315 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1316 RegCloseKey(hInstanceIdKey
);
1317 if (rc
== ERROR_FILE_NOT_FOUND
)
1320 /* Skip this bad entry as we can't verify it */
1323 else if (rc
!= ERROR_SUCCESS
)
1325 RegCloseKey(hDeviceIdKey
);
1328 else if (dwRegType
!= REG_SZ
)
1330 RegCloseKey(hDeviceIdKey
);
1331 return ERROR_GEN_FAILURE
;
1334 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1335 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1337 RegCloseKey(hDeviceIdKey
);
1338 return GetLastError();
1340 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1342 /* Skip this entry as it is not the right device class */
1346 /* Add the entry to the list */
1347 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1349 RegCloseKey(hDeviceIdKey
);
1350 return GetLastError();
1352 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1353 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1355 RegCloseKey(hDeviceIdKey
);
1358 return ERROR_SUCCESS
;
1361 static LONG
SETUP_CreateDevList(
1362 struct DeviceInfoSet
*list
,
1363 PCWSTR MachineName OPTIONAL
,
1364 LPGUID
class OPTIONAL
,
1365 PCWSTR Enumerator OPTIONAL
)
1367 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1368 WCHAR KeyBuffer
[MAX_PATH
];
1373 if (IsEqualIID(class, &GUID_NULL
))
1377 if (MachineName
!= NULL
)
1379 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1380 if (rc
!= ERROR_SUCCESS
)
1384 HKLM
= HKEY_LOCAL_MACHINE
;
1386 rc
= RegOpenKeyExW(HKLM
,
1389 KEY_ENUMERATE_SUB_KEYS
,
1391 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1392 if (rc
!= ERROR_SUCCESS
)
1395 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1396 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1405 KEY_ENUMERATE_SUB_KEYS
,
1407 RegCloseKey(hEnumKey
);
1408 if (rc
!= ERROR_SUCCESS
)
1410 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1411 RegCloseKey(hEnumeratorKey
);
1416 /* Enumerate enumerators */
1420 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1421 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1422 if (rc
== ERROR_NO_MORE_ITEMS
)
1424 if (rc
!= ERROR_SUCCESS
)
1426 RegCloseKey(hEnumKey
);
1432 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1433 if (rc
!= ERROR_SUCCESS
)
1435 RegCloseKey(hEnumKey
);
1439 /* Call SETUP_CreateDevListFromEnumerator */
1440 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1441 RegCloseKey(hEnumeratorKey
);
1442 if (rc
!= ERROR_SUCCESS
)
1444 RegCloseKey(hEnumKey
);
1448 RegCloseKey(hEnumKey
);
1449 return ERROR_SUCCESS
;
1454 static LONG
SETUP_CreateSerialDeviceList(
1455 struct DeviceInfoSet
*list
,
1457 LPGUID InterfaceGuid
,
1458 PCWSTR DeviceInstanceW
)
1460 static const size_t initialSize
= 100;
1462 WCHAR buf
[initialSize
];
1464 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1466 struct DeviceInfoElement
*deviceInfo
;
1469 WARN("'MachineName' is ignored on Wine!\n");
1470 if (DeviceInstanceW
)
1471 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1477 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1479 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1483 HeapFree(GetProcessHeap(), 0, devices
);
1484 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1486 return ERROR_NOT_ENOUGH_MEMORY
;
1492 HeapFree(GetProcessHeap(), 0, devices
);
1493 return GetLastError();
1497 /* 'devices' is a MULTI_SZ string */
1498 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1500 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1502 /* We have found a device */
1503 struct DeviceInterface
*interfaceInfo
;
1504 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1505 /* Step 1. Create a device info element */
1506 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1509 HeapFree(GetProcessHeap(), 0, devices
);
1510 return GetLastError();
1512 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1514 /* Step 2. Create an interface list for this element */
1515 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1518 HeapFree(GetProcessHeap(), 0, devices
);
1519 return GetLastError();
1521 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1525 HeapFree(GetProcessHeap(), 0, devices
);
1526 return ERROR_SUCCESS
;
1529 #else /* __REACTOS__ */
1531 static LONG
SETUP_CreateInterfaceList(
1532 struct DeviceInfoSet
*list
,
1534 LPGUID InterfaceGuid
,
1535 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1537 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1538 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1539 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1540 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1541 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1543 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1546 DWORD dwLength
, dwInstancePathLength
;
1549 struct DeviceInfoElement
*deviceInfo
;
1551 /* Open registry key related to this interface */
1552 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1553 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1554 return GetLastError();
1556 /* Enumerate sub keys of hInterfaceKey */
1560 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1561 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1562 if (rc
== ERROR_NO_MORE_ITEMS
)
1564 if (rc
!= ERROR_SUCCESS
)
1566 RegCloseKey(hInterfaceKey
);
1572 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1573 if (rc
!= ERROR_SUCCESS
)
1575 RegCloseKey(hInterfaceKey
);
1579 /* Read DeviceInstance */
1580 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1581 if (rc
!= ERROR_SUCCESS
)
1583 RegCloseKey(hDeviceInstanceKey
);
1584 RegCloseKey(hInterfaceKey
);
1587 if (dwRegType
!= REG_SZ
)
1589 RegCloseKey(hDeviceInstanceKey
);
1590 RegCloseKey(hInterfaceKey
);
1591 return ERROR_GEN_FAILURE
;
1593 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1596 RegCloseKey(hDeviceInstanceKey
);
1597 RegCloseKey(hInterfaceKey
);
1598 return ERROR_NOT_ENOUGH_MEMORY
;
1600 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1601 if (rc
!= ERROR_SUCCESS
)
1603 HeapFree(GetProcessHeap(), 0, InstancePath
);
1604 RegCloseKey(hDeviceInstanceKey
);
1605 RegCloseKey(hInterfaceKey
);
1608 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1609 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1611 if (DeviceInstanceW
)
1613 /* Check if device enumerator is not the right one */
1614 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1616 HeapFree(GetProcessHeap(), 0, InstancePath
);
1617 RegCloseKey(hDeviceInstanceKey
);
1622 /* Find class GUID associated to the device instance */
1627 KEY_ENUMERATE_SUB_KEYS
,
1629 if (rc
!= ERROR_SUCCESS
)
1631 HeapFree(GetProcessHeap(), 0, InstancePath
);
1632 RegCloseKey(hDeviceInstanceKey
);
1633 RegCloseKey(hInterfaceKey
);
1642 RegCloseKey(hEnumKey
);
1643 if (rc
!= ERROR_SUCCESS
)
1645 HeapFree(GetProcessHeap(), 0, InstancePath
);
1646 RegCloseKey(hDeviceInstanceKey
);
1647 RegCloseKey(hInterfaceKey
);
1650 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1651 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1653 if (rc
!= ERROR_SUCCESS
)
1655 HeapFree(GetProcessHeap(), 0, InstancePath
);
1656 RegCloseKey(hDeviceInstanceKey
);
1657 RegCloseKey(hInterfaceKey
);
1660 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1661 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1662 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1664 HeapFree(GetProcessHeap(), 0, InstancePath
);
1665 RegCloseKey(hDeviceInstanceKey
);
1666 RegCloseKey(hInterfaceKey
);
1667 return ERROR_GEN_FAILURE
;
1669 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1671 /* If current device doesn't match the list GUID (if any), skip this entry */
1672 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1674 HeapFree(GetProcessHeap(), 0, InstancePath
);
1675 RegCloseKey(hDeviceInstanceKey
);
1679 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1683 LPWSTR pSymbolicLink
;
1684 struct DeviceInterface
*interfaceInfo
;
1686 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1687 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1688 if (rc
== ERROR_NO_MORE_ITEMS
)
1690 if (rc
!= ERROR_SUCCESS
)
1692 HeapFree(GetProcessHeap(), 0, InstancePath
);
1693 RegCloseKey(hDeviceInstanceKey
);
1694 RegCloseKey(hInterfaceKey
);
1698 if (KeyBuffer
[0] != '#')
1699 /* This entry doesn't represent an interesting entry */
1703 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1704 if (rc
!= ERROR_SUCCESS
)
1706 RegCloseKey(hDeviceInstanceKey
);
1707 RegCloseKey(hInterfaceKey
);
1711 /* Read SymbolicLink value */
1712 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1713 if (rc
!= ERROR_SUCCESS
)
1715 RegCloseKey(hReferenceKey
);
1716 RegCloseKey(hDeviceInstanceKey
);
1717 RegCloseKey(hInterfaceKey
);
1720 if (dwRegType
!= REG_SZ
)
1722 RegCloseKey(hReferenceKey
);
1723 RegCloseKey(hDeviceInstanceKey
);
1724 RegCloseKey(hInterfaceKey
);
1725 return ERROR_GEN_FAILURE
;
1728 /* We have found a device */
1729 /* Step 1. Create a device info element */
1730 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1732 RegCloseKey(hReferenceKey
);
1733 RegCloseKey(hDeviceInstanceKey
);
1734 RegCloseKey(hInterfaceKey
);
1735 return GetLastError();
1737 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1738 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1740 /* Step 2. Create an interface list for this element */
1741 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1744 RegCloseKey(hReferenceKey
);
1745 RegCloseKey(hDeviceInstanceKey
);
1746 RegCloseKey(hInterfaceKey
);
1747 return ERROR_NOT_ENOUGH_MEMORY
;
1749 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1750 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1751 RegCloseKey(hReferenceKey
);
1752 if (rc
!= ERROR_SUCCESS
)
1754 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1755 RegCloseKey(hDeviceInstanceKey
);
1756 RegCloseKey(hInterfaceKey
);
1759 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1761 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1762 RegCloseKey(hDeviceInstanceKey
);
1763 RegCloseKey(hInterfaceKey
);
1764 return GetLastError();
1766 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1767 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1768 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1770 RegCloseKey(hDeviceInstanceKey
);
1772 RegCloseKey(hInterfaceKey
);
1773 return ERROR_SUCCESS
;
1775 #endif /* __REACTOS__ */
1777 /***********************************************************************
1778 * SetupDiGetClassDevsExW (SETUPAPI.@)
1780 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1789 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1790 struct DeviceInfoSet
*list
;
1794 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1795 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1797 /* Create the deviceset if not set */
1800 list
= (struct DeviceInfoSet
*)deviceset
;
1801 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1803 SetLastError(ERROR_INVALID_HANDLE
);
1804 return INVALID_HANDLE_VALUE
;
1806 hDeviceInfo
= deviceset
;
1810 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1811 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1812 NULL
, machine
, NULL
);
1813 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1814 return INVALID_HANDLE_VALUE
;
1815 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1818 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1821 pClassGuid
= &list
->ClassGuid
;
1823 if (flags
& DIGCF_PRESENT
)
1824 FIXME(": flag DIGCF_PRESENT ignored\n");
1825 if (flags
& DIGCF_PROFILE
)
1826 FIXME(": flag DIGCF_PROFILE ignored\n");
1828 if (flags
& DIGCF_ALLCLASSES
)
1830 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1831 if (rc
!= ERROR_SUCCESS
)
1835 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1836 return INVALID_HANDLE_VALUE
;
1840 else if (flags
& DIGCF_DEVICEINTERFACE
)
1844 SetLastError(ERROR_INVALID_PARAMETER
);
1846 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1847 return INVALID_HANDLE_VALUE
;
1851 /* Special case: find serial ports by calling QueryDosDevice */
1852 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1853 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1854 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1855 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1858 ERR("Wine can only enumerate serial devices at the moment!\n");
1859 rc
= ERROR_INVALID_PARAMETER
;
1861 #else /* __REACTOS__ */
1862 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1863 #endif /* __REACTOS__ */
1864 if (rc
!= ERROR_SUCCESS
)
1868 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1869 return INVALID_HANDLE_VALUE
;
1875 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1876 if (rc
!= ERROR_SUCCESS
)
1880 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1881 return INVALID_HANDLE_VALUE
;
1887 /***********************************************************************
1888 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1890 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1891 HDEVINFO DeviceInfoSet
,
1892 PSP_DEVINFO_DATA DeviceInfoData
,
1893 CONST GUID
* InterfaceClassGuid
,
1895 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1899 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1900 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1902 if (!DeviceInterfaceData
)
1903 SetLastError(ERROR_INVALID_PARAMETER
);
1904 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1905 SetLastError(ERROR_INVALID_USER_BUFFER
);
1906 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1908 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1910 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1912 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1914 while (ItemList
!= &list
->ListHead
&& !Found
)
1916 PLIST_ENTRY InterfaceListEntry
;
1917 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1918 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1920 /* We are not searching for this element */
1921 ItemList
= ItemList
->Flink
;
1924 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1925 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1927 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1928 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1930 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1933 if (MemberIndex
-- == 0)
1935 /* return this item */
1936 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1937 &DevItf
->InterfaceClassGuid
,
1939 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1940 /* Note: this appears to be dangerous, passing a private
1941 * pointer a heap-allocated datum to the caller. However, the
1942 * expected lifetime of the device data is the same as the
1943 * HDEVINFO; once that is closed, the data are no longer valid.
1945 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1948 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1950 ItemList
= ItemList
->Flink
;
1953 SetLastError(ERROR_NO_MORE_ITEMS
);
1958 SetLastError(ERROR_INVALID_HANDLE
);
1961 SetLastError(ERROR_INVALID_HANDLE
);
1965 /***********************************************************************
1966 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1968 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1972 TRACE("%p\n", devinfo
);
1973 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1975 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1977 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1979 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1980 struct DeviceInfoElement
*deviceInfo
;
1981 while (!IsListEmpty(&list
->ListHead
))
1983 ListEntry
= RemoveHeadList(&list
->ListHead
);
1984 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1985 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1987 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1988 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1990 HeapFree(GetProcessHeap(), 0, ListEntry
);
1992 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1993 RegCloseKey(list
->HKLM
);
1994 HeapFree(GetProcessHeap(), 0, list
);
1998 SetLastError(ERROR_INVALID_HANDLE
);
2001 SetLastError(ERROR_INVALID_HANDLE
);
2003 TRACE("Returning %d\n", ret
);
2007 /***********************************************************************
2008 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2010 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2011 HDEVINFO DeviceInfoSet
,
2012 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2013 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2014 DWORD DeviceInterfaceDetailDataSize
,
2015 PDWORD RequiredSize
,
2016 PSP_DEVINFO_DATA DeviceInfoData
)
2018 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2019 DWORD sizeW
= 0, sizeA
;
2022 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2023 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2024 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2026 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2027 SetLastError(ERROR_INVALID_USER_BUFFER
);
2028 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2029 SetLastError(ERROR_INVALID_PARAMETER
);
2030 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2031 SetLastError(ERROR_INVALID_PARAMETER
);
2034 if (DeviceInterfaceDetailData
!= NULL
)
2036 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2037 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2038 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2039 if (!DeviceInterfaceDetailDataW
)
2041 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2044 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2046 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2047 ret
= SetupDiGetDeviceInterfaceDetailW(
2049 DeviceInterfaceData
,
2050 DeviceInterfaceDetailDataW
,
2054 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2055 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2057 *RequiredSize
= sizeA
;
2058 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2060 if (!WideCharToMultiByte(
2062 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2063 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2070 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2073 TRACE("Returning %d\n", ret
);
2077 /***********************************************************************
2078 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2080 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2081 HDEVINFO DeviceInfoSet
,
2082 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2083 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2084 DWORD DeviceInterfaceDetailDataSize
,
2085 PDWORD RequiredSize
,
2086 PSP_DEVINFO_DATA DeviceInfoData
)
2090 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2091 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2092 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2094 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2095 SetLastError(ERROR_INVALID_PARAMETER
);
2096 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2097 SetLastError(ERROR_INVALID_HANDLE
);
2098 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2099 SetLastError(ERROR_INVALID_HANDLE
);
2100 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2101 SetLastError(ERROR_INVALID_USER_BUFFER
);
2102 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2103 SetLastError(ERROR_INVALID_USER_BUFFER
);
2104 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2105 SetLastError(ERROR_INVALID_USER_BUFFER
);
2106 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2107 SetLastError(ERROR_INVALID_PARAMETER
);
2108 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2109 SetLastError(ERROR_INVALID_PARAMETER
);
2112 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2113 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2114 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2115 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2117 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2119 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2121 *RequiredSize
= sizeRequired
;
2125 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2126 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2129 memcpy(&DeviceInfoData
->ClassGuid
,
2130 &deviceInterface
->DeviceInfo
->ClassGuid
,
2132 DeviceInfoData
->DevInst
= 0; /* FIXME */
2133 /* Note: this appears to be dangerous, passing a private
2134 * pointer a heap-allocated datum to the caller. However, the
2135 * expected lifetime of the device data is the same as the
2136 * HDEVINFO; once that is closed, the data are no longer valid.
2138 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2144 TRACE("Returning %d\n", ret
);
2148 /***********************************************************************
2149 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2151 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2153 PSP_DEVINFO_DATA DeviceInfoData
,
2155 PDWORD PropertyRegDataType
,
2156 PBYTE PropertyBuffer
,
2157 DWORD PropertyBufferSize
,
2158 PDWORD RequiredSize
)
2161 BOOL bIsStringProperty
;
2163 DWORD RequiredSizeA
, RequiredSizeW
;
2164 DWORD PropertyBufferSizeW
;
2165 PBYTE PropertyBufferW
;
2167 TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
2168 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2171 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2172 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2174 bResult
= SetupDiGetDeviceRegistryPropertyW(
2180 PropertyBufferSizeW
,
2185 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2189 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2191 if (bIsStringProperty
)
2192 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2194 RequiredSizeA
= RequiredSizeW
;
2196 if (RequiredSizeA
<= PropertyBufferSize
)
2198 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2200 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2202 /* Last error is already set by WideCharToMultiByte */
2207 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2211 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2215 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2216 if (PropertyRegDataType
)
2217 *PropertyRegDataType
= RegType
;
2219 *RequiredSize
= RequiredSizeA
;
2223 /***********************************************************************
2224 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2226 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2227 HDEVINFO DeviceInfoSet
,
2228 PSP_DEVINFO_DATA DeviceInfoData
,
2230 PDWORD PropertyRegDataType
,
2231 PBYTE PropertyBuffer
,
2232 DWORD PropertyBufferSize
,
2233 PDWORD RequiredSize
)
2235 HKEY hEnumKey
, hKey
;
2239 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2240 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2243 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2244 SetLastError(ERROR_INVALID_HANDLE
);
2245 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2246 SetLastError(ERROR_INVALID_HANDLE
);
2247 else if (!DeviceInfoData
)
2248 SetLastError(ERROR_INVALID_PARAMETER
);
2249 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2250 SetLastError(ERROR_INVALID_USER_BUFFER
);
2251 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2252 SetLastError(ERROR_INVALID_PARAMETER
);
2255 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2256 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2260 case SPDRP_CAPABILITIES
:
2262 case SPDRP_CLASSGUID
:
2263 case SPDRP_COMPATIBLEIDS
:
2264 case SPDRP_CONFIGFLAGS
:
2265 case SPDRP_DEVICEDESC
:
2267 case SPDRP_FRIENDLYNAME
:
2268 case SPDRP_HARDWAREID
:
2269 case SPDRP_LOCATION_INFORMATION
:
2270 case SPDRP_LOWERFILTERS
:
2272 case SPDRP_SECURITY
:
2274 case SPDRP_UI_NUMBER
:
2275 case SPDRP_UPPERFILTERS
:
2277 LPCWSTR RegistryPropertyName
;
2282 case SPDRP_CAPABILITIES
:
2283 RegistryPropertyName
= L
"Capabilities"; break;
2285 RegistryPropertyName
= L
"Class"; break;
2286 case SPDRP_CLASSGUID
:
2287 RegistryPropertyName
= L
"ClassGUID"; break;
2288 case SPDRP_COMPATIBLEIDS
:
2289 RegistryPropertyName
= L
"CompatibleIDs"; break;
2290 case SPDRP_CONFIGFLAGS
:
2291 RegistryPropertyName
= L
"ConfigFlags"; break;
2292 case SPDRP_DEVICEDESC
:
2293 RegistryPropertyName
= L
"DeviceDesc"; break;
2295 RegistryPropertyName
= L
"Driver"; break;
2296 case SPDRP_FRIENDLYNAME
:
2297 RegistryPropertyName
= L
"FriendlyName"; break;
2298 case SPDRP_HARDWAREID
:
2299 RegistryPropertyName
= L
"HardwareID"; break;
2300 case SPDRP_LOCATION_INFORMATION
:
2301 RegistryPropertyName
= L
"LocationInformation"; break;
2302 case SPDRP_LOWERFILTERS
:
2303 RegistryPropertyName
= L
"LowerFilters"; break;
2305 RegistryPropertyName
= L
"Mfg"; break;
2306 case SPDRP_SECURITY
:
2307 RegistryPropertyName
= L
"Security"; break;
2309 RegistryPropertyName
= L
"Service"; break;
2310 case SPDRP_UI_NUMBER
:
2311 RegistryPropertyName
= L
"UINumber"; break;
2312 case SPDRP_UPPERFILTERS
:
2313 RegistryPropertyName
= L
"UpperFilters"; break;
2315 /* Should not happen */
2316 RegistryPropertyName
= NULL
; break;
2319 /* Open registry key name */
2324 KEY_ENUMERATE_SUB_KEYS
,
2326 if (rc
!= ERROR_SUCCESS
)
2337 RegCloseKey(hEnumKey
);
2338 if (rc
!= ERROR_SUCCESS
)
2343 /* Read registry entry */
2344 BufferSize
= PropertyBufferSize
;
2345 rc
= RegQueryValueExW(
2347 RegistryPropertyName
,
2348 NULL
, /* Reserved */
2349 PropertyRegDataType
,
2353 *RequiredSize
= BufferSize
;
2354 if (rc
== ERROR_SUCCESS
)
2362 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2364 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2366 if (PropertyRegDataType
)
2367 *PropertyRegDataType
= REG_SZ
;
2369 *RequiredSize
= required
;
2370 if (PropertyBufferSize
>= required
)
2372 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2376 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2380 /*case SPDRP_BUSTYPEGUID:
2381 case SPDRP_LEGACYBUSTYPE:
2382 case SPDRP_BUSNUMBER:
2383 case SPDRP_ENUMERATOR_NAME:
2384 case SPDRP_SECURITY_SDS:
2386 case SPDRP_EXCLUSIVE:
2387 case SPDRP_CHARACTERISTICS:
2389 case SPDRP_UI_NUMBER_DESC_FORMAT:
2390 case SPDRP_DEVICE_POWER_DATA:*/
2391 #if (WINVER >= 0x501)
2392 /*case SPDRP_REMOVAL_POLICY:
2393 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2394 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2395 case SPDRP_INSTALL_STATE:*/
2400 FIXME("Property 0x%lx not implemented\n", Property
);
2401 SetLastError(ERROR_NOT_SUPPORTED
);
2406 TRACE("Returning %d\n", ret
);
2411 /***********************************************************************
2412 * SetupDiInstallClassA (SETUPAPI.@)
2414 BOOL WINAPI
SetupDiInstallClassA(
2420 UNICODE_STRING FileNameW
;
2423 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2425 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2429 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2431 RtlFreeUnicodeString(&FileNameW
);
2436 static HKEY
CreateClassKey(HINF hInf
)
2438 WCHAR FullBuffer
[MAX_PATH
];
2439 WCHAR Buffer
[MAX_PATH
];
2444 if (!SetupGetLineTextW(NULL
,
2452 return INVALID_HANDLE_VALUE
;
2455 lstrcpyW(FullBuffer
, ControlClass
);
2456 lstrcatW(FullBuffer
, Buffer
);
2459 if (!SetupGetLineTextW(NULL
,
2467 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2468 return INVALID_HANDLE_VALUE
;
2471 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2475 REG_OPTION_NON_VOLATILE
,
2481 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2482 return INVALID_HANDLE_VALUE
;
2485 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2490 RequiredSize
* sizeof(WCHAR
)))
2492 RegCloseKey(hClassKey
);
2493 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2494 return INVALID_HANDLE_VALUE
;
2500 /***********************************************************************
2501 * SetupDiInstallClassW (SETUPAPI.@)
2503 BOOL WINAPI
SetupDiInstallClassW(
2509 WCHAR SectionName
[MAX_PATH
];
2510 DWORD SectionNameLength
= 0;
2512 BOOL bFileQueueCreated
= FALSE
;
2515 FIXME("not fully implemented\n");
2517 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2519 SetLastError(ERROR_INVALID_PARAMETER
);
2523 /* Open the .inf file */
2524 hInf
= SetupOpenInfFileW(InfFileName
,
2528 if (hInf
== INVALID_HANDLE_VALUE
)
2534 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2535 hClassKey
= CreateClassKey(hInf
);
2536 if (hClassKey
== INVALID_HANDLE_VALUE
)
2538 SetupCloseInfFile(hInf
);
2544 /* Try to append a layout file */
2546 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2549 /* Retrieve the actual section name */
2550 SetupDiGetActualSectionToInstallW(hInf
,
2558 if (!(Flags
& DI_NOVCP
))
2560 FileQueue
= SetupOpenFileQueue();
2561 if (FileQueue
== INVALID_HANDLE_VALUE
)
2563 SetupCloseInfFile(hInf
);
2564 RegCloseKey(hClassKey
);
2568 bFileQueueCreated
= TRUE
;
2573 SetupInstallFromInfSectionW(NULL
,
2582 INVALID_HANDLE_VALUE
,
2585 /* FIXME: More code! */
2587 if (bFileQueueCreated
)
2588 SetupCloseFileQueue(FileQueue
);
2590 SetupCloseInfFile(hInf
);
2592 RegCloseKey(hClassKey
);
2597 /***********************************************************************
2598 * SetupDiOpenClassRegKey (SETUPAPI.@)
2600 HKEY WINAPI
SetupDiOpenClassRegKey(
2601 const GUID
* ClassGuid
,
2604 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2605 DIOCR_INSTALLER
, NULL
, NULL
);
2609 /***********************************************************************
2610 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2612 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2613 const GUID
* ClassGuid
,
2619 PWSTR MachineNameW
= NULL
;
2626 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2627 if (MachineNameW
== NULL
)
2628 return INVALID_HANDLE_VALUE
;
2631 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2632 Flags
, MachineNameW
, Reserved
);
2635 MyFree(MachineNameW
);
2641 /***********************************************************************
2642 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2644 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2645 const GUID
* ClassGuid
,
2651 LPWSTR lpGuidString
;
2652 LPWSTR lpFullGuidString
;
2660 if (Flags
== DIOCR_INSTALLER
)
2662 lpKeyName
= ControlClass
;
2664 else if (Flags
== DIOCR_INTERFACE
)
2666 lpKeyName
= DeviceClasses
;
2670 ERR("Invalid Flags parameter!\n");
2671 SetLastError(ERROR_INVALID_PARAMETER
);
2672 return INVALID_HANDLE_VALUE
;
2675 if (MachineName
!= NULL
)
2677 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2678 if (rc
!= ERROR_SUCCESS
)
2681 return INVALID_HANDLE_VALUE
;
2685 HKLM
= HKEY_LOCAL_MACHINE
;
2687 rc
= RegOpenKeyExW(HKLM
,
2692 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2693 if (rc
!= ERROR_SUCCESS
)
2696 return INVALID_HANDLE_VALUE
;
2699 if (ClassGuid
== NULL
)
2702 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2704 SetLastError(ERROR_GEN_FAILURE
);
2705 RegCloseKey(hClassesKey
);
2706 return INVALID_HANDLE_VALUE
;
2709 dwLength
= lstrlenW(lpGuidString
);
2710 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2711 if (!lpFullGuidString
)
2713 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2714 RpcStringFreeW(&lpGuidString
);
2715 return INVALID_HANDLE_VALUE
;
2717 lpFullGuidString
[0] = '{';
2718 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2719 lpFullGuidString
[dwLength
+ 1] = '}';
2720 lpFullGuidString
[dwLength
+ 2] = '\0';
2721 RpcStringFreeW(&lpGuidString
);
2723 rc
= RegOpenKeyExW(hClassesKey
,
2728 if (rc
!= ERROR_SUCCESS
)
2731 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2732 RegCloseKey(hClassesKey
);
2733 return INVALID_HANDLE_VALUE
;
2736 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2737 RegCloseKey(hClassesKey
);
2742 /***********************************************************************
2743 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2745 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2746 HDEVINFO DeviceInfoSet
,
2749 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2751 FIXME("%p %s %08lx %p\n",
2752 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2756 /***********************************************************************
2757 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2759 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2760 HDEVINFO DeviceInfoSet
,
2763 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2765 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
2766 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2770 /***********************************************************************
2771 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2773 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2774 HDEVINFO DeviceInfoSet
,
2775 PSP_DEVINFO_DATA DeviceInfoData
,
2776 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2777 DWORD ClassInstallParamsSize
)
2779 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2780 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2784 /***********************************************************************
2785 * SetupDiCallClassInstaller (SETUPAPI.@)
2787 BOOL WINAPI
SetupDiCallClassInstaller(
2788 IN DI_FUNCTION InstallFunction
,
2789 IN HDEVINFO DeviceInfoSet
,
2790 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2794 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2797 SetLastError(ERROR_INVALID_PARAMETER
);
2798 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2799 SetLastError(ERROR_INVALID_HANDLE
);
2800 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2801 SetLastError(ERROR_INVALID_HANDLE
);
2802 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2803 SetLastError(ERROR_INVALID_HANDLE
);
2804 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2805 SetLastError(ERROR_INVALID_USER_BUFFER
);
2808 #define CLASS_COINSTALLER 0x1
2809 #define DEVICE_COINSTALLER 0x2
2810 #define CLASS_INSTALLER 0x4
2811 UCHAR CanHandle
= 0;
2812 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2814 switch (InstallFunction
)
2816 case DIF_ALLOW_INSTALL
:
2817 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2819 case DIF_DESTROYPRIVATEDATA
:
2820 CanHandle
= CLASS_INSTALLER
;
2822 case DIF_INSTALLDEVICE
:
2823 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2824 DefaultHandler
= SetupDiInstallDevice
;
2826 case DIF_INSTALLDEVICEFILES
:
2827 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2828 DefaultHandler
= SetupDiInstallDriverFiles
;
2830 case DIF_INSTALLINTERFACES
:
2831 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2832 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2834 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2835 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2837 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2838 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2840 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2841 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2843 case DIF_REGISTER_COINSTALLERS
:
2844 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2845 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2847 case DIF_SELECTBESTCOMPATDRV
:
2848 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2849 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2852 FIXME("Install function %ld not implemented\n", InstallFunction
);
2853 SetLastError(ERROR_INVALID_PARAMETER
);
2858 LIST_ENTRY ClassCoInstallersListHead
;
2859 LIST_ENTRY DeviceCoInstallersListHead
;
2860 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2861 COINSTALLER_CONTEXT_DATA Context
;
2862 PLIST_ENTRY ListEntry
;
2864 DWORD dwRegType
, dwLength
;
2865 DWORD rc
= NO_ERROR
;
2867 InitializeListHead(&ClassCoInstallersListHead
);
2868 InitializeListHead(&DeviceCoInstallersListHead
);
2870 if (CanHandle
& CLASS_COINSTALLER
)
2872 FIXME("Doesn't use Class co-installers at the moment\n");
2874 if (CanHandle
& DEVICE_COINSTALLER
)
2878 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2882 if (rc
== ERROR_SUCCESS
)
2884 LPWSTR lpGuidString
;
2885 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2887 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2888 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2890 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2891 if (KeyBuffer
!= NULL
)
2893 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2894 if (rc
== ERROR_SUCCESS
)
2897 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2899 /* Add coinstaller to DeviceCoInstallersListHead list */
2900 FIXME("Device coinstaller is '%S'\n", ptr
);
2903 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2906 RpcStringFreeW(&lpGuidString
);
2911 if (CanHandle
& CLASS_INSTALLER
)
2913 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2914 if (hKey
!= INVALID_HANDLE_VALUE
)
2916 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2917 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2919 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2920 if (KeyBuffer
!= NULL
)
2922 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2923 if (rc
== ERROR_SUCCESS
)
2925 /* Set ClassInstaller function pointer */
2926 FIXME("Installer is '%S'\n", KeyBuffer
);
2928 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2935 /* Call Class co-installers */
2936 Context
.PostProcessing
= FALSE
;
2938 ListEntry
= ClassCoInstallersListHead
.Flink
;
2939 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
2941 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2942 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2943 coinstaller
->PrivateData
= Context
.PrivateData
;
2944 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2946 coinstaller
->DoPostProcessing
= TRUE
;
2949 ListEntry
= ListEntry
->Flink
;
2952 /* Call Device co-installers */
2953 ListEntry
= DeviceCoInstallersListHead
.Flink
;
2954 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
2956 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2957 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2958 coinstaller
->PrivateData
= Context
.PrivateData
;
2959 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2961 coinstaller
->DoPostProcessing
= TRUE
;
2964 ListEntry
= ListEntry
->Flink
;
2967 /* Call Class installer */
2969 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2971 rc
= ERROR_DI_DO_DEFAULT
;
2973 /* Call default handler */
2974 if (rc
== ERROR_DI_DO_DEFAULT
)
2976 if (DefaultHandler
/*FIXME && DI_NODI_DEFAULTACTION not set */)
2978 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
2981 rc
= GetLastError();
2987 /* Call Class co-installers that required postprocessing */
2988 Context
.PostProcessing
= TRUE
;
2989 ListEntry
= ClassCoInstallersListHead
.Flink
;
2990 while (ListEntry
!= &ClassCoInstallersListHead
)
2992 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2993 if (coinstaller
->DoPostProcessing
)
2995 Context
.InstallResult
= rc
;
2996 Context
.PrivateData
= coinstaller
->PrivateData
;
2997 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2999 ListEntry
= ListEntry
->Flink
;
3002 /* Call Device co-installers that required postprocessing */
3003 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3004 while (ListEntry
!= &DeviceCoInstallersListHead
)
3006 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3007 if (coinstaller
->DoPostProcessing
)
3009 Context
.InstallResult
= rc
;
3010 Context
.PrivateData
= coinstaller
->PrivateData
;
3011 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3013 ListEntry
= ListEntry
->Flink
;
3016 /* Free allocated memory */
3017 while (!IsListEmpty(&ClassCoInstallersListHead
))
3019 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3020 HeapFree(GetProcessHeap(), 0, ListEntry
);
3022 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3024 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3025 HeapFree(GetProcessHeap(), 0, ListEntry
);
3028 ret
= (rc
== NO_ERROR
);
3032 TRACE("Returning %d\n", ret
);
3036 /***********************************************************************
3037 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3039 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3040 IN HDEVINFO DeviceInfoSet
,
3041 IN PSP_DEVINFO_DATA DeviceInfoData
,
3042 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3044 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3047 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3049 if (DeviceInstallParams
== NULL
)
3050 SetLastError(ERROR_INVALID_PARAMETER
);
3051 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3052 SetLastError(ERROR_INVALID_USER_BUFFER
);
3055 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3056 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3060 /* Do W->A conversion */
3062 DeviceInstallParams
,
3063 &deviceInstallParamsW
,
3064 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3065 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3066 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3068 DeviceInstallParams
->DriverPath
[0] = '\0';
3074 TRACE("Returning %d\n", ret
);
3078 /***********************************************************************
3079 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3081 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3082 IN HDEVINFO DeviceInfoSet
,
3083 IN PSP_DEVINFO_DATA DeviceInfoData
,
3084 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3086 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3090 /***********************************************************************
3091 * SetupDiOpenDevRegKey (SETUPAPI.@)
3093 HKEY WINAPI
SetupDiOpenDevRegKey(
3094 HDEVINFO DeviceInfoSet
,
3095 PSP_DEVINFO_DATA DeviceInfoData
,
3101 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
3102 Scope
, HwProfile
, KeyType
, samDesired
);
3103 return INVALID_HANDLE_VALUE
;
3106 /***********************************************************************
3107 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3109 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3110 HDEVINFO DeviceInfoSet
,
3112 CONST GUID
*ClassGuid
,
3113 PCSTR DeviceDescription
,
3115 DWORD CreationFlags
,
3116 PSP_DEVINFO_DATA DeviceInfoData
)
3118 LPWSTR DeviceNameW
= NULL
;
3119 LPWSTR DeviceDescriptionW
= NULL
;
3126 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3127 if (DeviceNameW
== NULL
) return FALSE
;
3129 if (DeviceDescription
)
3131 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3132 if (DeviceDescriptionW
== NULL
)
3134 if (DeviceNameW
) MyFree(DeviceNameW
);
3139 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3140 ClassGuid
, DeviceDescriptionW
,
3141 hwndParent
, CreationFlags
,
3144 if (DeviceNameW
) MyFree(DeviceNameW
);
3145 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3150 /***********************************************************************
3151 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3153 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3154 HDEVINFO DeviceInfoSet
,
3156 CONST GUID
*ClassGuid
,
3157 PCWSTR DeviceDescription
,
3159 DWORD CreationFlags
,
3160 PSP_DEVINFO_DATA DeviceInfoData
)
3162 struct DeviceInfoSet
*list
;
3165 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3166 debugstr_guid(ClassGuid
), DeviceDescription
,
3167 hwndParent
, CreationFlags
, DeviceInfoData
);
3170 SetLastError(ERROR_INVALID_HANDLE
);
3171 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3172 SetLastError(ERROR_INVALID_HANDLE
);
3173 else if (!ClassGuid
)
3174 SetLastError(ERROR_INVALID_PARAMETER
);
3175 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3176 SetLastError(ERROR_CLASS_MISMATCH
);
3177 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3179 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3180 SetLastError(ERROR_INVALID_PARAMETER
);
3184 SP_DEVINFO_DATA DevInfo
;
3186 if (CreationFlags
& DICD_GENERATE_ID
)
3188 /* Generate a new unique ID for this device */
3189 SetLastError(ERROR_GEN_FAILURE
);
3190 FIXME("not implemented\n");
3194 /* Device name is fully qualified. Try to open it */
3197 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3198 rc
= SetupDiOpenDeviceInfoW(
3201 NULL
, /* hwndParent */
3202 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3207 /* SetupDiOpenDeviceInfoW has already added
3208 * the device info to the device info set
3210 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3212 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3214 struct DeviceInfoElement
*deviceInfo
;
3216 /* FIXME: ClassGuid can be NULL */
3217 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3219 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3221 if (!DeviceInfoData
)
3225 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3227 SetLastError(ERROR_INVALID_USER_BUFFER
);
3231 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3232 DeviceInfoData
->DevInst
= 0; /* FIXME */
3233 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3242 TRACE("Returning %d\n", ret
);
3246 /***********************************************************************
3247 * Helper functions for SetupDiBuildDriverInfoList
3251 IN PLIST_ENTRY DriverListHead
,
3252 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3253 IN INFCONTEXT ContextDevice
,
3255 IN LPCWSTR ProviderName
,
3256 IN LPCWSTR ManufacturerName
,
3257 FILETIME DriverDate
,
3258 DWORDLONG DriverVersion
,
3261 struct DriverInfoElement
*driverInfo
;
3262 DWORD RequiredSize
= 128; /* Initial buffer size */
3263 BOOL Result
= FALSE
;
3264 PLIST_ENTRY PreviousEntry
;
3265 LPWSTR DeviceDescription
= NULL
;
3266 LPWSTR InfInstallSection
= NULL
;
3268 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3271 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3275 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3276 driverInfo
->InfSection
= NULL
;
3277 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3279 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3280 driverInfo
->InfSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3281 if (!driverInfo
->InfSection
)
3283 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3284 HeapFree(GetProcessHeap(), 0, driverInfo
);
3287 Result
= SetupGetStringFieldW(
3290 driverInfo
->InfSection
, RequiredSize
,
3295 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3296 HeapFree(GetProcessHeap(), 0, driverInfo
);
3300 driverInfo
->InfPath
= HeapAlloc(GetProcessHeap(), 0, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3301 if (!driverInfo
->InfPath
)
3303 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3304 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3305 HeapFree(GetProcessHeap(), 0, driverInfo
);
3308 RtlCopyMemory(driverInfo
->InfPath
, InfFile
, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3311 RequiredSize
= 128; /* Initial buffer size */
3312 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3313 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3315 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3316 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3317 if (!DeviceDescription
)
3319 Result
= SetupGetStringFieldW(
3321 0, /* Field index */
3322 DeviceDescription
, RequiredSize
,
3327 HeapFree(GetProcessHeap(), 0, driverInfo
->InfPath
);
3328 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3329 HeapFree(GetProcessHeap(), 0, driverInfo
);
3330 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3335 RequiredSize
= 128; /* Initial buffer size */
3336 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3337 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3339 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3340 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3341 if (!InfInstallSection
)
3343 HeapFree(GetProcessHeap(), 0, driverInfo
->InfPath
);
3344 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3345 HeapFree(GetProcessHeap(), 0, driverInfo
);
3346 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3349 Result
= SetupGetStringFieldW(
3351 1, /* Field index */
3352 InfInstallSection
, RequiredSize
,
3357 HeapFree(GetProcessHeap(), 0, driverInfo
->InfPath
);
3358 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3359 HeapFree(GetProcessHeap(), 0, driverInfo
);
3360 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3361 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3365 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3366 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3368 driverInfo
->DriverRank
= Rank
;
3369 driverInfo
->Info
.DriverType
= DriverType
;
3370 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3371 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3372 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3373 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3374 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3377 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3378 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3381 driverInfo
->Info
.ProviderName
[0] = '\0';
3382 driverInfo
->Info
.DriverDate
= DriverDate
;
3383 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3385 /* Insert current driver in driver list, according to its rank */
3386 PreviousEntry
= DriverListHead
->Flink
;
3387 while (PreviousEntry
!= DriverListHead
)
3389 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3391 /* Insert before the current item */
3392 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3396 if (PreviousEntry
== DriverListHead
)
3398 /* Insert at the end of the list */
3399 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3402 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3403 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3408 GetVersionInformationFromInfFile(
3410 OUT LPGUID ClassGuid
,
3411 OUT LPWSTR
* pProviderName
,
3412 OUT FILETIME
* DriverDate
,
3413 OUT DWORDLONG
* DriverVersion
)
3416 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3417 LPWSTR ProviderName
= NULL
;
3420 if (!SetupGetLineTextW(
3423 L
"Version", L
"ClassGUID",
3424 guidW
, sizeof(guidW
),
3425 NULL
/* Required size */))
3430 /* Get Provider name, driver date, and driver version */
3432 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3433 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3437 Result
= SetupGetLineTextW(
3439 hInf
, L
"Version", L
"Provider",
3442 if (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3444 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3447 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3450 Result
= SetupGetLineTextW(
3452 hInf
, L
"Version", L
"Provider",
3453 ProviderName
, RequiredSize
,
3456 //FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
3457 RtlZeroMemory(DriverDate
, sizeof(FILETIME
));
3458 //FIXME: DriverVersion = Version.DriverVer => invalid = 0
3461 *pProviderName
= ProviderName
;
3465 /***********************************************************************
3466 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3469 SetupDiBuildDriverInfoList(
3470 IN HDEVINFO DeviceInfoSet
,
3471 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3472 IN DWORD DriverType
)
3474 struct DeviceInfoSet
*list
;
3475 PVOID Buffer
= NULL
;
3476 HINF hInf
= INVALID_HANDLE_VALUE
;
3477 LPWSTR ProviderName
= NULL
;
3478 LPWSTR ManufacturerName
= NULL
;
3479 LPWSTR ManufacturerSection
= NULL
;
3480 LPWSTR HardwareIDs
= NULL
;
3481 LPWSTR CompatibleIDs
= NULL
;
3482 FILETIME DriverDate
;
3483 DWORDLONG DriverVersion
;
3487 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3490 SetLastError(ERROR_INVALID_HANDLE
);
3491 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3492 SetLastError(ERROR_INVALID_HANDLE
);
3493 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3494 SetLastError(ERROR_INVALID_HANDLE
);
3495 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3496 SetLastError(ERROR_INVALID_PARAMETER
);
3497 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3498 SetLastError(ERROR_INVALID_PARAMETER
);
3499 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3500 SetLastError(ERROR_INVALID_PARAMETER
);
3501 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3502 SetLastError(ERROR_INVALID_USER_BUFFER
);
3505 BOOL Result
= FALSE
;
3507 if (DriverType
== SPDIT_COMPATDRIVER
)
3509 /* Get hardware IDs list */
3511 RequiredSize
= 512; /* Initial buffer size */
3512 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3513 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3515 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3516 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3519 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3522 Result
= SetupDiGetDeviceRegistryPropertyW(
3534 /* Get compatible IDs list */
3536 RequiredSize
= 512; /* Initial buffer size */
3537 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3538 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3540 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3541 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3544 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3547 Result
= SetupDiGetDeviceRegistryPropertyW(
3550 SPDRP_COMPATIBLEIDS
,
3552 (PBYTE
)CompatibleIDs
,
3555 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3557 /* No compatible ID for this device */
3558 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3559 CompatibleIDs
= NULL
;
3567 /* Enumerate .inf files */
3569 RequiredSize
= 32768; /* Initial buffer size */
3570 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3571 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3573 HeapFree(GetProcessHeap(), 0, Buffer
);
3574 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3578 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3581 Result
= SetupGetInfFileListW(
3582 NULL
, /* Directory path */
3584 Buffer
, RequiredSize
,
3591 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
3593 INFCONTEXT ContextManufacturer
, ContextDevice
;
3595 TRACE("Opening file %S\n", filename
);
3597 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
3598 if (hInf
== INVALID_HANDLE_VALUE
)
3601 if (!GetVersionInformationFromInfFile(
3608 SetupCloseInfFile(hInf
);
3609 hInf
= INVALID_HANDLE_VALUE
;
3613 if (DriverType
== SPDIT_CLASSDRIVER
)
3615 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3616 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
3622 /* Get the manufacturers list */
3623 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
3626 Result
= SetupGetStringFieldW(
3627 &ContextManufacturer
,
3628 0, /* Field index */
3633 /* We got the needed size for the buffer */
3634 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3635 if (!ManufacturerName
)
3637 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3640 Result
= SetupGetStringFieldW(
3641 &ContextManufacturer
,
3642 0, /* Field index */
3643 ManufacturerName
, RequiredSize
,
3646 Result
= SetupGetStringFieldW(
3647 &ContextManufacturer
,
3648 1, /* Field index */
3653 /* We got the needed size for the buffer */
3654 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3655 if (!ManufacturerSection
)
3657 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3660 Result
= SetupGetStringFieldW(
3661 &ContextManufacturer
,
3662 1, /* Field index */
3663 ManufacturerSection
, RequiredSize
,
3667 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
3668 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
3671 if (DriverType
== SPDIT_CLASSDRIVER
)
3673 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3674 if (!AddDriverToList(
3675 &list
->DriverListHead
,
3681 DriverDate
, DriverVersion
,
3687 else /* DriverType = SPDIT_COMPATDRIVER */
3689 /* 1. Get all fields */
3690 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
3694 BOOL DriverAlreadyAdded
;
3696 for (i
= 2; i
<= FieldCount
; i
++)
3698 LPWSTR DeviceId
= NULL
;
3700 RequiredSize
= 128; /* Initial buffer size */
3701 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3702 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3704 HeapFree(GetProcessHeap(), 0, DeviceId
);
3705 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3708 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3711 Result
= SetupGetStringFieldW(
3714 DeviceId
, RequiredSize
,
3719 HeapFree(GetProcessHeap(), 0, DeviceId
);
3722 DriverAlreadyAdded
= FALSE
;
3723 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3725 if (wcscmp(DeviceId
, currentId
) == 0)
3728 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3734 DriverDate
, DriverVersion
,
3735 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
3736 DriverAlreadyAdded
= TRUE
;
3741 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3743 if (wcscmp(DeviceId
, currentId
) == 0)
3746 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3752 DriverDate
, DriverVersion
,
3753 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
3754 DriverAlreadyAdded
= TRUE
;
3758 HeapFree(GetProcessHeap(), 0, DeviceId
);
3761 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
3764 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3765 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3766 ManufacturerName
= ManufacturerSection
= NULL
;
3767 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
3772 HeapFree(GetProcessHeap(), 0, ProviderName
);
3773 ProviderName
= NULL
;
3775 SetupCloseInfFile(hInf
);
3776 hInf
= INVALID_HANDLE_VALUE
;
3787 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3788 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
3791 list
->Flags
|= DI_DIDCLASS
;
3794 HeapFree(GetProcessHeap(), 0, ProviderName
);
3795 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3796 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3797 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3798 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3799 if (hInf
!= INVALID_HANDLE_VALUE
)
3800 SetupCloseInfFile(hInf
);
3801 HeapFree(GetProcessHeap(), 0, Buffer
);
3803 TRACE("Returning %d\n", ret
);
3807 /***********************************************************************
3808 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3811 SetupDiDeleteDeviceInfo(
3812 IN HDEVINFO DeviceInfoSet
,
3813 IN PSP_DEVINFO_DATA DeviceInfoData
)
3815 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3817 FIXME("not implemented\n");
3818 SetLastError(ERROR_GEN_FAILURE
);
3823 /***********************************************************************
3824 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3827 SetupDiDestroyDriverInfoList(
3828 IN HDEVINFO DeviceInfoSet
,
3829 IN PSP_DEVINFO_DATA DeviceInfoData
,
3830 IN DWORD DriverType
)
3832 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3834 FIXME("not implemented\n");
3835 SetLastError(ERROR_GEN_FAILURE
);
3840 /***********************************************************************
3841 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3844 SetupDiOpenDeviceInfoA(
3845 IN HDEVINFO DeviceInfoSet
,
3846 IN PCSTR DeviceInstanceId
,
3847 IN HWND hwndParent OPTIONAL
,
3849 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3851 LPWSTR DeviceInstanceIdW
= NULL
;
3854 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3856 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
3857 if (DeviceInstanceIdW
== NULL
)
3860 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
3861 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
3863 MyFree(DeviceInstanceIdW
);
3869 /***********************************************************************
3870 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3873 SetupDiOpenDeviceInfoW(
3874 IN HDEVINFO DeviceInfoSet
,
3875 IN PCWSTR DeviceInstanceId
,
3876 IN HWND hwndParent OPTIONAL
,
3878 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3880 struct DeviceInfoSet
*list
;
3881 HKEY hEnumKey
, hKey
;
3885 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3887 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
3888 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3891 SetLastError(ERROR_INVALID_HANDLE
);
3892 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3893 SetLastError(ERROR_INVALID_HANDLE
);
3894 else if (!DeviceInstanceId
)
3895 SetLastError(ERROR_INVALID_PARAMETER
);
3896 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
3898 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
3899 SetLastError(ERROR_INVALID_PARAMETER
);
3901 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3902 SetLastError(ERROR_INVALID_USER_BUFFER
);
3905 struct DeviceInfoElement
*deviceInfo
= NULL
;
3906 /* Search if device already exists in DeviceInfoSet.
3907 * If yes, return the existing element
3908 * If no, create a new element using informations in registry
3910 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
3911 while (ItemList
!= &list
->ListHead
)
3916 FIXME("not implemented\n");
3917 ItemList
= ItemList
->Flink
;
3922 /* good one found */
3927 /* Open supposed registry key */
3932 KEY_ENUMERATE_SUB_KEYS
,
3934 if (rc
!= ERROR_SUCCESS
)
3945 RegCloseKey(hEnumKey
);
3946 if (rc
!= ERROR_SUCCESS
)
3952 /* FIXME: GUID_NULL is not allowed */
3953 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
3958 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3964 if (ret
&& deviceInfo
&& DeviceInfoData
)
3966 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
3967 DeviceInfoData
->DevInst
= 0; /* FIXME */
3968 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3976 /***********************************************************************
3977 * SetupDiEnumDriverInfoA (SETUPAPI.@)
3980 SetupDiEnumDriverInfoA(
3981 IN HDEVINFO DeviceInfoSet
,
3982 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3983 IN DWORD DriverType
,
3984 IN DWORD MemberIndex
,
3985 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
3987 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
3990 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
3991 DriverType
, MemberIndex
, DriverInfoData
);
3993 if (DriverInfoData
== NULL
)
3994 SetLastError(ERROR_INVALID_PARAMETER
);
3995 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
3996 SetLastError(ERROR_INVALID_USER_BUFFER
);
3999 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4000 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4001 DriverType
, MemberIndex
, &driverInfoData2W
);
4005 /* Do W->A conversion */
4006 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4007 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4008 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4009 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4011 DriverInfoData
->Description
[0] = '\0';
4014 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4015 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4017 DriverInfoData
->MfgName
[0] = '\0';
4020 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4021 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4023 DriverInfoData
->ProviderName
[0] = '\0';
4026 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4028 /* Copy more fields */
4029 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4030 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4035 TRACE("Returning %d\n", ret
);
4040 /***********************************************************************
4041 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4044 SetupDiEnumDriverInfoW(
4045 IN HDEVINFO DeviceInfoSet
,
4046 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4047 IN DWORD DriverType
,
4048 IN DWORD MemberIndex
,
4049 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4051 PLIST_ENTRY ListHead
;
4054 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4055 DriverType
, MemberIndex
, DriverInfoData
);
4057 if (!DeviceInfoSet
|| !DriverInfoData
)
4058 SetLastError(ERROR_INVALID_PARAMETER
);
4059 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4060 SetLastError(ERROR_INVALID_HANDLE
);
4061 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4062 SetLastError(ERROR_INVALID_HANDLE
);
4063 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4064 SetLastError(ERROR_INVALID_PARAMETER
);
4065 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4066 SetLastError(ERROR_INVALID_PARAMETER
);
4067 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4068 SetLastError(ERROR_INVALID_PARAMETER
);
4069 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4070 SetLastError(ERROR_INVALID_USER_BUFFER
);
4073 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4074 PLIST_ENTRY ItemList
;
4075 if (DriverType
== SPDIT_CLASSDRIVER
||
4076 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4078 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4082 ListHead
= &devInfo
->DriverListHead
;
4085 ItemList
= ListHead
->Flink
;
4086 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4087 ItemList
= ItemList
->Flink
;
4088 if (ItemList
== ListHead
)
4089 SetLastError(ERROR_NO_MORE_ITEMS
);
4092 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4095 &DriverInfoData
->DriverType
,
4096 &DrvInfo
->Info
.DriverType
,
4097 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4102 TRACE("Returning %d\n", ret
);
4106 /***********************************************************************
4107 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4110 SetupDiGetSelectedDriverW(
4111 IN HDEVINFO DeviceInfoSet
,
4112 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4113 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4117 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4119 if (!DeviceInfoSet
|| !DriverInfoData
)
4120 SetLastError(ERROR_INVALID_PARAMETER
);
4121 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4122 SetLastError(ERROR_INVALID_HANDLE
);
4123 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4124 SetLastError(ERROR_INVALID_HANDLE
);
4125 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4126 SetLastError(ERROR_INVALID_USER_BUFFER
);
4127 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4128 SetLastError(ERROR_INVALID_USER_BUFFER
);
4131 struct DriverInfoElement
*driverInfo
;
4134 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4136 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4138 if (driverInfo
== NULL
)
4139 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4143 &DriverInfoData
->DriverType
,
4144 &driverInfo
->Info
.DriverType
,
4145 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4150 TRACE("Returning %d\n", ret
);
4154 /***********************************************************************
4155 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4158 SetupDiSetSelectedDriverW(
4159 IN HDEVINFO DeviceInfoSet
,
4160 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4161 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4165 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4168 SetLastError(ERROR_INVALID_PARAMETER
);
4169 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4170 SetLastError(ERROR_INVALID_HANDLE
);
4171 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4172 SetLastError(ERROR_INVALID_HANDLE
);
4173 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4174 SetLastError(ERROR_INVALID_USER_BUFFER
);
4175 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4176 SetLastError(ERROR_INVALID_USER_BUFFER
);
4179 struct DriverInfoElement
**pDriverInfo
;
4180 PLIST_ENTRY ListHead
, ItemList
;
4184 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4185 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4189 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4190 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4193 if (!DriverInfoData
)
4195 *pDriverInfo
= NULL
;
4200 /* Search selected driver in list */
4201 ItemList
= ListHead
->Flink
;
4202 while (ItemList
!= ListHead
)
4204 if (DriverInfoData
->Reserved
!= 0)
4206 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4211 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4212 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4213 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4214 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4215 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4221 if (ItemList
== ListHead
)
4222 SetLastError(ERROR_INVALID_PARAMETER
);
4225 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4226 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4228 TRACE("Choosing driver whose rank is 0x%lx\n",
4229 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
4234 TRACE("Returning %d\n", ret
);
4238 /***********************************************************************
4239 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4242 SetupDiSelectBestCompatDrv(
4243 IN HDEVINFO DeviceInfoSet
,
4244 IN PSP_DEVINFO_DATA DeviceInfoData
)
4246 SP_DRVINFO_DATA_W drvInfoData
;
4249 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4251 /* Drivers are sorted by rank in the driver list, so
4252 * the first driver in the list is the best one.
4254 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4255 ret
= SetupDiEnumDriverInfoW(
4259 0, /* Member index */
4264 ret
= SetupDiSetSelectedDriverW(
4270 TRACE("Returning %d\n", ret
);
4274 /***********************************************************************
4275 * SetupDiInstallDriverFiles (SETUPAPI.@)
4278 SetupDiInstallDriverFiles(
4279 IN HDEVINFO DeviceInfoSet
,
4280 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4284 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4287 SetLastError(ERROR_INVALID_PARAMETER
);
4288 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4289 SetLastError(ERROR_INVALID_HANDLE
);
4290 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4291 SetLastError(ERROR_INVALID_HANDLE
);
4292 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4293 SetLastError(ERROR_INVALID_USER_BUFFER
);
4294 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4295 SetLastError(ERROR_INVALID_PARAMETER
);
4296 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4297 SetLastError(ERROR_INVALID_PARAMETER
);
4300 struct DriverInfoElement
*DriverInfo
;
4306 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4307 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4311 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4312 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4315 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4316 if (hInf
!= INVALID_HANDLE_VALUE
)
4318 WCHAR SectionName
[MAX_PATH
];
4319 DWORD SectionNameLength
= 0;
4321 ret
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4322 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4325 PVOID callback_context
= SetupInitDefaultQueueCallback(hWnd
);
4326 ret
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4327 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
4328 SetupDefaultQueueCallbackW
, callback_context
,
4330 SetupTermDefaultQueueCallback(callback_context
);
4332 SetupCloseInfFile(hInf
);
4336 TRACE("Returning %d\n", ret
);
4340 /***********************************************************************
4341 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4344 SetupDiRegisterCoDeviceInstallers(
4345 IN HDEVINFO DeviceInfoSet
,
4346 IN PSP_DEVINFO_DATA DeviceInfoData
)
4348 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4350 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4351 //SetLastError(ERROR_GEN_FAILURE);
4356 /***********************************************************************
4357 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4360 SetupDiInstallDeviceInterfaces(
4361 IN HDEVINFO DeviceInfoSet
,
4362 IN PSP_DEVINFO_DATA DeviceInfoData
)
4364 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4366 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4367 //SetLastError(ERROR_GEN_FAILURE);
4372 /***********************************************************************
4373 * SetupDiInstallDevice (SETUPAPI.@)
4376 SetupDiInstallDevice(
4377 IN HDEVINFO DeviceInfoSet
,
4378 IN PSP_DEVINFO_DATA DeviceInfoData
)
4380 struct DriverInfoElement
*DriverInfo
;
4381 struct DeviceInfoSet
*DevInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
;
4382 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4383 SYSTEMTIME DriverDate
;
4384 WCHAR SectionName
[MAX_PATH
];
4385 DWORD SectionNameLength
= 0;
4386 BOOL Result
= FALSE
;
4387 INFCONTEXT ContextService
;
4391 LPCWSTR AssociatedService
= NULL
;
4392 BOOL RebootRequired
= FALSE
;
4393 HKEY hEnumKey
, hKey
;
4396 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4399 SetLastError(ERROR_INVALID_PARAMETER
);
4400 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4401 SetLastError(ERROR_INVALID_HANDLE
);
4402 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4403 SetLastError(ERROR_INVALID_HANDLE
);
4404 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4405 SetLastError(ERROR_INVALID_USER_BUFFER
);
4406 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4407 SetLastError(ERROR_INVALID_PARAMETER
);
4408 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4409 SetLastError(ERROR_INVALID_PARAMETER
);
4415 /* One parameter is bad */
4419 /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
4422 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4424 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4425 FileTimeToSystemTime(&DriverInfo
->Info
.DriverDate
, &DriverDate
);
4427 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4428 if (hInf
== INVALID_HANDLE_VALUE
)
4431 Result
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4432 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4433 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
4435 SetupCloseInfFile(hInf
);
4439 /* Create driver key information */
4440 FIXME("FIXME: Create driver key information\n");
4442 /* Write information to driver key */
4443 FIXME("FIXME: Write information to driver key\n");
4444 FIXME("DriverDate : '%u-%u-%u'\n", 0, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4445 FIXME("DriverDateData :"); { ULONG i
; for (i
= 0; i
< sizeof(DriverInfo
->Info
.DriverDate
); i
++) DbgPrint(" %02x", ((PCHAR
)&DriverInfo
->Info
.DriverDate
)[i
] & 0xff); } DbgPrint("\n");
4446 FIXME("DriverDesc : '%S'\n", DriverInfo
->Info
.Description
);
4447 FIXME("DriverVersion : '%u.%u.%u.%u'\n", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4448 FIXME("InfPath : '%S'\n", DriverInfo
->InfPath
);
4449 FIXME("InfSection : '%S'\n", DriverInfo
->InfSection
); /* FIXME: remove extension */
4450 FIXME("InfSectionExt : '%S'\n", L
"???"); /* FIXME */
4451 FIXME("MatchingDeviceId: '%S'\n", L
"???"); /* FIXME */
4452 FIXME("ProviderName : '%S'\n", DriverInfo
->Info
.ProviderName
);
4454 /* Install services */
4455 wcscat(SectionName
, L
".Services");
4456 Result
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
4459 LPWSTR ServiceName
= NULL
;
4460 LPWSTR ServiceSection
= NULL
;
4462 Result
= SetupGetStringFieldW(
4464 1, /* Field index */
4469 if (RequiredSize
> 0)
4471 /* We got the needed size for the buffer */
4472 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4475 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4478 Result
= SetupGetStringFieldW(
4480 1, /* Field index */
4481 ServiceName
, RequiredSize
,
4486 Result
= SetupGetIntField(
4488 2, /* Field index */
4492 /* The field may be empty. Ignore the error */
4495 Result
= SetupGetStringFieldW(
4497 3, /* Field index */
4502 if (RequiredSize
> 0)
4504 /* We got the needed size for the buffer */
4505 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4506 if (!ServiceSection
)
4508 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4511 Result
= SetupGetStringFieldW(
4513 3, /* Field index */
4514 ServiceSection
, RequiredSize
,
4519 SetLastError(ERROR_SUCCESS
);
4520 Result
= SetupInstallServicesFromInfSectionExW(hInf
, ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, NULL
, NULL
);
4521 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
4523 AssociatedService
= ServiceName
;
4525 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
4526 RebootRequired
= TRUE
;
4529 HeapFree(GetProcessHeap(), 0, ServiceName
);
4530 HeapFree(GetProcessHeap(), 0, ServiceSection
);
4533 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4534 SetupCloseInfFile(hInf
);
4537 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
4540 /* Copy .inf file to Inf\ directory */
4541 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
4543 /* Write information to enum key */
4544 rc
= RegOpenKeyExW(DevInfoSet
->HKLM
,
4547 KEY_ENUMERATE_SUB_KEYS
,
4549 if (rc
!= ERROR_SUCCESS
)
4552 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4553 SetupCloseInfFile(hInf
);
4558 DevInfo
->DeviceName
,
4562 RegCloseKey(hEnumKey
);
4563 if (rc
!= ERROR_SUCCESS
)
4566 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4567 SetupCloseInfFile(hInf
);
4570 FIXME("FIXME: Write information to enum key\n");
4571 FIXME("ParentIdPrefix : '%S'\n", L
"0000"); /* FIXME */
4572 //FIXME("Service : '%S'\n", AssociatedService);
4573 FIXME("Class : '%S'\n", L
"???"); /* FIXME: SetupDiGetINFClass */
4574 FIXME("ClassGUID : '%S'\n", L
"???"); /* FIXME: SetupDiGetINFClass */
4575 //FIXME("DeviceDesc : '%S'\n", DriverInfo->Info.Description);
4576 FIXME("Driver : '%S'\n", L
"???"); /* FIXME: autogenerated key */
4577 //FIXME("Mfg : '%S'\n", DriverInfo->Info.MfgName);
4578 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
4579 if (rc
== ERROR_SUCCESS
)
4580 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
4581 if (rc
== ERROR_SUCCESS
)
4582 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.MfgName
, (wcslen(DriverInfo
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
4584 if (rc
!= ERROR_SUCCESS
)
4587 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4588 SetupCloseInfFile(hInf
);
4592 /* Load the driver/call AddDevice */
4593 FIXME("FIXME: Load the driver/call AddDevice\n");
4595 /* Send IRP_MN_START_DEVICE if needed */
4596 //if (!RebootRequired && !(Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
4597 FIXME("FIXME: Send IRP_MN_START_DEVICE\n");
4599 /* End of installation */
4600 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4601 SetupCloseInfFile(hInf
);