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
;
134 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
136 LIST_ENTRY ListEntry
;
138 /* Information about devnode:
140 * "Root\*PNP0501" for example.
141 * It doesn't contain the unique ID for the device
142 * (points into the Data field at the end of the structure)
143 * WARNING: no NULL char exist between DeviceName and UniqueId
146 * "5&1be2108e&0" or "0000"
147 * If DICD_GENERATE_ID is specified in creation flags,
148 * this unique ID is autogenerated using 4 digits, base 10
149 * (points into the Data field at the end of the structure)
150 * - DeviceDescription
151 * String which identifies the device. Can be NULL. If not NULL,
152 * points into the Data field at the end of the structure
154 * Identifies the class of this device. FIXME: can it be GUID_NULL?
156 * Is a combination of:
158 * the unique ID needs to be generated
159 * - DICD_INHERIT_CLASSDRVS
160 * inherit driver of the device info set (== same pointer)
162 * Used when doing device-specific actions. Can be NULL
166 PCWSTR DeviceDescription
;
171 /* Flags is a combination of:
173 * Set when the device driver list is created
174 * FlagsEx is a combination of:
179 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
180 /* If the driver is not searched/detected, this list is empty */
181 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
182 /* Points into DriverListHead list. The pointer is NULL if no driver is
183 * currently chosen. */
184 struct DriverInfoElement
*SelectedDriver
;
186 /* List of interfaces implemented by this device */
187 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
192 struct DeviceInfoSet
/* HDEVINFO */
194 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
195 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
196 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
197 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
199 /* Flags is a combination of:
201 * Set when the class driver list is created
202 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
203 * Forces SetupDiBuildDriverInfoList to build a class drivers list
204 * FlagsEx is a combination of:
209 /* If the driver is not searched/detected, this list is empty */
210 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
211 /* Points into DriverListHead list. The pointer is NULL if no driver is
212 * currently chosen. */
213 struct DriverInfoElement
*SelectedDriver
;
215 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
218 /***********************************************************************
219 * SetupDiBuildClassInfoList (SETUPAPI.@)
221 BOOL WINAPI
SetupDiBuildClassInfoList(
223 LPGUID ClassGuidList
,
224 DWORD ClassGuidListSize
,
228 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
229 ClassGuidListSize
, RequiredSize
,
233 /***********************************************************************
234 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
236 BOOL WINAPI
SetupDiBuildClassInfoListExA(
238 LPGUID ClassGuidList
,
239 DWORD ClassGuidListSize
,
244 LPWSTR MachineNameW
= NULL
;
251 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
252 if (MachineNameW
== NULL
) return FALSE
;
255 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
256 ClassGuidListSize
, RequiredSize
,
257 MachineNameW
, Reserved
);
260 MyFree(MachineNameW
);
265 /***********************************************************************
266 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
268 BOOL WINAPI
SetupDiBuildClassInfoListExW(
270 LPGUID ClassGuidList
,
271 DWORD ClassGuidListSize
,
276 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
282 DWORD dwGuidListIndex
= 0;
286 if (RequiredSize
!= NULL
)
289 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
294 if (hClassesKey
== INVALID_HANDLE_VALUE
)
299 for (dwIndex
= 0; ; dwIndex
++)
301 dwLength
= MAX_GUID_STRING_LEN
+ 1;
302 lError
= RegEnumKeyExW(hClassesKey
,
310 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
311 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
313 TRACE("Key name: %p\n", szKeyName
);
315 if (RegOpenKeyExW(hClassesKey
,
321 RegCloseKey(hClassesKey
);
325 if (!RegQueryValueExW(hClassKey
,
332 TRACE("'NoUseClass' value found!\n");
333 RegCloseKey(hClassKey
);
337 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
338 (!RegQueryValueExW(hClassKey
,
345 TRACE("'NoInstallClass' value found!\n");
346 RegCloseKey(hClassKey
);
350 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
351 (!RegQueryValueExW(hClassKey
,
358 TRACE("'NoDisplayClass' value found!\n");
359 RegCloseKey(hClassKey
);
363 RegCloseKey(hClassKey
);
365 TRACE("Guid: %p\n", szKeyName
);
366 if (dwGuidListIndex
< ClassGuidListSize
)
368 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
372 TRACE("Guid: %p\n", &szKeyName
[1]);
374 UuidFromStringW(&szKeyName
[1],
375 &ClassGuidList
[dwGuidListIndex
]);
381 if (lError
!= ERROR_SUCCESS
)
385 RegCloseKey(hClassesKey
);
387 if (RequiredSize
!= NULL
)
388 *RequiredSize
= dwGuidListIndex
;
390 if (ClassGuidListSize
< dwGuidListIndex
)
392 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
399 /***********************************************************************
400 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
402 BOOL WINAPI
SetupDiClassGuidsFromNameA(
404 LPGUID ClassGuidList
,
405 DWORD ClassGuidListSize
,
408 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
409 ClassGuidListSize
, RequiredSize
,
413 /***********************************************************************
414 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
416 BOOL WINAPI
SetupDiClassGuidsFromNameW(
418 LPGUID ClassGuidList
,
419 DWORD ClassGuidListSize
,
422 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
423 ClassGuidListSize
, RequiredSize
,
427 /***********************************************************************
428 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
430 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
432 LPGUID ClassGuidList
,
433 DWORD ClassGuidListSize
,
438 LPWSTR ClassNameW
= NULL
;
439 LPWSTR MachineNameW
= NULL
;
444 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
445 if (ClassNameW
== NULL
)
450 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
451 if (MachineNameW
== NULL
)
458 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
459 ClassGuidListSize
, RequiredSize
,
460 MachineNameW
, Reserved
);
463 MyFree(MachineNameW
);
470 /***********************************************************************
471 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
473 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
475 LPGUID ClassGuidList
,
476 DWORD ClassGuidListSize
,
481 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
482 WCHAR szClassName
[256];
488 DWORD dwGuidListIndex
= 0;
490 if (RequiredSize
!= NULL
)
493 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
494 KEY_ENUMERATE_SUB_KEYS
,
498 if (hClassesKey
== INVALID_HANDLE_VALUE
)
503 for (dwIndex
= 0; ; dwIndex
++)
505 dwLength
= MAX_GUID_STRING_LEN
+ 1;
506 lError
= RegEnumKeyExW(hClassesKey
,
514 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
515 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
517 TRACE("Key name: %p\n", szKeyName
);
519 if (RegOpenKeyExW(hClassesKey
,
525 RegCloseKey(hClassesKey
);
529 dwLength
= 256 * sizeof(WCHAR
);
530 if (!RegQueryValueExW(hClassKey
,
537 TRACE("Class name: %p\n", szClassName
);
539 if (strcmpiW(szClassName
, ClassName
) == 0)
541 TRACE("Found matching class name\n");
543 TRACE("Guid: %p\n", szKeyName
);
544 if (dwGuidListIndex
< ClassGuidListSize
)
546 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
550 TRACE("Guid: %p\n", &szKeyName
[1]);
552 UuidFromStringW(&szKeyName
[1],
553 &ClassGuidList
[dwGuidListIndex
]);
560 RegCloseKey(hClassKey
);
563 if (lError
!= ERROR_SUCCESS
)
567 RegCloseKey(hClassesKey
);
569 if (RequiredSize
!= NULL
)
570 *RequiredSize
= dwGuidListIndex
;
572 if (ClassGuidListSize
< dwGuidListIndex
)
574 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
581 /***********************************************************************
582 * SetupDiClassNameFromGuidA (SETUPAPI.@)
584 BOOL WINAPI
SetupDiClassNameFromGuidA(
585 const GUID
* ClassGuid
,
590 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
591 ClassNameSize
, RequiredSize
,
595 /***********************************************************************
596 * SetupDiClassNameFromGuidW (SETUPAPI.@)
598 BOOL WINAPI
SetupDiClassNameFromGuidW(
599 const GUID
* ClassGuid
,
604 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
605 ClassNameSize
, RequiredSize
,
609 /***********************************************************************
610 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
612 BOOL WINAPI
SetupDiClassNameFromGuidExA(
613 const GUID
* ClassGuid
,
620 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
621 LPWSTR MachineNameW
= NULL
;
625 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
626 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
627 NULL
, MachineNameW
, Reserved
);
630 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
631 ClassNameSize
, NULL
, NULL
);
633 if (!ClassNameSize
&& RequiredSize
)
636 MyFree(MachineNameW
);
640 /***********************************************************************
641 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
643 BOOL WINAPI
SetupDiClassNameFromGuidExW(
644 const GUID
* ClassGuid
,
655 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
660 if (hKey
== INVALID_HANDLE_VALUE
)
665 if (RequiredSize
!= NULL
)
668 rc
= RegQueryValueExW(hKey
,
674 if (rc
!= ERROR_SUCCESS
)
681 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
684 dwLength
= ClassNameSize
* sizeof(WCHAR
);
685 rc
= RegQueryValueExW(hKey
,
691 if (rc
!= ERROR_SUCCESS
)
703 /***********************************************************************
704 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
707 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
710 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
713 /***********************************************************************
714 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
717 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
722 LPWSTR MachineNameW
= NULL
;
725 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
729 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
730 if (MachineNameW
== NULL
)
731 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
734 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
735 MachineNameW
, Reserved
);
738 MyFree(MachineNameW
);
743 /***********************************************************************
744 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
747 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
752 struct DeviceInfoSet
*list
;
755 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
757 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
760 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
761 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
764 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
767 ClassGuid
? ClassGuid
: &GUID_NULL
,
768 sizeof(list
->ClassGuid
));
769 list
->hwndParent
= hwndParent
;
772 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
773 if (rc
!= ERROR_SUCCESS
)
776 HeapFree(GetProcessHeap(), 0, list
);
777 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
782 list
->HKLM
= HKEY_LOCAL_MACHINE
;
784 list
->Flags
= 0; /* FIXME */
785 list
->FlagsEx
= 0; /* FIXME */
786 InitializeListHead(&list
->DriverListHead
);
787 InitializeListHead(&list
->ListHead
);
788 return (HDEVINFO
)list
;
791 /***********************************************************************
792 * SetupDiEnumDeviceInfo (SETUPAPI.@)
794 BOOL WINAPI
SetupDiEnumDeviceInfo(
795 HDEVINFO DeviceInfoSet
,
797 PSP_DEVINFO_DATA DeviceInfoData
)
801 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
803 SetLastError(ERROR_INVALID_PARAMETER
);
804 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
806 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
808 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
809 SetLastError(ERROR_INVALID_HANDLE
);
810 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
811 SetLastError(ERROR_INVALID_USER_BUFFER
);
814 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
815 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
816 ItemList
= ItemList
->Flink
;
817 if (ItemList
== &list
->ListHead
)
818 SetLastError(ERROR_NO_MORE_ITEMS
);
821 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
822 memcpy(&DeviceInfoData
->ClassGuid
,
825 DeviceInfoData
->DevInst
= 0; /* FIXME */
826 /* Note: this appears to be dangerous, passing a private
827 * pointer a heap-allocated datum to the caller. However, the
828 * expected lifetime of the device data is the same as the
829 * HDEVINFO; once that is closed, the data are no longer valid.
831 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
837 SetLastError(ERROR_INVALID_HANDLE
);
841 /***********************************************************************
842 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
844 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
846 PCSTR InfSectionName
,
847 PSTR InfSectionWithExt
,
848 DWORD InfSectionWithExtSize
,
852 LPWSTR InfSectionNameW
= NULL
;
853 PWSTR InfSectionWithExtW
= NULL
;
855 BOOL bResult
= FALSE
;
861 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
862 if (InfSectionNameW
== NULL
) goto end
;
864 if (InfSectionWithExt
)
866 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
867 if (InfSectionWithExtW
== NULL
) goto end
;
870 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
871 InfSectionWithExt
? InfSectionNameW
: NULL
,
872 InfSectionWithExtSize
, RequiredSize
,
873 Extension
? &ExtensionW
: NULL
);
875 if (bResult
&& InfSectionWithExt
)
877 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
878 InfSectionWithExtSize
, NULL
, NULL
) != 0;
880 if (bResult
&& Extension
)
882 if (ExtensionW
== NULL
)
885 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
889 if (InfSectionNameW
) MyFree(InfSectionNameW
);
890 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
895 /***********************************************************************
896 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
898 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
900 PCWSTR InfSectionName
,
901 PWSTR InfSectionWithExt
,
902 DWORD InfSectionWithExtSize
,
906 WCHAR szBuffer
[MAX_PATH
];
909 LONG lLineCount
= -1;
911 lstrcpyW(szBuffer
, InfSectionName
);
912 dwLength
= lstrlenW(szBuffer
);
914 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
916 /* Test section name with '.NTx86' extension */
917 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
918 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
920 if (lLineCount
== -1)
922 /* Test section name with '.NT' extension */
923 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
924 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
929 /* Test section name with '.Win' extension */
930 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
931 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
934 if (lLineCount
== -1)
936 /* Test section name without extension */
937 szBuffer
[dwLength
] = 0;
938 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
941 if (lLineCount
== -1)
943 SetLastError(ERROR_INVALID_PARAMETER
);
947 dwFullLength
= lstrlenW(szBuffer
);
949 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
951 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
953 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
957 lstrcpyW(InfSectionWithExt
, szBuffer
);
958 if (Extension
!= NULL
)
960 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
964 if (RequiredSize
!= NULL
)
966 *RequiredSize
= dwFullLength
+ 1;
972 /***********************************************************************
973 * SetupDiGetClassDescriptionA (SETUPAPI.@)
975 BOOL WINAPI
SetupDiGetClassDescriptionA(
976 const GUID
* ClassGuid
,
977 PSTR ClassDescription
,
978 DWORD ClassDescriptionSize
,
981 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
982 ClassDescriptionSize
,
983 RequiredSize
, NULL
, NULL
);
986 /***********************************************************************
987 * SetupDiGetClassDescriptionW (SETUPAPI.@)
989 BOOL WINAPI
SetupDiGetClassDescriptionW(
990 const GUID
* ClassGuid
,
991 PWSTR ClassDescription
,
992 DWORD ClassDescriptionSize
,
995 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
996 ClassDescriptionSize
,
997 RequiredSize
, NULL
, NULL
);
1000 /***********************************************************************
1001 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1003 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1004 const GUID
* ClassGuid
,
1005 PSTR ClassDescription
,
1006 DWORD ClassDescriptionSize
,
1007 PDWORD RequiredSize
,
1011 PWCHAR ClassDescriptionW
;
1012 LPWSTR MachineNameW
= NULL
;
1016 if (ClassDescriptionSize
> 0)
1018 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1019 if (!ClassDescriptionW
)
1021 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1027 ClassDescriptionW
= NULL
;
1031 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1034 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1040 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1041 NULL
, MachineNameW
, Reserved
);
1044 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1045 ClassDescriptionSize
, NULL
, NULL
);
1047 if (!ClassDescriptionSize
&& RequiredSize
)
1048 *RequiredSize
= len
;
1052 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1053 MyFree(MachineNameW
);
1057 /***********************************************************************
1058 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1060 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1061 const GUID
* ClassGuid
,
1062 PWSTR ClassDescription
,
1063 DWORD ClassDescriptionSize
,
1064 PDWORD RequiredSize
,
1071 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1076 if (hKey
== INVALID_HANDLE_VALUE
)
1078 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1082 if (RequiredSize
!= NULL
)
1085 if (RegQueryValueExW(hKey
,
1096 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1099 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1100 if (RegQueryValueExW(hKey
,
1104 (LPBYTE
)ClassDescription
,
1116 /***********************************************************************
1117 * SetupDiGetClassDevsA (SETUPAPI.@)
1119 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1125 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1126 flags
, NULL
, NULL
, NULL
);
1129 /***********************************************************************
1130 * SetupDiGetClassDevsW (SETUPAPI.@)
1132 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1138 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1139 flags
, NULL
, NULL
, NULL
);
1142 /***********************************************************************
1143 * SetupDiGetClassDevsExA (SETUPAPI.@)
1145 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1155 LPWSTR enumstrW
= NULL
;
1156 LPWSTR machineW
= NULL
;
1160 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1161 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1164 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1167 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1171 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1172 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1175 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1178 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1180 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1183 HeapFree(GetProcessHeap(), 0, enumstrW
);
1184 HeapFree(GetProcessHeap(), 0, machineW
);
1189 CreateDeviceInfoElement(
1190 IN LPCWSTR InstancePath
,
1192 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1194 struct DeviceInfoElement
*deviceInfo
;
1196 *pDeviceInfo
= NULL
;
1197 if (IsEqualIID(&pClassGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1199 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1202 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1205 wcscpy(deviceInfo
->Data
, InstancePath
);
1206 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1207 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1208 deviceInfo
->DeviceDescription
= NULL
;
1209 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1210 deviceInfo
->CreationFlags
= 0;
1211 deviceInfo
->hwndParent
= NULL
;
1212 deviceInfo
->Flags
= 0; /* FIXME */
1213 deviceInfo
->FlagsEx
= 0; /* FIXME */
1214 deviceInfo
->SelectedDriver
= NULL
;
1215 InitializeListHead(&deviceInfo
->DriverListHead
);
1216 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1218 *pDeviceInfo
= deviceInfo
;
1223 CreateDeviceInterface(
1224 IN
struct DeviceInfoElement
* deviceInfo
,
1225 IN LPCWSTR SymbolicLink
,
1226 IN LPCGUID pInterfaceGuid
,
1227 OUT
struct DeviceInterface
**pDeviceInterface
)
1229 struct DeviceInterface
*deviceInterface
;
1231 *pDeviceInterface
= NULL
;
1233 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1234 if (!deviceInterface
)
1236 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1239 deviceInterface
->DeviceInfo
= deviceInfo
;
1240 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1241 deviceInterface
->Flags
= 0; /* FIXME */
1242 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1244 *pDeviceInterface
= deviceInterface
;
1248 static LONG
SETUP_CreateDevListFromEnumerator(
1249 struct DeviceInfoSet
*list
,
1250 LPCGUID pClassGuid OPTIONAL
,
1252 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1254 HKEY hDeviceIdKey
, hInstanceIdKey
;
1255 WCHAR KeyBuffer
[MAX_PATH
];
1256 WCHAR InstancePath
[MAX_PATH
];
1257 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1258 struct DeviceInfoElement
*deviceInfo
;
1260 DWORD dwLength
, dwRegType
;
1263 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1266 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1267 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1268 if (rc
== ERROR_NO_MORE_ITEMS
)
1270 if (rc
!= ERROR_SUCCESS
)
1274 /* Open device id sub key */
1275 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1276 if (rc
!= ERROR_SUCCESS
)
1278 wcscpy(InstancePath
, Enumerator
);
1279 wcscat(InstancePath
, L
"\\");
1280 wcscat(InstancePath
, KeyBuffer
);
1281 wcscat(InstancePath
, L
"\\");
1282 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1284 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1290 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1291 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1292 if (rc
== ERROR_NO_MORE_ITEMS
)
1294 if (rc
!= ERROR_SUCCESS
)
1296 RegCloseKey(hDeviceIdKey
);
1301 /* Open instance id sub key */
1302 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1303 if (rc
!= ERROR_SUCCESS
)
1305 RegCloseKey(hDeviceIdKey
);
1308 *pEndOfInstancePath
= '\0';
1309 wcscat(InstancePath
, KeyBuffer
);
1311 /* Read ClassGUID value */
1312 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1313 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1314 RegCloseKey(hInstanceIdKey
);
1315 if (rc
== ERROR_FILE_NOT_FOUND
)
1318 /* Skip this bad entry as we can't verify it */
1321 else if (rc
!= ERROR_SUCCESS
)
1323 RegCloseKey(hDeviceIdKey
);
1326 else if (dwRegType
!= REG_SZ
)
1328 RegCloseKey(hDeviceIdKey
);
1329 return ERROR_GEN_FAILURE
;
1332 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1333 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1335 RegCloseKey(hDeviceIdKey
);
1336 return GetLastError();
1338 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1340 /* Skip this entry as it is not the right device class */
1344 /* Add the entry to the list */
1345 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1347 RegCloseKey(hDeviceIdKey
);
1348 return GetLastError();
1350 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1351 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1353 RegCloseKey(hDeviceIdKey
);
1356 return ERROR_SUCCESS
;
1359 static LONG
SETUP_CreateDevList(
1360 struct DeviceInfoSet
*list
,
1361 PCWSTR MachineName OPTIONAL
,
1362 LPGUID
class OPTIONAL
,
1363 PCWSTR Enumerator OPTIONAL
)
1365 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1366 WCHAR KeyBuffer
[MAX_PATH
];
1371 if (IsEqualIID(class, &GUID_NULL
))
1375 if (MachineName
!= NULL
)
1377 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1378 if (rc
!= ERROR_SUCCESS
)
1382 HKLM
= HKEY_LOCAL_MACHINE
;
1384 rc
= RegOpenKeyExW(HKLM
,
1387 KEY_ENUMERATE_SUB_KEYS
,
1389 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1390 if (rc
!= ERROR_SUCCESS
)
1393 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1394 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1403 KEY_ENUMERATE_SUB_KEYS
,
1405 RegCloseKey(hEnumKey
);
1406 if (rc
!= ERROR_SUCCESS
)
1408 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1409 RegCloseKey(hEnumeratorKey
);
1414 /* Enumerate enumerators */
1418 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1419 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1420 if (rc
== ERROR_NO_MORE_ITEMS
)
1422 if (rc
!= ERROR_SUCCESS
)
1424 RegCloseKey(hEnumKey
);
1430 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1431 if (rc
!= ERROR_SUCCESS
)
1433 RegCloseKey(hEnumKey
);
1437 /* Call SETUP_CreateDevListFromEnumerator */
1438 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1439 RegCloseKey(hEnumeratorKey
);
1440 if (rc
!= ERROR_SUCCESS
)
1442 RegCloseKey(hEnumKey
);
1446 RegCloseKey(hEnumKey
);
1447 return ERROR_SUCCESS
;
1452 static LONG
SETUP_CreateSerialDeviceList(
1453 struct DeviceInfoSet
*list
,
1455 LPGUID InterfaceGuid
,
1456 PCWSTR DeviceInstanceW
)
1458 static const size_t initialSize
= 100;
1460 WCHAR buf
[initialSize
];
1462 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1464 struct DeviceInfoElement
*deviceInfo
;
1467 WARN("'MachineName' is ignored on Wine!\n");
1468 if (DeviceInstanceW
)
1469 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1475 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1477 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1481 HeapFree(GetProcessHeap(), 0, devices
);
1482 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1484 return ERROR_NOT_ENOUGH_MEMORY
;
1490 HeapFree(GetProcessHeap(), 0, devices
);
1491 return GetLastError();
1495 /* 'devices' is a MULTI_SZ string */
1496 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1498 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1500 /* We have found a device */
1501 struct DeviceInterface
*interfaceInfo
;
1502 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1503 /* Step 1. Create a device info element */
1504 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1507 HeapFree(GetProcessHeap(), 0, devices
);
1508 return GetLastError();
1510 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1512 /* Step 2. Create an interface list for this element */
1513 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1516 HeapFree(GetProcessHeap(), 0, devices
);
1517 return GetLastError();
1519 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1523 HeapFree(GetProcessHeap(), 0, devices
);
1524 return ERROR_SUCCESS
;
1527 #else /* __REACTOS__ */
1529 static LONG
SETUP_CreateInterfaceList(
1530 struct DeviceInfoSet
*list
,
1532 LPGUID InterfaceGuid
,
1533 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1535 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1536 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1537 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1538 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1539 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1541 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1544 DWORD dwLength
, dwInstancePathLength
;
1547 struct DeviceInfoElement
*deviceInfo
;
1549 /* Open registry key related to this interface */
1550 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1551 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1552 return GetLastError();
1554 /* Enumerate sub keys of hInterfaceKey */
1558 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1559 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1560 if (rc
== ERROR_NO_MORE_ITEMS
)
1562 if (rc
!= ERROR_SUCCESS
)
1564 RegCloseKey(hInterfaceKey
);
1570 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1571 if (rc
!= ERROR_SUCCESS
)
1573 RegCloseKey(hInterfaceKey
);
1577 /* Read DeviceInstance */
1578 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1579 if (rc
!= ERROR_SUCCESS
)
1581 RegCloseKey(hDeviceInstanceKey
);
1582 RegCloseKey(hInterfaceKey
);
1585 if (dwRegType
!= REG_SZ
)
1587 RegCloseKey(hDeviceInstanceKey
);
1588 RegCloseKey(hInterfaceKey
);
1589 return ERROR_GEN_FAILURE
;
1591 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1594 RegCloseKey(hDeviceInstanceKey
);
1595 RegCloseKey(hInterfaceKey
);
1596 return ERROR_NOT_ENOUGH_MEMORY
;
1598 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1599 if (rc
!= ERROR_SUCCESS
)
1601 HeapFree(GetProcessHeap(), 0, InstancePath
);
1602 RegCloseKey(hDeviceInstanceKey
);
1603 RegCloseKey(hInterfaceKey
);
1606 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1607 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1609 if (DeviceInstanceW
)
1611 /* Check if device enumerator is not the right one */
1612 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1614 HeapFree(GetProcessHeap(), 0, InstancePath
);
1615 RegCloseKey(hDeviceInstanceKey
);
1620 /* Find class GUID associated to the device instance */
1625 KEY_ENUMERATE_SUB_KEYS
,
1627 if (rc
!= ERROR_SUCCESS
)
1629 HeapFree(GetProcessHeap(), 0, InstancePath
);
1630 RegCloseKey(hDeviceInstanceKey
);
1631 RegCloseKey(hInterfaceKey
);
1640 RegCloseKey(hEnumKey
);
1641 if (rc
!= ERROR_SUCCESS
)
1643 HeapFree(GetProcessHeap(), 0, InstancePath
);
1644 RegCloseKey(hDeviceInstanceKey
);
1645 RegCloseKey(hInterfaceKey
);
1648 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1649 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1651 if (rc
!= ERROR_SUCCESS
)
1653 HeapFree(GetProcessHeap(), 0, InstancePath
);
1654 RegCloseKey(hDeviceInstanceKey
);
1655 RegCloseKey(hInterfaceKey
);
1658 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1659 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1660 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1662 HeapFree(GetProcessHeap(), 0, InstancePath
);
1663 RegCloseKey(hDeviceInstanceKey
);
1664 RegCloseKey(hInterfaceKey
);
1665 return ERROR_GEN_FAILURE
;
1667 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1669 /* If current device doesn't match the list GUID (if any), skip this entry */
1670 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1672 HeapFree(GetProcessHeap(), 0, InstancePath
);
1673 RegCloseKey(hDeviceInstanceKey
);
1677 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1681 LPWSTR pSymbolicLink
;
1682 struct DeviceInterface
*interfaceInfo
;
1684 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1685 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1686 if (rc
== ERROR_NO_MORE_ITEMS
)
1688 if (rc
!= ERROR_SUCCESS
)
1690 HeapFree(GetProcessHeap(), 0, InstancePath
);
1691 RegCloseKey(hDeviceInstanceKey
);
1692 RegCloseKey(hInterfaceKey
);
1696 if (KeyBuffer
[0] != '#')
1697 /* This entry doesn't represent an interesting entry */
1701 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1702 if (rc
!= ERROR_SUCCESS
)
1704 RegCloseKey(hDeviceInstanceKey
);
1705 RegCloseKey(hInterfaceKey
);
1709 /* Read SymbolicLink value */
1710 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1711 if (rc
!= ERROR_SUCCESS
)
1713 RegCloseKey(hReferenceKey
);
1714 RegCloseKey(hDeviceInstanceKey
);
1715 RegCloseKey(hInterfaceKey
);
1718 if (dwRegType
!= REG_SZ
)
1720 RegCloseKey(hReferenceKey
);
1721 RegCloseKey(hDeviceInstanceKey
);
1722 RegCloseKey(hInterfaceKey
);
1723 return ERROR_GEN_FAILURE
;
1726 /* We have found a device */
1727 /* Step 1. Create a device info element */
1728 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1730 RegCloseKey(hReferenceKey
);
1731 RegCloseKey(hDeviceInstanceKey
);
1732 RegCloseKey(hInterfaceKey
);
1733 return GetLastError();
1735 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1736 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1738 /* Step 2. Create an interface list for this element */
1739 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1742 RegCloseKey(hReferenceKey
);
1743 RegCloseKey(hDeviceInstanceKey
);
1744 RegCloseKey(hInterfaceKey
);
1745 return ERROR_NOT_ENOUGH_MEMORY
;
1747 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1748 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1749 RegCloseKey(hReferenceKey
);
1750 if (rc
!= ERROR_SUCCESS
)
1752 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1753 RegCloseKey(hDeviceInstanceKey
);
1754 RegCloseKey(hInterfaceKey
);
1757 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1759 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1760 RegCloseKey(hDeviceInstanceKey
);
1761 RegCloseKey(hInterfaceKey
);
1762 return GetLastError();
1764 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1765 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1766 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1768 RegCloseKey(hDeviceInstanceKey
);
1770 RegCloseKey(hInterfaceKey
);
1771 return ERROR_SUCCESS
;
1773 #endif /* __REACTOS__ */
1775 /***********************************************************************
1776 * SetupDiGetClassDevsExW (SETUPAPI.@)
1778 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1787 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1788 struct DeviceInfoSet
*list
;
1792 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1793 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1795 /* Create the deviceset if not set */
1798 list
= (struct DeviceInfoSet
*)deviceset
;
1799 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1801 SetLastError(ERROR_INVALID_HANDLE
);
1802 return INVALID_HANDLE_VALUE
;
1804 hDeviceInfo
= deviceset
;
1808 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1809 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1810 NULL
, machine
, NULL
);
1811 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1812 return INVALID_HANDLE_VALUE
;
1813 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1816 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1819 pClassGuid
= &list
->ClassGuid
;
1821 if (flags
& DIGCF_PRESENT
)
1822 FIXME(": flag DIGCF_PRESENT ignored\n");
1823 if (flags
& DIGCF_PROFILE
)
1824 FIXME(": flag DIGCF_PROFILE ignored\n");
1826 if (flags
& DIGCF_ALLCLASSES
)
1828 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1829 if (rc
!= ERROR_SUCCESS
)
1833 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1834 return INVALID_HANDLE_VALUE
;
1838 else if (flags
& DIGCF_DEVICEINTERFACE
)
1842 SetLastError(ERROR_INVALID_PARAMETER
);
1844 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1845 return INVALID_HANDLE_VALUE
;
1849 /* Special case: find serial ports by calling QueryDosDevice */
1850 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1851 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1852 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1853 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1856 ERR("Wine can only enumerate serial devices at the moment!\n");
1857 rc
= ERROR_INVALID_PARAMETER
;
1859 #else /* __REACTOS__ */
1860 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1861 #endif /* __REACTOS__ */
1862 if (rc
!= ERROR_SUCCESS
)
1866 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1867 return INVALID_HANDLE_VALUE
;
1873 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1874 if (rc
!= ERROR_SUCCESS
)
1878 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1879 return INVALID_HANDLE_VALUE
;
1885 /***********************************************************************
1886 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1888 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1889 HDEVINFO DeviceInfoSet
,
1890 PSP_DEVINFO_DATA DeviceInfoData
,
1891 CONST GUID
* InterfaceClassGuid
,
1893 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1897 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1898 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1900 if (!DeviceInterfaceData
)
1901 SetLastError(ERROR_INVALID_PARAMETER
);
1902 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1903 SetLastError(ERROR_INVALID_USER_BUFFER
);
1904 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1906 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1908 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1910 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1912 while (ItemList
!= &list
->ListHead
&& !Found
)
1914 PLIST_ENTRY InterfaceListEntry
;
1915 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1916 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1918 /* We are not searching for this element */
1919 ItemList
= ItemList
->Flink
;
1922 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1923 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1925 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1926 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1928 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1931 if (MemberIndex
-- == 0)
1933 /* return this item */
1934 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1935 &DevItf
->InterfaceClassGuid
,
1937 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1938 /* Note: this appears to be dangerous, passing a private
1939 * pointer a heap-allocated datum to the caller. However, the
1940 * expected lifetime of the device data is the same as the
1941 * HDEVINFO; once that is closed, the data are no longer valid.
1943 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1946 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1948 ItemList
= ItemList
->Flink
;
1951 SetLastError(ERROR_NO_MORE_ITEMS
);
1956 SetLastError(ERROR_INVALID_HANDLE
);
1959 SetLastError(ERROR_INVALID_HANDLE
);
1963 /***********************************************************************
1964 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1966 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1970 TRACE("%p\n", devinfo
);
1971 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1973 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1975 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1977 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1978 struct DeviceInfoElement
*deviceInfo
;
1979 while (!IsListEmpty(&list
->ListHead
))
1981 ListEntry
= RemoveHeadList(&list
->ListHead
);
1982 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1983 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1985 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1986 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1988 HeapFree(GetProcessHeap(), 0, ListEntry
);
1990 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1991 RegCloseKey(list
->HKLM
);
1992 HeapFree(GetProcessHeap(), 0, list
);
1996 SetLastError(ERROR_INVALID_HANDLE
);
1999 SetLastError(ERROR_INVALID_HANDLE
);
2001 TRACE("Returning %d\n", ret
);
2005 /***********************************************************************
2006 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2008 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2009 HDEVINFO DeviceInfoSet
,
2010 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2011 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2012 DWORD DeviceInterfaceDetailDataSize
,
2013 PDWORD RequiredSize
,
2014 PSP_DEVINFO_DATA DeviceInfoData
)
2016 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2017 DWORD sizeW
= 0, sizeA
;
2020 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2021 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2022 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2024 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2025 SetLastError(ERROR_INVALID_USER_BUFFER
);
2026 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2027 SetLastError(ERROR_INVALID_PARAMETER
);
2028 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2029 SetLastError(ERROR_INVALID_PARAMETER
);
2032 if (DeviceInterfaceDetailData
!= NULL
)
2034 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2035 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2036 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2037 if (!DeviceInterfaceDetailDataW
)
2039 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2042 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2044 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2045 ret
= SetupDiGetDeviceInterfaceDetailW(
2047 DeviceInterfaceData
,
2048 DeviceInterfaceDetailDataW
,
2052 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2053 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2055 *RequiredSize
= sizeA
;
2056 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2058 if (!WideCharToMultiByte(
2060 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2061 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2068 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2071 TRACE("Returning %d\n", ret
);
2075 /***********************************************************************
2076 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2078 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2079 HDEVINFO DeviceInfoSet
,
2080 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2081 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2082 DWORD DeviceInterfaceDetailDataSize
,
2083 PDWORD RequiredSize
,
2084 PSP_DEVINFO_DATA DeviceInfoData
)
2088 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2089 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2090 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2092 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2093 SetLastError(ERROR_INVALID_PARAMETER
);
2094 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2095 SetLastError(ERROR_INVALID_HANDLE
);
2096 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2097 SetLastError(ERROR_INVALID_HANDLE
);
2098 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2099 SetLastError(ERROR_INVALID_USER_BUFFER
);
2100 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2101 SetLastError(ERROR_INVALID_USER_BUFFER
);
2102 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2103 SetLastError(ERROR_INVALID_USER_BUFFER
);
2104 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2105 SetLastError(ERROR_INVALID_PARAMETER
);
2106 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2107 SetLastError(ERROR_INVALID_PARAMETER
);
2110 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2111 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2112 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2113 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2115 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2117 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2119 *RequiredSize
= sizeRequired
;
2123 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2124 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2127 memcpy(&DeviceInfoData
->ClassGuid
,
2128 &deviceInterface
->DeviceInfo
->ClassGuid
,
2130 DeviceInfoData
->DevInst
= 0; /* FIXME */
2131 /* Note: this appears to be dangerous, passing a private
2132 * pointer a heap-allocated datum to the caller. However, the
2133 * expected lifetime of the device data is the same as the
2134 * HDEVINFO; once that is closed, the data are no longer valid.
2136 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2142 TRACE("Returning %d\n", ret
);
2146 /***********************************************************************
2147 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2149 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2151 PSP_DEVINFO_DATA DeviceInfoData
,
2153 PDWORD PropertyRegDataType
,
2154 PBYTE PropertyBuffer
,
2155 DWORD PropertyBufferSize
,
2156 PDWORD RequiredSize
)
2159 BOOL bIsStringProperty
;
2161 DWORD RequiredSizeA
, RequiredSizeW
;
2162 DWORD PropertyBufferSizeW
;
2163 PBYTE PropertyBufferW
;
2165 TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
2166 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2169 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2170 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2172 bResult
= SetupDiGetDeviceRegistryPropertyW(
2178 PropertyBufferSizeW
,
2183 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2187 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2189 if (bIsStringProperty
)
2190 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2192 RequiredSizeA
= RequiredSizeW
;
2194 if (RequiredSizeA
<= PropertyBufferSize
)
2196 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2198 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2200 /* Last error is already set by WideCharToMultiByte */
2205 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2209 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2213 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2214 if (PropertyRegDataType
)
2215 *PropertyRegDataType
= RegType
;
2217 *RequiredSize
= RequiredSizeA
;
2221 /***********************************************************************
2222 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2224 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2225 HDEVINFO DeviceInfoSet
,
2226 PSP_DEVINFO_DATA DeviceInfoData
,
2228 PDWORD PropertyRegDataType
,
2229 PBYTE PropertyBuffer
,
2230 DWORD PropertyBufferSize
,
2231 PDWORD RequiredSize
)
2233 HKEY hEnumKey
, hKey
;
2237 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2238 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2241 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2242 SetLastError(ERROR_INVALID_HANDLE
);
2243 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2244 SetLastError(ERROR_INVALID_HANDLE
);
2245 else if (!DeviceInfoData
)
2246 SetLastError(ERROR_INVALID_PARAMETER
);
2247 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2248 SetLastError(ERROR_INVALID_USER_BUFFER
);
2249 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2250 SetLastError(ERROR_INVALID_PARAMETER
);
2253 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2254 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2258 case SPDRP_CAPABILITIES
:
2260 case SPDRP_CLASSGUID
:
2261 case SPDRP_COMPATIBLEIDS
:
2262 case SPDRP_CONFIGFLAGS
:
2263 case SPDRP_DEVICEDESC
:
2265 case SPDRP_FRIENDLYNAME
:
2266 case SPDRP_HARDWAREID
:
2267 case SPDRP_LOCATION_INFORMATION
:
2268 case SPDRP_LOWERFILTERS
:
2270 case SPDRP_SECURITY
:
2272 case SPDRP_UI_NUMBER
:
2273 case SPDRP_UPPERFILTERS
:
2275 LPCWSTR RegistryPropertyName
;
2280 case SPDRP_CAPABILITIES
:
2281 RegistryPropertyName
= L
"Capabilities"; break;
2283 RegistryPropertyName
= L
"Class"; break;
2284 case SPDRP_CLASSGUID
:
2285 RegistryPropertyName
= L
"ClassGUID"; break;
2286 case SPDRP_COMPATIBLEIDS
:
2287 RegistryPropertyName
= L
"CompatibleIDs"; break;
2288 case SPDRP_CONFIGFLAGS
:
2289 RegistryPropertyName
= L
"ConfigFlags"; break;
2290 case SPDRP_DEVICEDESC
:
2291 RegistryPropertyName
= L
"DeviceDesc"; break;
2293 RegistryPropertyName
= L
"Driver"; break;
2294 case SPDRP_FRIENDLYNAME
:
2295 RegistryPropertyName
= L
"FriendlyName"; break;
2296 case SPDRP_HARDWAREID
:
2297 RegistryPropertyName
= L
"HardwareID"; break;
2298 case SPDRP_LOCATION_INFORMATION
:
2299 RegistryPropertyName
= L
"LocationInformation"; break;
2300 case SPDRP_LOWERFILTERS
:
2301 RegistryPropertyName
= L
"LowerFilters"; break;
2303 RegistryPropertyName
= L
"Mfg"; break;
2304 case SPDRP_SECURITY
:
2305 RegistryPropertyName
= L
"Security"; break;
2307 RegistryPropertyName
= L
"Service"; break;
2308 case SPDRP_UI_NUMBER
:
2309 RegistryPropertyName
= L
"UINumber"; break;
2310 case SPDRP_UPPERFILTERS
:
2311 RegistryPropertyName
= L
"UpperFilters"; break;
2313 /* Should not happen */
2314 RegistryPropertyName
= NULL
; break;
2317 /* Open registry key name */
2322 KEY_ENUMERATE_SUB_KEYS
,
2324 if (rc
!= ERROR_SUCCESS
)
2335 RegCloseKey(hEnumKey
);
2336 if (rc
!= ERROR_SUCCESS
)
2341 /* Read registry entry */
2342 BufferSize
= PropertyBufferSize
;
2343 rc
= RegQueryValueExW(
2345 RegistryPropertyName
,
2346 NULL
, /* Reserved */
2347 PropertyRegDataType
,
2351 *RequiredSize
= BufferSize
;
2352 if (rc
== ERROR_SUCCESS
)
2360 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2362 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2364 if (PropertyRegDataType
)
2365 *PropertyRegDataType
= REG_SZ
;
2367 *RequiredSize
= required
;
2368 if (PropertyBufferSize
>= required
)
2370 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2374 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2378 /*case SPDRP_BUSTYPEGUID:
2379 case SPDRP_LEGACYBUSTYPE:
2380 case SPDRP_BUSNUMBER:
2381 case SPDRP_ENUMERATOR_NAME:
2382 case SPDRP_SECURITY_SDS:
2384 case SPDRP_EXCLUSIVE:
2385 case SPDRP_CHARACTERISTICS:
2387 case SPDRP_UI_NUMBER_DESC_FORMAT:
2388 case SPDRP_DEVICE_POWER_DATA:*/
2389 #if (WINVER >= 0x501)
2390 /*case SPDRP_REMOVAL_POLICY:
2391 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2392 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2393 case SPDRP_INSTALL_STATE:*/
2398 FIXME("Property 0x%lx not implemented\n", Property
);
2399 SetLastError(ERROR_NOT_SUPPORTED
);
2404 TRACE("Returning %d\n", ret
);
2409 /***********************************************************************
2410 * SetupDiInstallClassA (SETUPAPI.@)
2412 BOOL WINAPI
SetupDiInstallClassA(
2418 UNICODE_STRING FileNameW
;
2421 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2423 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2427 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2429 RtlFreeUnicodeString(&FileNameW
);
2434 static HKEY
CreateClassKey(HINF hInf
)
2436 WCHAR FullBuffer
[MAX_PATH
];
2437 WCHAR Buffer
[MAX_PATH
];
2442 if (!SetupGetLineTextW(NULL
,
2450 return INVALID_HANDLE_VALUE
;
2453 lstrcpyW(FullBuffer
, ControlClass
);
2454 lstrcatW(FullBuffer
, Buffer
);
2457 if (!SetupGetLineTextW(NULL
,
2465 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2466 return INVALID_HANDLE_VALUE
;
2469 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2473 REG_OPTION_NON_VOLATILE
,
2479 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2480 return INVALID_HANDLE_VALUE
;
2483 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2488 RequiredSize
* sizeof(WCHAR
)))
2490 RegCloseKey(hClassKey
);
2491 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2492 return INVALID_HANDLE_VALUE
;
2498 /***********************************************************************
2499 * SetupDiInstallClassW (SETUPAPI.@)
2501 BOOL WINAPI
SetupDiInstallClassW(
2507 WCHAR SectionName
[MAX_PATH
];
2508 DWORD SectionNameLength
= 0;
2510 BOOL bFileQueueCreated
= FALSE
;
2513 FIXME("not fully implemented\n");
2515 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2517 SetLastError(ERROR_INVALID_PARAMETER
);
2521 /* Open the .inf file */
2522 hInf
= SetupOpenInfFileW(InfFileName
,
2526 if (hInf
== INVALID_HANDLE_VALUE
)
2532 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2533 hClassKey
= CreateClassKey(hInf
);
2534 if (hClassKey
== INVALID_HANDLE_VALUE
)
2536 SetupCloseInfFile(hInf
);
2542 /* Try to append a layout file */
2544 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2547 /* Retrieve the actual section name */
2548 SetupDiGetActualSectionToInstallW(hInf
,
2556 if (!(Flags
& DI_NOVCP
))
2558 FileQueue
= SetupOpenFileQueue();
2559 if (FileQueue
== INVALID_HANDLE_VALUE
)
2561 SetupCloseInfFile(hInf
);
2562 RegCloseKey(hClassKey
);
2566 bFileQueueCreated
= TRUE
;
2571 SetupInstallFromInfSectionW(NULL
,
2580 INVALID_HANDLE_VALUE
,
2583 /* FIXME: More code! */
2585 if (bFileQueueCreated
)
2586 SetupCloseFileQueue(FileQueue
);
2588 SetupCloseInfFile(hInf
);
2590 RegCloseKey(hClassKey
);
2595 /***********************************************************************
2596 * SetupDiOpenClassRegKey (SETUPAPI.@)
2598 HKEY WINAPI
SetupDiOpenClassRegKey(
2599 const GUID
* ClassGuid
,
2602 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2603 DIOCR_INSTALLER
, NULL
, NULL
);
2607 /***********************************************************************
2608 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2610 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2611 const GUID
* ClassGuid
,
2617 PWSTR MachineNameW
= NULL
;
2624 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2625 if (MachineNameW
== NULL
)
2626 return INVALID_HANDLE_VALUE
;
2629 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2630 Flags
, MachineNameW
, Reserved
);
2633 MyFree(MachineNameW
);
2639 /***********************************************************************
2640 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2642 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2643 const GUID
* ClassGuid
,
2649 LPWSTR lpGuidString
;
2650 LPWSTR lpFullGuidString
;
2658 if (Flags
== DIOCR_INSTALLER
)
2660 lpKeyName
= ControlClass
;
2662 else if (Flags
== DIOCR_INTERFACE
)
2664 lpKeyName
= DeviceClasses
;
2668 ERR("Invalid Flags parameter!\n");
2669 SetLastError(ERROR_INVALID_PARAMETER
);
2670 return INVALID_HANDLE_VALUE
;
2673 if (MachineName
!= NULL
)
2675 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2676 if (rc
!= ERROR_SUCCESS
)
2679 return INVALID_HANDLE_VALUE
;
2683 HKLM
= HKEY_LOCAL_MACHINE
;
2685 rc
= RegOpenKeyExW(HKLM
,
2690 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2691 if (rc
!= ERROR_SUCCESS
)
2694 return INVALID_HANDLE_VALUE
;
2697 if (ClassGuid
== NULL
)
2700 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2702 SetLastError(ERROR_GEN_FAILURE
);
2703 RegCloseKey(hClassesKey
);
2704 return INVALID_HANDLE_VALUE
;
2707 dwLength
= lstrlenW(lpGuidString
);
2708 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2709 if (!lpFullGuidString
)
2711 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2712 RpcStringFreeW(&lpGuidString
);
2713 return INVALID_HANDLE_VALUE
;
2715 lpFullGuidString
[0] = '{';
2716 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2717 lpFullGuidString
[dwLength
+ 1] = '}';
2718 lpFullGuidString
[dwLength
+ 2] = '\0';
2719 RpcStringFreeW(&lpGuidString
);
2721 rc
= RegOpenKeyExW(hClassesKey
,
2726 if (rc
!= ERROR_SUCCESS
)
2729 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2730 RegCloseKey(hClassesKey
);
2731 return INVALID_HANDLE_VALUE
;
2734 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2735 RegCloseKey(hClassesKey
);
2740 /***********************************************************************
2741 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2743 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2744 HDEVINFO DeviceInfoSet
,
2747 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2749 FIXME("%p %s %08lx %p\n",
2750 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2754 /***********************************************************************
2755 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2757 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2758 HDEVINFO DeviceInfoSet
,
2761 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2763 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
2764 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2768 /***********************************************************************
2769 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2771 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2772 HDEVINFO DeviceInfoSet
,
2773 PSP_DEVINFO_DATA DeviceInfoData
,
2774 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2775 DWORD ClassInstallParamsSize
)
2777 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2778 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2782 /***********************************************************************
2783 * SetupDiCallClassInstaller (SETUPAPI.@)
2785 BOOL WINAPI
SetupDiCallClassInstaller(
2786 IN DI_FUNCTION InstallFunction
,
2787 IN HDEVINFO DeviceInfoSet
,
2788 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2792 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2795 SetLastError(ERROR_INVALID_PARAMETER
);
2796 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2797 SetLastError(ERROR_INVALID_HANDLE
);
2798 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2799 SetLastError(ERROR_INVALID_HANDLE
);
2800 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2801 SetLastError(ERROR_INVALID_HANDLE
);
2802 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2803 SetLastError(ERROR_INVALID_USER_BUFFER
);
2806 #define CLASS_COINSTALLER 0x1
2807 #define DEVICE_COINSTALLER 0x2
2808 #define CLASS_INSTALLER 0x4
2809 UCHAR CanHandle
= 0;
2810 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2812 switch (InstallFunction
)
2814 case DIF_ALLOW_INSTALL
:
2815 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2817 case DIF_DESTROYPRIVATEDATA
:
2818 CanHandle
= CLASS_INSTALLER
;
2820 case DIF_INSTALLDEVICE
:
2821 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2822 DefaultHandler
= SetupDiInstallDevice
;
2824 case DIF_INSTALLDEVICEFILES
:
2825 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2826 DefaultHandler
= SetupDiInstallDriverFiles
;
2828 case DIF_INSTALLINTERFACES
:
2829 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2830 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2832 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2833 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2835 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2836 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2838 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2839 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2841 case DIF_REGISTER_COINSTALLERS
:
2842 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2843 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2845 case DIF_SELECTBESTCOMPATDRV
:
2846 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2847 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2850 FIXME("Install function %ld not implemented\n", InstallFunction
);
2851 SetLastError(ERROR_INVALID_PARAMETER
);
2856 LIST_ENTRY ClassCoInstallersListHead
;
2857 LIST_ENTRY DeviceCoInstallersListHead
;
2858 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2859 COINSTALLER_CONTEXT_DATA Context
;
2860 PLIST_ENTRY ListEntry
;
2862 DWORD dwRegType
, dwLength
;
2863 DWORD rc
= NO_ERROR
;
2865 InitializeListHead(&ClassCoInstallersListHead
);
2866 InitializeListHead(&DeviceCoInstallersListHead
);
2868 if (CanHandle
& CLASS_COINSTALLER
)
2870 FIXME("Doesn't use Class co-installers at the moment\n");
2872 if (CanHandle
& DEVICE_COINSTALLER
)
2876 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2880 if (rc
== ERROR_SUCCESS
)
2882 LPWSTR lpGuidString
;
2883 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2885 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2886 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2888 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2889 if (KeyBuffer
!= NULL
)
2891 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2892 if (rc
== ERROR_SUCCESS
)
2895 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2897 /* Add coinstaller to DeviceCoInstallersListHead list */
2898 FIXME("Device coinstaller is '%S'\n", ptr
);
2901 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2904 RpcStringFreeW(&lpGuidString
);
2909 if (CanHandle
& CLASS_INSTALLER
)
2911 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2912 if (hKey
!= INVALID_HANDLE_VALUE
)
2914 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2915 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2917 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2918 if (KeyBuffer
!= NULL
)
2920 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2921 if (rc
== ERROR_SUCCESS
)
2923 /* Set ClassInstaller function pointer */
2924 FIXME("Installer is '%S'\n", KeyBuffer
);
2926 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2933 /* Call Class co-installers */
2934 Context
.PostProcessing
= FALSE
;
2936 ListEntry
= ClassCoInstallersListHead
.Flink
;
2937 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
2939 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2940 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2941 coinstaller
->PrivateData
= Context
.PrivateData
;
2942 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2944 coinstaller
->DoPostProcessing
= TRUE
;
2947 ListEntry
= ListEntry
->Flink
;
2950 /* Call Device co-installers */
2951 ListEntry
= DeviceCoInstallersListHead
.Flink
;
2952 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
2954 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2955 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2956 coinstaller
->PrivateData
= Context
.PrivateData
;
2957 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
2959 coinstaller
->DoPostProcessing
= TRUE
;
2962 ListEntry
= ListEntry
->Flink
;
2965 /* Call Class installer */
2967 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2969 rc
= ERROR_DI_DO_DEFAULT
;
2971 /* Call default handler */
2972 if (rc
== ERROR_DI_DO_DEFAULT
)
2974 if (DefaultHandler
/*FIXME && DI_NODI_DEFAULTACTION not set */)
2976 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
2979 rc
= GetLastError();
2985 /* Call Class co-installers that required postprocessing */
2986 Context
.PostProcessing
= TRUE
;
2987 ListEntry
= ClassCoInstallersListHead
.Flink
;
2988 while (ListEntry
!= &ClassCoInstallersListHead
)
2990 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
2991 if (coinstaller
->DoPostProcessing
)
2993 Context
.InstallResult
= rc
;
2994 Context
.PrivateData
= coinstaller
->PrivateData
;
2995 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
2997 ListEntry
= ListEntry
->Flink
;
3000 /* Call Device co-installers that required postprocessing */
3001 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3002 while (ListEntry
!= &DeviceCoInstallersListHead
)
3004 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3005 if (coinstaller
->DoPostProcessing
)
3007 Context
.InstallResult
= rc
;
3008 Context
.PrivateData
= coinstaller
->PrivateData
;
3009 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3011 ListEntry
= ListEntry
->Flink
;
3014 /* Free allocated memory */
3015 while (!IsListEmpty(&ClassCoInstallersListHead
))
3017 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3018 HeapFree(GetProcessHeap(), 0, ListEntry
);
3020 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3022 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3023 HeapFree(GetProcessHeap(), 0, ListEntry
);
3026 ret
= (rc
== NO_ERROR
);
3030 TRACE("Returning %d\n", ret
);
3034 /***********************************************************************
3035 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3037 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3038 IN HDEVINFO DeviceInfoSet
,
3039 IN PSP_DEVINFO_DATA DeviceInfoData
,
3040 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3042 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3045 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3047 if (DeviceInstallParams
== NULL
)
3048 SetLastError(ERROR_INVALID_PARAMETER
);
3049 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3050 SetLastError(ERROR_INVALID_USER_BUFFER
);
3053 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3054 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3058 /* Do W->A conversion */
3060 DeviceInstallParams
,
3061 &deviceInstallParamsW
,
3062 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3063 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3064 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3066 DeviceInstallParams
->DriverPath
[0] = '\0';
3072 TRACE("Returning %d\n", ret
);
3076 /***********************************************************************
3077 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3079 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3080 IN HDEVINFO DeviceInfoSet
,
3081 IN PSP_DEVINFO_DATA DeviceInfoData
,
3082 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3084 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3088 /***********************************************************************
3089 * SetupDiOpenDevRegKey (SETUPAPI.@)
3091 HKEY WINAPI
SetupDiOpenDevRegKey(
3092 HDEVINFO DeviceInfoSet
,
3093 PSP_DEVINFO_DATA DeviceInfoData
,
3099 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
3100 Scope
, HwProfile
, KeyType
, samDesired
);
3101 return INVALID_HANDLE_VALUE
;
3104 /***********************************************************************
3105 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3107 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3108 HDEVINFO DeviceInfoSet
,
3110 CONST GUID
*ClassGuid
,
3111 PCSTR DeviceDescription
,
3113 DWORD CreationFlags
,
3114 PSP_DEVINFO_DATA DeviceInfoData
)
3116 LPWSTR DeviceNameW
= NULL
;
3117 LPWSTR DeviceDescriptionW
= NULL
;
3124 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3125 if (DeviceNameW
== NULL
) return FALSE
;
3127 if (DeviceDescription
)
3129 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3130 if (DeviceDescriptionW
== NULL
)
3132 if (DeviceNameW
) MyFree(DeviceNameW
);
3137 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3138 ClassGuid
, DeviceDescriptionW
,
3139 hwndParent
, CreationFlags
,
3142 if (DeviceNameW
) MyFree(DeviceNameW
);
3143 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3148 /***********************************************************************
3149 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3151 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3152 HDEVINFO DeviceInfoSet
,
3154 CONST GUID
*ClassGuid
,
3155 PCWSTR DeviceDescription
,
3157 DWORD CreationFlags
,
3158 PSP_DEVINFO_DATA DeviceInfoData
)
3160 struct DeviceInfoSet
*list
;
3163 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3164 debugstr_guid(ClassGuid
), DeviceDescription
,
3165 hwndParent
, CreationFlags
, DeviceInfoData
);
3168 SetLastError(ERROR_INVALID_HANDLE
);
3169 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3170 SetLastError(ERROR_INVALID_HANDLE
);
3171 else if (!ClassGuid
)
3172 SetLastError(ERROR_INVALID_PARAMETER
);
3173 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3174 SetLastError(ERROR_CLASS_MISMATCH
);
3175 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3177 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3178 SetLastError(ERROR_INVALID_PARAMETER
);
3182 SP_DEVINFO_DATA DevInfo
;
3184 if (CreationFlags
& DICD_GENERATE_ID
)
3186 /* Generate a new unique ID for this device */
3187 SetLastError(ERROR_GEN_FAILURE
);
3188 FIXME("not implemented\n");
3192 /* Device name is fully qualified. Try to open it */
3195 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3196 rc
= SetupDiOpenDeviceInfoW(
3199 NULL
, /* hwndParent */
3200 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3205 /* SetupDiOpenDeviceInfoW has already added
3206 * the device info to the device info set
3208 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3210 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3212 struct DeviceInfoElement
*deviceInfo
;
3214 /* FIXME: ClassGuid can be NULL */
3215 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3217 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3219 if (!DeviceInfoData
)
3223 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3225 SetLastError(ERROR_INVALID_USER_BUFFER
);
3229 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3230 DeviceInfoData
->DevInst
= 0; /* FIXME */
3231 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3240 TRACE("Returning %d\n", ret
);
3244 /***********************************************************************
3245 * Helper functions for SetupDiBuildDriverInfoList
3249 IN PLIST_ENTRY DriverListHead
,
3250 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3251 IN INFCONTEXT ContextDevice
,
3253 IN LPCWSTR ProviderName
,
3254 IN LPCWSTR ManufacturerName
,
3255 FILETIME DriverDate
,
3256 DWORDLONG DriverVersion
,
3259 struct DriverInfoElement
*driverInfo
;
3260 DWORD RequiredSize
= 128; /* Initial buffer size */
3261 BOOL Result
= FALSE
;
3262 PLIST_ENTRY PreviousEntry
;
3263 LPWSTR DeviceDescription
= NULL
;
3264 LPWSTR InfInstallSection
= NULL
;
3266 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3269 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3273 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3274 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3276 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3277 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3278 if (!DeviceDescription
)
3280 Result
= SetupGetStringFieldW(
3282 0, /* Field index */
3283 DeviceDescription
, RequiredSize
,
3288 HeapFree(GetProcessHeap(), 0, driverInfo
);
3289 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3294 RequiredSize
= 128; /* Initial buffer size */
3295 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3296 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3298 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3299 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3300 if (!InfInstallSection
)
3302 HeapFree(GetProcessHeap(), 0, driverInfo
);
3303 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3306 Result
= SetupGetStringFieldW(
3308 1, /* Field index */
3309 InfInstallSection
, RequiredSize
,
3314 HeapFree(GetProcessHeap(), 0, driverInfo
);
3315 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3316 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3320 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3321 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3323 driverInfo
->DriverRank
= Rank
;
3324 driverInfo
->Info
.DriverType
= DriverType
;
3325 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3326 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3327 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3328 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3329 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3332 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3333 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3336 driverInfo
->Info
.ProviderName
[0] = '\0';
3337 driverInfo
->Info
.DriverDate
= DriverDate
;
3338 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3340 /* Insert current driver in driver list, according to its rank */
3341 PreviousEntry
= DriverListHead
->Flink
;
3342 while (PreviousEntry
!= DriverListHead
)
3344 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3346 /* Insert before the current item */
3347 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3351 if (PreviousEntry
== DriverListHead
)
3353 /* Insert at the end of the list */
3354 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3357 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3358 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3363 GetVersionInformationFromInfFile(
3365 OUT LPGUID ClassGuid
,
3366 OUT LPWSTR
* pProviderName
,
3367 OUT FILETIME
* DriverDate
,
3368 OUT DWORDLONG
* DriverVersion
)
3371 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3372 LPWSTR ProviderName
= NULL
;
3375 if (!SetupGetLineTextW(
3378 L
"Version", L
"ClassGUID",
3379 guidW
, sizeof(guidW
),
3380 NULL
/* Required size */))
3385 /* Get Provider name, driver date, and driver version */
3387 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3388 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3392 Result
= SetupGetLineTextW(
3394 hInf
, L
"Version", L
"Provider",
3397 if (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3399 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3402 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3405 Result
= SetupGetLineTextW(
3407 hInf
, L
"Version", L
"Provider",
3408 ProviderName
, RequiredSize
,
3411 //FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
3412 //FIXME: DriverVersion = Version.DriverVer => invalid = 0
3414 *pProviderName
= ProviderName
;
3418 /***********************************************************************
3419 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3422 SetupDiBuildDriverInfoList(
3423 IN HDEVINFO DeviceInfoSet
,
3424 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3425 IN DWORD DriverType
)
3427 struct DeviceInfoSet
*list
;
3428 PVOID Buffer
= NULL
;
3429 HINF hInf
= INVALID_HANDLE_VALUE
;
3430 LPWSTR ProviderName
= NULL
;
3431 LPWSTR ManufacturerName
= NULL
;
3432 LPWSTR ManufacturerSection
= NULL
;
3433 LPWSTR HardwareIDs
= NULL
;
3434 LPWSTR CompatibleIDs
= NULL
;
3435 FILETIME DriverDate
;
3436 DWORDLONG DriverVersion
;
3440 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3443 SetLastError(ERROR_INVALID_HANDLE
);
3444 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3445 SetLastError(ERROR_INVALID_HANDLE
);
3446 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3447 SetLastError(ERROR_INVALID_HANDLE
);
3448 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3449 SetLastError(ERROR_INVALID_PARAMETER
);
3450 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3451 SetLastError(ERROR_INVALID_PARAMETER
);
3452 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3453 SetLastError(ERROR_INVALID_PARAMETER
);
3454 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3455 SetLastError(ERROR_INVALID_USER_BUFFER
);
3458 BOOL Result
= FALSE
;
3460 if (DriverType
== SPDIT_COMPATDRIVER
)
3462 /* Get hardware IDs list */
3464 RequiredSize
= 512; /* Initial buffer size */
3465 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3466 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3468 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3469 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3472 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3475 Result
= SetupDiGetDeviceRegistryPropertyW(
3487 /* Get compatible IDs list */
3489 RequiredSize
= 512; /* Initial buffer size */
3490 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3491 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3493 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3494 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3497 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3500 Result
= SetupDiGetDeviceRegistryPropertyW(
3503 SPDRP_COMPATIBLEIDS
,
3505 (PBYTE
)CompatibleIDs
,
3508 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3510 /* No compatible ID for this device */
3511 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3512 CompatibleIDs
= NULL
;
3520 /* Enumerate .inf files */
3522 RequiredSize
= 32768; /* Initial buffer size */
3523 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3524 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3526 HeapFree(GetProcessHeap(), 0, Buffer
);
3527 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3531 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3534 Result
= SetupGetInfFileListW(
3535 NULL
, /* Directory path */
3537 Buffer
, RequiredSize
,
3544 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
3546 INFCONTEXT ContextManufacturer
, ContextDevice
;
3548 TRACE("Opening file %S\n", filename
);
3550 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
3551 if (hInf
== INVALID_HANDLE_VALUE
)
3554 if (!GetVersionInformationFromInfFile(
3561 SetupCloseInfFile(hInf
);
3562 hInf
= INVALID_HANDLE_VALUE
;
3566 if (DriverType
== SPDIT_CLASSDRIVER
)
3568 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3569 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
3571 SetupCloseInfFile(hInf
);
3572 hInf
= INVALID_HANDLE_VALUE
;
3577 /* Get the manufacturers list */
3578 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
3581 Result
= SetupGetStringFieldW(
3582 &ContextManufacturer
,
3583 0, /* Field index */
3588 /* We got the needed size for the buffer */
3589 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3590 if (!ManufacturerName
)
3592 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3595 Result
= SetupGetStringFieldW(
3596 &ContextManufacturer
,
3597 0, /* Field index */
3598 ManufacturerName
, RequiredSize
,
3601 Result
= SetupGetStringFieldW(
3602 &ContextManufacturer
,
3603 1, /* Field index */
3608 /* We got the needed size for the buffer */
3609 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3610 if (!ManufacturerSection
)
3612 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3615 Result
= SetupGetStringFieldW(
3616 &ContextManufacturer
,
3617 1, /* Field index */
3618 ManufacturerSection
, RequiredSize
,
3622 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
3623 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
3626 if (DriverType
== SPDIT_CLASSDRIVER
)
3628 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3629 if (!AddDriverToList(
3630 &list
->DriverListHead
,
3636 DriverDate
, DriverVersion
,
3642 else /* DriverType = SPDIT_COMPATDRIVER */
3644 /* 1. Get all fields */
3645 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
3649 BOOL DriverAlreadyAdded
;
3651 for (i
= 2; i
<= FieldCount
; i
++)
3653 LPWSTR DeviceId
= NULL
;
3655 RequiredSize
= 128; /* Initial buffer size */
3656 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3657 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3659 HeapFree(GetProcessHeap(), 0, DeviceId
);
3660 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3663 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3666 Result
= SetupGetStringFieldW(
3669 DeviceId
, RequiredSize
,
3674 HeapFree(GetProcessHeap(), 0, DeviceId
);
3677 DriverAlreadyAdded
= FALSE
;
3678 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3680 if (wcscmp(DeviceId
, currentId
) == 0)
3683 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3689 DriverDate
, DriverVersion
,
3690 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
3691 DriverAlreadyAdded
= TRUE
;
3696 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3698 if (wcscmp(DeviceId
, currentId
) == 0)
3701 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3707 DriverDate
, DriverVersion
,
3708 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
3709 DriverAlreadyAdded
= TRUE
;
3713 HeapFree(GetProcessHeap(), 0, DeviceId
);
3716 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
3719 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3720 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3721 ManufacturerName
= ManufacturerSection
= NULL
;
3722 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
3724 HeapFree(GetProcessHeap(), 0, ProviderName
);
3725 ProviderName
= NULL
;
3728 SetupCloseInfFile(hInf
);
3729 hInf
= INVALID_HANDLE_VALUE
;
3740 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
;
3741 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
3744 list
->Flags
|= DI_DIDCLASS
;
3747 HeapFree(GetProcessHeap(), 0, ProviderName
);
3748 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3749 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3750 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3751 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3752 if (hInf
!= INVALID_HANDLE_VALUE
)
3753 SetupCloseInfFile(hInf
);
3754 HeapFree(GetProcessHeap(), 0, Buffer
);
3756 TRACE("Returning %d\n", ret
);
3760 /***********************************************************************
3761 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3764 SetupDiDeleteDeviceInfo(
3765 IN HDEVINFO DeviceInfoSet
,
3766 IN PSP_DEVINFO_DATA DeviceInfoData
)
3768 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3770 FIXME("not implemented\n");
3771 SetLastError(ERROR_GEN_FAILURE
);
3776 /***********************************************************************
3777 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3780 SetupDiDestroyDriverInfoList(
3781 IN HDEVINFO DeviceInfoSet
,
3782 IN PSP_DEVINFO_DATA DeviceInfoData
,
3783 IN DWORD DriverType
)
3785 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3787 FIXME("not implemented\n");
3788 SetLastError(ERROR_GEN_FAILURE
);
3793 /***********************************************************************
3794 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3797 SetupDiOpenDeviceInfoA(
3798 IN HDEVINFO DeviceInfoSet
,
3799 IN PCSTR DeviceInstanceId
,
3800 IN HWND hwndParent OPTIONAL
,
3802 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3804 LPWSTR DeviceInstanceIdW
= NULL
;
3807 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3809 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
3810 if (DeviceInstanceIdW
== NULL
)
3813 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
3814 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
3816 MyFree(DeviceInstanceIdW
);
3822 /***********************************************************************
3823 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3826 SetupDiOpenDeviceInfoW(
3827 IN HDEVINFO DeviceInfoSet
,
3828 IN PCWSTR DeviceInstanceId
,
3829 IN HWND hwndParent OPTIONAL
,
3831 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3833 struct DeviceInfoSet
*list
;
3834 HKEY hEnumKey
, hKey
;
3838 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3840 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
3841 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3844 SetLastError(ERROR_INVALID_HANDLE
);
3845 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3846 SetLastError(ERROR_INVALID_HANDLE
);
3847 else if (!DeviceInstanceId
)
3848 SetLastError(ERROR_INVALID_PARAMETER
);
3849 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
3851 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
3852 SetLastError(ERROR_INVALID_PARAMETER
);
3854 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3855 SetLastError(ERROR_INVALID_USER_BUFFER
);
3858 struct DeviceInfoElement
*deviceInfo
= NULL
;
3859 /* Search if device already exists in DeviceInfoSet.
3860 * If yes, return the existing element
3861 * If no, create a new element using informations in registry
3863 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
3864 while (ItemList
!= &list
->ListHead
)
3869 FIXME("not implemented\n");
3870 ItemList
= ItemList
->Flink
;
3875 /* good one found */
3880 /* Open supposed registry key */
3885 KEY_ENUMERATE_SUB_KEYS
,
3887 if (rc
!= ERROR_SUCCESS
)
3898 RegCloseKey(hEnumKey
);
3899 if (rc
!= ERROR_SUCCESS
)
3905 /* FIXME: GUID_NULL is not allowed */
3906 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
3911 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3917 if (ret
&& deviceInfo
&& DeviceInfoData
)
3919 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
3920 DeviceInfoData
->DevInst
= 0; /* FIXME */
3921 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3929 /***********************************************************************
3930 * SetupDiEnumDriverInfoA (SETUPAPI.@)
3933 SetupDiEnumDriverInfoA(
3934 IN HDEVINFO DeviceInfoSet
,
3935 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3936 IN DWORD DriverType
,
3937 IN DWORD MemberIndex
,
3938 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
3940 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
3943 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
3944 DriverType
, MemberIndex
, DriverInfoData
);
3946 if (DriverInfoData
== NULL
)
3947 SetLastError(ERROR_INVALID_PARAMETER
);
3948 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
3949 SetLastError(ERROR_INVALID_USER_BUFFER
);
3952 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
3953 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
3954 DriverType
, MemberIndex
, &driverInfoData2W
);
3958 /* Do W->A conversion */
3959 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
3960 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
3961 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
3962 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
3964 DriverInfoData
->Description
[0] = '\0';
3967 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
3968 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
3970 DriverInfoData
->MfgName
[0] = '\0';
3973 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
3974 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
3976 DriverInfoData
->ProviderName
[0] = '\0';
3979 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
3981 /* Copy more fields */
3982 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
3983 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
3988 TRACE("Returning %d\n", ret
);
3993 /***********************************************************************
3994 * SetupDiEnumDriverInfoW (SETUPAPI.@)
3997 SetupDiEnumDriverInfoW(
3998 IN HDEVINFO DeviceInfoSet
,
3999 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4000 IN DWORD DriverType
,
4001 IN DWORD MemberIndex
,
4002 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4004 PLIST_ENTRY ListHead
;
4007 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4008 DriverType
, MemberIndex
, DriverInfoData
);
4010 if (!DeviceInfoSet
|| !DriverInfoData
)
4011 SetLastError(ERROR_INVALID_PARAMETER
);
4012 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4013 SetLastError(ERROR_INVALID_HANDLE
);
4014 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4015 SetLastError(ERROR_INVALID_HANDLE
);
4016 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4017 SetLastError(ERROR_INVALID_PARAMETER
);
4018 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4019 SetLastError(ERROR_INVALID_PARAMETER
);
4020 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4021 SetLastError(ERROR_INVALID_PARAMETER
);
4022 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4023 SetLastError(ERROR_INVALID_USER_BUFFER
);
4026 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4027 PLIST_ENTRY ItemList
;
4028 if (DriverType
== SPDIT_CLASSDRIVER
||
4029 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4031 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4035 ListHead
= &devInfo
->DriverListHead
;
4038 ItemList
= ListHead
->Flink
;
4039 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4040 ItemList
= ItemList
->Flink
;
4041 if (ItemList
== ListHead
)
4042 SetLastError(ERROR_NO_MORE_ITEMS
);
4045 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4048 &DriverInfoData
->DriverType
,
4049 &DrvInfo
->Info
.DriverType
,
4050 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4055 TRACE("Returning %d\n", ret
);
4059 /***********************************************************************
4060 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4063 SetupDiGetSelectedDriverW(
4064 IN HDEVINFO DeviceInfoSet
,
4065 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4066 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4070 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4072 if (!DeviceInfoSet
|| !DriverInfoData
)
4073 SetLastError(ERROR_INVALID_PARAMETER
);
4074 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4075 SetLastError(ERROR_INVALID_HANDLE
);
4076 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4077 SetLastError(ERROR_INVALID_HANDLE
);
4078 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4079 SetLastError(ERROR_INVALID_USER_BUFFER
);
4080 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4081 SetLastError(ERROR_INVALID_USER_BUFFER
);
4084 struct DriverInfoElement
*driverInfo
;
4087 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4089 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4091 if (driverInfo
== NULL
)
4092 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4096 &DriverInfoData
->DriverType
,
4097 &driverInfo
->Info
.DriverType
,
4098 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4103 TRACE("Returning %d\n", ret
);
4107 /***********************************************************************
4108 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4111 SetupDiSetSelectedDriverW(
4112 IN HDEVINFO DeviceInfoSet
,
4113 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4114 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4118 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4121 SetLastError(ERROR_INVALID_PARAMETER
);
4122 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4123 SetLastError(ERROR_INVALID_HANDLE
);
4124 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4125 SetLastError(ERROR_INVALID_HANDLE
);
4126 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4127 SetLastError(ERROR_INVALID_USER_BUFFER
);
4128 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4129 SetLastError(ERROR_INVALID_USER_BUFFER
);
4132 struct DriverInfoElement
**pDriverInfo
;
4133 PLIST_ENTRY ListHead
, ItemList
;
4137 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4138 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4142 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4143 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4146 if (!DriverInfoData
)
4148 *pDriverInfo
= NULL
;
4153 /* Search selected driver in list */
4154 ItemList
= ListHead
->Flink
;
4155 while (ItemList
!= ListHead
)
4157 if (DriverInfoData
->Reserved
!= 0)
4159 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4164 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4165 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4166 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4167 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4168 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4174 if (ItemList
== ListHead
)
4175 SetLastError(ERROR_INVALID_PARAMETER
);
4178 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4179 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4181 TRACE("Choosing driver whose rank is 0x%lx\n",
4182 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
4187 TRACE("Returning %d\n", ret
);
4191 /***********************************************************************
4192 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4195 SetupDiSelectBestCompatDrv(
4196 IN HDEVINFO DeviceInfoSet
,
4197 IN PSP_DEVINFO_DATA DeviceInfoData
)
4199 SP_DRVINFO_DATA_W drvInfoData
;
4202 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4204 /* Drivers are sorted by rank in the driver list, so
4205 * the first driver in the list is the best one.
4207 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4208 ret
= SetupDiEnumDriverInfoW(
4212 0, /* Member index */
4217 ret
= SetupDiSetSelectedDriverW(
4223 TRACE("Returning %d\n", ret
);
4227 /***********************************************************************
4228 * SetupDiInstallDriverFiles (SETUPAPI.@)
4231 SetupDiInstallDriverFiles(
4232 IN HDEVINFO DeviceInfoSet
,
4233 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4235 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4237 FIXME("SetupDiInstallDriverFiles not implemented. Doing nothing\n");
4238 //SetLastError(ERROR_GEN_FAILURE);
4243 /***********************************************************************
4244 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4247 SetupDiRegisterCoDeviceInstallers(
4248 IN HDEVINFO DeviceInfoSet
,
4249 IN PSP_DEVINFO_DATA DeviceInfoData
)
4251 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4253 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4254 //SetLastError(ERROR_GEN_FAILURE);
4259 /***********************************************************************
4260 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4263 SetupDiInstallDeviceInterfaces(
4264 IN HDEVINFO DeviceInfoSet
,
4265 IN PSP_DEVINFO_DATA DeviceInfoData
)
4267 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4269 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4270 //SetLastError(ERROR_GEN_FAILURE);
4275 /***********************************************************************
4276 * SetupDiInstallDevice (SETUPAPI.@)
4279 SetupDiInstallDevice(
4280 IN HDEVINFO DeviceInfoSet
,
4281 IN PSP_DEVINFO_DATA DeviceInfoData
)
4283 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4286 * 0. If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit
4287 * 1. Create driver key and write InfPath and ProviderName
4288 * 2a Process inf sections: {DDInstall}, {DDInstall}.HW [SetupDiOpenDevRegKey]
4289 * b Process {DDInstall}.LogConfigOverride if present [SetupDiOpenDevRegKey]
4290 * c Process {DDInstall}.Services [SetupDiOpenDevRegKey]
4291 * 3. Copy inf file to Inf\ directory [SetupCopyOEMInf]
4292 * 4. Install other waiting files
4293 * 5. Load the driver/Call AddDevice
4294 * 6. Send IRP_MN_START_DEVICE if DI_NEEDRESTART, DI_NEEDREBOOT and DI_DONOTCALLCONFIGMG are not set
4297 FIXME("SetupDiInstallDevice not implemented. Doing nothing\n");
4298 //SetLastError(ERROR_GEN_FAILURE);