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"
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
33 #define NTOS_MODE_USER
34 #include <ndk/ntndk.h>
36 #include "setupapi_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
41 /* Unicode constants */
42 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
43 static const WCHAR Class
[] = {'C','l','a','s','s',0};
44 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
45 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
46 static const WCHAR NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
47 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
48 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
49 static const WCHAR NtExtension
[] = {'.','N','T',0};
50 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
51 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
52 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
53 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
55 /* Registry key and value names */
56 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
57 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
58 'C','o','n','t','r','o','l','\\',
59 'C','l','a','s','s',0};
61 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
62 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
63 'C','o','n','t','r','o','l','\\',
64 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
66 static const WCHAR EnumKeyName
[] = {'S','y','s','t','e','m','\\',
67 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
71 /* FIXME: header mess */
72 DEFINE_GUID(GUID_NULL
,
73 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
75 (CALLBACK
* CLASS_INSTALL_PROC
) (
76 IN DI_FUNCTION InstallFunction
,
77 IN HDEVINFO DeviceInfoSet
,
78 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
80 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
81 IN HDEVINFO DeviceInfoSet
,
82 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
84 (CALLBACK
* COINSTALLER_PROC
) (
85 IN DI_FUNCTION InstallFunction
,
86 IN HDEVINFO DeviceInfoSet
,
87 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
88 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
90 #define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
92 struct CoInstallerElement
97 COINSTALLER_PROC Function
;
98 BOOL DoPostProcessing
;
102 struct DeviceInterface
/* Element of DeviceInfoElement.InterfaceListHead */
104 LIST_ENTRY ListEntry
;
106 struct DeviceInfoElement
* DeviceInfo
;
107 GUID InterfaceClassGuid
;
110 /* SPINT_ACTIVE : the interface is active/enabled
111 * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
112 * SPINT_REMOVED: the interface is removed
116 WCHAR SymbolicLink
[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
119 struct DriverInfoElement
/* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
121 LIST_ENTRY ListEntry
;
124 SP_DRVINFO_DATA_V2_W Info
;
131 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
133 LIST_ENTRY ListEntry
;
135 /* Information about devnode:
137 * "Root\*PNP0501" for example.
138 * It doesn't contain the unique ID for the device
139 * (points into the Data field at the end of the structure)
140 * WARNING: no NULL char exist between DeviceName and UniqueId
143 * "5&1be2108e&0" or "0000"
144 * If DICD_GENERATE_ID is specified in creation flags,
145 * this unique ID is autogenerated using 4 digits, base 10
146 * (points into the Data field at the end of the structure)
147 * - DeviceDescription
148 * String which identifies the device. Can be NULL. If not NULL,
149 * points into the Data field at the end of the structure
151 * Identifies the class of this device. FIXME: can it be GUID_NULL?
153 * Is a combination of:
155 * the unique ID needs to be generated
156 * - DICD_INHERIT_CLASSDRVS
157 * inherit driver of the device info set (== same pointer)
159 * Used when doing device-specific actions. Can be NULL
163 PCWSTR DeviceDescription
;
168 /* Flags is a combination of:
170 * Set when the device driver list is created
171 * FlagsEx is a combination of:
176 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
177 /* If the driver is not searched/detected, this list is empty */
178 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
179 /* Points into DriverListHead list. The pointer is NULL if no driver is
180 * currently chosen. */
181 struct DriverInfoElement
*SelectedDriver
;
183 /* List of interfaces implemented by this device */
184 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
189 struct DeviceInfoSet
/* HDEVINFO */
191 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
192 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
193 HWND hwndParent
; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
194 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
196 /* Flags is a combination of:
198 * Set when the class driver list is created
199 * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
200 * Forces SetupDiBuildDriverInfoList to build a class drivers list
201 * FlagsEx is a combination of:
206 /* If the driver is not searched/detected, this list is empty */
207 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
208 /* Points into DriverListHead list. The pointer is NULL if no driver is
209 * currently chosen. */
210 struct DriverInfoElement
*SelectedDriver
;
212 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
215 /***********************************************************************
216 * SetupDiBuildClassInfoList (SETUPAPI.@)
218 BOOL WINAPI
SetupDiBuildClassInfoList(
220 LPGUID ClassGuidList
,
221 DWORD ClassGuidListSize
,
225 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
226 ClassGuidListSize
, RequiredSize
,
230 /***********************************************************************
231 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
233 BOOL WINAPI
SetupDiBuildClassInfoListExA(
235 LPGUID ClassGuidList
,
236 DWORD ClassGuidListSize
,
241 LPWSTR MachineNameW
= NULL
;
248 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
249 if (MachineNameW
== NULL
) return FALSE
;
252 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
253 ClassGuidListSize
, RequiredSize
,
254 MachineNameW
, Reserved
);
257 MyFree(MachineNameW
);
262 /***********************************************************************
263 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
265 BOOL WINAPI
SetupDiBuildClassInfoListExW(
267 LPGUID ClassGuidList
,
268 DWORD ClassGuidListSize
,
273 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
279 DWORD dwGuidListIndex
= 0;
283 if (RequiredSize
!= NULL
)
286 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
291 if (hClassesKey
== INVALID_HANDLE_VALUE
)
296 for (dwIndex
= 0; ; dwIndex
++)
298 dwLength
= MAX_GUID_STRING_LEN
+ 1;
299 lError
= RegEnumKeyExW(hClassesKey
,
307 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
308 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
310 TRACE("Key name: %p\n", szKeyName
);
312 if (RegOpenKeyExW(hClassesKey
,
318 RegCloseKey(hClassesKey
);
322 if (!RegQueryValueExW(hClassKey
,
329 TRACE("'NoUseClass' value found!\n");
330 RegCloseKey(hClassKey
);
334 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
335 (!RegQueryValueExW(hClassKey
,
342 TRACE("'NoInstallClass' value found!\n");
343 RegCloseKey(hClassKey
);
347 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
348 (!RegQueryValueExW(hClassKey
,
355 TRACE("'NoDisplayClass' value found!\n");
356 RegCloseKey(hClassKey
);
360 RegCloseKey(hClassKey
);
362 TRACE("Guid: %p\n", szKeyName
);
363 if (dwGuidListIndex
< ClassGuidListSize
)
365 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
369 TRACE("Guid: %p\n", &szKeyName
[1]);
371 UuidFromStringW(&szKeyName
[1],
372 &ClassGuidList
[dwGuidListIndex
]);
378 if (lError
!= ERROR_SUCCESS
)
382 RegCloseKey(hClassesKey
);
384 if (RequiredSize
!= NULL
)
385 *RequiredSize
= dwGuidListIndex
;
387 if (ClassGuidListSize
< dwGuidListIndex
)
389 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
396 /***********************************************************************
397 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
399 BOOL WINAPI
SetupDiClassGuidsFromNameA(
401 LPGUID ClassGuidList
,
402 DWORD ClassGuidListSize
,
405 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
406 ClassGuidListSize
, RequiredSize
,
410 /***********************************************************************
411 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
413 BOOL WINAPI
SetupDiClassGuidsFromNameW(
415 LPGUID ClassGuidList
,
416 DWORD ClassGuidListSize
,
419 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
420 ClassGuidListSize
, RequiredSize
,
424 /***********************************************************************
425 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
427 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
429 LPGUID ClassGuidList
,
430 DWORD ClassGuidListSize
,
435 LPWSTR ClassNameW
= NULL
;
436 LPWSTR MachineNameW
= NULL
;
441 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
442 if (ClassNameW
== NULL
)
447 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
448 if (MachineNameW
== NULL
)
455 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
456 ClassGuidListSize
, RequiredSize
,
457 MachineNameW
, Reserved
);
460 MyFree(MachineNameW
);
467 /***********************************************************************
468 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
470 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
472 LPGUID ClassGuidList
,
473 DWORD ClassGuidListSize
,
478 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
479 WCHAR szClassName
[256];
485 DWORD dwGuidListIndex
= 0;
487 if (RequiredSize
!= NULL
)
490 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
491 KEY_ENUMERATE_SUB_KEYS
,
495 if (hClassesKey
== INVALID_HANDLE_VALUE
)
500 for (dwIndex
= 0; ; dwIndex
++)
502 dwLength
= MAX_GUID_STRING_LEN
+ 1;
503 lError
= RegEnumKeyExW(hClassesKey
,
511 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
512 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
514 TRACE("Key name: %p\n", szKeyName
);
516 if (RegOpenKeyExW(hClassesKey
,
522 RegCloseKey(hClassesKey
);
526 dwLength
= 256 * sizeof(WCHAR
);
527 if (!RegQueryValueExW(hClassKey
,
534 TRACE("Class name: %p\n", szClassName
);
536 if (strcmpiW(szClassName
, ClassName
) == 0)
538 TRACE("Found matching class name\n");
540 TRACE("Guid: %p\n", szKeyName
);
541 if (dwGuidListIndex
< ClassGuidListSize
)
543 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
547 TRACE("Guid: %p\n", &szKeyName
[1]);
549 UuidFromStringW(&szKeyName
[1],
550 &ClassGuidList
[dwGuidListIndex
]);
557 RegCloseKey(hClassKey
);
560 if (lError
!= ERROR_SUCCESS
)
564 RegCloseKey(hClassesKey
);
566 if (RequiredSize
!= NULL
)
567 *RequiredSize
= dwGuidListIndex
;
569 if (ClassGuidListSize
< dwGuidListIndex
)
571 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
578 /***********************************************************************
579 * SetupDiClassNameFromGuidA (SETUPAPI.@)
581 BOOL WINAPI
SetupDiClassNameFromGuidA(
582 const GUID
* ClassGuid
,
587 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
588 ClassNameSize
, RequiredSize
,
592 /***********************************************************************
593 * SetupDiClassNameFromGuidW (SETUPAPI.@)
595 BOOL WINAPI
SetupDiClassNameFromGuidW(
596 const GUID
* ClassGuid
,
601 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
602 ClassNameSize
, RequiredSize
,
606 /***********************************************************************
607 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
609 BOOL WINAPI
SetupDiClassNameFromGuidExA(
610 const GUID
* ClassGuid
,
617 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
618 LPWSTR MachineNameW
= NULL
;
622 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
623 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
624 NULL
, MachineNameW
, Reserved
);
627 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
628 ClassNameSize
, NULL
, NULL
);
630 if (!ClassNameSize
&& RequiredSize
)
633 MyFree(MachineNameW
);
637 /***********************************************************************
638 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
640 BOOL WINAPI
SetupDiClassNameFromGuidExW(
641 const GUID
* ClassGuid
,
652 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
657 if (hKey
== INVALID_HANDLE_VALUE
)
662 if (RequiredSize
!= NULL
)
665 rc
= RegQueryValueExW(hKey
,
671 if (rc
!= ERROR_SUCCESS
)
678 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
681 dwLength
= ClassNameSize
* sizeof(WCHAR
);
682 rc
= RegQueryValueExW(hKey
,
688 if (rc
!= ERROR_SUCCESS
)
700 /***********************************************************************
701 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
704 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
707 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
710 /***********************************************************************
711 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
714 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
719 LPWSTR MachineNameW
= NULL
;
722 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
726 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
727 if (MachineNameW
== NULL
)
728 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
731 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
732 MachineNameW
, Reserved
);
735 MyFree(MachineNameW
);
740 /***********************************************************************
741 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
744 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
749 struct DeviceInfoSet
*list
;
752 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
754 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
757 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
758 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
761 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
764 ClassGuid
? ClassGuid
: &GUID_NULL
,
765 sizeof(list
->ClassGuid
));
766 list
->hwndParent
= hwndParent
;
769 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
770 if (rc
!= ERROR_SUCCESS
)
773 HeapFree(GetProcessHeap(), 0, list
);
774 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
779 list
->HKLM
= HKEY_LOCAL_MACHINE
;
781 list
->Flags
= 0; /* FIXME */
782 list
->FlagsEx
= 0; /* FIXME */
783 InitializeListHead(&list
->DriverListHead
);
784 InitializeListHead(&list
->ListHead
);
785 return (HDEVINFO
)list
;
788 /***********************************************************************
789 * SetupDiEnumDeviceInfo (SETUPAPI.@)
791 BOOL WINAPI
SetupDiEnumDeviceInfo(
792 HDEVINFO DeviceInfoSet
,
794 PSP_DEVINFO_DATA DeviceInfoData
)
798 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
800 SetLastError(ERROR_INVALID_PARAMETER
);
801 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
803 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
805 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
806 SetLastError(ERROR_INVALID_HANDLE
);
807 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
808 SetLastError(ERROR_INVALID_USER_BUFFER
);
811 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
812 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
813 ItemList
= ItemList
->Flink
;
814 if (ItemList
== &list
->ListHead
)
815 SetLastError(ERROR_NO_MORE_ITEMS
);
818 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
819 memcpy(&DeviceInfoData
->ClassGuid
,
822 DeviceInfoData
->DevInst
= 0; /* FIXME */
823 /* Note: this appears to be dangerous, passing a private
824 * pointer a heap-allocated datum to the caller. However, the
825 * expected lifetime of the device data is the same as the
826 * HDEVINFO; once that is closed, the data are no longer valid.
828 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
834 SetLastError(ERROR_INVALID_HANDLE
);
838 /***********************************************************************
839 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
841 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
843 PCSTR InfSectionName
,
844 PSTR InfSectionWithExt
,
845 DWORD InfSectionWithExtSize
,
849 LPWSTR InfSectionNameW
= NULL
;
850 PWSTR InfSectionWithExtW
= NULL
;
852 BOOL bResult
= FALSE
;
858 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
859 if (InfSectionNameW
== NULL
) goto end
;
861 if (InfSectionWithExt
)
863 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
864 if (InfSectionWithExtW
== NULL
) goto end
;
867 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
868 InfSectionWithExt
? InfSectionNameW
: NULL
,
869 InfSectionWithExtSize
, RequiredSize
,
870 Extension
? &ExtensionW
: NULL
);
872 if (bResult
&& InfSectionWithExt
)
874 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
875 InfSectionWithExtSize
, NULL
, NULL
) != 0;
877 if (bResult
&& Extension
)
879 if (ExtensionW
== NULL
)
882 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
886 if (InfSectionNameW
) MyFree(InfSectionNameW
);
887 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
892 /***********************************************************************
893 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
895 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
897 PCWSTR InfSectionName
,
898 PWSTR InfSectionWithExt
,
899 DWORD InfSectionWithExtSize
,
903 WCHAR szBuffer
[MAX_PATH
];
906 LONG lLineCount
= -1;
908 lstrcpyW(szBuffer
, InfSectionName
);
909 dwLength
= lstrlenW(szBuffer
);
911 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
913 /* Test section name with '.NTx86' extension */
914 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
915 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
917 if (lLineCount
== -1)
919 /* Test section name with '.NT' extension */
920 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
921 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
926 /* Test section name with '.Win' extension */
927 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
928 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
931 if (lLineCount
== -1)
933 /* Test section name without extension */
934 szBuffer
[dwLength
] = 0;
935 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
938 if (lLineCount
== -1)
940 SetLastError(ERROR_INVALID_PARAMETER
);
944 dwFullLength
= lstrlenW(szBuffer
);
946 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
948 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
950 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
954 lstrcpyW(InfSectionWithExt
, szBuffer
);
955 if (Extension
!= NULL
)
957 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
961 if (RequiredSize
!= NULL
)
963 *RequiredSize
= dwFullLength
+ 1;
969 /***********************************************************************
970 * SetupDiGetClassDescriptionA (SETUPAPI.@)
972 BOOL WINAPI
SetupDiGetClassDescriptionA(
973 const GUID
* ClassGuid
,
974 PSTR ClassDescription
,
975 DWORD ClassDescriptionSize
,
978 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
979 ClassDescriptionSize
,
980 RequiredSize
, NULL
, NULL
);
983 /***********************************************************************
984 * SetupDiGetClassDescriptionW (SETUPAPI.@)
986 BOOL WINAPI
SetupDiGetClassDescriptionW(
987 const GUID
* ClassGuid
,
988 PWSTR ClassDescription
,
989 DWORD ClassDescriptionSize
,
992 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
993 ClassDescriptionSize
,
994 RequiredSize
, NULL
, NULL
);
997 /***********************************************************************
998 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1000 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1001 const GUID
* ClassGuid
,
1002 PSTR ClassDescription
,
1003 DWORD ClassDescriptionSize
,
1004 PDWORD RequiredSize
,
1008 PWCHAR ClassDescriptionW
;
1009 LPWSTR MachineNameW
= NULL
;
1013 if (ClassDescriptionSize
> 0)
1015 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1016 if (!ClassDescriptionW
)
1018 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1024 ClassDescriptionW
= NULL
;
1028 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1031 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1037 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1038 NULL
, MachineNameW
, Reserved
);
1041 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1042 ClassDescriptionSize
, NULL
, NULL
);
1044 if (!ClassDescriptionSize
&& RequiredSize
)
1045 *RequiredSize
= len
;
1049 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1050 MyFree(MachineNameW
);
1054 /***********************************************************************
1055 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1057 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1058 const GUID
* ClassGuid
,
1059 PWSTR ClassDescription
,
1060 DWORD ClassDescriptionSize
,
1061 PDWORD RequiredSize
,
1068 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1073 if (hKey
== INVALID_HANDLE_VALUE
)
1075 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1079 if (RequiredSize
!= NULL
)
1082 if (RegQueryValueExW(hKey
,
1093 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1096 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1097 if (RegQueryValueExW(hKey
,
1101 (LPBYTE
)ClassDescription
,
1113 /***********************************************************************
1114 * SetupDiGetClassDevsA (SETUPAPI.@)
1116 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1122 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1123 flags
, NULL
, NULL
, NULL
);
1126 /***********************************************************************
1127 * SetupDiGetClassDevsW (SETUPAPI.@)
1129 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1135 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1136 flags
, NULL
, NULL
, NULL
);
1139 /***********************************************************************
1140 * SetupDiGetClassDevsExA (SETUPAPI.@)
1142 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1152 LPWSTR enumstrW
= NULL
;
1153 LPWSTR machineW
= NULL
;
1157 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1158 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1161 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1164 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1168 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1169 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1172 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1175 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1177 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1180 HeapFree(GetProcessHeap(), 0, enumstrW
);
1181 HeapFree(GetProcessHeap(), 0, machineW
);
1186 CreateDeviceInfoElement(
1187 IN LPCWSTR InstancePath
,
1188 IN LPCGUID pClassGuid
,
1189 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1191 struct DeviceInfoElement
*deviceInfo
;
1193 *pDeviceInfo
= NULL
;
1195 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
));
1198 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1201 wcscpy(deviceInfo
->Data
, InstancePath
);
1202 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1203 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1204 deviceInfo
->DeviceDescription
= NULL
;
1205 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1206 deviceInfo
->CreationFlags
= 0;
1207 deviceInfo
->hwndParent
= NULL
;
1208 deviceInfo
->Flags
= 0; /* FIXME */
1209 deviceInfo
->FlagsEx
= 0; /* FIXME */
1210 deviceInfo
->SelectedDriver
= NULL
;
1211 InitializeListHead(&deviceInfo
->DriverListHead
);
1212 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1214 *pDeviceInfo
= deviceInfo
;
1219 CreateDeviceInterface(
1220 IN
struct DeviceInfoElement
* deviceInfo
,
1221 IN LPCWSTR SymbolicLink
,
1222 IN LPCGUID pInterfaceGuid
,
1223 OUT
struct DeviceInterface
**pDeviceInterface
)
1225 struct DeviceInterface
*deviceInterface
;
1227 *pDeviceInterface
= NULL
;
1229 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1230 if (!deviceInterface
)
1232 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1235 deviceInterface
->DeviceInfo
= deviceInfo
;
1236 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1237 deviceInterface
->Flags
= 0; /* FIXME */
1238 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1240 *pDeviceInterface
= deviceInterface
;
1244 static LONG
SETUP_CreateDevListFromEnumerator(
1245 struct DeviceInfoSet
*list
,
1246 LPCGUID pClassGuid OPTIONAL
,
1248 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1250 HKEY hDeviceIdKey
, hInstanceIdKey
;
1251 WCHAR KeyBuffer
[MAX_PATH
];
1252 WCHAR InstancePath
[MAX_PATH
];
1253 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1254 struct DeviceInfoElement
*deviceInfo
;
1256 DWORD dwLength
, dwRegType
;
1259 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1262 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1263 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1264 if (rc
== ERROR_NO_MORE_ITEMS
)
1266 if (rc
!= ERROR_SUCCESS
)
1270 /* Open device id sub key */
1271 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1272 if (rc
!= ERROR_SUCCESS
)
1274 wcscpy(InstancePath
, Enumerator
);
1275 wcscat(InstancePath
, L
"\\");
1276 wcscat(InstancePath
, KeyBuffer
);
1277 wcscat(InstancePath
, L
"\\");
1278 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1280 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1286 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1287 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1288 if (rc
== ERROR_NO_MORE_ITEMS
)
1290 if (rc
!= ERROR_SUCCESS
)
1292 RegCloseKey(hDeviceIdKey
);
1297 /* Open instance id sub key */
1298 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1299 if (rc
!= ERROR_SUCCESS
)
1301 RegCloseKey(hDeviceIdKey
);
1304 *pEndOfInstancePath
= '\0';
1305 wcscat(InstancePath
, KeyBuffer
);
1307 /* Read ClassGUID value */
1308 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1309 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1310 RegCloseKey(hInstanceIdKey
);
1311 if (rc
== ERROR_FILE_NOT_FOUND
)
1314 /* Skip this bad entry as we can't verify it */
1317 else if (rc
!= ERROR_SUCCESS
)
1319 RegCloseKey(hDeviceIdKey
);
1322 else if (dwRegType
!= REG_SZ
)
1324 RegCloseKey(hDeviceIdKey
);
1325 return ERROR_GEN_FAILURE
;
1328 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1329 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1331 RegCloseKey(hDeviceIdKey
);
1332 return GetLastError();
1334 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1336 /* Skip this entry as it is not the right device class */
1340 /* Add the entry to the list */
1341 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1343 RegCloseKey(hDeviceIdKey
);
1344 return GetLastError();
1346 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1347 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1349 RegCloseKey(hDeviceIdKey
);
1352 return ERROR_SUCCESS
;
1355 static LONG
SETUP_CreateDevList(
1356 struct DeviceInfoSet
*list
,
1357 PCWSTR MachineName OPTIONAL
,
1358 LPGUID
class OPTIONAL
,
1359 PCWSTR Enumerator OPTIONAL
)
1361 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1362 WCHAR KeyBuffer
[MAX_PATH
];
1367 if (IsEqualIID(class, &GUID_NULL
))
1371 if (MachineName
!= NULL
)
1373 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1374 if (rc
!= ERROR_SUCCESS
)
1378 HKLM
= HKEY_LOCAL_MACHINE
;
1380 rc
= RegOpenKeyExW(HKLM
,
1383 KEY_ENUMERATE_SUB_KEYS
,
1385 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1386 if (rc
!= ERROR_SUCCESS
)
1389 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1390 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1399 KEY_ENUMERATE_SUB_KEYS
,
1401 RegCloseKey(hEnumKey
);
1402 if (rc
!= ERROR_SUCCESS
)
1404 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1405 RegCloseKey(hEnumeratorKey
);
1410 /* Enumerate enumerators */
1414 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1415 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1416 if (rc
== ERROR_NO_MORE_ITEMS
)
1418 if (rc
!= ERROR_SUCCESS
)
1420 RegCloseKey(hEnumKey
);
1426 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1427 if (rc
!= ERROR_SUCCESS
)
1429 RegCloseKey(hEnumKey
);
1433 /* Call SETUP_CreateDevListFromEnumerator */
1434 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1435 RegCloseKey(hEnumeratorKey
);
1436 if (rc
!= ERROR_SUCCESS
)
1438 RegCloseKey(hEnumKey
);
1442 RegCloseKey(hEnumKey
);
1443 return ERROR_SUCCESS
;
1448 static LONG
SETUP_CreateSerialDeviceList(
1449 struct DeviceInfoSet
*list
,
1451 LPGUID InterfaceGuid
,
1452 PCWSTR DeviceInstanceW
)
1454 static const size_t initialSize
= 100;
1456 WCHAR buf
[initialSize
];
1458 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1460 struct DeviceInfoElement
*deviceInfo
;
1463 WARN("'MachineName' is ignored on Wine!\n");
1464 if (DeviceInstanceW
)
1465 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1471 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1473 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1477 HeapFree(GetProcessHeap(), 0, devices
);
1478 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1480 return ERROR_NOT_ENOUGH_MEMORY
;
1486 HeapFree(GetProcessHeap(), 0, devices
);
1487 return GetLastError();
1491 /* 'devices' is a MULTI_SZ string */
1492 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1494 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1496 /* We have found a device */
1497 struct DeviceInterface
*interfaceInfo
;
1498 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1499 /* Step 1. Create a device info element */
1500 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1503 HeapFree(GetProcessHeap(), 0, devices
);
1504 return GetLastError();
1506 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1508 /* Step 2. Create an interface list for this element */
1509 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1512 HeapFree(GetProcessHeap(), 0, devices
);
1513 return GetLastError();
1515 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1519 HeapFree(GetProcessHeap(), 0, devices
);
1520 return ERROR_SUCCESS
;
1523 #else /* __REACTOS__ */
1525 static LONG
SETUP_CreateInterfaceList(
1526 struct DeviceInfoSet
*list
,
1528 LPGUID InterfaceGuid
,
1529 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1531 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1532 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1533 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1534 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1535 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1537 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1540 DWORD dwLength
, dwInstancePathLength
;
1543 struct DeviceInfoElement
*deviceInfo
;
1545 /* Open registry key related to this interface */
1546 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1547 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1548 return GetLastError();
1550 /* Enumerate sub keys of hInterfaceKey */
1554 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1555 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1556 if (rc
== ERROR_NO_MORE_ITEMS
)
1558 if (rc
!= ERROR_SUCCESS
)
1560 RegCloseKey(hInterfaceKey
);
1566 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1567 if (rc
!= ERROR_SUCCESS
)
1569 RegCloseKey(hInterfaceKey
);
1573 /* Read DeviceInstance */
1574 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1575 if (rc
!= ERROR_SUCCESS
)
1577 RegCloseKey(hDeviceInstanceKey
);
1578 RegCloseKey(hInterfaceKey
);
1581 if (dwRegType
!= REG_SZ
)
1583 RegCloseKey(hDeviceInstanceKey
);
1584 RegCloseKey(hInterfaceKey
);
1585 return ERROR_GEN_FAILURE
;
1587 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1590 RegCloseKey(hDeviceInstanceKey
);
1591 RegCloseKey(hInterfaceKey
);
1592 return ERROR_NOT_ENOUGH_MEMORY
;
1594 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1595 if (rc
!= ERROR_SUCCESS
)
1597 HeapFree(GetProcessHeap(), 0, InstancePath
);
1598 RegCloseKey(hDeviceInstanceKey
);
1599 RegCloseKey(hInterfaceKey
);
1602 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1603 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1605 if (DeviceInstanceW
)
1607 /* Check if device enumerator is not the right one */
1608 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1610 HeapFree(GetProcessHeap(), 0, InstancePath
);
1611 RegCloseKey(hDeviceInstanceKey
);
1616 /* Find class GUID associated to the device instance */
1621 KEY_ENUMERATE_SUB_KEYS
,
1623 if (rc
!= ERROR_SUCCESS
)
1625 HeapFree(GetProcessHeap(), 0, InstancePath
);
1626 RegCloseKey(hDeviceInstanceKey
);
1627 RegCloseKey(hInterfaceKey
);
1636 RegCloseKey(hEnumKey
);
1637 if (rc
!= ERROR_SUCCESS
)
1639 HeapFree(GetProcessHeap(), 0, InstancePath
);
1640 RegCloseKey(hDeviceInstanceKey
);
1641 RegCloseKey(hInterfaceKey
);
1644 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1645 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1647 if (rc
!= ERROR_SUCCESS
)
1649 HeapFree(GetProcessHeap(), 0, InstancePath
);
1650 RegCloseKey(hDeviceInstanceKey
);
1651 RegCloseKey(hInterfaceKey
);
1654 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1655 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1656 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1658 HeapFree(GetProcessHeap(), 0, InstancePath
);
1659 RegCloseKey(hDeviceInstanceKey
);
1660 RegCloseKey(hInterfaceKey
);
1661 return ERROR_GEN_FAILURE
;
1663 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1665 /* If current device doesn't match the list GUID (if any), skip this entry */
1666 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1668 HeapFree(GetProcessHeap(), 0, InstancePath
);
1669 RegCloseKey(hDeviceInstanceKey
);
1673 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1677 LPWSTR pSymbolicLink
;
1678 struct DeviceInterface
*interfaceInfo
;
1680 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1681 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1682 if (rc
== ERROR_NO_MORE_ITEMS
)
1684 if (rc
!= ERROR_SUCCESS
)
1686 HeapFree(GetProcessHeap(), 0, InstancePath
);
1687 RegCloseKey(hDeviceInstanceKey
);
1688 RegCloseKey(hInterfaceKey
);
1692 if (KeyBuffer
[0] != '#')
1693 /* This entry doesn't represent an interesting entry */
1697 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1698 if (rc
!= ERROR_SUCCESS
)
1700 RegCloseKey(hDeviceInstanceKey
);
1701 RegCloseKey(hInterfaceKey
);
1705 /* Read SymbolicLink value */
1706 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1707 if (rc
!= ERROR_SUCCESS
)
1709 RegCloseKey(hReferenceKey
);
1710 RegCloseKey(hDeviceInstanceKey
);
1711 RegCloseKey(hInterfaceKey
);
1714 if (dwRegType
!= REG_SZ
)
1716 RegCloseKey(hReferenceKey
);
1717 RegCloseKey(hDeviceInstanceKey
);
1718 RegCloseKey(hInterfaceKey
);
1719 return ERROR_GEN_FAILURE
;
1722 /* We have found a device */
1723 /* Step 1. Create a device info element */
1724 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1726 RegCloseKey(hReferenceKey
);
1727 RegCloseKey(hDeviceInstanceKey
);
1728 RegCloseKey(hInterfaceKey
);
1729 return GetLastError();
1731 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1732 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1734 /* Step 2. Create an interface list for this element */
1735 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1738 RegCloseKey(hReferenceKey
);
1739 RegCloseKey(hDeviceInstanceKey
);
1740 RegCloseKey(hInterfaceKey
);
1741 return ERROR_NOT_ENOUGH_MEMORY
;
1743 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1744 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1745 RegCloseKey(hReferenceKey
);
1746 if (rc
!= ERROR_SUCCESS
)
1748 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1749 RegCloseKey(hDeviceInstanceKey
);
1750 RegCloseKey(hInterfaceKey
);
1753 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1755 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1756 RegCloseKey(hDeviceInstanceKey
);
1757 RegCloseKey(hInterfaceKey
);
1758 return GetLastError();
1760 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1761 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1762 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1764 RegCloseKey(hDeviceInstanceKey
);
1766 RegCloseKey(hInterfaceKey
);
1767 return ERROR_SUCCESS
;
1769 #endif /* __REACTOS__ */
1771 /***********************************************************************
1772 * SetupDiGetClassDevsExW (SETUPAPI.@)
1774 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1783 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1784 struct DeviceInfoSet
*list
;
1788 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1789 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1791 /* Create the deviceset if not set */
1794 list
= (struct DeviceInfoSet
*)deviceset
;
1795 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1797 SetLastError(ERROR_INVALID_HANDLE
);
1798 return INVALID_HANDLE_VALUE
;
1800 hDeviceInfo
= deviceset
;
1804 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1805 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1806 NULL
, machine
, NULL
);
1807 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1808 return INVALID_HANDLE_VALUE
;
1809 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1812 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1815 pClassGuid
= &list
->ClassGuid
;
1817 if (flags
& DIGCF_PRESENT
)
1818 FIXME(": flag DIGCF_PRESENT ignored\n");
1819 if (flags
& DIGCF_PROFILE
)
1820 FIXME(": flag DIGCF_PROFILE ignored\n");
1822 if (flags
& DIGCF_ALLCLASSES
)
1824 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1825 if (rc
!= ERROR_SUCCESS
)
1829 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1830 return INVALID_HANDLE_VALUE
;
1834 else if (flags
& DIGCF_DEVICEINTERFACE
)
1838 SetLastError(ERROR_INVALID_PARAMETER
);
1840 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1841 return INVALID_HANDLE_VALUE
;
1845 /* Special case: find serial ports by calling QueryDosDevice */
1846 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1847 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1848 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1849 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1852 ERR("Wine can only enumerate serial devices at the moment!\n");
1853 rc
= ERROR_INVALID_PARAMETER
;
1855 #else /* __REACTOS__ */
1856 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1857 #endif /* __REACTOS__ */
1858 if (rc
!= ERROR_SUCCESS
)
1862 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1863 return INVALID_HANDLE_VALUE
;
1869 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1870 if (rc
!= ERROR_SUCCESS
)
1874 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1875 return INVALID_HANDLE_VALUE
;
1881 /***********************************************************************
1882 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1884 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1885 HDEVINFO DeviceInfoSet
,
1886 PSP_DEVINFO_DATA DeviceInfoData
,
1887 CONST GUID
* InterfaceClassGuid
,
1889 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1893 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1894 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1896 if (!DeviceInterfaceData
)
1897 SetLastError(ERROR_INVALID_PARAMETER
);
1898 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1899 SetLastError(ERROR_INVALID_USER_BUFFER
);
1900 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1902 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1904 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1906 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1908 while (ItemList
!= &list
->ListHead
&& !Found
)
1910 PLIST_ENTRY InterfaceListEntry
;
1911 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1912 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1914 /* We are not searching for this element */
1915 ItemList
= ItemList
->Flink
;
1918 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1919 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1921 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1922 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1924 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1927 if (MemberIndex
-- == 0)
1929 /* return this item */
1930 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1931 &DevItf
->InterfaceClassGuid
,
1933 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1934 /* Note: this appears to be dangerous, passing a private
1935 * pointer a heap-allocated datum to the caller. However, the
1936 * expected lifetime of the device data is the same as the
1937 * HDEVINFO; once that is closed, the data are no longer valid.
1939 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1942 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1944 ItemList
= ItemList
->Flink
;
1947 SetLastError(ERROR_NO_MORE_ITEMS
);
1952 SetLastError(ERROR_INVALID_HANDLE
);
1955 SetLastError(ERROR_INVALID_HANDLE
);
1959 /***********************************************************************
1960 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1962 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1966 TRACE("%p\n", devinfo
);
1967 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1969 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1971 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1973 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1974 struct DeviceInfoElement
*deviceInfo
;
1975 while (!IsListEmpty(&list
->ListHead
))
1977 ListEntry
= RemoveHeadList(&list
->ListHead
);
1978 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1979 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1981 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1982 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1984 HeapFree(GetProcessHeap(), 0, ListEntry
);
1986 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1987 RegCloseKey(list
->HKLM
);
1988 HeapFree(GetProcessHeap(), 0, list
);
1992 SetLastError(ERROR_INVALID_HANDLE
);
1995 SetLastError(ERROR_INVALID_HANDLE
);
1997 TRACE("Returning %d\n", ret
);
2001 /***********************************************************************
2002 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2004 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2005 HDEVINFO DeviceInfoSet
,
2006 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2007 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2008 DWORD DeviceInterfaceDetailDataSize
,
2009 PDWORD RequiredSize
,
2010 PSP_DEVINFO_DATA DeviceInfoData
)
2012 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2013 DWORD sizeW
= 0, sizeA
;
2016 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
2017 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2018 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2020 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2021 SetLastError(ERROR_INVALID_USER_BUFFER
);
2022 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2023 SetLastError(ERROR_INVALID_PARAMETER
);
2024 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2025 SetLastError(ERROR_INVALID_PARAMETER
);
2028 if (DeviceInterfaceDetailData
!= NULL
)
2030 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2031 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2032 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2033 if (!DeviceInterfaceDetailDataW
)
2035 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2038 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2040 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2041 ret
= SetupDiGetDeviceInterfaceDetailW(
2043 DeviceInterfaceData
,
2044 DeviceInterfaceDetailDataW
,
2048 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2049 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2051 *RequiredSize
= sizeA
;
2052 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2054 if (!WideCharToMultiByte(
2056 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2057 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2064 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2067 TRACE("Returning %d\n", ret
);
2071 /***********************************************************************
2072 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2074 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2075 HDEVINFO DeviceInfoSet
,
2076 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2077 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2078 DWORD DeviceInterfaceDetailDataSize
,
2079 PDWORD RequiredSize
,
2080 PSP_DEVINFO_DATA DeviceInfoData
)
2084 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2085 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2086 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2088 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2089 SetLastError(ERROR_INVALID_PARAMETER
);
2090 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2091 SetLastError(ERROR_INVALID_HANDLE
);
2092 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2093 SetLastError(ERROR_INVALID_HANDLE
);
2094 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2095 SetLastError(ERROR_INVALID_USER_BUFFER
);
2096 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2097 SetLastError(ERROR_INVALID_USER_BUFFER
);
2098 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2099 SetLastError(ERROR_INVALID_USER_BUFFER
);
2100 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2101 SetLastError(ERROR_INVALID_PARAMETER
);
2102 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2103 SetLastError(ERROR_INVALID_PARAMETER
);
2106 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2107 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2108 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2109 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2111 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2113 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2115 *RequiredSize
= sizeRequired
;
2119 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2120 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2123 memcpy(&DeviceInfoData
->ClassGuid
,
2124 &deviceInterface
->DeviceInfo
->ClassGuid
,
2126 DeviceInfoData
->DevInst
= 0; /* FIXME */
2127 /* Note: this appears to be dangerous, passing a private
2128 * pointer a heap-allocated datum to the caller. However, the
2129 * expected lifetime of the device data is the same as the
2130 * HDEVINFO; once that is closed, the data are no longer valid.
2132 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2138 TRACE("Returning %d\n", ret
);
2142 /***********************************************************************
2143 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2145 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2147 PSP_DEVINFO_DATA DeviceInfoData
,
2149 PDWORD PropertyRegDataType
,
2150 PBYTE PropertyBuffer
,
2151 DWORD PropertyBufferSize
,
2152 PDWORD RequiredSize
)
2155 BOOL bIsStringProperty
;
2157 DWORD RequiredSizeA
, RequiredSizeW
;
2158 DWORD PropertyBufferSizeW
;
2159 PBYTE PropertyBufferW
;
2161 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2162 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2165 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2166 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2168 bResult
= SetupDiGetDeviceRegistryPropertyW(
2174 PropertyBufferSizeW
,
2177 if (bResult
|| GetLastError() == ERROR_MORE_DATA
)
2179 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2181 if (bIsStringProperty
)
2182 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2184 RequiredSizeA
= RequiredSizeW
;
2186 *RequiredSize
= RequiredSizeA
;
2187 if (PropertyRegDataType
)
2188 *PropertyRegDataType
= RegType
;
2193 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2197 if (RequiredSizeA
<= PropertyBufferSize
)
2199 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2201 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2203 /* Last error is already set by WideCharToMultiByte */
2208 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2212 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2216 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2220 /***********************************************************************
2221 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2223 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2224 HDEVINFO DeviceInfoSet
,
2225 PSP_DEVINFO_DATA DeviceInfoData
,
2227 PDWORD PropertyRegDataType
,
2228 PBYTE PropertyBuffer
,
2229 DWORD PropertyBufferSize
,
2230 PDWORD RequiredSize
)
2232 HKEY hEnumKey
, hKey
;
2236 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2237 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2240 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2241 SetLastError(ERROR_INVALID_HANDLE
);
2242 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2243 SetLastError(ERROR_INVALID_HANDLE
);
2244 else if (!DeviceInfoData
)
2245 SetLastError(ERROR_INVALID_PARAMETER
);
2246 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2247 SetLastError(ERROR_INVALID_USER_BUFFER
);
2248 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2249 SetLastError(ERROR_INVALID_PARAMETER
);
2252 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2253 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2257 case SPDRP_CAPABILITIES
:
2259 case SPDRP_CLASSGUID
:
2260 case SPDRP_COMPATIBLEIDS
:
2261 case SPDRP_CONFIGFLAGS
:
2262 case SPDRP_DEVICEDESC
:
2264 case SPDRP_FRIENDLYNAME
:
2265 case SPDRP_HARDWAREID
:
2266 case SPDRP_LOCATION_INFORMATION
:
2267 case SPDRP_LOWERFILTERS
:
2269 case SPDRP_SECURITY
:
2271 case SPDRP_UI_NUMBER
:
2272 case SPDRP_UPPERFILTERS
:
2274 LPCWSTR RegistryPropertyName
;
2279 case SPDRP_CAPABILITIES
:
2280 RegistryPropertyName
= L
"Capabilities"; break;
2282 RegistryPropertyName
= L
"Class"; break;
2283 case SPDRP_CLASSGUID
:
2284 RegistryPropertyName
= L
"ClassGUID"; break;
2285 case SPDRP_COMPATIBLEIDS
:
2286 RegistryPropertyName
= L
"CompatibleIDs"; break;
2287 case SPDRP_CONFIGFLAGS
:
2288 RegistryPropertyName
= L
"ConfigFlags"; break;
2289 case SPDRP_DEVICEDESC
:
2290 RegistryPropertyName
= L
"DeviceDesc"; break;
2292 RegistryPropertyName
= L
"Driver"; break;
2293 case SPDRP_FRIENDLYNAME
:
2294 RegistryPropertyName
= L
"FriendlyName"; break;
2295 case SPDRP_HARDWAREID
:
2296 RegistryPropertyName
= L
"HardwareID"; break;
2297 case SPDRP_LOCATION_INFORMATION
:
2298 RegistryPropertyName
= L
"LocationInformation"; break;
2299 case SPDRP_LOWERFILTERS
:
2300 RegistryPropertyName
= L
"LowerFilters"; break;
2302 RegistryPropertyName
= L
"Mfg"; break;
2303 case SPDRP_SECURITY
:
2304 RegistryPropertyName
= L
"Security"; break;
2306 RegistryPropertyName
= L
"Service"; break;
2307 case SPDRP_UI_NUMBER
:
2308 RegistryPropertyName
= L
"UINumber"; break;
2309 case SPDRP_UPPERFILTERS
:
2310 RegistryPropertyName
= L
"UpperFilters"; break;
2312 /* Should not happen */
2313 RegistryPropertyName
= NULL
; break;
2316 /* Open registry key name */
2321 KEY_ENUMERATE_SUB_KEYS
,
2323 if (rc
!= ERROR_SUCCESS
)
2334 RegCloseKey(hEnumKey
);
2335 if (rc
!= ERROR_SUCCESS
)
2340 /* Read registry entry */
2341 BufferSize
= PropertyBufferSize
;
2342 rc
= RegQueryValueExW(
2344 RegistryPropertyName
,
2345 NULL
, /* Reserved */
2346 PropertyRegDataType
,
2350 *RequiredSize
= BufferSize
;
2351 if (rc
== ERROR_SUCCESS
)
2359 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2361 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2363 if (PropertyRegDataType
)
2364 *PropertyRegDataType
= REG_SZ
;
2366 *RequiredSize
= required
;
2367 if (PropertyBufferSize
>= required
)
2369 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2373 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2377 /*case SPDRP_BUSTYPEGUID:
2378 case SPDRP_LEGACYBUSTYPE:
2379 case SPDRP_BUSNUMBER:
2380 case SPDRP_ENUMERATOR_NAME:
2381 case SPDRP_SECURITY_SDS:
2383 case SPDRP_EXCLUSIVE:
2384 case SPDRP_CHARACTERISTICS:
2386 case SPDRP_UI_NUMBER_DESC_FORMAT:
2387 case SPDRP_DEVICE_POWER_DATA:*/
2388 #if (WINVER >= 0x501)
2389 /*case SPDRP_REMOVAL_POLICY:
2390 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2391 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2392 case SPDRP_INSTALL_STATE:*/
2397 FIXME("Property 0x%lx not implemented\n", Property
);
2398 SetLastError(ERROR_NOT_SUPPORTED
);
2403 TRACE("Returning %d\n", ret
);
2408 /***********************************************************************
2409 * SetupDiInstallClassA (SETUPAPI.@)
2411 BOOL WINAPI
SetupDiInstallClassA(
2417 UNICODE_STRING FileNameW
;
2420 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2422 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2426 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2428 RtlFreeUnicodeString(&FileNameW
);
2433 static HKEY
CreateClassKey(HINF hInf
)
2435 WCHAR FullBuffer
[MAX_PATH
];
2436 WCHAR Buffer
[MAX_PATH
];
2441 if (!SetupGetLineTextW(NULL
,
2449 return INVALID_HANDLE_VALUE
;
2452 lstrcpyW(FullBuffer
, ControlClass
);
2453 lstrcatW(FullBuffer
, Buffer
);
2456 if (!SetupGetLineTextW(NULL
,
2464 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2465 return INVALID_HANDLE_VALUE
;
2468 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2472 REG_OPTION_NON_VOLATILE
,
2478 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2479 return INVALID_HANDLE_VALUE
;
2482 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2487 RequiredSize
* sizeof(WCHAR
)))
2489 RegCloseKey(hClassKey
);
2490 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2491 return INVALID_HANDLE_VALUE
;
2497 /***********************************************************************
2498 * SetupDiInstallClassW (SETUPAPI.@)
2500 BOOL WINAPI
SetupDiInstallClassW(
2506 WCHAR SectionName
[MAX_PATH
];
2507 DWORD SectionNameLength
= 0;
2509 BOOL bFileQueueCreated
= FALSE
;
2512 FIXME("not fully implemented\n");
2514 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2516 SetLastError(ERROR_INVALID_PARAMETER
);
2520 /* Open the .inf file */
2521 hInf
= SetupOpenInfFileW(InfFileName
,
2525 if (hInf
== INVALID_HANDLE_VALUE
)
2531 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2532 hClassKey
= CreateClassKey(hInf
);
2533 if (hClassKey
== INVALID_HANDLE_VALUE
)
2535 SetupCloseInfFile(hInf
);
2541 /* Try to append a layout file */
2543 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2546 /* Retrieve the actual section name */
2547 SetupDiGetActualSectionToInstallW(hInf
,
2555 if (!(Flags
& DI_NOVCP
))
2557 FileQueue
= SetupOpenFileQueue();
2558 if (FileQueue
== INVALID_HANDLE_VALUE
)
2560 SetupCloseInfFile(hInf
);
2561 RegCloseKey(hClassKey
);
2565 bFileQueueCreated
= TRUE
;
2570 SetupInstallFromInfSectionW(NULL
,
2579 INVALID_HANDLE_VALUE
,
2582 /* FIXME: More code! */
2584 if (bFileQueueCreated
)
2585 SetupCloseFileQueue(FileQueue
);
2587 SetupCloseInfFile(hInf
);
2589 RegCloseKey(hClassKey
);
2594 /***********************************************************************
2595 * SetupDiOpenClassRegKey (SETUPAPI.@)
2597 HKEY WINAPI
SetupDiOpenClassRegKey(
2598 const GUID
* ClassGuid
,
2601 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2602 DIOCR_INSTALLER
, NULL
, NULL
);
2606 /***********************************************************************
2607 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2609 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2610 const GUID
* ClassGuid
,
2616 PWSTR MachineNameW
= NULL
;
2623 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2624 if (MachineNameW
== NULL
)
2625 return INVALID_HANDLE_VALUE
;
2628 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2629 Flags
, MachineNameW
, Reserved
);
2632 MyFree(MachineNameW
);
2638 /***********************************************************************
2639 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2641 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2642 const GUID
* ClassGuid
,
2648 LPWSTR lpGuidString
;
2649 LPWSTR lpFullGuidString
;
2657 if (Flags
== DIOCR_INSTALLER
)
2659 lpKeyName
= ControlClass
;
2661 else if (Flags
== DIOCR_INTERFACE
)
2663 lpKeyName
= DeviceClasses
;
2667 ERR("Invalid Flags parameter!\n");
2668 SetLastError(ERROR_INVALID_PARAMETER
);
2669 return INVALID_HANDLE_VALUE
;
2672 if (MachineName
!= NULL
)
2674 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2675 if (rc
!= ERROR_SUCCESS
)
2678 return INVALID_HANDLE_VALUE
;
2682 HKLM
= HKEY_LOCAL_MACHINE
;
2684 rc
= RegOpenKeyExW(HKLM
,
2689 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2690 if (rc
!= ERROR_SUCCESS
)
2693 return INVALID_HANDLE_VALUE
;
2696 if (ClassGuid
== NULL
)
2699 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2701 SetLastError(ERROR_GEN_FAILURE
);
2702 RegCloseKey(hClassesKey
);
2703 return INVALID_HANDLE_VALUE
;
2706 dwLength
= lstrlenW(lpGuidString
);
2707 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2708 if (!lpFullGuidString
)
2710 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2711 RpcStringFreeW(&lpGuidString
);
2712 return INVALID_HANDLE_VALUE
;
2714 lpFullGuidString
[0] = '{';
2715 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2716 lpFullGuidString
[dwLength
+ 1] = '}';
2717 lpFullGuidString
[dwLength
+ 2] = '\0';
2718 RpcStringFreeW(&lpGuidString
);
2720 rc
= RegOpenKeyExW(hClassesKey
,
2725 if (rc
!= ERROR_SUCCESS
)
2728 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2729 RegCloseKey(hClassesKey
);
2730 return INVALID_HANDLE_VALUE
;
2733 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2734 RegCloseKey(hClassesKey
);
2739 /***********************************************************************
2740 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2742 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2743 HDEVINFO DeviceInfoSet
,
2746 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2748 FIXME("%p %s %08lx %p\n",
2749 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2753 /***********************************************************************
2754 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2756 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2757 HDEVINFO DeviceInfoSet
,
2760 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2762 LPWSTR DevicePathW
= NULL
;
2765 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2767 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2768 if (DevicePathW
== NULL
)
2771 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2772 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2774 MyFree(DevicePathW
);
2779 /***********************************************************************
2780 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2782 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2783 HDEVINFO DeviceInfoSet
,
2784 PSP_DEVINFO_DATA DeviceInfoData
,
2785 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2786 DWORD ClassInstallParamsSize
)
2788 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2789 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2795 IN PWSTR InstallerName
,
2796 OUT HMODULE
* ModulePointer
,
2797 OUT PVOID
* FunctionPointer
)
2799 HMODULE hModule
= NULL
;
2800 LPSTR FunctionNameA
= NULL
;
2804 *ModulePointer
= NULL
;
2805 *FunctionPointer
= NULL
;
2807 Comma
= strchrW(InstallerName
, ',');
2810 rc
= ERROR_INVALID_PARAMETER
;
2814 /* W->A conversion for function name */
2815 FunctionNameA
= UnicodeToMultiByte(Comma
+ 1, CP_ACP
);
2818 rc
= GetLastError();
2824 hModule
= LoadLibraryW(InstallerName
);
2828 rc
= GetLastError();
2832 /* Search function */
2833 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
2834 if (!*FunctionPointer
)
2836 rc
= GetLastError();
2840 *ModulePointer
= hModule
;
2844 if (rc
!= ERROR_SUCCESS
&& hModule
)
2845 FreeLibrary(hModule
);
2846 MyFree(FunctionNameA
);
2851 FreeFunctionPointer(
2852 IN HMODULE ModulePointer
,
2853 IN PVOID FunctionPointer
)
2855 if (ModulePointer
== NULL
)
2856 return ERROR_SUCCESS
;
2857 if (FreeLibrary(ModulePointer
))
2858 return ERROR_SUCCESS
;
2860 return GetLastError();
2863 /***********************************************************************
2864 * SetupDiCallClassInstaller (SETUPAPI.@)
2866 BOOL WINAPI
SetupDiCallClassInstaller(
2867 IN DI_FUNCTION InstallFunction
,
2868 IN HDEVINFO DeviceInfoSet
,
2869 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2873 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2876 SetLastError(ERROR_INVALID_PARAMETER
);
2877 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2878 SetLastError(ERROR_INVALID_HANDLE
);
2879 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2880 SetLastError(ERROR_INVALID_HANDLE
);
2881 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2882 SetLastError(ERROR_INVALID_HANDLE
);
2883 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2884 SetLastError(ERROR_INVALID_USER_BUFFER
);
2887 #define CLASS_COINSTALLER 0x1
2888 #define DEVICE_COINSTALLER 0x2
2889 #define CLASS_INSTALLER 0x4
2890 UCHAR CanHandle
= 0;
2891 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2893 switch (InstallFunction
)
2895 case DIF_ALLOW_INSTALL
:
2896 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2898 case DIF_DESTROYPRIVATEDATA
:
2899 CanHandle
= CLASS_INSTALLER
;
2901 case DIF_INSTALLDEVICE
:
2902 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2903 DefaultHandler
= SetupDiInstallDevice
;
2905 case DIF_INSTALLDEVICEFILES
:
2906 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2907 DefaultHandler
= SetupDiInstallDriverFiles
;
2909 case DIF_INSTALLINTERFACES
:
2910 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2911 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2913 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2914 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2916 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2917 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2919 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2920 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2922 case DIF_REGISTER_COINSTALLERS
:
2923 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2924 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2926 case DIF_SELECTBESTCOMPATDRV
:
2927 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2928 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2931 FIXME("Install function %ld not implemented\n", InstallFunction
);
2932 SetLastError(ERROR_INVALID_PARAMETER
);
2937 LIST_ENTRY ClassCoInstallersListHead
;
2938 LIST_ENTRY DeviceCoInstallersListHead
;
2939 HMODULE ClassInstallerLibrary
= NULL
;
2940 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2941 COINSTALLER_CONTEXT_DATA Context
;
2942 PLIST_ENTRY ListEntry
;
2944 DWORD dwRegType
, dwLength
;
2945 DWORD rc
= NO_ERROR
;
2947 InitializeListHead(&ClassCoInstallersListHead
);
2948 InitializeListHead(&DeviceCoInstallersListHead
);
2950 if (CanHandle
& DEVICE_COINSTALLER
)
2952 FIXME("Doesn't use Device co-installers at the moment\n");
2954 if (CanHandle
& CLASS_COINSTALLER
)
2958 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2962 if (rc
== ERROR_SUCCESS
)
2964 LPWSTR lpGuidString
;
2965 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2967 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
2968 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2970 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2971 if (KeyBuffer
!= NULL
)
2973 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2974 if (rc
== ERROR_SUCCESS
)
2977 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2979 /* Add coinstaller to ClassCoInstallersListHead list */
2980 FIXME("Class coinstaller is '%S'. UNIMPLEMENTED!\n", ptr
);
2983 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2986 RpcStringFreeW(&lpGuidString
);
2991 if (CanHandle
& CLASS_INSTALLER
)
2993 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2994 if (hKey
!= INVALID_HANDLE_VALUE
)
2996 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2997 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2999 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3000 if (KeyBuffer
!= NULL
)
3002 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3003 if (rc
== ERROR_SUCCESS
)
3005 /* Get ClassInstaller function pointer */
3006 rc
= GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
);
3008 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3015 /* Call Class co-installers */
3016 Context
.PostProcessing
= FALSE
;
3018 ListEntry
= ClassCoInstallersListHead
.Flink
;
3019 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3021 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3022 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3023 coinstaller
->PrivateData
= Context
.PrivateData
;
3024 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3026 coinstaller
->DoPostProcessing
= TRUE
;
3029 ListEntry
= ListEntry
->Flink
;
3032 /* Call Device co-installers */
3033 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3034 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3036 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3037 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3038 coinstaller
->PrivateData
= Context
.PrivateData
;
3039 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3041 coinstaller
->DoPostProcessing
= TRUE
;
3044 ListEntry
= ListEntry
->Flink
;
3047 /* Call Class installer */
3050 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3051 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3054 rc
= ERROR_DI_DO_DEFAULT
;
3056 /* Call default handler */
3057 if (rc
== ERROR_DI_DO_DEFAULT
)
3059 if (DefaultHandler
/*FIXME && DI_NODI_DEFAULTACTION not set */)
3061 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3064 rc
= GetLastError();
3070 /* Call Class co-installers that required postprocessing */
3071 Context
.PostProcessing
= TRUE
;
3072 ListEntry
= ClassCoInstallersListHead
.Flink
;
3073 while (ListEntry
!= &ClassCoInstallersListHead
)
3075 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3076 if (coinstaller
->DoPostProcessing
)
3078 Context
.InstallResult
= rc
;
3079 Context
.PrivateData
= coinstaller
->PrivateData
;
3080 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3082 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3083 ListEntry
= ListEntry
->Flink
;
3086 /* Call Device co-installers that required postprocessing */
3087 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3088 while (ListEntry
!= &DeviceCoInstallersListHead
)
3090 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3091 if (coinstaller
->DoPostProcessing
)
3093 Context
.InstallResult
= rc
;
3094 Context
.PrivateData
= coinstaller
->PrivateData
;
3095 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3097 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3098 ListEntry
= ListEntry
->Flink
;
3101 /* Free allocated memory */
3102 while (!IsListEmpty(&ClassCoInstallersListHead
))
3104 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3105 HeapFree(GetProcessHeap(), 0, ListEntry
);
3107 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3109 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3110 HeapFree(GetProcessHeap(), 0, ListEntry
);
3113 ret
= (rc
== NO_ERROR
);
3117 TRACE("Returning %d\n", ret
);
3121 /***********************************************************************
3122 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3124 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3125 IN HDEVINFO DeviceInfoSet
,
3126 IN PSP_DEVINFO_DATA DeviceInfoData
,
3127 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3129 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3132 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3134 if (DeviceInstallParams
== NULL
)
3135 SetLastError(ERROR_INVALID_PARAMETER
);
3136 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3137 SetLastError(ERROR_INVALID_USER_BUFFER
);
3140 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3141 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3145 /* Do W->A conversion */
3147 DeviceInstallParams
,
3148 &deviceInstallParamsW
,
3149 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3150 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3151 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3153 DeviceInstallParams
->DriverPath
[0] = '\0';
3159 TRACE("Returning %d\n", ret
);
3163 /***********************************************************************
3164 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3166 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3167 IN HDEVINFO DeviceInfoSet
,
3168 IN PSP_DEVINFO_DATA DeviceInfoData
,
3169 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3171 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3175 /***********************************************************************
3176 * SetupDiCreateDevRegKey (SETUPAPI.@)
3178 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3179 IN HDEVINFO DeviceInfoSet
,
3180 IN PSP_DEVINFO_DATA DeviceInfoData
,
3184 IN HINF InfHandle OPTIONAL
,
3185 IN PCWSTR InfSectionName OPTIONAL
)
3187 struct DeviceInfoSet
*list
;
3188 HKEY ret
= INVALID_HANDLE_VALUE
;
3190 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3191 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3194 SetLastError(ERROR_INVALID_HANDLE
);
3195 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3196 SetLastError(ERROR_INVALID_HANDLE
);
3197 else if (!DeviceInfoData
)
3198 SetLastError(ERROR_INVALID_PARAMETER
);
3199 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3200 SetLastError(ERROR_INVALID_USER_BUFFER
);
3201 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3202 SetLastError(ERROR_INVALID_PARAMETER
);
3203 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3204 SetLastError(ERROR_INVALID_PARAMETER
);
3205 else if (InfHandle
&& !InfSectionName
)
3206 SetLastError(ERROR_INVALID_PARAMETER
);
3207 else if (!InfHandle
&& InfSectionName
)
3208 SetLastError(ERROR_INVALID_PARAMETER
);
3211 LPWSTR lpGuidString
= NULL
;
3212 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3213 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3214 DWORD Index
; /* Index used in the DriverKey name */
3216 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3217 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3218 HKEY hKey
= INVALID_HANDLE_VALUE
;
3220 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3222 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3226 if (KeyType
== DIREG_DEV
)
3228 FIXME("DIREG_DEV case unimplemented\n");
3230 else /* KeyType == DIREG_DRV */
3232 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3234 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3235 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3238 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3241 wcscpy(DriverKey
, L
"{");
3242 wcscat(DriverKey
, lpGuidString
);
3243 wcscat(DriverKey
, L
"}\\");
3244 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3245 rc
= RegOpenKeyExW(list
->HKLM
,
3250 if (rc
!= ERROR_SUCCESS
)
3256 /* Try all values for Index between 0 and 9999 */
3258 while (Index
<= 9999)
3261 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3262 rc
= RegCreateKeyEx(hClassKey
,
3266 REG_OPTION_NON_VOLATILE
,
3267 KEY_READ
| KEY_WRITE
,
3271 if (rc
!= ERROR_SUCCESS
)
3276 if (Disposition
== REG_CREATED_NEW_KEY
)
3279 hKey
= INVALID_HANDLE_VALUE
;
3284 /* Unable to create more than 9999 devices within the same class */
3285 SetLastError(ERROR_GEN_FAILURE
);
3289 /* Open device key, to write Driver value */
3290 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3291 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3293 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3294 if (rc
!= ERROR_SUCCESS
)
3301 /* Do installation of the specified section */
3304 FIXME("Need to install section %s in file %p\n",
3305 debugstr_w(InfSectionName
), InfHandle
);
3311 RpcStringFreeW(&lpGuidString
);
3312 HeapFree(GetProcessHeap(), 0, DriverKey
);
3313 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3314 RegCloseKey(hClassKey
);
3315 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3316 RegCloseKey(hDeviceKey
);
3317 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3321 TRACE("Returning 0x%p\n", ret
);
3325 /***********************************************************************
3326 * SetupDiOpenDevRegKey (SETUPAPI.@)
3328 HKEY WINAPI
SetupDiOpenDevRegKey(
3329 HDEVINFO DeviceInfoSet
,
3330 PSP_DEVINFO_DATA DeviceInfoData
,
3336 struct DeviceInfoSet
*list
;
3337 HKEY ret
= INVALID_HANDLE_VALUE
;
3339 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3340 Scope
, HwProfile
, KeyType
, samDesired
);
3343 SetLastError(ERROR_INVALID_HANDLE
);
3344 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3345 SetLastError(ERROR_INVALID_HANDLE
);
3346 else if (!DeviceInfoData
)
3347 SetLastError(ERROR_INVALID_PARAMETER
);
3348 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3349 SetLastError(ERROR_INVALID_USER_BUFFER
);
3350 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3351 SetLastError(ERROR_INVALID_PARAMETER
);
3352 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3353 SetLastError(ERROR_INVALID_PARAMETER
);
3356 HKEY hKey
= INVALID_HANDLE_VALUE
;
3357 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3358 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3359 LPWSTR DriverKey
= NULL
;
3364 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3366 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3368 else /* Scope == DICS_FLAG_GLOBAL */
3374 KEY_ENUMERATE_SUB_KEYS
,
3376 if (rc
!= ERROR_SUCCESS
)
3383 deviceInfo
->DeviceName
,
3385 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3387 RegCloseKey(hRootKey
);
3388 hRootKey
= INVALID_HANDLE_VALUE
;
3389 if (rc
!= ERROR_SUCCESS
)
3394 if (KeyType
== DIREG_DEV
)
3396 /* We're done. Just return the hKey handle */
3400 /* Read the 'Driver' key */
3401 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3402 if (rc
!= ERROR_SUCCESS
)
3407 if (dwRegType
!= REG_SZ
)
3409 SetLastError(ERROR_GEN_FAILURE
);
3412 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3415 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3418 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3419 if (rc
!= ERROR_SUCCESS
)
3425 hKey
= INVALID_HANDLE_VALUE
;
3426 /* Need to open the driver key */
3431 KEY_ENUMERATE_SUB_KEYS
,
3433 if (rc
!= ERROR_SUCCESS
)
3444 if (rc
!= ERROR_SUCCESS
)
3452 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3453 RegCloseKey(hRootKey
);
3454 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3458 TRACE("Returning 0x%p\n", ret
);
3462 /***********************************************************************
3463 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3465 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3466 HDEVINFO DeviceInfoSet
,
3468 CONST GUID
*ClassGuid
,
3469 PCSTR DeviceDescription
,
3471 DWORD CreationFlags
,
3472 PSP_DEVINFO_DATA DeviceInfoData
)
3474 LPWSTR DeviceNameW
= NULL
;
3475 LPWSTR DeviceDescriptionW
= NULL
;
3482 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3483 if (DeviceNameW
== NULL
) return FALSE
;
3485 if (DeviceDescription
)
3487 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3488 if (DeviceDescriptionW
== NULL
)
3490 if (DeviceNameW
) MyFree(DeviceNameW
);
3495 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3496 ClassGuid
, DeviceDescriptionW
,
3497 hwndParent
, CreationFlags
,
3500 if (DeviceNameW
) MyFree(DeviceNameW
);
3501 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3506 /***********************************************************************
3507 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3509 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3510 HDEVINFO DeviceInfoSet
,
3512 CONST GUID
*ClassGuid
,
3513 PCWSTR DeviceDescription
,
3515 DWORD CreationFlags
,
3516 PSP_DEVINFO_DATA DeviceInfoData
)
3518 struct DeviceInfoSet
*list
;
3521 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3522 debugstr_guid(ClassGuid
), DeviceDescription
,
3523 hwndParent
, CreationFlags
, DeviceInfoData
);
3526 SetLastError(ERROR_INVALID_HANDLE
);
3527 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3528 SetLastError(ERROR_INVALID_HANDLE
);
3529 else if (!ClassGuid
)
3530 SetLastError(ERROR_INVALID_PARAMETER
);
3531 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3532 SetLastError(ERROR_CLASS_MISMATCH
);
3533 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3535 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3536 SetLastError(ERROR_INVALID_PARAMETER
);
3540 SP_DEVINFO_DATA DevInfo
;
3542 if (CreationFlags
& DICD_GENERATE_ID
)
3544 /* Generate a new unique ID for this device */
3545 SetLastError(ERROR_GEN_FAILURE
);
3546 FIXME("not implemented\n");
3550 /* Device name is fully qualified. Try to open it */
3553 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3554 rc
= SetupDiOpenDeviceInfoW(
3557 NULL
, /* hwndParent */
3558 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3563 /* SetupDiOpenDeviceInfoW has already added
3564 * the device info to the device info set
3566 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3568 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3570 struct DeviceInfoElement
*deviceInfo
;
3572 /* FIXME: ClassGuid can be NULL */
3573 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3575 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3577 if (!DeviceInfoData
)
3581 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3583 SetLastError(ERROR_INVALID_USER_BUFFER
);
3587 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3588 DeviceInfoData
->DevInst
= 0; /* FIXME */
3589 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3598 TRACE("Returning %d\n", ret
);
3602 /***********************************************************************
3603 * Helper functions for SetupDiBuildDriverInfoList
3607 IN PLIST_ENTRY DriverListHead
,
3608 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3609 IN LPGUID ClassGuid
,
3610 IN INFCONTEXT ContextDevice
,
3612 IN LPCWSTR ProviderName
,
3613 IN LPCWSTR ManufacturerName
,
3614 IN LPCWSTR MatchingId
,
3615 FILETIME DriverDate
,
3616 DWORDLONG DriverVersion
,
3619 struct DriverInfoElement
*driverInfo
= NULL
;
3620 DWORD RequiredSize
= 128; /* Initial buffer size */
3621 BOOL Result
= FALSE
;
3622 PLIST_ENTRY PreviousEntry
;
3623 LPWSTR DeviceDescription
= NULL
;
3624 LPWSTR InfInstallSection
= NULL
;
3627 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3630 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3633 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3635 /* Fill InfSection field */
3636 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3637 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3639 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3640 driverInfo
->InfSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3641 if (!driverInfo
->InfSection
)
3643 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3646 Result
= SetupGetStringFieldW(
3649 driverInfo
->InfSection
, RequiredSize
,
3655 /* Copy InfFile information */
3656 driverInfo
->InfPath
= HeapAlloc(GetProcessHeap(), 0, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3657 if (!driverInfo
->InfPath
)
3659 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3662 RtlCopyMemory(driverInfo
->InfPath
, InfFile
, (wcslen(InfFile
) + 1) * sizeof(WCHAR
));
3664 /* Copy MatchingId information */
3665 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3666 if (!driverInfo
->MatchingId
)
3668 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3671 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3673 /* Get device description */
3675 RequiredSize
= 128; /* Initial buffer size */
3676 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3677 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3679 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3680 DeviceDescription
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3681 if (!DeviceDescription
)
3683 Result
= SetupGetStringFieldW(
3685 0, /* Field index */
3686 DeviceDescription
, RequiredSize
,
3692 /* Get inf install section */
3694 RequiredSize
= 128; /* Initial buffer size */
3695 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3696 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3698 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3699 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3700 if (!InfInstallSection
)
3702 Result
= SetupGetStringFieldW(
3704 1, /* Field index */
3705 InfInstallSection
, RequiredSize
,
3711 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3712 DeviceDescription
, InfFile
, InfInstallSection
, Rank
);
3714 driverInfo
->DriverRank
= Rank
;
3715 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3716 driverInfo
->Info
.DriverType
= DriverType
;
3717 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3718 wcsncpy(driverInfo
->Info
.Description
, DeviceDescription
, LINE_LEN
- 1);
3719 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3720 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3721 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3724 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3725 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3728 driverInfo
->Info
.ProviderName
[0] = '\0';
3729 driverInfo
->Info
.DriverDate
= DriverDate
;
3730 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3732 /* Insert current driver in driver list, according to its rank */
3733 PreviousEntry
= DriverListHead
->Flink
;
3734 while (PreviousEntry
!= DriverListHead
)
3736 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3738 /* Insert before the current item */
3739 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3743 if (PreviousEntry
== DriverListHead
)
3745 /* Insert at the end of the list */
3746 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3756 HeapFree(GetProcessHeap(), 0, driverInfo
->InfPath
);
3757 HeapFree(GetProcessHeap(), 0, driverInfo
->InfSection
);
3758 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
3760 HeapFree(GetProcessHeap(), 0, driverInfo
);
3762 HeapFree(GetProcessHeap(), 0, DeviceDescription
);
3763 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3769 GetVersionInformationFromInfFile(
3771 OUT LPGUID ClassGuid
,
3772 OUT LPWSTR
* pProviderName
,
3773 OUT FILETIME
* DriverDate
,
3774 OUT DWORDLONG
* DriverVersion
)
3777 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3778 LPWSTR DriverVer
= NULL
;
3779 LPWSTR ProviderName
= NULL
;
3780 LPWSTR pComma
; /* Points into DriverVer */
3781 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
3782 SYSTEMTIME SystemTime
;
3784 BOOL ret
= FALSE
; /* Final result */
3786 /* Get class Guid */
3787 if (!SetupGetLineTextW(
3790 L
"Version", L
"ClassGUID",
3791 guidW
, sizeof(guidW
),
3792 NULL
/* Required size */))
3796 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3797 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3799 SetLastError(ERROR_GEN_FAILURE
);
3803 /* Get provider name */
3804 Result
= SetupGetLineTextW(
3806 hInf
, L
"Version", L
"Provider",
3811 /* We know know the needed buffer size */
3812 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3815 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3818 Result
= SetupGetLineTextW(
3820 hInf
, L
"Version", L
"Provider",
3821 ProviderName
, RequiredSize
,
3826 *pProviderName
= ProviderName
;
3828 /* Read the "DriverVer" value */
3829 Result
= SetupGetLineTextW(
3831 hInf
, L
"Version", L
"DriverVer",
3836 /* We know know the needed buffer size */
3837 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3840 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3843 Result
= SetupGetLineTextW(
3845 hInf
, L
"Version", L
"DriverVer",
3846 DriverVer
, RequiredSize
,
3852 /* Get driver date and driver version, by analyzing the "DriverVer" value */
3853 pComma
= wcschr(DriverVer
, ',');
3856 *pComma
= UNICODE_NULL
;
3857 pVersion
= pComma
+ 1;
3859 /* Get driver date version. Invalid date = 00/00/00 */
3860 memset(DriverDate
, 0, sizeof(FILETIME
));
3861 if (wcslen(DriverVer
) == 10
3862 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
3863 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
3865 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
3866 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
3867 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
3868 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
3869 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
3870 SystemTimeToFileTime(&SystemTime
, DriverDate
);
3872 /* Get driver version. Invalid version = 0.0.0.0 */
3874 /* FIXME: use pVersion to fill DriverVersion variable */
3880 HeapFree(GetProcessHeap(), 0, ProviderName
);
3881 HeapFree(GetProcessHeap(), 0, DriverVer
);
3883 TRACE("Returning %d\n", ret
);
3887 /***********************************************************************
3888 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3891 SetupDiBuildDriverInfoList(
3892 IN HDEVINFO DeviceInfoSet
,
3893 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3894 IN DWORD DriverType
)
3896 struct DeviceInfoSet
*list
;
3897 PVOID Buffer
= NULL
;
3898 HINF hInf
= INVALID_HANDLE_VALUE
;
3899 LPWSTR ProviderName
= NULL
;
3900 LPWSTR ManufacturerName
= NULL
;
3901 LPWSTR ManufacturerSection
= NULL
;
3902 LPWSTR HardwareIDs
= NULL
;
3903 LPWSTR CompatibleIDs
= NULL
;
3904 FILETIME DriverDate
;
3905 DWORDLONG DriverVersion
= 0;
3909 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3912 SetLastError(ERROR_INVALID_HANDLE
);
3913 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3914 SetLastError(ERROR_INVALID_HANDLE
);
3915 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3916 SetLastError(ERROR_INVALID_HANDLE
);
3917 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3918 SetLastError(ERROR_INVALID_PARAMETER
);
3919 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3920 SetLastError(ERROR_INVALID_PARAMETER
);
3921 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3922 SetLastError(ERROR_INVALID_PARAMETER
);
3923 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3924 SetLastError(ERROR_INVALID_USER_BUFFER
);
3927 BOOL Result
= FALSE
;
3929 if (DriverType
== SPDIT_COMPATDRIVER
)
3931 /* Get hardware IDs list */
3933 RequiredSize
= 512; /* Initial buffer size */
3934 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3935 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3937 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3938 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3941 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3944 Result
= SetupDiGetDeviceRegistryPropertyW(
3956 /* Get compatible IDs list */
3958 RequiredSize
= 512; /* Initial buffer size */
3959 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3960 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3962 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3963 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3966 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3969 Result
= SetupDiGetDeviceRegistryPropertyW(
3972 SPDRP_COMPATIBLEIDS
,
3974 (PBYTE
)CompatibleIDs
,
3977 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3979 /* No compatible ID for this device */
3980 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
3981 CompatibleIDs
= NULL
;
3989 /* Enumerate .inf files */
3991 RequiredSize
= 32768; /* Initial buffer size */
3992 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3993 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3995 HeapFree(GetProcessHeap(), 0, Buffer
);
3996 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4000 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4003 Result
= SetupGetInfFileListW(
4004 NULL
, /* Directory path */
4006 Buffer
, RequiredSize
,
4013 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4015 INFCONTEXT ContextManufacturer
, ContextDevice
;
4017 TRACE("Opening file %S\n", filename
);
4019 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
4020 if (hInf
== INVALID_HANDLE_VALUE
)
4023 if (!GetVersionInformationFromInfFile(
4030 SetupCloseInfFile(hInf
);
4031 hInf
= INVALID_HANDLE_VALUE
;
4035 if (DriverType
== SPDIT_CLASSDRIVER
)
4037 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4038 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4044 /* Get the manufacturers list */
4045 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4048 Result
= SetupGetStringFieldW(
4049 &ContextManufacturer
,
4050 0, /* Field index */
4055 /* We got the needed size for the buffer */
4056 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4057 if (!ManufacturerName
)
4059 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4062 Result
= SetupGetStringFieldW(
4063 &ContextManufacturer
,
4064 0, /* Field index */
4065 ManufacturerName
, RequiredSize
,
4068 Result
= SetupGetStringFieldW(
4069 &ContextManufacturer
,
4070 1, /* Field index */
4075 /* We got the needed size for the buffer */
4076 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4077 if (!ManufacturerSection
)
4079 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4082 Result
= SetupGetStringFieldW(
4083 &ContextManufacturer
,
4084 1, /* Field index */
4085 ManufacturerSection
, RequiredSize
,
4089 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4090 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4093 if (DriverType
== SPDIT_CLASSDRIVER
)
4095 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4096 if (!AddDriverToList(
4097 &list
->DriverListHead
,
4105 DriverDate
, DriverVersion
,
4111 else /* DriverType = SPDIT_COMPATDRIVER */
4113 /* 1. Get all fields */
4114 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4118 BOOL DriverAlreadyAdded
;
4120 for (i
= 2; i
<= FieldCount
; i
++)
4122 LPWSTR DeviceId
= NULL
;
4124 RequiredSize
= 128; /* Initial buffer size */
4125 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4126 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4128 HeapFree(GetProcessHeap(), 0, DeviceId
);
4129 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4132 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4135 Result
= SetupGetStringFieldW(
4138 DeviceId
, RequiredSize
,
4143 HeapFree(GetProcessHeap(), 0, DeviceId
);
4146 DriverAlreadyAdded
= FALSE
;
4147 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4149 if (wcscmp(DeviceId
, currentId
) == 0)
4152 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4160 DriverDate
, DriverVersion
,
4161 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4162 DriverAlreadyAdded
= TRUE
;
4167 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4169 if (wcscmp(DeviceId
, currentId
) == 0)
4172 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4180 DriverDate
, DriverVersion
,
4181 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4182 DriverAlreadyAdded
= TRUE
;
4186 HeapFree(GetProcessHeap(), 0, DeviceId
);
4189 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4192 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4193 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
4194 ManufacturerName
= ManufacturerSection
= NULL
;
4195 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4200 HeapFree(GetProcessHeap(), 0, ProviderName
);
4201 ProviderName
= NULL
;
4203 SetupCloseInfFile(hInf
);
4204 hInf
= INVALID_HANDLE_VALUE
;
4215 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4216 deviceInfo
->Flags
|= DI_DIDCOMPAT
;
4219 list
->Flags
|= DI_DIDCLASS
;
4222 HeapFree(GetProcessHeap(), 0, ProviderName
);
4223 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4224 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
4225 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4226 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4227 if (hInf
!= INVALID_HANDLE_VALUE
)
4228 SetupCloseInfFile(hInf
);
4229 HeapFree(GetProcessHeap(), 0, Buffer
);
4231 TRACE("Returning %d\n", ret
);
4235 /***********************************************************************
4236 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4239 SetupDiDeleteDeviceInfo(
4240 IN HDEVINFO DeviceInfoSet
,
4241 IN PSP_DEVINFO_DATA DeviceInfoData
)
4243 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4245 FIXME("not implemented\n");
4246 SetLastError(ERROR_GEN_FAILURE
);
4251 /***********************************************************************
4252 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4255 SetupDiDestroyDriverInfoList(
4256 IN HDEVINFO DeviceInfoSet
,
4257 IN PSP_DEVINFO_DATA DeviceInfoData
,
4258 IN DWORD DriverType
)
4260 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4262 FIXME("not implemented\n");
4263 SetLastError(ERROR_GEN_FAILURE
);
4268 /***********************************************************************
4269 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4272 SetupDiOpenDeviceInfoA(
4273 IN HDEVINFO DeviceInfoSet
,
4274 IN PCSTR DeviceInstanceId
,
4275 IN HWND hwndParent OPTIONAL
,
4277 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4279 LPWSTR DeviceInstanceIdW
= NULL
;
4282 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4284 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4285 if (DeviceInstanceIdW
== NULL
)
4288 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4289 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4291 MyFree(DeviceInstanceIdW
);
4297 /***********************************************************************
4298 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4301 SetupDiOpenDeviceInfoW(
4302 IN HDEVINFO DeviceInfoSet
,
4303 IN PCWSTR DeviceInstanceId
,
4304 IN HWND hwndParent OPTIONAL
,
4306 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4308 struct DeviceInfoSet
*list
;
4309 HKEY hEnumKey
, hKey
;
4313 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4315 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4316 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4319 SetLastError(ERROR_INVALID_HANDLE
);
4320 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4321 SetLastError(ERROR_INVALID_HANDLE
);
4322 else if (!DeviceInstanceId
)
4323 SetLastError(ERROR_INVALID_PARAMETER
);
4324 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4326 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4327 SetLastError(ERROR_INVALID_PARAMETER
);
4329 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4330 SetLastError(ERROR_INVALID_USER_BUFFER
);
4333 struct DeviceInfoElement
*deviceInfo
= NULL
;
4334 /* Search if device already exists in DeviceInfoSet.
4335 * If yes, return the existing element
4336 * If no, create a new element using informations in registry
4338 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4339 while (ItemList
!= &list
->ListHead
)
4344 FIXME("not implemented\n");
4345 ItemList
= ItemList
->Flink
;
4350 /* good one found */
4355 /* Open supposed registry key */
4360 KEY_ENUMERATE_SUB_KEYS
,
4362 if (rc
!= ERROR_SUCCESS
)
4373 RegCloseKey(hEnumKey
);
4374 if (rc
!= ERROR_SUCCESS
)
4380 /* FIXME: GUID_NULL is not allowed */
4381 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
4386 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4392 if (ret
&& deviceInfo
&& DeviceInfoData
)
4394 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4395 DeviceInfoData
->DevInst
= 0; /* FIXME */
4396 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4404 /***********************************************************************
4405 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4408 SetupDiEnumDriverInfoA(
4409 IN HDEVINFO DeviceInfoSet
,
4410 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4411 IN DWORD DriverType
,
4412 IN DWORD MemberIndex
,
4413 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4415 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4418 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4419 DriverType
, MemberIndex
, DriverInfoData
);
4421 if (DriverInfoData
== NULL
)
4422 SetLastError(ERROR_INVALID_PARAMETER
);
4423 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4424 SetLastError(ERROR_INVALID_USER_BUFFER
);
4427 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4428 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4429 DriverType
, MemberIndex
, &driverInfoData2W
);
4433 /* Do W->A conversion */
4434 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4435 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4436 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4437 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4439 DriverInfoData
->Description
[0] = '\0';
4442 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4443 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4445 DriverInfoData
->MfgName
[0] = '\0';
4448 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4449 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4451 DriverInfoData
->ProviderName
[0] = '\0';
4454 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4456 /* Copy more fields */
4457 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4458 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4463 TRACE("Returning %d\n", ret
);
4468 /***********************************************************************
4469 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4472 SetupDiEnumDriverInfoW(
4473 IN HDEVINFO DeviceInfoSet
,
4474 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4475 IN DWORD DriverType
,
4476 IN DWORD MemberIndex
,
4477 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4479 PLIST_ENTRY ListHead
;
4482 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4483 DriverType
, MemberIndex
, DriverInfoData
);
4485 if (!DeviceInfoSet
|| !DriverInfoData
)
4486 SetLastError(ERROR_INVALID_PARAMETER
);
4487 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4488 SetLastError(ERROR_INVALID_HANDLE
);
4489 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4490 SetLastError(ERROR_INVALID_HANDLE
);
4491 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4492 SetLastError(ERROR_INVALID_PARAMETER
);
4493 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4494 SetLastError(ERROR_INVALID_PARAMETER
);
4495 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4496 SetLastError(ERROR_INVALID_PARAMETER
);
4497 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4498 SetLastError(ERROR_INVALID_USER_BUFFER
);
4501 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4502 PLIST_ENTRY ItemList
;
4503 if (DriverType
== SPDIT_CLASSDRIVER
||
4504 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4506 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4510 ListHead
= &devInfo
->DriverListHead
;
4513 ItemList
= ListHead
->Flink
;
4514 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4515 ItemList
= ItemList
->Flink
;
4516 if (ItemList
== ListHead
)
4517 SetLastError(ERROR_NO_MORE_ITEMS
);
4520 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4523 &DriverInfoData
->DriverType
,
4524 &DrvInfo
->Info
.DriverType
,
4525 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4530 TRACE("Returning %d\n", ret
);
4534 /***********************************************************************
4535 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4538 SetupDiGetSelectedDriverW(
4539 IN HDEVINFO DeviceInfoSet
,
4540 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4541 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4545 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4547 if (!DeviceInfoSet
|| !DriverInfoData
)
4548 SetLastError(ERROR_INVALID_PARAMETER
);
4549 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4550 SetLastError(ERROR_INVALID_HANDLE
);
4551 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4552 SetLastError(ERROR_INVALID_HANDLE
);
4553 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4554 SetLastError(ERROR_INVALID_USER_BUFFER
);
4555 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4556 SetLastError(ERROR_INVALID_USER_BUFFER
);
4559 struct DriverInfoElement
*driverInfo
;
4562 driverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4564 driverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4566 if (driverInfo
== NULL
)
4567 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4571 &DriverInfoData
->DriverType
,
4572 &driverInfo
->Info
.DriverType
,
4573 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4578 TRACE("Returning %d\n", ret
);
4582 /***********************************************************************
4583 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4586 SetupDiSetSelectedDriverW(
4587 IN HDEVINFO DeviceInfoSet
,
4588 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4589 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4593 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4596 SetLastError(ERROR_INVALID_PARAMETER
);
4597 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4598 SetLastError(ERROR_INVALID_HANDLE
);
4599 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4600 SetLastError(ERROR_INVALID_HANDLE
);
4601 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4602 SetLastError(ERROR_INVALID_USER_BUFFER
);
4603 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4604 SetLastError(ERROR_INVALID_USER_BUFFER
);
4607 struct DriverInfoElement
**pDriverInfo
;
4608 PLIST_ENTRY ListHead
, ItemList
;
4612 pDriverInfo
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4613 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4617 pDriverInfo
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4618 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4621 if (!DriverInfoData
)
4623 *pDriverInfo
= NULL
;
4628 /* Search selected driver in list */
4629 ItemList
= ListHead
->Flink
;
4630 while (ItemList
!= ListHead
)
4632 if (DriverInfoData
->Reserved
!= 0)
4634 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4639 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4640 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4641 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4642 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4643 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4649 if (ItemList
== ListHead
)
4650 SetLastError(ERROR_INVALID_PARAMETER
);
4653 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4654 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4656 TRACE("Choosing driver whose rank is 0x%lx\n",
4657 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
4659 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
4664 TRACE("Returning %d\n", ret
);
4668 /***********************************************************************
4669 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4672 SetupDiSelectBestCompatDrv(
4673 IN HDEVINFO DeviceInfoSet
,
4674 IN PSP_DEVINFO_DATA DeviceInfoData
)
4676 SP_DRVINFO_DATA_W drvInfoData
;
4679 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4681 /* Drivers are sorted by rank in the driver list, so
4682 * the first driver in the list is the best one.
4684 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4685 ret
= SetupDiEnumDriverInfoW(
4689 0, /* Member index */
4694 ret
= SetupDiSetSelectedDriverW(
4700 TRACE("Returning %d\n", ret
);
4704 /***********************************************************************
4705 * SetupDiInstallDriverFiles (SETUPAPI.@)
4708 SetupDiInstallDriverFiles(
4709 IN HDEVINFO DeviceInfoSet
,
4710 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4714 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4717 SetLastError(ERROR_INVALID_PARAMETER
);
4718 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4719 SetLastError(ERROR_INVALID_HANDLE
);
4720 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4721 SetLastError(ERROR_INVALID_HANDLE
);
4722 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4723 SetLastError(ERROR_INVALID_USER_BUFFER
);
4724 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4725 SetLastError(ERROR_INVALID_PARAMETER
);
4726 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4727 SetLastError(ERROR_INVALID_PARAMETER
);
4730 struct DriverInfoElement
*DriverInfo
;
4736 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4737 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4741 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4742 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4745 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4746 if (hInf
!= INVALID_HANDLE_VALUE
)
4748 WCHAR SectionName
[MAX_PATH
];
4749 DWORD SectionNameLength
= 0;
4751 ret
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4752 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4755 PVOID callback_context
= SetupInitDefaultQueueCallback(hWnd
);
4756 ret
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4757 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
4758 SetupDefaultQueueCallbackW
, callback_context
,
4760 SetupTermDefaultQueueCallback(callback_context
);
4762 SetupCloseInfFile(hInf
);
4766 TRACE("Returning %d\n", ret
);
4770 /***********************************************************************
4771 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4774 SetupDiRegisterCoDeviceInstallers(
4775 IN HDEVINFO DeviceInfoSet
,
4776 IN PSP_DEVINFO_DATA DeviceInfoData
)
4778 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4780 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
4781 //SetLastError(ERROR_GEN_FAILURE);
4786 /***********************************************************************
4787 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
4790 SetupDiInstallDeviceInterfaces(
4791 IN HDEVINFO DeviceInfoSet
,
4792 IN PSP_DEVINFO_DATA DeviceInfoData
)
4794 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4796 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
4797 //SetLastError(ERROR_GEN_FAILURE);
4802 /***********************************************************************
4803 * SetupDiInstallDevice (SETUPAPI.@)
4806 SetupDiInstallDevice(
4807 IN HDEVINFO DeviceInfoSet
,
4808 IN PSP_DEVINFO_DATA DeviceInfoData
)
4810 struct DriverInfoElement
*DriverInfo
;
4811 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4812 SYSTEMTIME DriverDate
;
4813 WCHAR SectionName
[MAX_PATH
];
4815 DWORD SectionNameLength
= 0;
4816 BOOL Result
= FALSE
;
4817 INFCONTEXT ContextService
;
4820 HINF hInf
= INVALID_HANDLE_VALUE
;
4821 LPCWSTR AssociatedService
= NULL
;
4822 LPWSTR pSectionName
= NULL
;
4823 LPWSTR ClassName
= NULL
;
4825 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
4826 BOOL RebootRequired
= FALSE
;
4827 HKEY hKey
= INVALID_HANDLE_VALUE
;
4828 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4831 BOOL ret
= FALSE
; /* Return value */
4833 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4836 SetLastError(ERROR_INVALID_PARAMETER
);
4837 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4838 SetLastError(ERROR_INVALID_HANDLE
);
4839 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4840 SetLastError(ERROR_INVALID_HANDLE
);
4841 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4842 SetLastError(ERROR_INVALID_USER_BUFFER
);
4843 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
== NULL
)
4844 SetLastError(ERROR_INVALID_PARAMETER
);
4845 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
== NULL
)
4846 SetLastError(ERROR_INVALID_PARAMETER
);
4852 /* One parameter is bad */
4856 /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
4860 DriverInfo
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->SelectedDriver
;
4861 hWnd
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->hwndParent
;
4865 DriverInfo
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->SelectedDriver
;
4866 hWnd
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->hwndParent
;
4868 FileTimeToSystemTime(&DriverInfo
->Info
.DriverDate
, &DriverDate
);
4870 hInf
= SetupOpenInfFileW(DriverInfo
->InfPath
, NULL
, INF_STYLE_WIN4
, NULL
);
4871 if (hInf
== INVALID_HANDLE_VALUE
)
4874 Result
= SetupDiGetActualSectionToInstallW(hInf
, DriverInfo
->InfSection
,
4875 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4876 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
4878 pSectionName
= &SectionName
[wcslen(SectionName
)];
4880 /* Get information from [Version] section */
4883 if (!SetupDiGetINFClassW(DriverInfo
->InfPath
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
4885 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
4887 ClassName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4890 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4893 if (!SetupDiGetINFClassW(DriverInfo
->InfPath
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
4896 /* Format ClassGuid to a string */
4897 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4899 RequiredSize
= lstrlenW(lpGuidString
);
4900 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
4901 if (!lpFullGuidString
)
4903 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4906 lpFullGuidString
[0] = '{';
4907 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
4908 lpFullGuidString
[RequiredSize
+ 1] = '}';
4909 lpFullGuidString
[RequiredSize
+ 2] = '\0';
4911 /* Open/Create driver key information */
4912 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_SET_VALUE
);
4913 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4914 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
4915 if (hKey
== INVALID_HANDLE_VALUE
)
4918 /* Install main section */
4919 /* Files have already been copied in SetupDiInstallDriverFiles.
4920 * Process only registry entries. */
4921 *pSectionName
= '\0';
4922 Result
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
4923 SPINST_REGISTRY
, hKey
, NULL
, 0,
4924 SetupDefaultQueueCallbackW
, NULL
,
4929 /* Write information to driver key */
4930 *pSectionName
= UNICODE_NULL
;
4931 TRACE("Write information to driver key\n");
4932 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4933 TRACE("DriverDesc : '%S'\n", DriverInfo
->Info
.Description
);
4934 TRACE("DriverVersion : '%u.%u.%u.%u'\n", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4935 TRACE("InfPath : '%S'\n", DriverInfo
->InfPath
);
4936 TRACE("InfSection : '%S'\n", DriverInfo
->InfSection
);
4937 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(DriverInfo
->InfSection
)]); /* FIXME */
4938 TRACE("MatchingDeviceId: '%S'\n", DriverInfo
->MatchingId
);
4939 TRACE("ProviderName : '%S'\n", DriverInfo
->Info
.ProviderName
);
4940 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
4941 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
4942 if (rc
== ERROR_SUCCESS
)
4943 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&DriverInfo
->Info
.DriverDate
, sizeof(FILETIME
));
4944 if (rc
== ERROR_SUCCESS
)
4945 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
4946 if (rc
== ERROR_SUCCESS
)
4948 swprintf(Buffer
, L
"%u.%u.%u.%u", DriverInfo
->Info
.DriverVersion
& 0xff, (DriverInfo
->Info
.DriverVersion
>> 8) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 16) & 0xff, (DriverInfo
->Info
.DriverVersion
>> 24) & 0xff);
4949 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
4951 if (rc
== ERROR_SUCCESS
)
4952 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)DriverInfo
->InfPath
, (wcslen(DriverInfo
->InfPath
) + 1) * sizeof(WCHAR
));
4953 if (rc
== ERROR_SUCCESS
)
4954 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)DriverInfo
->InfSection
, (wcslen(DriverInfo
->InfSection
) + 1) * sizeof(WCHAR
));
4955 if (rc
== ERROR_SUCCESS
)
4956 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(DriverInfo
->InfSection
)], (wcslen(SectionName
) - wcslen(DriverInfo
->InfSection
) + 1) * sizeof(WCHAR
));
4957 if (rc
== ERROR_SUCCESS
)
4958 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)DriverInfo
->MatchingId
, (wcslen(DriverInfo
->MatchingId
) + 1) * sizeof(WCHAR
));
4959 if (rc
== ERROR_SUCCESS
)
4960 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.ProviderName
, (wcslen(DriverInfo
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
4961 if (rc
!= ERROR_SUCCESS
)
4967 hKey
= INVALID_HANDLE_VALUE
;
4969 /* Install .Services section */
4970 wcscpy(pSectionName
, L
".Services");
4971 Result
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
4974 LPWSTR ServiceName
= NULL
;
4975 LPWSTR ServiceSection
= NULL
;
4977 Result
= SetupGetStringFieldW(
4979 1, /* Field index */
4984 if (RequiredSize
> 0)
4986 /* We got the needed size for the buffer */
4987 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4990 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4993 Result
= SetupGetStringFieldW(
4995 1, /* Field index */
4996 ServiceName
, RequiredSize
,
5001 Result
= SetupGetIntField(
5003 2, /* Field index */
5007 /* The field may be empty. Ignore the error */
5010 Result
= SetupGetStringFieldW(
5012 3, /* Field index */
5017 if (RequiredSize
> 0)
5019 /* We got the needed size for the buffer */
5020 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5021 if (!ServiceSection
)
5023 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5026 Result
= SetupGetStringFieldW(
5028 3, /* Field index */
5029 ServiceSection
, RequiredSize
,
5034 SetLastError(ERROR_SUCCESS
);
5035 Result
= SetupInstallServicesFromInfSectionExW(hInf
, ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
5036 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
5038 AssociatedService
= ServiceName
;
5040 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5041 RebootRequired
= TRUE
;
5044 HeapFree(GetProcessHeap(), 0, ServiceName
);
5045 HeapFree(GetProcessHeap(), 0, ServiceSection
);
5048 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
5051 /* Copy .inf file to Inf\ directory */
5052 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
5054 /* Open device registry key */
5055 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5056 if (hKey
== INVALID_HANDLE_VALUE
)
5059 /* Install .HW section */
5060 wcscpy(pSectionName
, L
".HW");
5061 Result
= SetupInstallFromInfSectionW(hWnd
, hInf
, SectionName
,
5062 SPINST_REGISTRY
, hKey
, NULL
, 0,
5063 SetupDefaultQueueCallbackW
, NULL
,
5068 /* Write information to enum key */
5069 TRACE("Write information to enum key\n");
5070 TRACE("Service : '%S'\n", AssociatedService
);
5071 TRACE("Class : '%S'\n", ClassName
);
5072 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
5073 TRACE("DeviceDesc : '%S'\n", DriverInfo
->Info
.Description
);
5074 TRACE("Mfg : '%S'\n", DriverInfo
->Info
.MfgName
);
5075 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
5076 if (rc
== ERROR_SUCCESS
)
5077 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
5078 if (rc
== ERROR_SUCCESS
)
5079 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5080 if (rc
== ERROR_SUCCESS
)
5081 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.Description
, (wcslen(DriverInfo
->Info
.Description
) + 1) * sizeof(WCHAR
));
5082 if (rc
== ERROR_SUCCESS
)
5083 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)DriverInfo
->Info
.MfgName
, (wcslen(DriverInfo
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5084 if (rc
!= ERROR_SUCCESS
)
5090 /* Start the device */
5091 if (!RebootRequired
&& !(Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5093 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
5095 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
5096 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
5097 ret
= NT_SUCCESS(Status
);
5103 /* End of installation */
5104 if (hClassKey
!= INVALID_HANDLE_VALUE
)
5105 RegCloseKey(hClassKey
);
5106 if (hKey
!= INVALID_HANDLE_VALUE
)
5109 RpcStringFreeW(&lpGuidString
);
5110 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
5111 HeapFree(GetProcessHeap(), 0, ClassName
);
5112 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5113 if (hInf
!= INVALID_HANDLE_VALUE
)
5114 SetupCloseInfFile(hInf
);
5116 TRACE("Returning %d\n", ret
);