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 #define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
85 struct DeviceInterface
/* Element of DeviceInfoElement.InterfaceListHead */
89 struct DeviceInfoElement
* DeviceInfo
;
90 GUID InterfaceClassGuid
;
93 /* SPINT_ACTIVE : the interface is active/enabled
94 * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
95 * SPINT_REMOVED: the interface is removed
99 WCHAR SymbolicLink
[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
102 struct DriverInfoElement
/* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
104 LIST_ENTRY ListEntry
;
106 SP_DRVINFO_DATA_V2_W Info
;
109 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
111 LIST_ENTRY ListEntry
;
113 /* Information about devnode:
115 * "Root\*PNP0501" for example.
116 * It doesn't contain the unique ID for the device
117 * (points into the Data field at the end of the structure)
118 * WARNING: no NULL char exist between DeviceName and UniqueId
121 * "5&1be2108e&0" or "0000"
122 * If DICD_GENERATE_ID is specified in creation flags,
123 * this unique ID is autogenerated using 4 digits, base 10
124 * (points into the Data field at the end of the structure)
125 * - DeviceDescription
126 * String which identifies the device. Can be NULL. If not NULL,
127 * points into the Data field at the end of the structure
129 * Identifies the class of this device. FIXME: can it be GUID_NULL?
131 * Is a combination of:
133 * the unique ID needs to be generated
134 * - DICD_INHERIT_CLASSDRVS
135 * inherit driver of the device info set (== same pointer)
137 * Used when doing device-specific actions. Can be NULL
141 PCWSTR DeviceDescription
;
146 /* Flags is a combination of:
148 * Set when the device driver list is created
149 * FlagsEx is a combination of:
154 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
155 /* If the driver is not searched/detected, this list is empty */
156 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
157 /* Points into DriverListHead list. The pointer is NULL if no driver is
158 * currently chosen. */
159 struct DriverInfoElement
*SelectedDriver
;
161 /* List of interfaces implemented by this device */
162 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
167 struct DeviceInfoSet
/* HDEVINFO */
169 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
170 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
171 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
172 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
174 /* Flags is a combination of:
176 * Set when the class driver list is created
177 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
178 * Forces SetupDiBuildDriverInfoList to build a class drivers list
179 * FlagsEx is a combination of:
184 /* If the driver is not searched/detected, this list is empty */
185 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
186 /* Points into DriverListHead list. The pointer is NULL if no driver is
187 * currently chosen. */
188 struct DriverInfoElement
*SelectedDriver
;
190 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
193 /***********************************************************************
194 * SetupDiBuildClassInfoList (SETUPAPI.@)
196 BOOL WINAPI
SetupDiBuildClassInfoList(
198 LPGUID ClassGuidList
,
199 DWORD ClassGuidListSize
,
203 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
204 ClassGuidListSize
, RequiredSize
,
208 /***********************************************************************
209 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
211 BOOL WINAPI
SetupDiBuildClassInfoListExA(
213 LPGUID ClassGuidList
,
214 DWORD ClassGuidListSize
,
219 LPWSTR MachineNameW
= NULL
;
226 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
227 if (MachineNameW
== NULL
) return FALSE
;
230 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
231 ClassGuidListSize
, RequiredSize
,
232 MachineNameW
, Reserved
);
235 MyFree(MachineNameW
);
240 /***********************************************************************
241 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
243 BOOL WINAPI
SetupDiBuildClassInfoListExW(
245 LPGUID ClassGuidList
,
246 DWORD ClassGuidListSize
,
251 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
257 DWORD dwGuidListIndex
= 0;
261 if (RequiredSize
!= NULL
)
264 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
269 if (hClassesKey
== INVALID_HANDLE_VALUE
)
274 for (dwIndex
= 0; ; dwIndex
++)
276 dwLength
= MAX_GUID_STRING_LEN
+ 1;
277 lError
= RegEnumKeyExW(hClassesKey
,
285 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
286 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
288 TRACE("Key name: %p\n", szKeyName
);
290 if (RegOpenKeyExW(hClassesKey
,
296 RegCloseKey(hClassesKey
);
300 if (!RegQueryValueExW(hClassKey
,
307 TRACE("'NoUseClass' value found!\n");
308 RegCloseKey(hClassKey
);
312 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
313 (!RegQueryValueExW(hClassKey
,
320 TRACE("'NoInstallClass' value found!\n");
321 RegCloseKey(hClassKey
);
325 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
326 (!RegQueryValueExW(hClassKey
,
333 TRACE("'NoDisplayClass' value found!\n");
334 RegCloseKey(hClassKey
);
338 RegCloseKey(hClassKey
);
340 TRACE("Guid: %p\n", szKeyName
);
341 if (dwGuidListIndex
< ClassGuidListSize
)
343 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
347 TRACE("Guid: %p\n", &szKeyName
[1]);
349 UuidFromStringW(&szKeyName
[1],
350 &ClassGuidList
[dwGuidListIndex
]);
356 if (lError
!= ERROR_SUCCESS
)
360 RegCloseKey(hClassesKey
);
362 if (RequiredSize
!= NULL
)
363 *RequiredSize
= dwGuidListIndex
;
365 if (ClassGuidListSize
< dwGuidListIndex
)
367 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
374 /***********************************************************************
375 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
377 BOOL WINAPI
SetupDiClassGuidsFromNameA(
379 LPGUID ClassGuidList
,
380 DWORD ClassGuidListSize
,
383 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
384 ClassGuidListSize
, RequiredSize
,
388 /***********************************************************************
389 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
391 BOOL WINAPI
SetupDiClassGuidsFromNameW(
393 LPGUID ClassGuidList
,
394 DWORD ClassGuidListSize
,
397 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
398 ClassGuidListSize
, RequiredSize
,
402 /***********************************************************************
403 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
405 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
407 LPGUID ClassGuidList
,
408 DWORD ClassGuidListSize
,
413 LPWSTR ClassNameW
= NULL
;
414 LPWSTR MachineNameW
= NULL
;
419 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
420 if (ClassNameW
== NULL
)
425 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
426 if (MachineNameW
== NULL
)
433 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
434 ClassGuidListSize
, RequiredSize
,
435 MachineNameW
, Reserved
);
438 MyFree(MachineNameW
);
445 /***********************************************************************
446 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
448 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
450 LPGUID ClassGuidList
,
451 DWORD ClassGuidListSize
,
456 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
457 WCHAR szClassName
[256];
463 DWORD dwGuidListIndex
= 0;
465 if (RequiredSize
!= NULL
)
468 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
469 KEY_ENUMERATE_SUB_KEYS
,
473 if (hClassesKey
== INVALID_HANDLE_VALUE
)
478 for (dwIndex
= 0; ; dwIndex
++)
480 dwLength
= MAX_GUID_STRING_LEN
+ 1;
481 lError
= RegEnumKeyExW(hClassesKey
,
489 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
490 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
492 TRACE("Key name: %p\n", szKeyName
);
494 if (RegOpenKeyExW(hClassesKey
,
500 RegCloseKey(hClassesKey
);
504 dwLength
= 256 * sizeof(WCHAR
);
505 if (!RegQueryValueExW(hClassKey
,
512 TRACE("Class name: %p\n", szClassName
);
514 if (strcmpiW(szClassName
, ClassName
) == 0)
516 TRACE("Found matching class name\n");
518 TRACE("Guid: %p\n", szKeyName
);
519 if (dwGuidListIndex
< ClassGuidListSize
)
521 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
525 TRACE("Guid: %p\n", &szKeyName
[1]);
527 UuidFromStringW(&szKeyName
[1],
528 &ClassGuidList
[dwGuidListIndex
]);
535 RegCloseKey(hClassKey
);
538 if (lError
!= ERROR_SUCCESS
)
542 RegCloseKey(hClassesKey
);
544 if (RequiredSize
!= NULL
)
545 *RequiredSize
= dwGuidListIndex
;
547 if (ClassGuidListSize
< dwGuidListIndex
)
549 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
556 /***********************************************************************
557 * SetupDiClassNameFromGuidA (SETUPAPI.@)
559 BOOL WINAPI
SetupDiClassNameFromGuidA(
560 const GUID
* ClassGuid
,
565 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
566 ClassNameSize
, RequiredSize
,
570 /***********************************************************************
571 * SetupDiClassNameFromGuidW (SETUPAPI.@)
573 BOOL WINAPI
SetupDiClassNameFromGuidW(
574 const GUID
* ClassGuid
,
579 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
580 ClassNameSize
, RequiredSize
,
584 /***********************************************************************
585 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
587 BOOL WINAPI
SetupDiClassNameFromGuidExA(
588 const GUID
* ClassGuid
,
595 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
596 LPWSTR MachineNameW
= NULL
;
600 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
601 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
602 NULL
, MachineNameW
, Reserved
);
605 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
606 ClassNameSize
, NULL
, NULL
);
608 if (!ClassNameSize
&& RequiredSize
)
611 MyFree(MachineNameW
);
615 /***********************************************************************
616 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
618 BOOL WINAPI
SetupDiClassNameFromGuidExW(
619 const GUID
* ClassGuid
,
630 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
635 if (hKey
== INVALID_HANDLE_VALUE
)
640 if (RequiredSize
!= NULL
)
643 rc
= RegQueryValueExW(hKey
,
649 if (rc
!= ERROR_SUCCESS
)
656 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
659 dwLength
= ClassNameSize
* sizeof(WCHAR
);
660 rc
= RegQueryValueExW(hKey
,
666 if (rc
!= ERROR_SUCCESS
)
678 /***********************************************************************
679 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
682 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
685 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
688 /***********************************************************************
689 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
692 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
697 LPWSTR MachineNameW
= NULL
;
700 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
704 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
705 if (MachineNameW
== NULL
)
706 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
709 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
710 MachineNameW
, Reserved
);
713 MyFree(MachineNameW
);
718 /***********************************************************************
719 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
722 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
727 struct DeviceInfoSet
*list
;
730 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
732 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
735 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
736 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
739 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
742 ClassGuid
? ClassGuid
: &GUID_NULL
,
743 sizeof(list
->ClassGuid
));
744 list
->hwndParent
= hwndParent
;
747 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
748 if (rc
!= ERROR_SUCCESS
)
751 HeapFree(GetProcessHeap(), 0, list
);
752 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
757 list
->HKLM
= HKEY_LOCAL_MACHINE
;
759 list
->Flags
= 0; /* FIXME */
760 list
->FlagsEx
= 0; /* FIXME */
761 InitializeListHead(&list
->DriverListHead
);
762 InitializeListHead(&list
->ListHead
);
763 return (HDEVINFO
)list
;
766 /***********************************************************************
767 * SetupDiEnumDeviceInfo (SETUPAPI.@)
769 BOOL WINAPI
SetupDiEnumDeviceInfo(
770 HDEVINFO DeviceInfoSet
,
772 PSP_DEVINFO_DATA DeviceInfoData
)
776 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
778 SetLastError(ERROR_INVALID_PARAMETER
);
779 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
781 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
783 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
784 SetLastError(ERROR_INVALID_HANDLE
);
785 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
786 SetLastError(ERROR_INVALID_USER_BUFFER
);
789 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
790 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
791 ItemList
= ItemList
->Flink
;
792 if (ItemList
== &list
->ListHead
)
793 SetLastError(ERROR_NO_MORE_ITEMS
);
796 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
797 memcpy(&DeviceInfoData
->ClassGuid
,
800 DeviceInfoData
->DevInst
= 0; /* FIXME */
801 /* Note: this appears to be dangerous, passing a private
802 * pointer a heap-allocated datum to the caller. However, the
803 * expected lifetime of the device data is the same as the
804 * HDEVINFO; once that is closed, the data are no longer valid.
806 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
812 SetLastError(ERROR_INVALID_HANDLE
);
816 /***********************************************************************
817 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
819 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
821 PCSTR InfSectionName
,
822 PSTR InfSectionWithExt
,
823 DWORD InfSectionWithExtSize
,
827 LPWSTR InfSectionNameW
= NULL
;
828 PWSTR InfSectionWithExtW
= NULL
;
830 BOOL bResult
= FALSE
;
836 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
837 if (InfSectionNameW
== NULL
) goto end
;
839 if (InfSectionWithExt
)
841 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
842 if (InfSectionWithExtW
== NULL
) goto end
;
845 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
846 InfSectionWithExt
? InfSectionNameW
: NULL
,
847 InfSectionWithExtSize
, RequiredSize
,
848 Extension
? &ExtensionW
: NULL
);
850 if (bResult
&& InfSectionWithExt
)
852 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
853 InfSectionWithExtSize
, NULL
, NULL
) != 0;
855 if (bResult
&& Extension
)
857 if (ExtensionW
== NULL
)
860 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
864 if (InfSectionNameW
) MyFree(InfSectionNameW
);
865 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
870 /***********************************************************************
871 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
873 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
875 PCWSTR InfSectionName
,
876 PWSTR InfSectionWithExt
,
877 DWORD InfSectionWithExtSize
,
881 WCHAR szBuffer
[MAX_PATH
];
884 LONG lLineCount
= -1;
886 lstrcpyW(szBuffer
, InfSectionName
);
887 dwLength
= lstrlenW(szBuffer
);
889 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
891 /* Test section name with '.NTx86' extension */
892 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
893 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
895 if (lLineCount
== -1)
897 /* Test section name with '.NT' extension */
898 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
899 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
904 /* Test section name with '.Win' extension */
905 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
906 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
909 if (lLineCount
== -1)
911 /* Test section name without extension */
912 szBuffer
[dwLength
] = 0;
913 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
916 if (lLineCount
== -1)
918 SetLastError(ERROR_INVALID_PARAMETER
);
922 dwFullLength
= lstrlenW(szBuffer
);
924 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
926 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
928 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
932 lstrcpyW(InfSectionWithExt
, szBuffer
);
933 if (Extension
!= NULL
)
935 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
939 if (RequiredSize
!= NULL
)
941 *RequiredSize
= dwFullLength
+ 1;
947 /***********************************************************************
948 * SetupDiGetClassDescriptionA (SETUPAPI.@)
950 BOOL WINAPI
SetupDiGetClassDescriptionA(
951 const GUID
* ClassGuid
,
952 PSTR ClassDescription
,
953 DWORD ClassDescriptionSize
,
956 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
957 ClassDescriptionSize
,
958 RequiredSize
, NULL
, NULL
);
961 /***********************************************************************
962 * SetupDiGetClassDescriptionW (SETUPAPI.@)
964 BOOL WINAPI
SetupDiGetClassDescriptionW(
965 const GUID
* ClassGuid
,
966 PWSTR ClassDescription
,
967 DWORD ClassDescriptionSize
,
970 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
971 ClassDescriptionSize
,
972 RequiredSize
, NULL
, NULL
);
975 /***********************************************************************
976 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
978 BOOL WINAPI
SetupDiGetClassDescriptionExA(
979 const GUID
* ClassGuid
,
980 PSTR ClassDescription
,
981 DWORD ClassDescriptionSize
,
986 PWCHAR ClassDescriptionW
;
987 LPWSTR MachineNameW
= NULL
;
991 if (ClassDescriptionSize
> 0)
993 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
994 if (!ClassDescriptionW
)
996 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1002 ClassDescriptionW
= NULL
;
1006 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1009 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1015 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1016 NULL
, MachineNameW
, Reserved
);
1019 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1020 ClassDescriptionSize
, NULL
, NULL
);
1022 if (!ClassDescriptionSize
&& RequiredSize
)
1023 *RequiredSize
= len
;
1027 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1028 MyFree(MachineNameW
);
1032 /***********************************************************************
1033 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1035 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1036 const GUID
* ClassGuid
,
1037 PWSTR ClassDescription
,
1038 DWORD ClassDescriptionSize
,
1039 PDWORD RequiredSize
,
1046 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1051 if (hKey
== INVALID_HANDLE_VALUE
)
1053 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1057 if (RequiredSize
!= NULL
)
1060 if (RegQueryValueExW(hKey
,
1071 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1074 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1075 if (RegQueryValueExW(hKey
,
1079 (LPBYTE
)ClassDescription
,
1091 /***********************************************************************
1092 * SetupDiGetClassDevsA (SETUPAPI.@)
1094 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1100 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1101 flags
, NULL
, NULL
, NULL
);
1104 /***********************************************************************
1105 * SetupDiGetClassDevsW (SETUPAPI.@)
1107 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1113 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1114 flags
, NULL
, NULL
, NULL
);
1117 /***********************************************************************
1118 * SetupDiGetClassDevsExA (SETUPAPI.@)
1120 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1130 LPWSTR enumstrW
= NULL
;
1131 LPWSTR machineW
= NULL
;
1135 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1136 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1139 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1142 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1146 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1147 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1150 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1153 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1155 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1158 HeapFree(GetProcessHeap(), 0, enumstrW
);
1159 HeapFree(GetProcessHeap(), 0, machineW
);
1164 CreateDeviceInfoElement(
1165 IN LPCWSTR InstancePath
,
1167 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1169 struct DeviceInfoElement
*deviceInfo
;
1171 *pDeviceInfo
= NULL
;
1172 if (IsEqualIID(&pClassGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1174 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1177 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1180 wcscpy(deviceInfo
->Data
, InstancePath
);
1181 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1182 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1183 deviceInfo
->DeviceDescription
= NULL
;
1184 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1185 deviceInfo
->CreationFlags
= 0;
1186 deviceInfo
->hwndParent
= NULL
;
1187 deviceInfo
->Flags
= 0; /* FIXME */
1188 deviceInfo
->FlagsEx
= 0; /* FIXME */
1189 deviceInfo
->SelectedDriver
= NULL
;
1190 InitializeListHead(&deviceInfo
->DriverListHead
);
1191 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1193 *pDeviceInfo
= deviceInfo
;
1198 CreateDeviceInterface(
1199 IN
struct DeviceInfoElement
* deviceInfo
,
1200 IN LPCWSTR SymbolicLink
,
1201 IN LPCGUID pInterfaceGuid
,
1202 OUT
struct DeviceInterface
**pDeviceInterface
)
1204 struct DeviceInterface
*deviceInterface
;
1206 *pDeviceInterface
= NULL
;
1207 if (IsEqualIID(&pInterfaceGuid
, &GUID_NULL
)) { FIXME("Bad argument!!!"); return FALSE
; }/* FIXME: remove */
1209 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1210 if (!deviceInterface
)
1212 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1215 deviceInterface
->DeviceInfo
= deviceInfo
;
1216 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1217 deviceInterface
->Flags
= 0; /* FIXME */
1218 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1220 *pDeviceInterface
= deviceInterface
;
1224 static LONG
SETUP_CreateDevListFromEnumerator(
1225 struct DeviceInfoSet
*list
,
1226 LPCGUID pClassGuid OPTIONAL
,
1228 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1230 HKEY hDeviceIdKey
, hInstanceIdKey
;
1231 WCHAR KeyBuffer
[MAX_PATH
];
1232 WCHAR InstancePath
[MAX_PATH
];
1233 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1234 struct DeviceInfoElement
*deviceInfo
;
1236 DWORD dwLength
, dwRegType
;
1239 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1242 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1243 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1244 if (rc
== ERROR_NO_MORE_ITEMS
)
1246 if (rc
!= ERROR_SUCCESS
)
1250 /* Open device id sub key */
1251 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1252 if (rc
!= ERROR_SUCCESS
)
1254 wcscpy(InstancePath
, Enumerator
);
1255 wcscat(InstancePath
, L
"\\");
1256 wcscat(InstancePath
, KeyBuffer
);
1257 wcscat(InstancePath
, L
"\\");
1258 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1260 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1264 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1265 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1266 if (rc
== ERROR_NO_MORE_ITEMS
)
1268 if (rc
!= ERROR_SUCCESS
)
1270 RegCloseKey(hDeviceIdKey
);
1275 /* Open instance id sub key */
1276 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1277 if (rc
!= ERROR_SUCCESS
)
1279 RegCloseKey(hDeviceIdKey
);
1282 *pEndOfInstancePath
= '\0';
1283 wcscat(InstancePath
, KeyBuffer
);
1285 /* Read ClassGUID value */
1286 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1287 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1288 RegCloseKey(hInstanceIdKey
);
1289 if (rc
== ERROR_FILE_NOT_FOUND
)
1292 /* Skip this bad entry as we can't verify it */
1295 else if (rc
!= ERROR_SUCCESS
)
1297 RegCloseKey(hDeviceIdKey
);
1300 else if (dwRegType
!= REG_SZ
)
1302 RegCloseKey(hDeviceIdKey
);
1303 return ERROR_GEN_FAILURE
;
1305 else if (pClassGuid
)
1308 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1309 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1311 RegCloseKey(hDeviceIdKey
);
1312 return GetLastError();
1314 if (!IsEqualIID(&KeyGuid
, pClassGuid
))
1315 /* Skip this entry as it is not the right device class */
1319 /* Add the entry to the list */
1320 if (!CreateDeviceInfoElement(InstancePath
, pClassGuid
, &deviceInfo
))
1322 RegCloseKey(hDeviceIdKey
);
1323 return GetLastError();
1325 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1326 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1328 RegCloseKey(hDeviceIdKey
);
1331 return ERROR_SUCCESS
;
1334 static LONG
SETUP_CreateDevList(
1335 struct DeviceInfoSet
*list
,
1336 PCWSTR MachineName OPTIONAL
,
1337 LPGUID
class OPTIONAL
,
1338 PCWSTR Enumerator OPTIONAL
)
1340 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1341 WCHAR KeyBuffer
[MAX_PATH
];
1346 if (IsEqualIID(class, &GUID_NULL
))
1350 if (MachineName
!= NULL
)
1352 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1353 if (rc
!= ERROR_SUCCESS
)
1357 HKLM
= HKEY_LOCAL_MACHINE
;
1359 rc
= RegOpenKeyExW(HKLM
,
1362 KEY_ENUMERATE_SUB_KEYS
,
1364 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1365 if (rc
!= ERROR_SUCCESS
)
1368 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1369 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1378 KEY_ENUMERATE_SUB_KEYS
,
1380 RegCloseKey(hEnumKey
);
1381 if (rc
!= ERROR_SUCCESS
)
1383 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1384 RegCloseKey(hEnumeratorKey
);
1389 /* Enumerate enumerators */
1393 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1394 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1395 if (rc
== ERROR_NO_MORE_ITEMS
)
1397 if (rc
!= ERROR_SUCCESS
)
1399 RegCloseKey(hEnumKey
);
1405 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1406 if (rc
!= ERROR_SUCCESS
)
1408 RegCloseKey(hEnumKey
);
1412 /* Call SETUP_CreateDevListFromEnumerator */
1413 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1414 RegCloseKey(hEnumeratorKey
);
1415 if (rc
!= ERROR_SUCCESS
)
1417 RegCloseKey(hEnumKey
);
1421 RegCloseKey(hEnumKey
);
1422 return ERROR_SUCCESS
;
1427 static LONG
SETUP_CreateSerialDeviceList(
1428 struct DeviceInfoSet
*list
,
1430 LPGUID InterfaceGuid
,
1431 PCWSTR DeviceInstanceW
)
1433 static const size_t initialSize
= 100;
1435 WCHAR buf
[initialSize
];
1437 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1439 struct DeviceInfoElement
*deviceInfo
;
1442 WARN("'MachineName' is ignored on Wine!\n");
1443 if (DeviceInstanceW
)
1444 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1450 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1452 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1456 HeapFree(GetProcessHeap(), 0, devices
);
1457 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1459 return ERROR_NOT_ENOUGH_MEMORY
;
1465 HeapFree(GetProcessHeap(), 0, devices
);
1466 return GetLastError();
1470 /* 'devices' is a MULTI_SZ string */
1471 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1473 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1475 /* We have found a device */
1476 struct DeviceInterface
*interfaceInfo
;
1477 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1478 /* Step 1. Create a device info element */
1479 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1482 HeapFree(GetProcessHeap(), 0, devices
);
1483 return GetLastError();
1485 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1487 /* Step 2. Create an interface list for this element */
1488 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1491 HeapFree(GetProcessHeap(), 0, devices
);
1492 return GetLastError();
1494 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1498 HeapFree(GetProcessHeap(), 0, devices
);
1499 return ERROR_SUCCESS
;
1502 #else /* __REACTOS__ */
1504 static LONG
SETUP_CreateInterfaceList(
1505 struct DeviceInfoSet
*list
,
1507 LPGUID InterfaceGuid
,
1508 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1510 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1511 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1512 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1513 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1514 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1516 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1519 DWORD dwLength
, dwInstancePathLength
;
1522 struct DeviceInfoElement
*deviceInfo
;
1524 /* Open registry key related to this interface */
1525 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1526 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1527 return GetLastError();
1529 /* Enumerate sub keys of hInterfaceKey */
1533 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1534 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1535 if (rc
== ERROR_NO_MORE_ITEMS
)
1537 if (rc
!= ERROR_SUCCESS
)
1539 RegCloseKey(hInterfaceKey
);
1545 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1546 if (rc
!= ERROR_SUCCESS
)
1548 RegCloseKey(hInterfaceKey
);
1552 /* Read DeviceInstance */
1553 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1554 if (rc
!= ERROR_SUCCESS
)
1556 RegCloseKey(hDeviceInstanceKey
);
1557 RegCloseKey(hInterfaceKey
);
1560 if (dwRegType
!= REG_SZ
)
1562 RegCloseKey(hDeviceInstanceKey
);
1563 RegCloseKey(hInterfaceKey
);
1564 return ERROR_GEN_FAILURE
;
1566 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1569 RegCloseKey(hDeviceInstanceKey
);
1570 RegCloseKey(hInterfaceKey
);
1571 return ERROR_NOT_ENOUGH_MEMORY
;
1573 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1574 if (rc
!= ERROR_SUCCESS
)
1576 HeapFree(GetProcessHeap(), 0, InstancePath
);
1577 RegCloseKey(hDeviceInstanceKey
);
1578 RegCloseKey(hInterfaceKey
);
1581 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1582 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1584 if (DeviceInstanceW
)
1586 /* Check if device enumerator is not the right one */
1587 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1589 HeapFree(GetProcessHeap(), 0, InstancePath
);
1590 RegCloseKey(hDeviceInstanceKey
);
1595 /* Find class GUID associated to the device instance */
1600 KEY_ENUMERATE_SUB_KEYS
,
1602 if (rc
!= ERROR_SUCCESS
)
1604 HeapFree(GetProcessHeap(), 0, InstancePath
);
1605 RegCloseKey(hDeviceInstanceKey
);
1606 RegCloseKey(hInterfaceKey
);
1615 RegCloseKey(hEnumKey
);
1616 if (rc
!= ERROR_SUCCESS
)
1618 HeapFree(GetProcessHeap(), 0, InstancePath
);
1619 RegCloseKey(hDeviceInstanceKey
);
1620 RegCloseKey(hInterfaceKey
);
1623 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1624 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1626 if (rc
!= ERROR_SUCCESS
)
1628 HeapFree(GetProcessHeap(), 0, InstancePath
);
1629 RegCloseKey(hDeviceInstanceKey
);
1630 RegCloseKey(hInterfaceKey
);
1633 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1634 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1635 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1637 HeapFree(GetProcessHeap(), 0, InstancePath
);
1638 RegCloseKey(hDeviceInstanceKey
);
1639 RegCloseKey(hInterfaceKey
);
1640 return ERROR_GEN_FAILURE
;
1642 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1644 /* If current device doesn't match the list GUID (if any), skip this entry */
1645 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1647 HeapFree(GetProcessHeap(), 0, InstancePath
);
1648 RegCloseKey(hDeviceInstanceKey
);
1652 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1656 LPWSTR pSymbolicLink
;
1657 struct DeviceInterface
*interfaceInfo
;
1659 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1660 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1661 if (rc
== ERROR_NO_MORE_ITEMS
)
1663 if (rc
!= ERROR_SUCCESS
)
1665 HeapFree(GetProcessHeap(), 0, InstancePath
);
1666 RegCloseKey(hDeviceInstanceKey
);
1667 RegCloseKey(hInterfaceKey
);
1671 if (KeyBuffer
[0] != '#')
1672 /* This entry doesn't represent an interesting entry */
1676 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1677 if (rc
!= ERROR_SUCCESS
)
1679 RegCloseKey(hDeviceInstanceKey
);
1680 RegCloseKey(hInterfaceKey
);
1684 /* Read SymbolicLink value */
1685 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1686 if (rc
!= ERROR_SUCCESS
)
1688 RegCloseKey(hReferenceKey
);
1689 RegCloseKey(hDeviceInstanceKey
);
1690 RegCloseKey(hInterfaceKey
);
1693 if (dwRegType
!= REG_SZ
)
1695 RegCloseKey(hReferenceKey
);
1696 RegCloseKey(hDeviceInstanceKey
);
1697 RegCloseKey(hInterfaceKey
);
1698 return ERROR_GEN_FAILURE
;
1701 /* We have found a device */
1702 /* Step 1. Create a device info element */
1703 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1705 RegCloseKey(hReferenceKey
);
1706 RegCloseKey(hDeviceInstanceKey
);
1707 RegCloseKey(hInterfaceKey
);
1708 return GetLastError();
1710 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1711 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1713 /* Step 2. Create an interface list for this element */
1714 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1717 RegCloseKey(hReferenceKey
);
1718 RegCloseKey(hDeviceInstanceKey
);
1719 RegCloseKey(hInterfaceKey
);
1720 return ERROR_NOT_ENOUGH_MEMORY
;
1722 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1723 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1724 RegCloseKey(hReferenceKey
);
1725 if (rc
!= ERROR_SUCCESS
)
1727 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1728 RegCloseKey(hDeviceInstanceKey
);
1729 RegCloseKey(hInterfaceKey
);
1732 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1734 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1735 RegCloseKey(hDeviceInstanceKey
);
1736 RegCloseKey(hInterfaceKey
);
1737 return GetLastError();
1739 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1740 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1741 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1743 RegCloseKey(hDeviceInstanceKey
);
1745 RegCloseKey(hInterfaceKey
);
1746 return ERROR_SUCCESS
;
1748 #endif /* __REACTOS__ */
1750 /***********************************************************************
1751 * SetupDiGetClassDevsExW (SETUPAPI.@)
1753 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1762 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1763 struct DeviceInfoSet
*list
;
1767 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1768 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1770 /* Create the deviceset if not set */
1773 list
= (struct DeviceInfoSet
*)deviceset
;
1774 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1776 SetLastError(ERROR_INVALID_HANDLE
);
1777 return INVALID_HANDLE_VALUE
;
1779 hDeviceInfo
= deviceset
;
1783 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1784 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1785 NULL
, machine
, NULL
);
1786 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1787 return INVALID_HANDLE_VALUE
;
1788 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1791 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1794 pClassGuid
= &list
->ClassGuid
;
1796 if (flags
& DIGCF_PRESENT
)
1797 FIXME(": flag DIGCF_PRESENT ignored\n");
1798 if (flags
& DIGCF_PROFILE
)
1799 FIXME(": flag DIGCF_PROFILE ignored\n");
1801 if (flags
& DIGCF_ALLCLASSES
)
1803 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1804 if (rc
!= ERROR_SUCCESS
)
1808 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1809 return INVALID_HANDLE_VALUE
;
1813 else if (flags
& DIGCF_DEVICEINTERFACE
)
1817 SetLastError(ERROR_INVALID_PARAMETER
);
1819 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1820 return INVALID_HANDLE_VALUE
;
1824 /* Special case: find serial ports by calling QueryDosDevice */
1825 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1826 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1827 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1828 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1831 ERR("Wine can only enumerate serial devices at the moment!\n");
1832 rc
= ERROR_INVALID_PARAMETER
;
1834 #else /* __REACTOS__ */
1835 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1836 #endif /* __REACTOS__ */
1837 if (rc
!= ERROR_SUCCESS
)
1841 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1842 return INVALID_HANDLE_VALUE
;
1848 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1849 if (rc
!= ERROR_SUCCESS
)
1853 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1854 return INVALID_HANDLE_VALUE
;
1860 /***********************************************************************
1861 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1863 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1864 HDEVINFO DeviceInfoSet
,
1865 PSP_DEVINFO_DATA DeviceInfoData
,
1866 CONST GUID
* InterfaceClassGuid
,
1868 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1872 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1873 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1875 if (!DeviceInterfaceData
)
1876 SetLastError(ERROR_INVALID_PARAMETER
);
1877 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1878 SetLastError(ERROR_INVALID_USER_BUFFER
);
1879 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1881 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1883 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1885 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1887 while (ItemList
!= &list
->ListHead
&& !Found
)
1889 PLIST_ENTRY InterfaceListEntry
;
1890 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1891 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1893 /* We are not searching for this element */
1894 ItemList
= ItemList
->Flink
;
1897 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1898 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1900 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1901 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1903 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1906 if (MemberIndex
-- == 0)
1908 /* return this item */
1909 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1910 &DevItf
->InterfaceClassGuid
,
1912 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1913 /* Note: this appears to be dangerous, passing a private
1914 * pointer a heap-allocated datum to the caller. However, the
1915 * expected lifetime of the device data is the same as the
1916 * HDEVINFO; once that is closed, the data are no longer valid.
1918 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1921 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1923 ItemList
= ItemList
->Flink
;
1926 SetLastError(ERROR_NO_MORE_ITEMS
);
1931 SetLastError(ERROR_INVALID_HANDLE
);
1934 SetLastError(ERROR_INVALID_HANDLE
);
1938 /***********************************************************************
1939 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1941 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1945 TRACE("%p\n", devinfo
);
1946 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1948 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1950 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1952 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1953 struct DeviceInfoElement
*deviceInfo
;
1954 while (!IsListEmpty(&list
->ListHead
))
1956 ListEntry
= RemoveHeadList(&list
->ListHead
);
1957 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1958 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1960 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1961 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1963 HeapFree(GetProcessHeap(), 0, ListEntry
);
1965 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1966 RegCloseKey(list
->HKLM
);
1967 HeapFree(GetProcessHeap(), 0, list
);
1971 SetLastError(ERROR_INVALID_HANDLE
);
1974 SetLastError(ERROR_INVALID_HANDLE
);
1976 TRACE("Returning %d\n", ret
);
1980 /***********************************************************************
1981 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1983 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1984 HDEVINFO DeviceInfoSet
,
1985 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1986 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1987 DWORD DeviceInterfaceDetailDataSize
,
1988 PDWORD RequiredSize
,
1989 PSP_DEVINFO_DATA DeviceInfoData
)
1991 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
1992 DWORD sizeW
= 0, sizeA
;
1995 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
1996 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1997 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1999 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2000 SetLastError(ERROR_INVALID_USER_BUFFER
);
2001 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2002 SetLastError(ERROR_INVALID_PARAMETER
);
2003 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2004 SetLastError(ERROR_INVALID_PARAMETER
);
2007 if (DeviceInterfaceDetailData
!= NULL
)
2009 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2010 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2011 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2012 if (!DeviceInterfaceDetailDataW
)
2014 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2017 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2019 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2020 ret
= SetupDiGetDeviceInterfaceDetailW(
2022 DeviceInterfaceData
,
2023 DeviceInterfaceDetailDataW
,
2027 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2028 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2030 *RequiredSize
= sizeA
;
2031 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2033 if (!WideCharToMultiByte(
2035 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2036 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2043 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2046 TRACE("Returning %d\n", ret
);
2050 /***********************************************************************
2051 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2053 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2054 HDEVINFO DeviceInfoSet
,
2055 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2056 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2057 DWORD DeviceInterfaceDetailDataSize
,
2058 PDWORD RequiredSize
,
2059 PSP_DEVINFO_DATA DeviceInfoData
)
2063 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2064 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2065 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2067 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2068 SetLastError(ERROR_INVALID_PARAMETER
);
2069 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2070 SetLastError(ERROR_INVALID_HANDLE
);
2071 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2072 SetLastError(ERROR_INVALID_HANDLE
);
2073 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2074 SetLastError(ERROR_INVALID_USER_BUFFER
);
2075 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2076 SetLastError(ERROR_INVALID_USER_BUFFER
);
2077 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2078 SetLastError(ERROR_INVALID_USER_BUFFER
);
2079 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2080 SetLastError(ERROR_INVALID_PARAMETER
);
2081 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2082 SetLastError(ERROR_INVALID_PARAMETER
);
2085 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2086 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2087 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2088 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2090 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2092 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2094 *RequiredSize
= sizeRequired
;
2098 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2099 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2102 memcpy(&DeviceInfoData
->ClassGuid
,
2103 &deviceInterface
->DeviceInfo
->ClassGuid
,
2105 DeviceInfoData
->DevInst
= 0; /* FIXME */
2106 /* Note: this appears to be dangerous, passing a private
2107 * pointer a heap-allocated datum to the caller. However, the
2108 * expected lifetime of the device data is the same as the
2109 * HDEVINFO; once that is closed, the data are no longer valid.
2111 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2117 TRACE("Returning %d\n", ret
);
2121 /***********************************************************************
2122 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2124 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2126 PSP_DEVINFO_DATA DeviceInfoData
,
2128 PDWORD PropertyRegDataType
,
2129 PBYTE PropertyBuffer
,
2130 DWORD PropertyBufferSize
,
2131 PDWORD RequiredSize
)
2134 BOOL bIsStringProperty
;
2136 DWORD RequiredSizeA
, RequiredSizeW
;
2137 DWORD PropertyBufferSizeW
;
2138 PBYTE PropertyBufferW
;
2140 TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
2141 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2144 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2145 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2147 bResult
= SetupDiGetDeviceRegistryPropertyW(
2153 PropertyBufferSizeW
,
2158 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2162 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2164 if (bIsStringProperty
)
2165 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2167 RequiredSizeA
= RequiredSizeW
;
2169 if (RequiredSizeA
<= PropertyBufferSize
)
2171 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2173 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2175 /* Last error is already set by WideCharToMultiByte */
2180 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2184 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2188 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2189 if (PropertyRegDataType
)
2190 *PropertyRegDataType
= RegType
;
2192 *RequiredSize
= RequiredSizeA
;
2196 /***********************************************************************
2197 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2199 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2200 HDEVINFO DeviceInfoSet
,
2201 PSP_DEVINFO_DATA DeviceInfoData
,
2203 PDWORD PropertyRegDataType
,
2204 PBYTE PropertyBuffer
,
2205 DWORD PropertyBufferSize
,
2206 PDWORD RequiredSize
)
2208 HKEY hEnumKey
, hKey
;
2212 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2213 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2216 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2217 SetLastError(ERROR_INVALID_HANDLE
);
2218 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2219 SetLastError(ERROR_INVALID_HANDLE
);
2220 else if (!DeviceInfoData
)
2221 SetLastError(ERROR_INVALID_PARAMETER
);
2222 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2223 SetLastError(ERROR_INVALID_USER_BUFFER
);
2224 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2225 SetLastError(ERROR_INVALID_PARAMETER
);
2228 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2229 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2233 case SPDRP_CAPABILITIES
:
2235 case SPDRP_CLASSGUID
:
2236 case SPDRP_COMPATIBLEIDS
:
2237 case SPDRP_CONFIGFLAGS
:
2238 case SPDRP_DEVICEDESC
:
2240 case SPDRP_FRIENDLYNAME
:
2241 case SPDRP_HARDWAREID
:
2242 case SPDRP_LOCATION_INFORMATION
:
2243 case SPDRP_LOWERFILTERS
:
2245 case SPDRP_SECURITY
:
2247 case SPDRP_UI_NUMBER
:
2248 case SPDRP_UPPERFILTERS
:
2250 LPCWSTR RegistryPropertyName
;
2255 case SPDRP_CAPABILITIES
:
2256 RegistryPropertyName
= L
"Capabilities"; break;
2258 RegistryPropertyName
= L
"Class"; break;
2259 case SPDRP_CLASSGUID
:
2260 RegistryPropertyName
= L
"ClassGUID"; break;
2261 case SPDRP_COMPATIBLEIDS
:
2262 RegistryPropertyName
= L
"CompatibleIDs"; break;
2263 case SPDRP_CONFIGFLAGS
:
2264 RegistryPropertyName
= L
"ConfigFlags"; break;
2265 case SPDRP_DEVICEDESC
:
2266 RegistryPropertyName
= L
"DeviceDesc"; break;
2268 RegistryPropertyName
= L
"Driver"; break;
2269 case SPDRP_FRIENDLYNAME
:
2270 RegistryPropertyName
= L
"FriendlyName"; break;
2271 case SPDRP_HARDWAREID
:
2272 RegistryPropertyName
= L
"HardwareID"; break;
2273 case SPDRP_LOCATION_INFORMATION
:
2274 RegistryPropertyName
= L
"LocationInformation"; break;
2275 case SPDRP_LOWERFILTERS
:
2276 RegistryPropertyName
= L
"LowerFilters"; break;
2278 RegistryPropertyName
= L
"Mfg"; break;
2279 case SPDRP_SECURITY
:
2280 RegistryPropertyName
= L
"Security"; break;
2282 RegistryPropertyName
= L
"Service"; break;
2283 case SPDRP_UI_NUMBER
:
2284 RegistryPropertyName
= L
"UINumber"; break;
2285 case SPDRP_UPPERFILTERS
:
2286 RegistryPropertyName
= L
"UpperFilters"; break;
2288 /* Should not happen */
2289 RegistryPropertyName
= NULL
; break;
2292 /* Open registry key name */
2297 KEY_ENUMERATE_SUB_KEYS
,
2299 if (rc
!= ERROR_SUCCESS
)
2310 RegCloseKey(hEnumKey
);
2311 if (rc
!= ERROR_SUCCESS
)
2316 /* Read registry entry */
2317 BufferSize
= PropertyBufferSize
;
2318 rc
= RegQueryValueExW(
2320 RegistryPropertyName
,
2321 NULL
, /* Reserved */
2322 PropertyRegDataType
,
2326 *RequiredSize
= BufferSize
;
2327 if (rc
== ERROR_SUCCESS
)
2335 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2337 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2339 if (PropertyRegDataType
)
2340 *PropertyRegDataType
= REG_SZ
;
2342 *RequiredSize
= required
;
2343 if (PropertyBufferSize
>= required
)
2345 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2349 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2353 /*case SPDRP_BUSTYPEGUID:
2354 case SPDRP_LEGACYBUSTYPE:
2355 case SPDRP_BUSNUMBER:
2356 case SPDRP_ENUMERATOR_NAME:
2357 case SPDRP_SECURITY_SDS:
2359 case SPDRP_EXCLUSIVE:
2360 case SPDRP_CHARACTERISTICS:
2362 case SPDRP_UI_NUMBER_DESC_FORMAT:
2363 case SPDRP_DEVICE_POWER_DATA:*/
2364 #if (WINVER >= 0x501)
2365 /*case SPDRP_REMOVAL_POLICY:
2366 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2367 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2368 case SPDRP_INSTALL_STATE:*/
2373 FIXME("Property 0x%lx not implemented\n", Property
);
2374 SetLastError(ERROR_NOT_SUPPORTED
);
2379 TRACE("Returning %d\n", ret
);
2384 /***********************************************************************
2385 * SetupDiInstallClassA (SETUPAPI.@)
2387 BOOL WINAPI
SetupDiInstallClassA(
2393 UNICODE_STRING FileNameW
;
2396 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2398 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2402 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2404 RtlFreeUnicodeString(&FileNameW
);
2409 static HKEY
CreateClassKey(HINF hInf
)
2411 WCHAR FullBuffer
[MAX_PATH
];
2412 WCHAR Buffer
[MAX_PATH
];
2417 if (!SetupGetLineTextW(NULL
,
2425 return INVALID_HANDLE_VALUE
;
2428 lstrcpyW(FullBuffer
, ControlClass
);
2429 lstrcatW(FullBuffer
, Buffer
);
2432 if (!SetupGetLineTextW(NULL
,
2440 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2441 return INVALID_HANDLE_VALUE
;
2444 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2448 REG_OPTION_NON_VOLATILE
,
2454 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2455 return INVALID_HANDLE_VALUE
;
2458 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2463 RequiredSize
* sizeof(WCHAR
)))
2465 RegCloseKey(hClassKey
);
2466 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2467 return INVALID_HANDLE_VALUE
;
2473 /***********************************************************************
2474 * SetupDiInstallClassW (SETUPAPI.@)
2476 BOOL WINAPI
SetupDiInstallClassW(
2482 WCHAR SectionName
[MAX_PATH
];
2483 DWORD SectionNameLength
= 0;
2485 BOOL bFileQueueCreated
= FALSE
;
2488 FIXME("not fully implemented\n");
2490 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2492 SetLastError(ERROR_INVALID_PARAMETER
);
2496 /* Open the .inf file */
2497 hInf
= SetupOpenInfFileW(InfFileName
,
2501 if (hInf
== INVALID_HANDLE_VALUE
)
2507 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2508 hClassKey
= CreateClassKey(hInf
);
2509 if (hClassKey
== INVALID_HANDLE_VALUE
)
2511 SetupCloseInfFile(hInf
);
2517 /* Try to append a layout file */
2519 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2522 /* Retrieve the actual section name */
2523 SetupDiGetActualSectionToInstallW(hInf
,
2531 if (!(Flags
& DI_NOVCP
))
2533 FileQueue
= SetupOpenFileQueue();
2534 if (FileQueue
== INVALID_HANDLE_VALUE
)
2536 SetupCloseInfFile(hInf
);
2537 RegCloseKey(hClassKey
);
2541 bFileQueueCreated
= TRUE
;
2546 SetupInstallFromInfSectionW(NULL
,
2555 INVALID_HANDLE_VALUE
,
2558 /* FIXME: More code! */
2560 if (bFileQueueCreated
)
2561 SetupCloseFileQueue(FileQueue
);
2563 SetupCloseInfFile(hInf
);
2565 RegCloseKey(hClassKey
);
2570 /***********************************************************************
2571 * SetupDiOpenClassRegKey (SETUPAPI.@)
2573 HKEY WINAPI
SetupDiOpenClassRegKey(
2574 const GUID
* ClassGuid
,
2577 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2578 DIOCR_INSTALLER
, NULL
, NULL
);
2582 /***********************************************************************
2583 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2585 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2586 const GUID
* ClassGuid
,
2592 PWSTR MachineNameW
= NULL
;
2599 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2600 if (MachineNameW
== NULL
)
2601 return INVALID_HANDLE_VALUE
;
2604 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2605 Flags
, MachineNameW
, Reserved
);
2608 MyFree(MachineNameW
);
2614 /***********************************************************************
2615 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2617 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2618 const GUID
* ClassGuid
,
2624 LPWSTR lpGuidString
;
2625 LPWSTR lpFullGuidString
;
2633 if (Flags
== DIOCR_INSTALLER
)
2635 lpKeyName
= ControlClass
;
2637 else if (Flags
== DIOCR_INTERFACE
)
2639 lpKeyName
= DeviceClasses
;
2643 ERR("Invalid Flags parameter!\n");
2644 SetLastError(ERROR_INVALID_PARAMETER
);
2645 return INVALID_HANDLE_VALUE
;
2648 if (MachineName
!= NULL
)
2650 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2651 if (rc
!= ERROR_SUCCESS
)
2654 return INVALID_HANDLE_VALUE
;
2658 HKLM
= HKEY_LOCAL_MACHINE
;
2660 rc
= RegOpenKeyExW(HKLM
,
2665 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2666 if (rc
!= ERROR_SUCCESS
)
2669 return INVALID_HANDLE_VALUE
;
2672 if (ClassGuid
== NULL
)
2675 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2677 SetLastError(ERROR_GEN_FAILURE
);
2678 RegCloseKey(hClassesKey
);
2679 return INVALID_HANDLE_VALUE
;
2682 dwLength
= lstrlenW(lpGuidString
);
2683 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2684 if (!lpFullGuidString
)
2686 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2687 RpcStringFreeW(&lpGuidString
);
2688 return INVALID_HANDLE_VALUE
;
2690 lpFullGuidString
[0] = '{';
2691 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2692 lpFullGuidString
[dwLength
+ 1] = '}';
2693 lpFullGuidString
[dwLength
+ 2] = '\0';
2694 RpcStringFreeW(&lpGuidString
);
2696 rc
= RegOpenKeyExW(hClassesKey
,
2701 if (rc
!= ERROR_SUCCESS
)
2704 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2705 RegCloseKey(hClassesKey
);
2706 return INVALID_HANDLE_VALUE
;
2709 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2710 RegCloseKey(hClassesKey
);
2715 /***********************************************************************
2716 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2718 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2719 HDEVINFO DeviceInfoSet
,
2722 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2724 FIXME("%p %s %08lx %p\n",
2725 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2729 /***********************************************************************
2730 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2732 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2733 HDEVINFO DeviceInfoSet
,
2736 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2738 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
2739 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2743 /***********************************************************************
2744 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2746 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2747 HDEVINFO DeviceInfoSet
,
2748 PSP_DEVINFO_DATA DeviceInfoData
,
2749 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2750 DWORD ClassInstallParamsSize
)
2752 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2753 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2757 /***********************************************************************
2758 * SetupDiCallClassInstaller (SETUPAPI.@)
2760 BOOL WINAPI
SetupDiCallClassInstaller(
2761 DI_FUNCTION InstallFunction
,
2762 HDEVINFO DeviceInfoSet
,
2763 PSP_DEVINFO_DATA DeviceInfoData
)
2765 FIXME("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2769 /***********************************************************************
2770 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
2772 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
2773 HDEVINFO DeviceInfoSet
,
2774 PSP_DEVINFO_DATA DeviceInfoData
,
2775 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
2777 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
2781 /***********************************************************************
2782 * SetupDiOpenDevRegKey (SETUPAPI.@)
2784 HKEY WINAPI
SetupDiOpenDevRegKey(
2785 HDEVINFO DeviceInfoSet
,
2786 PSP_DEVINFO_DATA DeviceInfoData
,
2792 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
2793 Scope
, HwProfile
, KeyType
, samDesired
);
2794 return INVALID_HANDLE_VALUE
;
2797 /***********************************************************************
2798 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
2800 BOOL WINAPI
SetupDiCreateDeviceInfoA(
2801 HDEVINFO DeviceInfoSet
,
2803 CONST GUID
*ClassGuid
,
2804 PCSTR DeviceDescription
,
2806 DWORD CreationFlags
,
2807 PSP_DEVINFO_DATA DeviceInfoData
)
2809 LPWSTR DeviceNameW
= NULL
;
2810 LPWSTR DeviceDescriptionW
= NULL
;
2817 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
2818 if (DeviceNameW
== NULL
) return FALSE
;
2820 if (DeviceDescription
)
2822 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
2823 if (DeviceDescriptionW
== NULL
)
2825 if (DeviceNameW
) MyFree(DeviceNameW
);
2830 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
2831 ClassGuid
, DeviceDescriptionW
,
2832 hwndParent
, CreationFlags
,
2835 if (DeviceNameW
) MyFree(DeviceNameW
);
2836 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
2841 /***********************************************************************
2842 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
2844 BOOL WINAPI
SetupDiCreateDeviceInfoW(
2845 HDEVINFO DeviceInfoSet
,
2847 CONST GUID
*ClassGuid
,
2848 PCWSTR DeviceDescription
,
2850 DWORD CreationFlags
,
2851 PSP_DEVINFO_DATA DeviceInfoData
)
2853 struct DeviceInfoSet
*list
;
2856 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
2857 debugstr_guid(ClassGuid
), DeviceDescription
,
2858 hwndParent
, CreationFlags
, DeviceInfoData
);
2861 SetLastError(ERROR_INVALID_HANDLE
);
2862 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2863 SetLastError(ERROR_INVALID_HANDLE
);
2864 else if (!ClassGuid
)
2865 SetLastError(ERROR_INVALID_PARAMETER
);
2866 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
2867 SetLastError(ERROR_CLASS_MISMATCH
);
2868 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
2870 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
2871 SetLastError(ERROR_INVALID_PARAMETER
);
2875 SP_DEVINFO_DATA DevInfo
;
2877 if (CreationFlags
& DICD_GENERATE_ID
)
2879 /* Generate a new unique ID for this device */
2880 SetLastError(ERROR_GEN_FAILURE
);
2881 FIXME("not implemented\n");
2885 /* Device name is fully qualified. Try to open it */
2888 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
2889 rc
= SetupDiOpenDeviceInfoW(
2892 NULL
, /* hwndParent */
2893 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
2898 /* SetupDiOpenDeviceInfoW has already added
2899 * the device info to the device info set
2901 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
2903 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
2905 struct DeviceInfoElement
*deviceInfo
;
2907 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
2909 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
2911 if (!DeviceInfoData
)
2915 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
2917 SetLastError(ERROR_INVALID_USER_BUFFER
);
2921 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
2922 DeviceInfoData
->DevInst
= 0; /* FIXME */
2923 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
2932 TRACE("Returning %d\n", ret
);
2936 /***********************************************************************
2937 * Helper functions for SetupDiBuildDriverInfoList
2941 IN PLIST_ENTRY DriverListHead
,
2942 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
2943 IN INFCONTEXT ContextDevice
,
2945 IN LPCWSTR ProviderName
,
2946 IN LPCWSTR ManufacturerName
,
2947 FILETIME DriverDate
,
2948 DWORDLONG DriverVersion
,
2951 struct DriverInfoElement
*driverInfo
;
2952 DWORD RequiredSize
= 128; /* Initial buffer size */
2953 BOOL Result
= FALSE
;
2954 LPWSTR DeviceDescription
= NULL
;
2955 LPWSTR InfInstallSection
= NULL
;
2957 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
2960 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2964 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2965 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2967 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
2968 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
2969 if (!DeviceDescription
)
2971 Result
= SetupGetStringFieldW(
2973 0, /* Field index */
2974 DeviceDescription
, RequiredSize
,
2979 HeapFree(GetProcessHeap(), 0, driverInfo
);
2980 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
2985 RequiredSize
= 128; /* Initial buffer size */
2986 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2987 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2989 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
2990 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
2991 if (!InfInstallSection
)
2993 HeapFree(GetProcessHeap(), 0, driverInfo
);
2994 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
2997 Result
= SetupGetStringFieldW(
2999 1, /* Field index */
3000 InfInstallSection
, RequiredSize
,
3005 HeapFree(GetProcessHeap(), 0, driverInfo
);
3006 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3007 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3011 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3012 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3014 driverInfo
->Info
.DriverType
= DriverType
;
3015 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3016 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3017 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3018 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3019 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3022 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3023 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3026 driverInfo
->Info
.ProviderName
[0] = '\0';
3027 driverInfo
->Info
.DriverDate
= DriverDate
;
3028 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3029 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3031 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3032 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3037 GetVersionInformationFromInfFile(
3039 OUT LPGUID ClassGuid
,
3040 OUT LPWSTR
* pProviderName
,
3041 OUT FILETIME
* DriverDate
,
3042 OUT DWORDLONG
* DriverVersion
)
3045 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3046 LPWSTR ProviderName
= NULL
;
3049 if (!SetupGetLineTextW(
3052 L
"Version", L
"ClassGUID",
3053 guidW
, sizeof(guidW
),
3054 NULL
/* Required size */))
3059 /* Get Provider name, driver date, and driver version */
3061 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3062 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3066 Result
= SetupGetLineTextW(
3068 hInf
, L
"Version", L
"Provider",
3071 if (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3073 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3076 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3079 Result
= SetupGetLineTextW(
3081 hInf
, L
"Version", L
"Provider",
3082 ProviderName
, RequiredSize
,
3085 //FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
3086 //FIXME: DriverVersion = Version.DriverVer => invalid = 0
3088 *pProviderName
= ProviderName
;
3092 /***********************************************************************
3093 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3096 SetupDiBuildDriverInfoList(
3097 IN HDEVINFO DeviceInfoSet
,
3098 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3099 IN DWORD DriverType
)
3101 struct DeviceInfoSet
*list
;
3102 PVOID Buffer
= NULL
;
3103 HINF hInf
= INVALID_HANDLE_VALUE
;
3104 LPWSTR ProviderName
= NULL
;
3105 LPWSTR ManufacturerName
= NULL
;
3106 LPWSTR ManufacturerSection
= NULL
;
3107 LPWSTR HardwareIDs
= NULL
;
3108 LPWSTR CompatibleIDs
= NULL
;
3109 FILETIME DriverDate
;
3110 DWORDLONG DriverVersion
;
3114 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3117 SetLastError(ERROR_INVALID_HANDLE
);
3118 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3119 SetLastError(ERROR_INVALID_HANDLE
);
3120 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3121 SetLastError(ERROR_INVALID_HANDLE
);
3122 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3123 SetLastError(ERROR_INVALID_PARAMETER
);
3124 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3125 SetLastError(ERROR_INVALID_PARAMETER
);
3126 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3127 SetLastError(ERROR_INVALID_PARAMETER
);
3128 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3129 SetLastError(ERROR_INVALID_USER_BUFFER
);
3132 BOOL Result
= FALSE
;
3134 if (DriverType
== SPDIT_COMPATDRIVER
)
3136 /* Get hardware IDs list */
3138 RequiredSize
= 512; /* Initial buffer size */
3139 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3140 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3142 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3143 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3146 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3149 Result
= SetupDiGetDeviceRegistryPropertyW(
3161 /* Get compatible IDs list */
3163 RequiredSize
= 512; /* Initial buffer size */
3164 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3165 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3167 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3168 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3171 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3174 Result
= SetupDiGetDeviceRegistryPropertyW(
3177 SPDRP_COMPATIBLEIDS
,
3179 (PBYTE
)CompatibleIDs
,
3182 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3184 /* No compatible ID for this device */
3185 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3186 CompatibleIDs
= NULL
;
3194 /* Enumerate .inf files */
3196 RequiredSize
= 32768; /* Initial buffer size */
3197 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3198 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3200 HeapFree(GetProcessHeap(), 0, Buffer
);
3201 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3205 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3208 Result
= SetupGetInfFileListW(
3209 NULL
, /* Directory path */
3211 Buffer
, RequiredSize
,
3218 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
3220 INFCONTEXT ContextManufacturer
, ContextDevice
;
3222 TRACE("Opening file %S\n", filename
);
3224 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
3225 if (hInf
== INVALID_HANDLE_VALUE
)
3228 if (!GetVersionInformationFromInfFile(
3235 SetupCloseInfFile(hInf
);
3236 hInf
= INVALID_HANDLE_VALUE
;
3240 if (DriverType
== SPDIT_CLASSDRIVER
)
3242 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
3243 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
3245 SetupCloseInfFile(hInf
);
3246 hInf
= INVALID_HANDLE_VALUE
;
3251 /* Get the manufacturers list */
3252 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
3255 Result
= SetupGetStringFieldW(
3256 &ContextManufacturer
,
3257 0, /* Field index */
3260 if (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3262 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3263 if (!ManufacturerName
)
3265 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3268 Result
= SetupGetStringFieldW(
3269 &ContextManufacturer
,
3270 0, /* Field index */
3271 ManufacturerName
, RequiredSize
,
3274 Result
= SetupGetStringFieldW(
3275 &ContextManufacturer
,
3276 1, /* Field index */
3279 if (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3281 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3282 if (!ManufacturerSection
)
3284 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3287 Result
= SetupGetStringFieldW(
3288 &ContextManufacturer
,
3289 1, /* Field index */
3290 ManufacturerSection
, RequiredSize
,
3294 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
3295 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
3298 if (DriverType
== SPDIT_CLASSDRIVER
)
3300 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
3301 if (!AddDriverToList(
3302 &list
->DriverListHead
,
3308 DriverDate
, DriverVersion
,
3314 else /* DriverType = SPDIT_COMPATDRIVER */
3316 /* 1. Get all fields */
3317 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
3321 BOOL DriverAlreadyAdded
;
3323 for (i
= 2; i
<= FieldCount
; i
++)
3325 LPWSTR DeviceId
= NULL
;
3327 RequiredSize
= 128; /* Initial buffer size */
3328 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3329 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3331 HeapFree(GetProcessHeap(), 0, DeviceId
);
3332 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3335 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3338 Result
= SetupGetStringFieldW(
3341 DeviceId
, RequiredSize
,
3346 HeapFree(GetProcessHeap(), 0, DeviceId
);
3349 DriverAlreadyAdded
= FALSE
;
3350 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3352 if (wcscmp(DeviceId
, currentId
) == 0)
3355 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3361 DriverDate
, DriverVersion
,
3362 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
3363 DriverAlreadyAdded
= TRUE
;
3368 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
3370 if (wcscmp(DeviceId
, currentId
) == 0)
3373 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
3379 DriverDate
, DriverVersion
,
3380 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
3381 DriverAlreadyAdded
= TRUE
;
3385 HeapFree(GetProcessHeap(), 0, DeviceId
);
3388 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
3391 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3392 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3393 ManufacturerName
= ManufacturerSection
= NULL
;
3394 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
3396 HeapFree(GetProcessHeap(), 0, ProviderName
);
3397 ProviderName
= NULL
;
3400 SetupCloseInfFile(hInf
);
3401 hInf
= INVALID_HANDLE_VALUE
;
3412 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
;
3413 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
3416 list
->Flags
|= DI_DIDCLASS
;
3419 HeapFree(GetProcessHeap(), 0, ProviderName
);
3420 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
3421 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
3422 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3423 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3424 if (hInf
!= INVALID_HANDLE_VALUE
)
3425 SetupCloseInfFile(hInf
);
3426 HeapFree(GetProcessHeap(), 0, Buffer
);
3428 TRACE("Returning %d\n", ret
);
3432 /***********************************************************************
3433 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
3436 SetupDiDeleteDeviceInfo(
3437 IN HDEVINFO DeviceInfoSet
,
3438 IN PSP_DEVINFO_DATA DeviceInfoData
)
3440 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3442 FIXME("not implemented\n");
3443 SetLastError(ERROR_GEN_FAILURE
);
3448 /***********************************************************************
3449 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
3452 SetupDiDestroyDriverInfoList(
3453 IN HDEVINFO DeviceInfoSet
,
3454 IN PSP_DEVINFO_DATA DeviceInfoData
,
3455 IN DWORD DriverType
)
3457 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3459 FIXME("not implemented\n");
3460 SetLastError(ERROR_GEN_FAILURE
);
3465 /***********************************************************************
3466 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
3469 SetupDiOpenDeviceInfoA(
3470 IN HDEVINFO DeviceInfoSet
,
3471 IN PCSTR DeviceInstanceId
,
3472 IN HWND hwndParent OPTIONAL
,
3474 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3476 LPWSTR DeviceInstanceIdW
= NULL
;
3479 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3481 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
3482 if (DeviceInstanceIdW
== NULL
)
3485 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
3486 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
3488 MyFree(DeviceInstanceIdW
);
3494 /***********************************************************************
3495 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
3498 SetupDiOpenDeviceInfoW(
3499 IN HDEVINFO DeviceInfoSet
,
3500 IN PCWSTR DeviceInstanceId
,
3501 IN HWND hwndParent OPTIONAL
,
3503 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3505 struct DeviceInfoSet
*list
;
3506 HKEY hEnumKey
, hKey
;
3510 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
3512 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
3513 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
3516 SetLastError(ERROR_INVALID_HANDLE
);
3517 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3518 SetLastError(ERROR_INVALID_HANDLE
);
3519 else if (!DeviceInstanceId
)
3520 SetLastError(ERROR_INVALID_PARAMETER
);
3521 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
3523 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
3524 SetLastError(ERROR_INVALID_PARAMETER
);
3526 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3527 SetLastError(ERROR_INVALID_USER_BUFFER
);
3530 struct DeviceInfoElement
*deviceInfo
= NULL
;
3531 /* Search if device already exists in DeviceInfoSet.
3532 * If yes, return the existing element
3533 * If no, create a new element using informations in registry
3535 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
3536 while (ItemList
!= &list
->ListHead
)
3541 FIXME("not implemented\n");
3542 ItemList
= ItemList
->Flink
;
3550 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
3551 DeviceInfoData
->DevInst
= 0; /* FIXME */
3552 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3558 /* Open supposed registry key */
3563 KEY_ENUMERATE_SUB_KEYS
,
3565 if (rc
!= ERROR_SUCCESS
)
3576 RegCloseKey(hEnumKey
);
3577 if (rc
!= ERROR_SUCCESS
)
3583 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
3588 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3594 if (ret
&& deviceInfo
&& DeviceInfoData
)
3596 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
3597 DeviceInfoData
->DevInst
= 0; /* FIXME */
3598 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3606 /***********************************************************************
3607 * SetupDiEnumDriverInfoA (SETUPAPI.@)
3610 SetupDiEnumDriverInfoA(
3611 IN HDEVINFO DeviceInfoSet
,
3612 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3613 IN DWORD DriverType
,
3614 IN DWORD MemberIndex
,
3615 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
3617 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
3620 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
3621 DriverType
, MemberIndex
, DriverInfoData
);
3623 if (DriverInfoData
== NULL
)
3624 SetLastError(ERROR_INVALID_PARAMETER
);
3625 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
3626 SetLastError(ERROR_INVALID_USER_BUFFER
);
3629 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
3630 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
3631 DriverType
, MemberIndex
, &driverInfoData2W
);
3635 /* Do W->A conversion */
3636 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
3637 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
3638 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
3639 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
3641 DriverInfoData
->Description
[0] = '\0';
3644 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
3645 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
3647 DriverInfoData
->MfgName
[0] = '\0';
3650 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
3651 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
3653 DriverInfoData
->ProviderName
[0] = '\0';
3656 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
3658 /* Copy more fields */
3659 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
3660 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
3665 TRACE("Returning %d\n", ret
);
3670 /***********************************************************************
3671 * SetupDiEnumDriverInfoW (SETUPAPI.@)
3674 SetupDiEnumDriverInfoW(
3675 IN HDEVINFO DeviceInfoSet
,
3676 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3677 IN DWORD DriverType
,
3678 IN DWORD MemberIndex
,
3679 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
3681 PLIST_ENTRY ListHead
;
3684 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
3685 DriverType
, MemberIndex
, DriverInfoData
);
3687 if (!DeviceInfoSet
|| !DriverInfoData
)
3688 SetLastError(ERROR_INVALID_PARAMETER
);
3689 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3690 SetLastError(ERROR_INVALID_HANDLE
);
3691 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3692 SetLastError(ERROR_INVALID_HANDLE
);
3693 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3694 SetLastError(ERROR_INVALID_PARAMETER
);
3695 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3696 SetLastError(ERROR_INVALID_PARAMETER
);
3697 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3698 SetLastError(ERROR_INVALID_PARAMETER
);
3699 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
3700 SetLastError(ERROR_INVALID_USER_BUFFER
);
3703 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3704 PLIST_ENTRY ItemList
;
3705 if (DriverType
== SPDIT_CLASSDRIVER
||
3706 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
3708 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
3712 ListHead
= &devInfo
->DriverListHead
;
3715 ItemList
= ListHead
->Flink
;
3716 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
3717 ItemList
= ItemList
->Flink
;
3718 if (ItemList
== ListHead
)
3719 SetLastError(ERROR_NO_MORE_ITEMS
);
3722 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
3727 DriverInfoData
->cbSize
);
3732 TRACE("Returning %d\n", ret
);
3736 /***********************************************************************
3737 * SetupDiGetSelectedDriverW (SETUPAPI.@)
3740 SetupDiGetSelectedDriverW(
3741 IN HDEVINFO DeviceInfoSet
,
3742 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3743 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
3747 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
3749 if (!DeviceInfoSet
|| !DriverInfoData
)
3750 SetLastError(ERROR_INVALID_PARAMETER
);
3751 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3752 SetLastError(ERROR_INVALID_HANDLE
);
3753 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3754 SetLastError(ERROR_INVALID_HANDLE
);
3755 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3756 SetLastError(ERROR_INVALID_USER_BUFFER
);
3757 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
3758 SetLastError(ERROR_INVALID_USER_BUFFER
);
3761 struct DriverInfoElement
*driverInfo
;
3764 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
3766 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
3768 if (driverInfo
== NULL
)
3769 SetLastError(ERROR_NO_DRIVER_SELECTED
);
3775 DriverInfoData
->cbSize
);
3780 TRACE("Returning %d\n", ret
);
3784 /***********************************************************************
3785 * SetupDiSetSelectedDriverW (SETUPAPI.@)
3788 SetupDiSetSelectedDriverW(
3789 IN HDEVINFO DeviceInfoSet
,
3790 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3791 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
3795 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
3798 SetLastError(ERROR_INVALID_PARAMETER
);
3799 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3800 SetLastError(ERROR_INVALID_HANDLE
);
3801 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3802 SetLastError(ERROR_INVALID_HANDLE
);
3803 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3804 SetLastError(ERROR_INVALID_USER_BUFFER
);
3805 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
3806 SetLastError(ERROR_INVALID_USER_BUFFER
);
3809 struct DriverInfoElement
**pDriverInfo
;
3810 PLIST_ENTRY ListHead
, ItemList
;
3814 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
3815 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
3819 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
3820 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
3823 if (!DriverInfoData
)
3825 *pDriverInfo
= NULL
;
3830 /* Search selected driver in list */
3831 ItemList
= ListHead
->Flink
;
3832 while (ItemList
!= ListHead
)
3834 if (DriverInfoData
->Reserved
!= 0)
3836 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
3841 /* The caller wants to compare only DriverType, Description and ProviderName fields */
3842 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
3843 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
3844 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
3845 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
3851 if (ItemList
== ListHead
)
3852 SetLastError(ERROR_INVALID_PARAMETER
);
3855 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
3856 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
3862 TRACE("Returning %d\n", ret
);