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
;
137 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
139 LIST_ENTRY ListEntry
;
141 /* Information about devnode:
143 * "Root\*PNP0501" for example.
144 * It doesn't contain the unique ID for the device
145 * (points into the Data field at the end of the structure)
146 * WARNING: no NULL char exist between DeviceName and UniqueId
149 * "5&1be2108e&0" or "0000"
150 * If DICD_GENERATE_ID is specified in creation flags,
151 * this unique ID is autogenerated using 4 digits, base 10
152 * (points into the Data field at the end of the structure)
153 * - DeviceDescription
154 * String which identifies the device. Can be NULL. If not NULL,
155 * points into the Data field at the end of the structure
157 * Identifies the class of this device. FIXME: can it be GUID_NULL?
159 * Is a combination of:
161 * the unique ID needs to be generated
162 * - DICD_INHERIT_CLASSDRVS
163 * inherit driver of the device info set (== same pointer)
165 * Used when doing device-specific actions. Can be NULL
169 PCWSTR DeviceDescription
;
174 /* Flags is a combination of:
176 * Set when the device driver list is created
177 * FlagsEx is a combination of:
182 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
183 /* If the driver is not searched/detected, this list is empty */
184 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
185 /* Points into DriverListHead list. The pointer is NULL if no driver is
186 * currently chosen. */
187 struct DriverInfoElement
*SelectedDriver
;
189 /* List of interfaces implemented by this device */
190 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
195 struct DeviceInfoSet
/* HDEVINFO */
197 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
198 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
199 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
200 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
202 /* Flags is a combination of:
204 * Set when the class driver list is created
205 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
206 * Forces SetupDiBuildDriverInfoList to build a class drivers list
207 * FlagsEx is a combination of:
212 /* If the driver is not searched/detected, this list is empty */
213 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
214 /* Points into DriverListHead list. The pointer is NULL if no driver is
215 * currently chosen. */
216 struct DriverInfoElement
*SelectedDriver
;
218 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
221 /***********************************************************************
222 * SetupDiBuildClassInfoList (SETUPAPI.@)
224 BOOL WINAPI
SetupDiBuildClassInfoList(
226 LPGUID ClassGuidList
,
227 DWORD ClassGuidListSize
,
231 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
232 ClassGuidListSize
, RequiredSize
,
236 /***********************************************************************
237 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
239 BOOL WINAPI
SetupDiBuildClassInfoListExA(
241 LPGUID ClassGuidList
,
242 DWORD ClassGuidListSize
,
247 LPWSTR MachineNameW
= NULL
;
254 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
255 if (MachineNameW
== NULL
) return FALSE
;
258 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
259 ClassGuidListSize
, RequiredSize
,
260 MachineNameW
, Reserved
);
263 MyFree(MachineNameW
);
268 /***********************************************************************
269 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
271 BOOL WINAPI
SetupDiBuildClassInfoListExW(
273 LPGUID ClassGuidList
,
274 DWORD ClassGuidListSize
,
279 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
285 DWORD dwGuidListIndex
= 0;
289 if (RequiredSize
!= NULL
)
292 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
297 if (hClassesKey
== INVALID_HANDLE_VALUE
)
302 for (dwIndex
= 0; ; dwIndex
++)
304 dwLength
= MAX_GUID_STRING_LEN
+ 1;
305 lError
= RegEnumKeyExW(hClassesKey
,
313 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
314 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
316 TRACE("Key name: %p\n", szKeyName
);
318 if (RegOpenKeyExW(hClassesKey
,
324 RegCloseKey(hClassesKey
);
328 if (!RegQueryValueExW(hClassKey
,
335 TRACE("'NoUseClass' value found!\n");
336 RegCloseKey(hClassKey
);
340 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
341 (!RegQueryValueExW(hClassKey
,
348 TRACE("'NoInstallClass' value found!\n");
349 RegCloseKey(hClassKey
);
353 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
354 (!RegQueryValueExW(hClassKey
,
361 TRACE("'NoDisplayClass' value found!\n");
362 RegCloseKey(hClassKey
);
366 RegCloseKey(hClassKey
);
368 TRACE("Guid: %p\n", szKeyName
);
369 if (dwGuidListIndex
< ClassGuidListSize
)
371 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
375 TRACE("Guid: %p\n", &szKeyName
[1]);
377 UuidFromStringW(&szKeyName
[1],
378 &ClassGuidList
[dwGuidListIndex
]);
384 if (lError
!= ERROR_SUCCESS
)
388 RegCloseKey(hClassesKey
);
390 if (RequiredSize
!= NULL
)
391 *RequiredSize
= dwGuidListIndex
;
393 if (ClassGuidListSize
< dwGuidListIndex
)
395 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
402 /***********************************************************************
403 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
405 BOOL WINAPI
SetupDiClassGuidsFromNameA(
407 LPGUID ClassGuidList
,
408 DWORD ClassGuidListSize
,
411 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
412 ClassGuidListSize
, RequiredSize
,
416 /***********************************************************************
417 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
419 BOOL WINAPI
SetupDiClassGuidsFromNameW(
421 LPGUID ClassGuidList
,
422 DWORD ClassGuidListSize
,
425 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
426 ClassGuidListSize
, RequiredSize
,
430 /***********************************************************************
431 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
433 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
435 LPGUID ClassGuidList
,
436 DWORD ClassGuidListSize
,
441 LPWSTR ClassNameW
= NULL
;
442 LPWSTR MachineNameW
= NULL
;
447 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
448 if (ClassNameW
== NULL
)
453 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
454 if (MachineNameW
== NULL
)
461 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
462 ClassGuidListSize
, RequiredSize
,
463 MachineNameW
, Reserved
);
466 MyFree(MachineNameW
);
473 /***********************************************************************
474 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
476 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
478 LPGUID ClassGuidList
,
479 DWORD ClassGuidListSize
,
484 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
485 WCHAR szClassName
[256];
491 DWORD dwGuidListIndex
= 0;
493 if (RequiredSize
!= NULL
)
496 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
497 KEY_ENUMERATE_SUB_KEYS
,
501 if (hClassesKey
== INVALID_HANDLE_VALUE
)
506 for (dwIndex
= 0; ; dwIndex
++)
508 dwLength
= MAX_GUID_STRING_LEN
+ 1;
509 lError
= RegEnumKeyExW(hClassesKey
,
517 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
518 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
520 TRACE("Key name: %p\n", szKeyName
);
522 if (RegOpenKeyExW(hClassesKey
,
528 RegCloseKey(hClassesKey
);
532 dwLength
= 256 * sizeof(WCHAR
);
533 if (!RegQueryValueExW(hClassKey
,
540 TRACE("Class name: %p\n", szClassName
);
542 if (strcmpiW(szClassName
, ClassName
) == 0)
544 TRACE("Found matching class name\n");
546 TRACE("Guid: %p\n", szKeyName
);
547 if (dwGuidListIndex
< ClassGuidListSize
)
549 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
553 TRACE("Guid: %p\n", &szKeyName
[1]);
555 UuidFromStringW(&szKeyName
[1],
556 &ClassGuidList
[dwGuidListIndex
]);
563 RegCloseKey(hClassKey
);
566 if (lError
!= ERROR_SUCCESS
)
570 RegCloseKey(hClassesKey
);
572 if (RequiredSize
!= NULL
)
573 *RequiredSize
= dwGuidListIndex
;
575 if (ClassGuidListSize
< dwGuidListIndex
)
577 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
584 /***********************************************************************
585 * SetupDiClassNameFromGuidA (SETUPAPI.@)
587 BOOL WINAPI
SetupDiClassNameFromGuidA(
588 const GUID
* ClassGuid
,
593 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
594 ClassNameSize
, RequiredSize
,
598 /***********************************************************************
599 * SetupDiClassNameFromGuidW (SETUPAPI.@)
601 BOOL WINAPI
SetupDiClassNameFromGuidW(
602 const GUID
* ClassGuid
,
607 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
608 ClassNameSize
, RequiredSize
,
612 /***********************************************************************
613 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
615 BOOL WINAPI
SetupDiClassNameFromGuidExA(
616 const GUID
* ClassGuid
,
623 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
624 LPWSTR MachineNameW
= NULL
;
628 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
629 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
630 NULL
, MachineNameW
, Reserved
);
633 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
634 ClassNameSize
, NULL
, NULL
);
636 if (!ClassNameSize
&& RequiredSize
)
639 MyFree(MachineNameW
);
643 /***********************************************************************
644 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
646 BOOL WINAPI
SetupDiClassNameFromGuidExW(
647 const GUID
* ClassGuid
,
658 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
663 if (hKey
== INVALID_HANDLE_VALUE
)
668 if (RequiredSize
!= NULL
)
671 rc
= RegQueryValueExW(hKey
,
677 if (rc
!= ERROR_SUCCESS
)
684 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
687 dwLength
= ClassNameSize
* sizeof(WCHAR
);
688 rc
= RegQueryValueExW(hKey
,
694 if (rc
!= ERROR_SUCCESS
)
706 /***********************************************************************
707 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
710 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
713 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
716 /***********************************************************************
717 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
720 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
725 LPWSTR MachineNameW
= NULL
;
728 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
732 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
733 if (MachineNameW
== NULL
)
734 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
737 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
738 MachineNameW
, Reserved
);
741 MyFree(MachineNameW
);
746 /***********************************************************************
747 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
750 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
755 struct DeviceInfoSet
*list
;
758 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
760 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
763 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
764 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
767 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
770 ClassGuid
? ClassGuid
: &GUID_NULL
,
771 sizeof(list
->ClassGuid
));
772 list
->hwndParent
= hwndParent
;
775 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
776 if (rc
!= ERROR_SUCCESS
)
779 HeapFree(GetProcessHeap(), 0, list
);
780 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
785 list
->HKLM
= HKEY_LOCAL_MACHINE
;
787 list
->Flags
= 0; /* FIXME */
788 list
->FlagsEx
= 0; /* FIXME */
789 InitializeListHead(&list
->DriverListHead
);
790 InitializeListHead(&list
->ListHead
);
791 return (HDEVINFO
)list
;
794 /***********************************************************************
795 * SetupDiEnumDeviceInfo (SETUPAPI.@)
797 BOOL WINAPI
SetupDiEnumDeviceInfo(
798 HDEVINFO DeviceInfoSet
,
800 PSP_DEVINFO_DATA DeviceInfoData
)
804 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
806 SetLastError(ERROR_INVALID_PARAMETER
);
807 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
809 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
811 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
812 SetLastError(ERROR_INVALID_HANDLE
);
813 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
814 SetLastError(ERROR_INVALID_USER_BUFFER
);
817 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
818 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
819 ItemList
= ItemList
->Flink
;
820 if (ItemList
== &list
->ListHead
)
821 SetLastError(ERROR_NO_MORE_ITEMS
);
824 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
825 memcpy(&DeviceInfoData
->ClassGuid
,
828 DeviceInfoData
->DevInst
= 0; /* FIXME */
829 /* Note: this appears to be dangerous, passing a private
830 * pointer a heap-allocated datum to the caller. However, the
831 * expected lifetime of the device data is the same as the
832 * HDEVINFO; once that is closed, the data are no longer valid.
834 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
840 SetLastError(ERROR_INVALID_HANDLE
);
844 /***********************************************************************
845 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
847 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
849 PCSTR InfSectionName
,
850 PSTR InfSectionWithExt
,
851 DWORD InfSectionWithExtSize
,
855 LPWSTR InfSectionNameW
= NULL
;
856 PWSTR InfSectionWithExtW
= NULL
;
858 BOOL bResult
= FALSE
;
864 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
865 if (InfSectionNameW
== NULL
) goto end
;
867 if (InfSectionWithExt
)
869 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
870 if (InfSectionWithExtW
== NULL
) goto end
;
873 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
874 InfSectionWithExt
? InfSectionNameW
: NULL
,
875 InfSectionWithExtSize
, RequiredSize
,
876 Extension
? &ExtensionW
: NULL
);
878 if (bResult
&& InfSectionWithExt
)
880 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
881 InfSectionWithExtSize
, NULL
, NULL
) != 0;
883 if (bResult
&& Extension
)
885 if (ExtensionW
== NULL
)
888 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
892 if (InfSectionNameW
) MyFree(InfSectionNameW
);
893 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
898 /***********************************************************************
899 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
901 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
903 PCWSTR InfSectionName
,
904 PWSTR InfSectionWithExt
,
905 DWORD InfSectionWithExtSize
,
909 WCHAR szBuffer
[MAX_PATH
];
912 LONG lLineCount
= -1;
914 lstrcpyW(szBuffer
, InfSectionName
);
915 dwLength
= lstrlenW(szBuffer
);
917 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
919 /* Test section name with '.NTx86' extension */
920 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
921 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
923 if (lLineCount
== -1)
925 /* Test section name with '.NT' extension */
926 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
927 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
932 /* Test section name with '.Win' extension */
933 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
934 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
937 if (lLineCount
== -1)
939 /* Test section name without extension */
940 szBuffer
[dwLength
] = 0;
941 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
944 if (lLineCount
== -1)
946 SetLastError(ERROR_INVALID_PARAMETER
);
950 dwFullLength
= lstrlenW(szBuffer
);
952 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
954 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
956 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
960 lstrcpyW(InfSectionWithExt
, szBuffer
);
961 if (Extension
!= NULL
)
963 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
967 if (RequiredSize
!= NULL
)
969 *RequiredSize
= dwFullLength
+ 1;
975 /***********************************************************************
976 * SetupDiGetClassDescriptionA (SETUPAPI.@)
978 BOOL WINAPI
SetupDiGetClassDescriptionA(
979 const GUID
* ClassGuid
,
980 PSTR ClassDescription
,
981 DWORD ClassDescriptionSize
,
984 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
985 ClassDescriptionSize
,
986 RequiredSize
, NULL
, NULL
);
989 /***********************************************************************
990 * SetupDiGetClassDescriptionW (SETUPAPI.@)
992 BOOL WINAPI
SetupDiGetClassDescriptionW(
993 const GUID
* ClassGuid
,
994 PWSTR ClassDescription
,
995 DWORD ClassDescriptionSize
,
998 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
999 ClassDescriptionSize
,
1000 RequiredSize
, NULL
, NULL
);
1003 /***********************************************************************
1004 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1006 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1007 const GUID
* ClassGuid
,
1008 PSTR ClassDescription
,
1009 DWORD ClassDescriptionSize
,
1010 PDWORD RequiredSize
,
1014 PWCHAR ClassDescriptionW
;
1015 LPWSTR MachineNameW
= NULL
;
1019 if (ClassDescriptionSize
> 0)
1021 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1022 if (!ClassDescriptionW
)
1024 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1030 ClassDescriptionW
= NULL
;
1034 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1037 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1043 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1044 NULL
, MachineNameW
, Reserved
);
1047 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1048 ClassDescriptionSize
, NULL
, NULL
);
1050 if (!ClassDescriptionSize
&& RequiredSize
)
1051 *RequiredSize
= len
;
1055 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1056 MyFree(MachineNameW
);
1060 /***********************************************************************
1061 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1063 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1064 const GUID
* ClassGuid
,
1065 PWSTR ClassDescription
,
1066 DWORD ClassDescriptionSize
,
1067 PDWORD RequiredSize
,
1074 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1079 if (hKey
== INVALID_HANDLE_VALUE
)
1081 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1085 if (RequiredSize
!= NULL
)
1088 if (RegQueryValueExW(hKey
,
1099 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1102 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1103 if (RegQueryValueExW(hKey
,
1107 (LPBYTE
)ClassDescription
,
1119 /***********************************************************************
1120 * SetupDiGetClassDevsA (SETUPAPI.@)
1122 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1128 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1129 flags
, NULL
, NULL
, NULL
);
1132 /***********************************************************************
1133 * SetupDiGetClassDevsW (SETUPAPI.@)
1135 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1141 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1142 flags
, NULL
, NULL
, NULL
);
1145 /***********************************************************************
1146 * SetupDiGetClassDevsExA (SETUPAPI.@)
1148 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1158 LPWSTR enumstrW
= NULL
;
1159 LPWSTR machineW
= NULL
;
1163 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1164 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1167 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1170 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1174 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1175 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1178 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1181 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1183 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1186 HeapFree(GetProcessHeap(), 0, enumstrW
);
1187 HeapFree(GetProcessHeap(), 0, machineW
);
1192 CreateDeviceInfoElement(
1193 IN LPCWSTR InstancePath
,
1195 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1197 struct DeviceInfoElement
*deviceInfo
;
1199 *pDeviceInfo
= NULL
;
1200 if (IsEqualIID(&pClassGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1202 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1205 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1208 wcscpy(deviceInfo
->Data
, InstancePath
);
1209 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1210 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1211 deviceInfo
->DeviceDescription
= NULL
;
1212 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1213 deviceInfo
->CreationFlags
= 0;
1214 deviceInfo
->hwndParent
= NULL
;
1215 deviceInfo
->Flags
= 0; /* FIXME */
1216 deviceInfo
->FlagsEx
= 0; /* FIXME */
1217 deviceInfo
->SelectedDriver
= NULL
;
1218 InitializeListHead(&deviceInfo
->DriverListHead
);
1219 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1221 *pDeviceInfo
= deviceInfo
;
1226 CreateDeviceInterface(
1227 IN
struct DeviceInfoElement
* deviceInfo
,
1228 IN LPCWSTR SymbolicLink
,
1229 IN LPCGUID pInterfaceGuid
,
1230 OUT
struct DeviceInterface
**pDeviceInterface
)
1232 struct DeviceInterface
*deviceInterface
;
1234 *pDeviceInterface
= NULL
;
1236 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1237 if (!deviceInterface
)
1239 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1242 deviceInterface
->DeviceInfo
= deviceInfo
;
1243 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1244 deviceInterface
->Flags
= 0; /* FIXME */
1245 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1247 *pDeviceInterface
= deviceInterface
;
1251 static LONG
SETUP_CreateDevListFromEnumerator(
1252 struct DeviceInfoSet
*list
,
1253 LPCGUID pClassGuid OPTIONAL
,
1255 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1257 HKEY hDeviceIdKey
, hInstanceIdKey
;
1258 WCHAR KeyBuffer
[MAX_PATH
];
1259 WCHAR InstancePath
[MAX_PATH
];
1260 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1261 struct DeviceInfoElement
*deviceInfo
;
1263 DWORD dwLength
, dwRegType
;
1266 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1269 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1270 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1271 if (rc
== ERROR_NO_MORE_ITEMS
)
1273 if (rc
!= ERROR_SUCCESS
)
1277 /* Open device id sub key */
1278 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1279 if (rc
!= ERROR_SUCCESS
)
1281 wcscpy(InstancePath
, Enumerator
);
1282 wcscat(InstancePath
, L
"\\");
1283 wcscat(InstancePath
, KeyBuffer
);
1284 wcscat(InstancePath
, L
"\\");
1285 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1287 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1293 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1294 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1295 if (rc
== ERROR_NO_MORE_ITEMS
)
1297 if (rc
!= ERROR_SUCCESS
)
1299 RegCloseKey(hDeviceIdKey
);
1304 /* Open instance id sub key */
1305 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1306 if (rc
!= ERROR_SUCCESS
)
1308 RegCloseKey(hDeviceIdKey
);
1311 *pEndOfInstancePath
= '\0';
1312 wcscat(InstancePath
, KeyBuffer
);
1314 /* Read ClassGUID value */
1315 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1316 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1317 RegCloseKey(hInstanceIdKey
);
1318 if (rc
== ERROR_FILE_NOT_FOUND
)
1321 /* Skip this bad entry as we can't verify it */
1324 else if (rc
!= ERROR_SUCCESS
)
1326 RegCloseKey(hDeviceIdKey
);
1329 else if (dwRegType
!= REG_SZ
)
1331 RegCloseKey(hDeviceIdKey
);
1332 return ERROR_GEN_FAILURE
;
1335 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1336 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1338 RegCloseKey(hDeviceIdKey
);
1339 return GetLastError();
1341 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1343 /* Skip this entry as it is not the right device class */
1347 /* Add the entry to the list */
1348 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1350 RegCloseKey(hDeviceIdKey
);
1351 return GetLastError();
1353 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1354 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1356 RegCloseKey(hDeviceIdKey
);
1359 return ERROR_SUCCESS
;
1362 static LONG
SETUP_CreateDevList(
1363 struct DeviceInfoSet
*list
,
1364 PCWSTR MachineName OPTIONAL
,
1365 LPGUID
class OPTIONAL
,
1366 PCWSTR Enumerator OPTIONAL
)
1368 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1369 WCHAR KeyBuffer
[MAX_PATH
];
1374 if (IsEqualIID(class, &GUID_NULL
))
1378 if (MachineName
!= NULL
)
1380 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1381 if (rc
!= ERROR_SUCCESS
)
1385 HKLM
= HKEY_LOCAL_MACHINE
;
1387 rc
= RegOpenKeyExW(HKLM
,
1390 KEY_ENUMERATE_SUB_KEYS
,
1392 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1393 if (rc
!= ERROR_SUCCESS
)
1396 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1397 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1406 KEY_ENUMERATE_SUB_KEYS
,
1408 RegCloseKey(hEnumKey
);
1409 if (rc
!= ERROR_SUCCESS
)
1411 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1412 RegCloseKey(hEnumeratorKey
);
1417 /* Enumerate enumerators */
1421 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1422 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1423 if (rc
== ERROR_NO_MORE_ITEMS
)
1425 if (rc
!= ERROR_SUCCESS
)
1427 RegCloseKey(hEnumKey
);
1433 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1434 if (rc
!= ERROR_SUCCESS
)
1436 RegCloseKey(hEnumKey
);
1440 /* Call SETUP_CreateDevListFromEnumerator */
1441 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1442 RegCloseKey(hEnumeratorKey
);
1443 if (rc
!= ERROR_SUCCESS
)
1445 RegCloseKey(hEnumKey
);
1449 RegCloseKey(hEnumKey
);
1450 return ERROR_SUCCESS
;
1455 static LONG
SETUP_CreateSerialDeviceList(
1456 struct DeviceInfoSet
*list
,
1458 LPGUID InterfaceGuid
,
1459 PCWSTR DeviceInstanceW
)
1461 static const size_t initialSize
= 100;
1463 WCHAR buf
[initialSize
];
1465 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1467 struct DeviceInfoElement
*deviceInfo
;
1470 WARN("'MachineName' is ignored on Wine!\n");
1471 if (DeviceInstanceW
)
1472 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1478 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1480 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1484 HeapFree(GetProcessHeap(), 0, devices
);
1485 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1487 return ERROR_NOT_ENOUGH_MEMORY
;
1493 HeapFree(GetProcessHeap(), 0, devices
);
1494 return GetLastError();
1498 /* 'devices' is a MULTI_SZ string */
1499 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1501 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1503 /* We have found a device */
1504 struct DeviceInterface
*interfaceInfo
;
1505 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1506 /* Step 1. Create a device info element */
1507 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1510 HeapFree(GetProcessHeap(), 0, devices
);
1511 return GetLastError();
1513 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1515 /* Step 2. Create an interface list for this element */
1516 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1519 HeapFree(GetProcessHeap(), 0, devices
);
1520 return GetLastError();
1522 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1526 HeapFree(GetProcessHeap(), 0, devices
);
1527 return ERROR_SUCCESS
;
1530 #else /* __REACTOS__ */
1532 static LONG
SETUP_CreateInterfaceList(
1533 struct DeviceInfoSet
*list
,
1535 LPGUID InterfaceGuid
,
1536 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1538 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1539 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1540 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1541 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1542 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1544 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1547 DWORD dwLength
, dwInstancePathLength
;
1550 struct DeviceInfoElement
*deviceInfo
;
1552 /* Open registry key related to this interface */
1553 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1554 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1555 return GetLastError();
1557 /* Enumerate sub keys of hInterfaceKey */
1561 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1562 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1563 if (rc
== ERROR_NO_MORE_ITEMS
)
1565 if (rc
!= ERROR_SUCCESS
)
1567 RegCloseKey(hInterfaceKey
);
1573 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1574 if (rc
!= ERROR_SUCCESS
)
1576 RegCloseKey(hInterfaceKey
);
1580 /* Read DeviceInstance */
1581 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1582 if (rc
!= ERROR_SUCCESS
)
1584 RegCloseKey(hDeviceInstanceKey
);
1585 RegCloseKey(hInterfaceKey
);
1588 if (dwRegType
!= REG_SZ
)
1590 RegCloseKey(hDeviceInstanceKey
);
1591 RegCloseKey(hInterfaceKey
);
1592 return ERROR_GEN_FAILURE
;
1594 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1597 RegCloseKey(hDeviceInstanceKey
);
1598 RegCloseKey(hInterfaceKey
);
1599 return ERROR_NOT_ENOUGH_MEMORY
;
1601 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1602 if (rc
!= ERROR_SUCCESS
)
1604 HeapFree(GetProcessHeap(), 0, InstancePath
);
1605 RegCloseKey(hDeviceInstanceKey
);
1606 RegCloseKey(hInterfaceKey
);
1609 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1610 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1612 if (DeviceInstanceW
)
1614 /* Check if device enumerator is not the right one */
1615 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1617 HeapFree(GetProcessHeap(), 0, InstancePath
);
1618 RegCloseKey(hDeviceInstanceKey
);
1623 /* Find class GUID associated to the device instance */
1628 KEY_ENUMERATE_SUB_KEYS
,
1630 if (rc
!= ERROR_SUCCESS
)
1632 HeapFree(GetProcessHeap(), 0, InstancePath
);
1633 RegCloseKey(hDeviceInstanceKey
);
1634 RegCloseKey(hInterfaceKey
);
1643 RegCloseKey(hEnumKey
);
1644 if (rc
!= ERROR_SUCCESS
)
1646 HeapFree(GetProcessHeap(), 0, InstancePath
);
1647 RegCloseKey(hDeviceInstanceKey
);
1648 RegCloseKey(hInterfaceKey
);
1651 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1652 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1654 if (rc
!= ERROR_SUCCESS
)
1656 HeapFree(GetProcessHeap(), 0, InstancePath
);
1657 RegCloseKey(hDeviceInstanceKey
);
1658 RegCloseKey(hInterfaceKey
);
1661 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1662 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1663 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1665 HeapFree(GetProcessHeap(), 0, InstancePath
);
1666 RegCloseKey(hDeviceInstanceKey
);
1667 RegCloseKey(hInterfaceKey
);
1668 return ERROR_GEN_FAILURE
;
1670 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1672 /* If current device doesn't match the list GUID (if any), skip this entry */
1673 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1675 HeapFree(GetProcessHeap(), 0, InstancePath
);
1676 RegCloseKey(hDeviceInstanceKey
);
1680 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1684 LPWSTR pSymbolicLink
;
1685 struct DeviceInterface
*interfaceInfo
;
1687 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1688 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1689 if (rc
== ERROR_NO_MORE_ITEMS
)
1691 if (rc
!= ERROR_SUCCESS
)
1693 HeapFree(GetProcessHeap(), 0, InstancePath
);
1694 RegCloseKey(hDeviceInstanceKey
);
1695 RegCloseKey(hInterfaceKey
);
1699 if (KeyBuffer
[0] != '#')
1700 /* This entry doesn't represent an interesting entry */
1704 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1705 if (rc
!= ERROR_SUCCESS
)
1707 RegCloseKey(hDeviceInstanceKey
);
1708 RegCloseKey(hInterfaceKey
);
1712 /* Read SymbolicLink value */
1713 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1714 if (rc
!= ERROR_SUCCESS
)
1716 RegCloseKey(hReferenceKey
);
1717 RegCloseKey(hDeviceInstanceKey
);
1718 RegCloseKey(hInterfaceKey
);
1721 if (dwRegType
!= REG_SZ
)
1723 RegCloseKey(hReferenceKey
);
1724 RegCloseKey(hDeviceInstanceKey
);
1725 RegCloseKey(hInterfaceKey
);
1726 return ERROR_GEN_FAILURE
;
1729 /* We have found a device */
1730 /* Step 1. Create a device info element */
1731 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1733 RegCloseKey(hReferenceKey
);
1734 RegCloseKey(hDeviceInstanceKey
);
1735 RegCloseKey(hInterfaceKey
);
1736 return GetLastError();
1738 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1739 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1741 /* Step 2. Create an interface list for this element */
1742 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1745 RegCloseKey(hReferenceKey
);
1746 RegCloseKey(hDeviceInstanceKey
);
1747 RegCloseKey(hInterfaceKey
);
1748 return ERROR_NOT_ENOUGH_MEMORY
;
1750 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1751 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1752 RegCloseKey(hReferenceKey
);
1753 if (rc
!= ERROR_SUCCESS
)
1755 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1756 RegCloseKey(hDeviceInstanceKey
);
1757 RegCloseKey(hInterfaceKey
);
1760 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1762 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1763 RegCloseKey(hDeviceInstanceKey
);
1764 RegCloseKey(hInterfaceKey
);
1765 return GetLastError();
1767 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1768 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1769 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1771 RegCloseKey(hDeviceInstanceKey
);
1773 RegCloseKey(hInterfaceKey
);
1774 return ERROR_SUCCESS
;
1776 #endif /* __REACTOS__ */
1778 /***********************************************************************
1779 * SetupDiGetClassDevsExW (SETUPAPI.@)
1781 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1790 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1791 struct DeviceInfoSet
*list
;
1795 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1796 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1798 /* Create the deviceset if not set */
1801 list
= (struct DeviceInfoSet
*)deviceset
;
1802 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1804 SetLastError(ERROR_INVALID_HANDLE
);
1805 return INVALID_HANDLE_VALUE
;
1807 hDeviceInfo
= deviceset
;
1811 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1812 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1813 NULL
, machine
, NULL
);
1814 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1815 return INVALID_HANDLE_VALUE
;
1816 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1819 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1822 pClassGuid
= &list
->ClassGuid
;
1824 if (flags
& DIGCF_PRESENT
)
1825 FIXME(": flag DIGCF_PRESENT ignored\n");
1826 if (flags
& DIGCF_PROFILE
)
1827 FIXME(": flag DIGCF_PROFILE ignored\n");
1829 if (flags
& DIGCF_ALLCLASSES
)
1831 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1832 if (rc
!= ERROR_SUCCESS
)
1836 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1837 return INVALID_HANDLE_VALUE
;
1841 else if (flags
& DIGCF_DEVICEINTERFACE
)
1845 SetLastError(ERROR_INVALID_PARAMETER
);
1847 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1848 return INVALID_HANDLE_VALUE
;
1852 /* Special case: find serial ports by calling QueryDosDevice */
1853 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1854 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1855 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1856 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1859 ERR("Wine can only enumerate serial devices at the moment!\n");
1860 rc
= ERROR_INVALID_PARAMETER
;
1862 #else /* __REACTOS__ */
1863 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1864 #endif /* __REACTOS__ */
1865 if (rc
!= ERROR_SUCCESS
)
1869 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1870 return INVALID_HANDLE_VALUE
;
1876 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1877 if (rc
!= ERROR_SUCCESS
)
1881 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1882 return INVALID_HANDLE_VALUE
;
1888 /***********************************************************************
1889 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1891 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1892 HDEVINFO DeviceInfoSet
,
1893 PSP_DEVINFO_DATA DeviceInfoData
,
1894 CONST GUID
* InterfaceClassGuid
,
1896 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1900 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1901 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1903 if (!DeviceInterfaceData
)
1904 SetLastError(ERROR_INVALID_PARAMETER
);
1905 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1906 SetLastError(ERROR_INVALID_USER_BUFFER
);
1907 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1909 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1911 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1913 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1915 while (ItemList
!= &list
->ListHead
&& !Found
)
1917 PLIST_ENTRY InterfaceListEntry
;
1918 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1919 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1921 /* We are not searching for this element */
1922 ItemList
= ItemList
->Flink
;
1925 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1926 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1928 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1929 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1931 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1934 if (MemberIndex
-- == 0)
1936 /* return this item */
1937 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1938 &DevItf
->InterfaceClassGuid
,
1940 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1941 /* Note: this appears to be dangerous, passing a private
1942 * pointer a heap-allocated datum to the caller. However, the
1943 * expected lifetime of the device data is the same as the
1944 * HDEVINFO; once that is closed, the data are no longer valid.
1946 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1949 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1951 ItemList
= ItemList
->Flink
;
1954 SetLastError(ERROR_NO_MORE_ITEMS
);
1959 SetLastError(ERROR_INVALID_HANDLE
);
1962 SetLastError(ERROR_INVALID_HANDLE
);
1966 /***********************************************************************
1967 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1969 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1973 TRACE("%p\n", devinfo
);
1974 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1976 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1978 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1980 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1981 struct DeviceInfoElement
*deviceInfo
;
1982 while (!IsListEmpty(&list
->ListHead
))
1984 ListEntry
= RemoveHeadList(&list
->ListHead
);
1985 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1986 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1988 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1989 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1991 HeapFree(GetProcessHeap(), 0, ListEntry
);
1993 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1994 RegCloseKey(list
->HKLM
);
1995 HeapFree(GetProcessHeap(), 0, list
);
1999 SetLastError(ERROR_INVALID_HANDLE
);
2002 SetLastError(ERROR_INVALID_HANDLE
);
2004 TRACE("Returning %d\n", ret
);
2008 /***********************************************************************
2009 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2011 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2012 HDEVINFO DeviceInfoSet
,
2013 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2014 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2015 DWORD DeviceInterfaceDetailDataSize
,
2016 PDWORD RequiredSize
,
2017 PSP_DEVINFO_DATA DeviceInfoData
)
2019 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2020 DWORD sizeW
= 0, sizeA
;
2023 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2024 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2025 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2027 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2028 SetLastError(ERROR_INVALID_USER_BUFFER
);
2029 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2030 SetLastError(ERROR_INVALID_PARAMETER
);
2031 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2032 SetLastError(ERROR_INVALID_PARAMETER
);
2035 if (DeviceInterfaceDetailData
!= NULL
)
2037 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2038 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2039 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2040 if (!DeviceInterfaceDetailDataW
)
2042 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2045 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2047 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2048 ret
= SetupDiGetDeviceInterfaceDetailW(
2050 DeviceInterfaceData
,
2051 DeviceInterfaceDetailDataW
,
2055 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2056 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2058 *RequiredSize
= sizeA
;
2059 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2061 if (!WideCharToMultiByte(
2063 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2064 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2071 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2074 TRACE("Returning %d\n", ret
);
2078 /***********************************************************************
2079 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2081 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2082 HDEVINFO DeviceInfoSet
,
2083 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2084 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2085 DWORD DeviceInterfaceDetailDataSize
,
2086 PDWORD RequiredSize
,
2087 PSP_DEVINFO_DATA DeviceInfoData
)
2091 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2092 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2093 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2095 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2096 SetLastError(ERROR_INVALID_PARAMETER
);
2097 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2098 SetLastError(ERROR_INVALID_HANDLE
);
2099 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2100 SetLastError(ERROR_INVALID_HANDLE
);
2101 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2102 SetLastError(ERROR_INVALID_USER_BUFFER
);
2103 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2104 SetLastError(ERROR_INVALID_USER_BUFFER
);
2105 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2106 SetLastError(ERROR_INVALID_USER_BUFFER
);
2107 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2108 SetLastError(ERROR_INVALID_PARAMETER
);
2109 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2110 SetLastError(ERROR_INVALID_PARAMETER
);
2113 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2114 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2115 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2116 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2118 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2120 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2122 *RequiredSize
= sizeRequired
;
2126 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2127 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2130 memcpy(&DeviceInfoData
->ClassGuid
,
2131 &deviceInterface
->DeviceInfo
->ClassGuid
,
2133 DeviceInfoData
->DevInst
= 0; /* FIXME */
2134 /* Note: this appears to be dangerous, passing a private
2135 * pointer a heap-allocated datum to the caller. However, the
2136 * expected lifetime of the device data is the same as the
2137 * HDEVINFO; once that is closed, the data are no longer valid.
2139 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2145 TRACE("Returning %d\n", ret
);
2149 /***********************************************************************
2150 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2152 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2154 PSP_DEVINFO_DATA DeviceInfoData
,
2156 PDWORD PropertyRegDataType
,
2157 PBYTE PropertyBuffer
,
2158 DWORD PropertyBufferSize
,
2159 PDWORD RequiredSize
)
2162 BOOL bIsStringProperty
;
2164 DWORD RequiredSizeA
, RequiredSizeW
;
2165 DWORD PropertyBufferSizeW
;
2166 PBYTE PropertyBufferW
;
2168 TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
2169 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2172 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2173 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2175 bResult
= SetupDiGetDeviceRegistryPropertyW(
2181 PropertyBufferSizeW
,
2186 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2190 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2192 if (bIsStringProperty
)
2193 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2195 RequiredSizeA
= RequiredSizeW
;
2197 if (RequiredSizeA
<= PropertyBufferSize
)
2199 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2201 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2203 /* Last error is already set by WideCharToMultiByte */
2208 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2212 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2216 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2217 if (PropertyRegDataType
)
2218 *PropertyRegDataType
= RegType
;
2220 *RequiredSize
= RequiredSizeA
;
2224 /***********************************************************************
2225 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2227 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2228 HDEVINFO DeviceInfoSet
,
2229 PSP_DEVINFO_DATA DeviceInfoData
,
2231 PDWORD PropertyRegDataType
,
2232 PBYTE PropertyBuffer
,
2233 DWORD PropertyBufferSize
,
2234 PDWORD RequiredSize
)
2236 HKEY hEnumKey
, hKey
;
2240 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2241 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2244 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2245 SetLastError(ERROR_INVALID_HANDLE
);
2246 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2247 SetLastError(ERROR_INVALID_HANDLE
);
2248 else if (!DeviceInfoData
)
2249 SetLastError(ERROR_INVALID_PARAMETER
);
2250 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2251 SetLastError(ERROR_INVALID_USER_BUFFER
);
2252 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2253 SetLastError(ERROR_INVALID_PARAMETER
);
2256 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2257 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2261 case SPDRP_CAPABILITIES
:
2263 case SPDRP_CLASSGUID
:
2264 case SPDRP_COMPATIBLEIDS
:
2265 case SPDRP_CONFIGFLAGS
:
2266 case SPDRP_DEVICEDESC
:
2268 case SPDRP_FRIENDLYNAME
:
2269 case SPDRP_HARDWAREID
:
2270 case SPDRP_LOCATION_INFORMATION
:
2271 case SPDRP_LOWERFILTERS
:
2273 case SPDRP_SECURITY
:
2275 case SPDRP_UI_NUMBER
:
2276 case SPDRP_UPPERFILTERS
:
2278 LPCWSTR RegistryPropertyName
;
2283 case SPDRP_CAPABILITIES
:
2284 RegistryPropertyName
= L
"Capabilities"; break;
2286 RegistryPropertyName
= L
"Class"; break;
2287 case SPDRP_CLASSGUID
:
2288 RegistryPropertyName
= L
"ClassGUID"; break;
2289 case SPDRP_COMPATIBLEIDS
:
2290 RegistryPropertyName
= L
"CompatibleIDs"; break;
2291 case SPDRP_CONFIGFLAGS
:
2292 RegistryPropertyName
= L
"ConfigFlags"; break;
2293 case SPDRP_DEVICEDESC
:
2294 RegistryPropertyName
= L
"DeviceDesc"; break;
2296 RegistryPropertyName
= L
"Driver"; break;
2297 case SPDRP_FRIENDLYNAME
:
2298 RegistryPropertyName
= L
"FriendlyName"; break;
2299 case SPDRP_HARDWAREID
:
2300 RegistryPropertyName
= L
"HardwareID"; break;
2301 case SPDRP_LOCATION_INFORMATION
:
2302 RegistryPropertyName
= L
"LocationInformation"; break;
2303 case SPDRP_LOWERFILTERS
:
2304 RegistryPropertyName
= L
"LowerFilters"; break;
2306 RegistryPropertyName
= L
"Mfg"; break;
2307 case SPDRP_SECURITY
:
2308 RegistryPropertyName
= L
"Security"; break;
2310 RegistryPropertyName
= L
"Service"; break;
2311 case SPDRP_UI_NUMBER
:
2312 RegistryPropertyName
= L
"UINumber"; break;
2313 case SPDRP_UPPERFILTERS
:
2314 RegistryPropertyName
= L
"UpperFilters"; break;
2316 /* Should not happen */
2317 RegistryPropertyName
= NULL
; break;
2320 /* Open registry key name */
2325 KEY_ENUMERATE_SUB_KEYS
,
2327 if (rc
!= ERROR_SUCCESS
)
2338 RegCloseKey(hEnumKey
);
2339 if (rc
!= ERROR_SUCCESS
)
2344 /* Read registry entry */
2345 BufferSize
= PropertyBufferSize
;
2346 rc
= RegQueryValueExW(
2348 RegistryPropertyName
,
2349 NULL
, /* Reserved */
2350 PropertyRegDataType
,
2354 *RequiredSize
= BufferSize
;
2355 if (rc
== ERROR_SUCCESS
)
2363 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2365 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2367 if (PropertyRegDataType
)
2368 *PropertyRegDataType
= REG_SZ
;
2370 *RequiredSize
= required
;
2371 if (PropertyBufferSize
>= required
)
2373 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2377 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2381 /*case SPDRP_BUSTYPEGUID:
2382 case SPDRP_LEGACYBUSTYPE:
2383 case SPDRP_BUSNUMBER:
2384 case SPDRP_ENUMERATOR_NAME:
2385 case SPDRP_SECURITY_SDS:
2387 case SPDRP_EXCLUSIVE:
2388 case SPDRP_CHARACTERISTICS:
2390 case SPDRP_UI_NUMBER_DESC_FORMAT:
2391 case SPDRP_DEVICE_POWER_DATA:*/
2392 #if (WINVER >= 0x501)
2393 /*case SPDRP_REMOVAL_POLICY:
2394 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2395 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2396 case SPDRP_INSTALL_STATE:*/
2401 FIXME("Property 0x%lx not implemented\n", Property
);
2402 SetLastError(ERROR_NOT_SUPPORTED
);
2407 TRACE("Returning %d\n", ret
);
2412 /***********************************************************************
2413 * SetupDiInstallClassA (SETUPAPI.@)
2415 BOOL WINAPI
SetupDiInstallClassA(
2421 UNICODE_STRING FileNameW
;
2424 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2426 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2430 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2432 RtlFreeUnicodeString(&FileNameW
);
2437 static HKEY
CreateClassKey(HINF hInf
)
2439 WCHAR FullBuffer
[MAX_PATH
];
2440 WCHAR Buffer
[MAX_PATH
];
2445 if (!SetupGetLineTextW(NULL
,
2453 return INVALID_HANDLE_VALUE
;
2456 lstrcpyW(FullBuffer
, ControlClass
);
2457 lstrcatW(FullBuffer
, Buffer
);
2460 if (!SetupGetLineTextW(NULL
,
2468 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2469 return INVALID_HANDLE_VALUE
;
2472 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2476 REG_OPTION_NON_VOLATILE
,
2482 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2483 return INVALID_HANDLE_VALUE
;
2486 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2491 RequiredSize
* sizeof(WCHAR
)))
2493 RegCloseKey(hClassKey
);
2494 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2495 return INVALID_HANDLE_VALUE
;
2501 /***********************************************************************
2502 * SetupDiInstallClassW (SETUPAPI.@)
2504 BOOL WINAPI
SetupDiInstallClassW(
2510 WCHAR SectionName
[MAX_PATH
];
2511 DWORD SectionNameLength
= 0;
2513 BOOL bFileQueueCreated
= FALSE
;
2516 FIXME("not fully implemented\n");
2518 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2520 SetLastError(ERROR_INVALID_PARAMETER
);
2524 /* Open the .inf file */
2525 hInf
= SetupOpenInfFileW(InfFileName
,
2529 if (hInf
== INVALID_HANDLE_VALUE
)
2535 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2536 hClassKey
= CreateClassKey(hInf
);
2537 if (hClassKey
== INVALID_HANDLE_VALUE
)
2539 SetupCloseInfFile(hInf
);
2545 /* Try to append a layout file */
2547 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2550 /* Retrieve the actual section name */
2551 SetupDiGetActualSectionToInstallW(hInf
,
2559 if (!(Flags
& DI_NOVCP
))
2561 FileQueue
= SetupOpenFileQueue();
2562 if (FileQueue
== INVALID_HANDLE_VALUE
)
2564 SetupCloseInfFile(hInf
);
2565 RegCloseKey(hClassKey
);
2569 bFileQueueCreated
= TRUE
;
2574 SetupInstallFromInfSectionW(NULL
,
2583 INVALID_HANDLE_VALUE
,
2586 /* FIXME: More code! */
2588 if (bFileQueueCreated
)
2589 SetupCloseFileQueue(FileQueue
);
2591 SetupCloseInfFile(hInf
);
2593 RegCloseKey(hClassKey
);
2598 /***********************************************************************
2599 * SetupDiOpenClassRegKey (SETUPAPI.@)
2601 HKEY WINAPI
SetupDiOpenClassRegKey(
2602 const GUID
* ClassGuid
,
2605 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2606 DIOCR_INSTALLER
, NULL
, NULL
);
2610 /***********************************************************************
2611 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2613 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2614 const GUID
* ClassGuid
,
2620 PWSTR MachineNameW
= NULL
;
2627 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2628 if (MachineNameW
== NULL
)
2629 return INVALID_HANDLE_VALUE
;
2632 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2633 Flags
, MachineNameW
, Reserved
);
2636 MyFree(MachineNameW
);
2642 /***********************************************************************
2643 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2645 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2646 const GUID
* ClassGuid
,
2652 LPWSTR lpGuidString
;
2653 LPWSTR lpFullGuidString
;
2661 if (Flags
== DIOCR_INSTALLER
)
2663 lpKeyName
= ControlClass
;
2665 else if (Flags
== DIOCR_INTERFACE
)
2667 lpKeyName
= DeviceClasses
;
2671 ERR("Invalid Flags parameter!\n");
2672 SetLastError(ERROR_INVALID_PARAMETER
);
2673 return INVALID_HANDLE_VALUE
;
2676 if (MachineName
!= NULL
)
2678 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2679 if (rc
!= ERROR_SUCCESS
)
2682 return INVALID_HANDLE_VALUE
;
2686 HKLM
= HKEY_LOCAL_MACHINE
;
2688 rc
= RegOpenKeyExW(HKLM
,
2693 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2694 if (rc
!= ERROR_SUCCESS
)
2697 return INVALID_HANDLE_VALUE
;
2700 if (ClassGuid
== NULL
)
2703 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2705 SetLastError(ERROR_GEN_FAILURE
);
2706 RegCloseKey(hClassesKey
);
2707 return INVALID_HANDLE_VALUE
;
2710 dwLength
= lstrlenW(lpGuidString
);
2711 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2712 if (!lpFullGuidString
)
2714 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2715 RpcStringFreeW(&lpGuidString
);
2716 return INVALID_HANDLE_VALUE
;
2718 lpFullGuidString
[0] = '{';
2719 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2720 lpFullGuidString
[dwLength
+ 1] = '}';
2721 lpFullGuidString
[dwLength
+ 2] = '\0';
2722 RpcStringFreeW(&lpGuidString
);
2724 rc
= RegOpenKeyExW(hClassesKey
,
2729 if (rc
!= ERROR_SUCCESS
)
2732 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2733 RegCloseKey(hClassesKey
);
2734 return INVALID_HANDLE_VALUE
;
2737 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2738 RegCloseKey(hClassesKey
);
2743 /***********************************************************************
2744 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2746 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2747 HDEVINFO DeviceInfoSet
,
2750 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2752 FIXME("%p %s %08lx %p\n",
2753 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2757 /***********************************************************************
2758 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2760 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2761 HDEVINFO DeviceInfoSet
,
2764 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2766 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
2767 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2771 /***********************************************************************
2772 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2774 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2775 HDEVINFO DeviceInfoSet
,
2776 PSP_DEVINFO_DATA DeviceInfoData
,
2777 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2778 DWORD ClassInstallParamsSize
)
2780 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2781 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2785 /***********************************************************************
2786 * SetupDiCallClassInstaller (SETUPAPI.@)
2788 BOOL WINAPI
SetupDiCallClassInstaller(
2789 IN DI_FUNCTION InstallFunction
,
2790 IN HDEVINFO DeviceInfoSet
,
2791 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2795 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2798 SetLastError(ERROR_INVALID_PARAMETER
);
2799 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2800 SetLastError(ERROR_INVALID_HANDLE
);
2801 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2802 SetLastError(ERROR_INVALID_HANDLE
);
2803 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2804 SetLastError(ERROR_INVALID_HANDLE
);
2805 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2806 SetLastError(ERROR_INVALID_USER_BUFFER
);
2809 #define CLASS_COINSTALLER 0x1
2810 #define DEVICE_COINSTALLER 0x2
2811 #define CLASS_INSTALLER 0x4
2812 UCHAR CanHandle
= 0;
2813 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2815 switch (InstallFunction
)
2817 case DIF_ALLOW_INSTALL
:
2818 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2820 case DIF_DESTROYPRIVATEDATA
:
2821 CanHandle
= CLASS_INSTALLER
;
2823 case DIF_INSTALLDEVICE
:
2824 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2825 DefaultHandler
= SetupDiInstallDevice
;
2827 case DIF_INSTALLDEVICEFILES
:
2828 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2829 DefaultHandler
= SetupDiInstallDriverFiles
;
2831 case DIF_INSTALLINTERFACES
:
2832 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2833 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2835 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2836 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2838 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2839 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2841 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2842 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2844 case DIF_REGISTER_COINSTALLERS
:
2845 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2846 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2848 case DIF_SELECTBESTCOMPATDRV
:
2849 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2850 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2853 FIXME("Install function %ld not implemented\n", InstallFunction
);
2854 SetLastError(ERROR_INVALID_PARAMETER
);
2859 LIST_ENTRY ClassCoInstallersListHead
;
2860 LIST_ENTRY DeviceCoInstallersListHead
;
2861 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2862 COINSTALLER_CONTEXT_DATA Context
;
2863 PLIST_ENTRY ListEntry
;
2865 DWORD dwRegType
, dwLength
;
2866 DWORD rc
= NO_ERROR
;
2868 InitializeListHead(&ClassCoInstallersListHead
);
2869 InitializeListHead(&DeviceCoInstallersListHead
);
2871 if (CanHandle
& DEVICE_COINSTALLER
)
2873 FIXME("Doesn't use Device co-installers at the moment\n");
2875 if (CanHandle
& CLASS_COINSTALLER
)
2879 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2883 if (rc
== ERROR_SUCCESS
)
2885 LPWSTR lpGuidString
;
2886 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2888 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2889 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2891 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2892 if (KeyBuffer
!= NULL
)
2894 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2895 if (rc
== ERROR_SUCCESS
)
2898 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2900 /* Add coinstaller to ClassCoInstallersListHead list */
2901 FIXME("Class coinstaller is '%S'. UNIMPLEMENTED!\n", ptr
);
2904 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2907 RpcStringFreeW(&lpGuidString
);
2912 if (CanHandle
& CLASS_INSTALLER
)
2914 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2915 if (hKey
!= INVALID_HANDLE_VALUE
)
2917 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2918 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2920 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2921 if (KeyBuffer
!= NULL
)
2923 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2924 if (rc
== ERROR_SUCCESS
)
2926 /* Set ClassInstaller function pointer */
2927 FIXME("Installer is '%S'\n", KeyBuffer
);
2929 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2936 /* Call Class co-installers */
2937 Context
.PostProcessing
= FALSE
;
2939 ListEntry
= ClassCoInstallersListHead
.Flink
;
2940 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
2942 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2943 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2944 coinstaller
->PrivateData
= Context
.PrivateData
;
2945 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2947 coinstaller
->DoPostProcessing
= TRUE
;
2950 ListEntry
= ListEntry
->Flink
;
2953 /* Call Device co-installers */
2954 ListEntry
= DeviceCoInstallersListHead
.Flink
;
2955 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
2957 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2958 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2959 coinstaller
->PrivateData
= Context
.PrivateData
;
2960 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2962 coinstaller
->DoPostProcessing
= TRUE
;
2965 ListEntry
= ListEntry
->Flink
;
2968 /* Call Class installer */
2970 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2972 rc
= ERROR_DI_DO_DEFAULT
;
2974 /* Call default handler */
2975 if (rc
== ERROR_DI_DO_DEFAULT
)
2977 if (DefaultHandler
/*FIXME && DI_NODI_DEFAULTACTION not set */)
2979 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
2982 rc
= GetLastError();
2988 /* Call Class co-installers that required postprocessing */
2989 Context
.PostProcessing
= TRUE
;
2990 ListEntry
= ClassCoInstallersListHead
.Flink
;
2991 while (ListEntry
!= &ClassCoInstallersListHead
)
2993 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2994 if (coinstaller
->DoPostProcessing
)
2996 Context
.InstallResult
= rc
;
2997 Context
.PrivateData
= coinstaller
->PrivateData
;
2998 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3000 ListEntry
= ListEntry
->Flink
;
3003 /* Call Device co-installers that required postprocessing */
3004 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3005 while (ListEntry
!= &DeviceCoInstallersListHead
)
3007 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3008 if (coinstaller
->DoPostProcessing
)
3010 Context
.InstallResult
= rc
;
3011 Context
.PrivateData
= coinstaller
->PrivateData
;
3012 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3014 ListEntry
= ListEntry
->Flink
;
3017 /* Free allocated memory */
3018 while (!IsListEmpty(&ClassCoInstallersListHead
))
3020 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3021 HeapFree(GetProcessHeap(), 0, ListEntry
);
3023 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3025 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3026 HeapFree(GetProcessHeap(), 0, ListEntry
);
3029 ret
= (rc
== NO_ERROR
);
3033 TRACE("Returning %d\n", ret
);
3037 /***********************************************************************
3038 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3040 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3041 IN HDEVINFO DeviceInfoSet
,
3042 IN PSP_DEVINFO_DATA DeviceInfoData
,
3043 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3045 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3048 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3050 if (DeviceInstallParams
== NULL
)
3051 SetLastError(ERROR_INVALID_PARAMETER
);
3052 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3053 SetLastError(ERROR_INVALID_USER_BUFFER
);
3056 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3057 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3061 /* Do W->A conversion */
3063 DeviceInstallParams
,
3064 &deviceInstallParamsW
,
3065 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3066 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3067 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3069 DeviceInstallParams
->DriverPath
[0] = '\0';
3075 TRACE("Returning %d\n", ret
);
3079 /***********************************************************************
3080 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3082 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3083 IN HDEVINFO DeviceInfoSet
,
3084 IN PSP_DEVINFO_DATA DeviceInfoData
,
3085 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3087 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3091 /***********************************************************************
3092 * SetupDiOpenDevRegKey (SETUPAPI.@)
3094 HKEY WINAPI
SetupDiOpenDevRegKey(
3095 HDEVINFO DeviceInfoSet
,
3096 PSP_DEVINFO_DATA DeviceInfoData
,
3102 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
3103 Scope
, HwProfile
, KeyType
, samDesired
);
3104 return INVALID_HANDLE_VALUE
;
3107 /***********************************************************************
3108 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3110 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3111 HDEVINFO DeviceInfoSet
,
3113 CONST GUID
*ClassGuid
,
3114 PCSTR DeviceDescription
,
3116 DWORD CreationFlags
,
3117 PSP_DEVINFO_DATA DeviceInfoData
)
3119 LPWSTR DeviceNameW
= NULL
;
3120 LPWSTR DeviceDescriptionW
= NULL
;
3127 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3128 if (DeviceNameW
== NULL
) return FALSE
;
3130 if (DeviceDescription
)
3132 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3133 if (DeviceDescriptionW
== NULL
)
3135 if (DeviceNameW
) MyFree(DeviceNameW
);
3140 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3141 ClassGuid
, DeviceDescriptionW
,
3142 hwndParent
, CreationFlags
,
3145 if (DeviceNameW
) MyFree(DeviceNameW
);
3146 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3151 /***********************************************************************
3152 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3154 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3155 HDEVINFO DeviceInfoSet
,
3157 CONST GUID
*ClassGuid
,
3158 PCWSTR DeviceDescription
,
3160 DWORD CreationFlags
,
3161 PSP_DEVINFO_DATA DeviceInfoData
)
3163 struct DeviceInfoSet
*list
;
3166 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3167 debugstr_guid(ClassGuid
), DeviceDescription
,
3168 hwndParent
, CreationFlags
, DeviceInfoData
);
3171 SetLastError(ERROR_INVALID_HANDLE
);
3172 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3173 SetLastError(ERROR_INVALID_HANDLE
);
3174 else if (!ClassGuid
)
3175 SetLastError(ERROR_INVALID_PARAMETER
);
3176 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3177 SetLastError(ERROR_CLASS_MISMATCH
);
3178 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3180 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3181 SetLastError(ERROR_INVALID_PARAMETER
);
3185 SP_DEVINFO_DATA DevInfo
;
3187 if (CreationFlags
& DICD_GENERATE_ID
)
3189 /* Generate a new unique ID for this device */
3190 SetLastError(ERROR_GEN_FAILURE
);
3191 FIXME("not implemented\n");
3195 /* Device name is fully qualified. Try to open it */
3198 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3199 rc
= SetupDiOpenDeviceInfoW(
3202 NULL
, /* hwndParent */
3203 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3208 /* SetupDiOpenDeviceInfoW has already added
3209 * the device info to the device info set
3211 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3213 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3215 struct DeviceInfoElement
*deviceInfo
;
3217 /* FIXME: ClassGuid can be NULL */
3218 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3220 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3222 if (!DeviceInfoData
)
3226 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3228 SetLastError(ERROR_INVALID_USER_BUFFER
);
3232 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3233 DeviceInfoData
->DevInst
= 0; /* FIXME */
3234 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3243 TRACE("Returning %d\n", ret
);
3247 /***********************************************************************
3248 * Helper functions for SetupDiBuildDriverInfoList
3252 IN PLIST_ENTRY DriverListHead
,
3253 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3254 IN INFCONTEXT ContextDevice
,
3256 IN LPCWSTR ProviderName
,
3257 IN LPCWSTR ManufacturerName
,
3258 IN LPCWSTR MatchingId
,
3259 FILETIME DriverDate
,
3260 DWORDLONG DriverVersion
,
3263 struct DriverInfoElement
*driverInfo
= NULL
;
3264 DWORD RequiredSize
= 128; /* Initial buffer size */
3265 BOOL Result
= FALSE
;
3266 PLIST_ENTRY PreviousEntry
;
3267 LPWSTR DeviceDescription
= NULL
;
3268 LPWSTR InfInstallSection
= NULL
;
3271 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3274 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3277 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3279 /* Fill InfSection field */
3280 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3281 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3283 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3284 driverInfo
->InfSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3285 if (!driverInfo
->InfSection
)
3287 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3290 Result
= SetupGetStringFieldW(
3293 driverInfo
->InfSection
, RequiredSize
,
3299 /* Copy InfFile information */
3300 driverInfo
->InfPath
= HeapAlloc(GetProcessHeap(), 0, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3301 if (!driverInfo
->InfPath
)
3303 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3306 RtlCopyMemory(driverInfo
->InfPath
, InfFile
, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3308 /* Copy MatchingId information */
3309 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3310 if (!driverInfo
->MatchingId
)
3312 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3315 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3317 /* Get device description */
3319 RequiredSize
= 128; /* Initial buffer size */
3320 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3321 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3323 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3324 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3325 if (!DeviceDescription
)
3327 Result
= SetupGetStringFieldW(
3329 0, /* Field index */
3330 DeviceDescription
, RequiredSize
,
3336 /* Get inf install section */
3338 RequiredSize
= 128; /* Initial buffer size */
3339 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3340 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3342 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3343 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3344 if (!InfInstallSection
)
3346 Result
= SetupGetStringFieldW(
3348 1, /* Field index */
3349 InfInstallSection
, RequiredSize
,
3355 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3356 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3358 driverInfo
->DriverRank
= Rank
;
3359 driverInfo
->Info
.DriverType
= DriverType
;
3360 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3361 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3362 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3363 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3364 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3367 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3368 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3371 driverInfo
->Info
.ProviderName
[0] = '\0';
3372 driverInfo
->Info
.DriverDate
= DriverDate
;
3373 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3375 /* Insert current driver in driver list, according to its rank */
3376 PreviousEntry
= DriverListHead
->Flink
;
3377 while (PreviousEntry
!= DriverListHead
)
3379 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3381 /* Insert before the current item */
3382 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3386 if (PreviousEntry
== DriverListHead
)
3388 /* Insert at the end of the list */
3389 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3399 HeapFree(GetProcessHeap(), 0, driverInfo
->InfPath
);
3400 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3401 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
3403 HeapFree(GetProcessHeap(), 0, driverInfo
);
3405 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3406 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3412 GetVersionInformationFromInfFile(
3414 OUT LPGUID ClassGuid
,
3415 OUT LPWSTR
* pProviderName
,
3416 OUT FILETIME
* DriverDate
,
3417 OUT DWORDLONG
* DriverVersion
)
3420 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3421 LPWSTR DriverVer
= NULL
;
3422 LPWSTR ProviderName
= NULL
;
3423 LPWSTR pComma
; /* Points into DriverVer */
3424 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
3425 SYSTEMTIME SystemTime
;
3427 BOOL ret
= FALSE
; /* Final result */
3429 /* Get class Guid */
3430 if (!SetupGetLineTextW(
3433 L
"Version", L
"ClassGUID",
3434 guidW
, sizeof(guidW
),
3435 NULL
/* Required size */))
3439 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3440 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3442 SetLastError(ERROR_GEN_FAILURE
);
3446 /* Get provider name */
3447 Result
= SetupGetLineTextW(
3449 hInf
, L
"Version", L
"Provider",
3454 /* We know know the needed buffer size */
3455 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3458 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3461 Result
= SetupGetLineTextW(
3463 hInf
, L
"Version", L
"Provider",
3464 ProviderName
, RequiredSize
,
3469 *pProviderName
= ProviderName
;
3471 /* Read the "DriverVer" value */
3472 Result
= SetupGetLineTextW(
3474 hInf
, L
"Version", L
"DriverVer",
3479 /* We know know the needed buffer size */
3480 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3483 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3486 Result
= SetupGetLineTextW(
3488 hInf
, L
"Version", L
"DriverVer",
3489 DriverVer
, RequiredSize
,
3495 /* Get driver date and driver version, by analyzing the "DriverVer" value */
3496 pComma
= wcschr(DriverVer
, ',');
3499 *pComma
= UNICODE_NULL
;
3500 pVersion
= pComma
+ 1;
3502 /* Get driver date version. Invalid date = 00/00/00 */
3503 memset(DriverDate
, 0, sizeof(FILETIME
));
3504 if (wcslen(DriverVer
) == 10
3505 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
3506 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
3508 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
3509 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
3510 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
3511 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
3512 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
3513 SystemTimeToFileTime(&SystemTime
, DriverDate
);
3515 /* Get driver version. Invalid version = 0.0.0.0 */
3517 /* FIXME: use pVersion to fill DriverVersion variable */
3523 HeapFree(GetProcessHeap(), 0, ProviderName
);
3524 HeapFree(GetProcessHeap(), 0, DriverVer
);
3526 TRACE("Returning %d\n", ret
);
3530 /***********************************************************************
3531 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3534 SetupDiBuildDriverInfoList(
3535 IN HDEVINFO DeviceInfoSet
,
3536 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3537 IN DWORD DriverType
)
3539 struct DeviceInfoSet
*list
;
3540 PVOID Buffer
= NULL
;
3541 HINF hInf
= INVALID_HANDLE_VALUE
;
3542 LPWSTR ProviderName
= NULL
;
3543 LPWSTR ManufacturerName
= NULL
;
3544 LPWSTR ManufacturerSection
= NULL
;
3545 LPWSTR HardwareIDs
= NULL
;
3546 LPWSTR CompatibleIDs
= NULL
;
3547 FILETIME DriverDate
;
3548 DWORDLONG DriverVersion
= 0;
3552 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3555 SetLastError(ERROR_INVALID_HANDLE
);
3556 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3557 SetLastError(ERROR_INVALID_HANDLE
);
3558 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3559 SetLastError(ERROR_INVALID_HANDLE
);
3560 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3561 SetLastError(ERROR_INVALID_PARAMETER
);
3562 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3563 SetLastError(ERROR_INVALID_PARAMETER
);
3564 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3565 SetLastError(ERROR_INVALID_PARAMETER
);
3566 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3567 SetLastError(ERROR_INVALID_USER_BUFFER
);
3570 BOOL Result
= FALSE
;
3572 if (DriverType
== SPDIT_COMPATDRIVER
)
3574 /* Get hardware IDs list */
3576 RequiredSize
= 512; /* Initial buffer size */
3577 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3578 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3580 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3581 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3584 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3587 Result
= SetupDiGetDeviceRegistryPropertyW(
3599 /* Get compatible IDs list */
3601 RequiredSize
= 512; /* Initial buffer size */
3602 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3603 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3605 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3606 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3609 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3612 Result
= SetupDiGetDeviceRegistryPropertyW(
3615 SPDRP_COMPATIBLEIDS
,
3617 (PBYTE
)CompatibleIDs
,
3620 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3622 /* No compatible ID for this device */
3623 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3624 CompatibleIDs
= NULL
;
3632 /* Enumerate .inf files */
3634 RequiredSize
= 32768; /* Initial buffer size */
3635 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3636 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3638 HeapFree(GetProcessHeap(), 0, Buffer
);
3639 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3643 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3646 Result
= SetupGetInfFileListW(
3647 NULL
, /* Directory path */
3649 Buffer
, RequiredSize
,
3656 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
3658 INFCONTEXT ContextManufacturer
, ContextDevice
;
3660 TRACE("Opening file %S\n", filename
);
3662 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
3663 if (hInf
== INVALID_HANDLE_VALUE
)
3666 if (!GetVersionInformationFromInfFile(
3673 SetupCloseInfFile(hInf
);
3674 hInf
= INVALID_HANDLE_VALUE
;
3678 if (DriverType
== SPDIT_CLASSDRIVER
)
3680 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3681 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
3687 /* Get the manufacturers list */
3688 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
3691 Result
= SetupGetStringFieldW(
3692 &ContextManufacturer
,
3693 0, /* Field index */
3698 /* We got the needed size for the buffer */
3699 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3700 if (!ManufacturerName
)
3702 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3705 Result
= SetupGetStringFieldW(
3706 &ContextManufacturer
,
3707 0, /* Field index */
3708 ManufacturerName
, RequiredSize
,
3711 Result
= SetupGetStringFieldW(
3712 &ContextManufacturer
,
3713 1, /* Field index */
3718 /* We got the needed size for the buffer */
3719 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3720 if (!ManufacturerSection
)
3722 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3725 Result
= SetupGetStringFieldW(
3726 &ContextManufacturer
,
3727 1, /* Field index */
3728 ManufacturerSection
, RequiredSize
,
3732 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
3733 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
3736 if (DriverType
== SPDIT_CLASSDRIVER
)
3738 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3739 if (!AddDriverToList(
3740 &list
->DriverListHead
,
3747 DriverDate
, DriverVersion
,
3753 else /* DriverType = SPDIT_COMPATDRIVER */
3755 /* 1. Get all fields */
3756 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
3760 BOOL DriverAlreadyAdded
;
3762 for (i
= 2; i
<= FieldCount
; i
++)
3764 LPWSTR DeviceId
= NULL
;
3766 RequiredSize
= 128; /* Initial buffer size */
3767 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3768 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3770 HeapFree(GetProcessHeap(), 0, DeviceId
);
3771 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3774 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3777 Result
= SetupGetStringFieldW(
3780 DeviceId
, RequiredSize
,
3785 HeapFree(GetProcessHeap(), 0, DeviceId
);
3788 DriverAlreadyAdded
= FALSE
;
3789 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3791 if (wcscmp(DeviceId
, currentId
) == 0)
3794 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3801 DriverDate
, DriverVersion
,
3802 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
3803 DriverAlreadyAdded
= TRUE
;
3808 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3810 if (wcscmp(DeviceId
, currentId
) == 0)
3813 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3820 DriverDate
, DriverVersion
,
3821 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
3822 DriverAlreadyAdded
= TRUE
;
3826 HeapFree(GetProcessHeap(), 0, DeviceId
);
3829 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
3832 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3833 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3834 ManufacturerName
= ManufacturerSection
= NULL
;
3835 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
3840 HeapFree(GetProcessHeap(), 0, ProviderName
);
3841 ProviderName
= NULL
;
3843 SetupCloseInfFile(hInf
);
3844 hInf
= INVALID_HANDLE_VALUE
;
3855 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3856 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
3859 list
->Flags
|= DI_DIDCLASS
;
3862 HeapFree(GetProcessHeap(), 0, ProviderName
);
3863 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3864 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3865 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3866 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3867 if (hInf
!= INVALID_HANDLE_VALUE
)
3868 SetupCloseInfFile(hInf
);
3869 HeapFree(GetProcessHeap(), 0, Buffer
);
3871 TRACE("Returning %d\n", ret
);
3875 /***********************************************************************
3876 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3879 SetupDiDeleteDeviceInfo(
3880 IN HDEVINFO DeviceInfoSet
,
3881 IN PSP_DEVINFO_DATA DeviceInfoData
)
3883 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3885 FIXME("not implemented\n");
3886 SetLastError(ERROR_GEN_FAILURE
);
3891 /***********************************************************************
3892 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3895 SetupDiDestroyDriverInfoList(
3896 IN HDEVINFO DeviceInfoSet
,
3897 IN PSP_DEVINFO_DATA DeviceInfoData
,
3898 IN DWORD DriverType
)
3900 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3902 FIXME("not implemented\n");
3903 SetLastError(ERROR_GEN_FAILURE
);
3908 /***********************************************************************
3909 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3912 SetupDiOpenDeviceInfoA(
3913 IN HDEVINFO DeviceInfoSet
,
3914 IN PCSTR DeviceInstanceId
,
3915 IN HWND hwndParent OPTIONAL
,
3917 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3919 LPWSTR DeviceInstanceIdW
= NULL
;
3922 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3924 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
3925 if (DeviceInstanceIdW
== NULL
)
3928 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
3929 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
3931 MyFree(DeviceInstanceIdW
);
3937 /***********************************************************************
3938 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3941 SetupDiOpenDeviceInfoW(
3942 IN HDEVINFO DeviceInfoSet
,
3943 IN PCWSTR DeviceInstanceId
,
3944 IN HWND hwndParent OPTIONAL
,
3946 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3948 struct DeviceInfoSet
*list
;
3949 HKEY hEnumKey
, hKey
;
3953 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3955 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
3956 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3959 SetLastError(ERROR_INVALID_HANDLE
);
3960 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3961 SetLastError(ERROR_INVALID_HANDLE
);
3962 else if (!DeviceInstanceId
)
3963 SetLastError(ERROR_INVALID_PARAMETER
);
3964 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
3966 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
3967 SetLastError(ERROR_INVALID_PARAMETER
);
3969 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3970 SetLastError(ERROR_INVALID_USER_BUFFER
);
3973 struct DeviceInfoElement
*deviceInfo
= NULL
;
3974 /* Search if device already exists in DeviceInfoSet.
3975 * If yes, return the existing element
3976 * If no, create a new element using informations in registry
3978 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
3979 while (ItemList
!= &list
->ListHead
)
3984 FIXME("not implemented\n");
3985 ItemList
= ItemList
->Flink
;
3990 /* good one found */
3995 /* Open supposed registry key */
4000 KEY_ENUMERATE_SUB_KEYS
,
4002 if (rc
!= ERROR_SUCCESS
)
4013 RegCloseKey(hEnumKey
);
4014 if (rc
!= ERROR_SUCCESS
)
4020 /* FIXME: GUID_NULL is not allowed */
4021 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
4026 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4032 if (ret
&& deviceInfo
&& DeviceInfoData
)
4034 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4035 DeviceInfoData
->DevInst
= 0; /* FIXME */
4036 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4044 /***********************************************************************
4045 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4048 SetupDiEnumDriverInfoA(
4049 IN HDEVINFO DeviceInfoSet
,
4050 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4051 IN DWORD DriverType
,
4052 IN DWORD MemberIndex
,
4053 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4055 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4058 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4059 DriverType
, MemberIndex
, DriverInfoData
);
4061 if (DriverInfoData
== NULL
)
4062 SetLastError(ERROR_INVALID_PARAMETER
);
4063 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4064 SetLastError(ERROR_INVALID_USER_BUFFER
);
4067 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4068 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4069 DriverType
, MemberIndex
, &driverInfoData2W
);
4073 /* Do W->A conversion */
4074 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4075 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4076 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4077 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4079 DriverInfoData
->Description
[0] = '\0';
4082 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4083 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4085 DriverInfoData
->MfgName
[0] = '\0';
4088 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4089 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4091 DriverInfoData
->ProviderName
[0] = '\0';
4094 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4096 /* Copy more fields */
4097 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4098 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4103 TRACE("Returning %d\n", ret
);
4108 /***********************************************************************
4109 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4112 SetupDiEnumDriverInfoW(
4113 IN HDEVINFO DeviceInfoSet
,
4114 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4115 IN DWORD DriverType
,
4116 IN DWORD MemberIndex
,
4117 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4119 PLIST_ENTRY ListHead
;
4122 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4123 DriverType
, MemberIndex
, DriverInfoData
);
4125 if (!DeviceInfoSet
|| !DriverInfoData
)
4126 SetLastError(ERROR_INVALID_PARAMETER
);
4127 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4128 SetLastError(ERROR_INVALID_HANDLE
);
4129 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4130 SetLastError(ERROR_INVALID_HANDLE
);
4131 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4132 SetLastError(ERROR_INVALID_PARAMETER
);
4133 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4134 SetLastError(ERROR_INVALID_PARAMETER
);
4135 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4136 SetLastError(ERROR_INVALID_PARAMETER
);
4137 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4138 SetLastError(ERROR_INVALID_USER_BUFFER
);
4141 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4142 PLIST_ENTRY ItemList
;
4143 if (DriverType
== SPDIT_CLASSDRIVER
||
4144 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4146 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4150 ListHead
= &devInfo
->DriverListHead
;
4153 ItemList
= ListHead
->Flink
;
4154 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4155 ItemList
= ItemList
->Flink
;
4156 if (ItemList
== ListHead
)
4157 SetLastError(ERROR_NO_MORE_ITEMS
);
4160 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4163 &DriverInfoData
->DriverType
,
4164 &DrvInfo
->Info
.DriverType
,
4165 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4170 TRACE("Returning %d\n", ret
);
4174 /***********************************************************************
4175 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4178 SetupDiGetSelectedDriverW(
4179 IN HDEVINFO DeviceInfoSet
,
4180 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4181 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4185 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4187 if (!DeviceInfoSet
|| !DriverInfoData
)
4188 SetLastError(ERROR_INVALID_PARAMETER
);
4189 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4190 SetLastError(ERROR_INVALID_HANDLE
);
4191 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4192 SetLastError(ERROR_INVALID_HANDLE
);
4193 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4194 SetLastError(ERROR_INVALID_USER_BUFFER
);
4195 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4196 SetLastError(ERROR_INVALID_USER_BUFFER
);
4199 struct DriverInfoElement
*driverInfo
;
4202 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4204 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4206 if (driverInfo
== NULL
)
4207 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4211 &DriverInfoData
->DriverType
,
4212 &driverInfo
->Info
.DriverType
,
4213 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4218 TRACE("Returning %d\n", ret
);
4222 /***********************************************************************
4223 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4226 SetupDiSetSelectedDriverW(
4227 IN HDEVINFO DeviceInfoSet
,
4228 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4229 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4233 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4236 SetLastError(ERROR_INVALID_PARAMETER
);
4237 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4238 SetLastError(ERROR_INVALID_HANDLE
);
4239 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4240 SetLastError(ERROR_INVALID_HANDLE
);
4241 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4242 SetLastError(ERROR_INVALID_USER_BUFFER
);
4243 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4244 SetLastError(ERROR_INVALID_USER_BUFFER
);
4247 struct DriverInfoElement
**pDriverInfo
;
4248 PLIST_ENTRY ListHead
, ItemList
;
4252 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4253 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4257 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4258 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4261 if (!DriverInfoData
)
4263 *pDriverInfo
= NULL
;
4268 /* Search selected driver in list */
4269 ItemList
= ListHead
->Flink
;
4270 while (ItemList
!= ListHead
)
4272 if (DriverInfoData
->Reserved
!= 0)
4274 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4279 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4280 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4281 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4282 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4283 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4289 if (ItemList
== ListHead
)
4290 SetLastError(ERROR_INVALID_PARAMETER
);
4293 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4294 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4296 TRACE("Choosing driver whose rank is 0x%lx\n",
4297 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
4302 TRACE("Returning %d\n", ret
);
4306 /***********************************************************************
4307 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4310 SetupDiSelectBestCompatDrv(
4311 IN HDEVINFO DeviceInfoSet
,
4312 IN PSP_DEVINFO_DATA DeviceInfoData
)
4314 SP_DRVINFO_DATA_W drvInfoData
;
4317 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4319 /* Drivers are sorted by rank in the driver list, so
4320 * the first driver in the list is the best one.
4322 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4323 ret
= SetupDiEnumDriverInfoW(
4327 0, /* Member index */
4332 ret
= SetupDiSetSelectedDriverW(
4338 TRACE("Returning %d\n", ret
);
4342 /***********************************************************************
4343 * SetupDiInstallDriverFiles (SETUPAPI.@)
4346 SetupDiInstallDriverFiles(
4347 IN HDEVINFO DeviceInfoSet
,
4348 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4352 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4355 SetLastError(ERROR_INVALID_PARAMETER
);
4356 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4357 SetLastError(ERROR_INVALID_HANDLE
);
4358 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4359 SetLastError(ERROR_INVALID_HANDLE
);
4360 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4361 SetLastError(ERROR_INVALID_USER_BUFFER
);
4362 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4363 SetLastError(ERROR_INVALID_PARAMETER
);
4364 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4365 SetLastError(ERROR_INVALID_PARAMETER
);
4368 struct DriverInfoElement
*DriverInfo
;
4374 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4375 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4379 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4380 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4383 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4384 if (hInf
!= INVALID_HANDLE_VALUE
)
4386 WCHAR SectionName
[MAX_PATH
];
4387 DWORD SectionNameLength
= 0;
4389 ret
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4390 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4393 PVOID callback_context
= SetupInitDefaultQueueCallback(hWnd
);
4394 ret
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4395 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
4396 SetupDefaultQueueCallbackW
, callback_context
,
4398 SetupTermDefaultQueueCallback(callback_context
);
4400 SetupCloseInfFile(hInf
);
4404 TRACE("Returning %d\n", ret
);
4408 /***********************************************************************
4409 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4412 SetupDiRegisterCoDeviceInstallers(
4413 IN HDEVINFO DeviceInfoSet
,
4414 IN PSP_DEVINFO_DATA DeviceInfoData
)
4416 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4418 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4419 //SetLastError(ERROR_GEN_FAILURE);
4424 /***********************************************************************
4425 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4428 SetupDiInstallDeviceInterfaces(
4429 IN HDEVINFO DeviceInfoSet
,
4430 IN PSP_DEVINFO_DATA DeviceInfoData
)
4432 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4434 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4435 //SetLastError(ERROR_GEN_FAILURE);
4440 /***********************************************************************
4441 * SetupDiInstallDevice (SETUPAPI.@)
4444 SetupDiInstallDevice(
4445 IN HDEVINFO DeviceInfoSet
,
4446 IN PSP_DEVINFO_DATA DeviceInfoData
)
4448 struct DriverInfoElement
*DriverInfo
;
4449 struct DeviceInfoSet
*DevInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
;
4450 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4451 SYSTEMTIME DriverDate
;
4452 WCHAR SectionName
[MAX_PATH
];
4454 DWORD SectionNameLength
= 0;
4455 BOOL Result
= FALSE
;
4456 INFCONTEXT ContextService
;
4459 HINF hInf
= INVALID_HANDLE_VALUE
;
4460 LPCWSTR AssociatedService
= NULL
;
4461 LPWSTR pSectionName
= NULL
;
4462 LPWSTR ClassName
= NULL
;
4464 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
4465 BOOL RebootRequired
= FALSE
;
4466 HKEY hEnumKey
, hKey
= INVALID_HANDLE_VALUE
;
4467 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4468 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4469 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4470 DWORD Index
; /* Index used in the DriverKey name */
4473 PVOID callback_context
;
4474 BOOL ret
= FALSE
; /* Return value */
4476 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4479 SetLastError(ERROR_INVALID_PARAMETER
);
4480 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4481 SetLastError(ERROR_INVALID_HANDLE
);
4482 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4483 SetLastError(ERROR_INVALID_HANDLE
);
4484 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4485 SetLastError(ERROR_INVALID_USER_BUFFER
);
4486 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4487 SetLastError(ERROR_INVALID_PARAMETER
);
4488 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4489 SetLastError(ERROR_INVALID_PARAMETER
);
4495 /* One parameter is bad */
4499 /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
4503 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4504 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4508 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4509 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4511 FileTimeToSystemTime(&DriverInfo
->Info
.DriverDate
, &DriverDate
);
4513 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4514 if (hInf
== INVALID_HANDLE_VALUE
)
4517 Result
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4518 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4519 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
4521 pSectionName
= &SectionName
[wcslen(SectionName
)];
4523 /* Get information from [Version] section */
4526 if (!SetupDiGetINFClassW(DriverInfo
->InfPath
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
4528 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
4530 ClassName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4533 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4536 if (!SetupDiGetINFClassW(DriverInfo
->InfPath
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
4539 /* Format ClassGuid to a string */
4540 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4542 RequiredSize
= lstrlenW(lpGuidString
);
4543 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
4544 if (!lpFullGuidString
)
4546 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4549 lpFullGuidString
[0] = '{';
4550 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
4551 lpFullGuidString
[RequiredSize
+ 1] = '}';
4552 lpFullGuidString
[RequiredSize
+ 2] = '\0';
4554 /* Create driver key information */
4555 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\{#ID} */
4556 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpFullGuidString
) + 6) * sizeof(WCHAR
));
4559 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4562 wcscpy(DriverKey
, lpFullGuidString
);
4563 wcscat(DriverKey
, L
"\\");
4564 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4565 rc
= RegOpenKeyExW(DevInfoSet
->HKLM
,
4570 if (rc
!= ERROR_SUCCESS
)
4575 /* Try all values for Index between 0 and 9999 */
4577 while (Index
<= 9999)
4580 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4581 rc
= RegCreateKeyEx(hClassKey
,
4585 REG_OPTION_NON_VOLATILE
,
4590 if (rc
!= ERROR_SUCCESS
)
4595 if (Disposition
== REG_CREATED_NEW_KEY
)
4598 hKey
= INVALID_HANDLE_VALUE
;
4603 /* Unable to create more than 9999 devices within the same class */
4604 SetLastError(ERROR_GEN_FAILURE
);
4608 /* Write information to driver key */
4609 *pSectionName
= UNICODE_NULL
;
4610 TRACE("Write information to driver key\n");
4611 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4612 TRACE("DriverDesc : '%S'\n", DriverInfo
->Info
.Description
);
4613 TRACE("DriverVersion : '%u.%u.%u.%u'\n", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4614 TRACE("InfPath : '%S'\n", DriverInfo
->InfPath
);
4615 TRACE("InfSection : '%S'\n", DriverInfo
->InfSection
);
4616 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(DriverInfo
->InfSection
)]); /* FIXME */
4617 TRACE("MatchingDeviceId: '%S'\n", DriverInfo
->MatchingId
);
4618 TRACE("ProviderName : '%S'\n", DriverInfo
->Info
.ProviderName
);
4619 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4620 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
4621 if (rc
== ERROR_SUCCESS
)
4622 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&DriverInfo
->Info
.DriverDate
, sizeof(FILETIME
));
4623 if (rc
== ERROR_SUCCESS
)
4624 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
4625 if (rc
== ERROR_SUCCESS
)
4627 swprintf(Buffer
, L
"%u.%u.%u.%u", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4628 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
4630 if (rc
== ERROR_SUCCESS
)
4631 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)DriverInfo
->InfPath
, (wcslen(DriverInfo
->InfPath
) + 1) * sizeof(WCHAR
));
4632 if (rc
== ERROR_SUCCESS
)
4633 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)DriverInfo
->InfSection
, (wcslen(DriverInfo
->InfSection
) + 1) * sizeof(WCHAR
));
4634 if (rc
== ERROR_SUCCESS
)
4635 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(DriverInfo
->InfSection
)], (wcslen(SectionName
) - wcslen(DriverInfo
->InfSection
) + 1) * sizeof(WCHAR
));
4636 if (rc
== ERROR_SUCCESS
)
4637 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)DriverInfo
->MatchingId
, (wcslen(DriverInfo
->MatchingId
) + 1) * sizeof(WCHAR
));
4638 if (rc
== ERROR_SUCCESS
)
4639 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.ProviderName
, (wcslen(DriverInfo
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
4640 if (rc
!= ERROR_SUCCESS
)
4646 hKey
= INVALID_HANDLE_VALUE
;
4648 /* Install .Services section */
4649 wcscpy(pSectionName
, L
".Services");
4650 Result
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
4653 LPWSTR ServiceName
= NULL
;
4654 LPWSTR ServiceSection
= NULL
;
4656 Result
= SetupGetStringFieldW(
4658 1, /* Field index */
4663 if (RequiredSize
> 0)
4665 /* We got the needed size for the buffer */
4666 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4669 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4672 Result
= SetupGetStringFieldW(
4674 1, /* Field index */
4675 ServiceName
, RequiredSize
,
4680 Result
= SetupGetIntField(
4682 2, /* Field index */
4686 /* The field may be empty. Ignore the error */
4689 Result
= SetupGetStringFieldW(
4691 3, /* Field index */
4696 if (RequiredSize
> 0)
4698 /* We got the needed size for the buffer */
4699 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4700 if (!ServiceSection
)
4702 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4705 Result
= SetupGetStringFieldW(
4707 3, /* Field index */
4708 ServiceSection
, RequiredSize
,
4713 SetLastError(ERROR_SUCCESS
);
4714 Result
= SetupInstallServicesFromInfSectionExW(hInf
, ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
4715 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
4717 AssociatedService
= ServiceName
;
4719 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
4720 RebootRequired
= TRUE
;
4723 HeapFree(GetProcessHeap(), 0, ServiceName
);
4724 HeapFree(GetProcessHeap(), 0, ServiceSection
);
4727 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
4730 /* Copy .inf file to Inf\ directory */
4731 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
4734 rc
= RegOpenKeyExW(DevInfoSet
->HKLM
,
4737 KEY_ENUMERATE_SUB_KEYS
,
4739 if (rc
!= ERROR_SUCCESS
)
4746 DevInfo
->DeviceName
,
4750 RegCloseKey(hEnumKey
);
4751 if (rc
!= ERROR_SUCCESS
)
4757 /* Install .HW section */
4758 wcscpy(pSectionName
, L
".HW");
4759 callback_context
= SetupInitDefaultQueueCallback(hWnd
);
4760 Result
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4761 SPINST_REGISTRY
, hKey
, NULL
, 0,
4762 SetupDefaultQueueCallbackW
, callback_context
,
4764 SetupTermDefaultQueueCallback(callback_context
);
4768 /* Write information to enum key */
4769 TRACE("Write information to enum key\n");
4770 TRACE("Service : '%S'\n", AssociatedService
);
4771 TRACE("Class : '%S'\n", ClassName
);
4772 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
4773 TRACE("DeviceDesc : '%S'\n", DriverInfo
->Info
.Description
);
4774 TRACE("Driver : '%S'\n", DriverKey
);
4775 TRACE("Mfg : '%S'\n", DriverInfo
->Info
.MfgName
);
4776 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
4777 if (rc
== ERROR_SUCCESS
)
4778 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
4779 if (rc
== ERROR_SUCCESS
)
4780 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
4781 if (rc
== ERROR_SUCCESS
)
4782 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
4783 if (rc
== ERROR_SUCCESS
)
4784 rc
= RegSetValueEx(hKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4785 if (rc
== ERROR_SUCCESS
)
4786 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.MfgName
, (wcslen(DriverInfo
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
4787 if (rc
!= ERROR_SUCCESS
)
4793 /* Load the driver/call AddDevice */
4794 FIXME("FIXME: Load the driver/call AddDevice\n");
4796 /* Send IRP_MN_START_DEVICE if needed */
4797 //if (!RebootRequired && !(Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
4798 FIXME("FIXME: Send IRP_MN_START_DEVICE\n");
4803 /* End of installation */
4804 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4805 RegCloseKey(hClassKey
);
4806 if (hKey
!= INVALID_HANDLE_VALUE
)
4809 RpcStringFreeW(&lpGuidString
);
4810 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
4811 HeapFree(GetProcessHeap(), 0, DriverKey
);
4812 HeapFree(GetProcessHeap(), 0, ClassName
);
4813 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
4814 if (hInf
!= INVALID_HANDLE_VALUE
)
4815 SetupCloseInfFile(hInf
);
4817 TRACE("Returning %d\n", ret
);