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
;
125 SP_DRVINFO_DETAIL_DATA_W Details
;
130 struct DeviceInfoElement
/* Element of DeviceInfoSet.ListHead */
132 LIST_ENTRY ListEntry
;
134 /* Reserved Field points to a struct DriverInfoElement */
135 SP_DEVINSTALL_PARAMS_W InstallParams
;
137 /* Information about devnode:
139 * "Root\*PNP0501" for example.
140 * It doesn't contain the unique ID for the device
141 * (points into the Data field at the end of the structure)
142 * WARNING: no NULL char exist between DeviceName and UniqueId
145 * "5&1be2108e&0" or "0000"
146 * If DICD_GENERATE_ID is specified in creation flags,
147 * this unique ID is autogenerated using 4 digits, base 10
148 * (points into the Data field at the end of the structure)
149 * - DeviceDescription
150 * String which identifies the device. Can be NULL. If not NULL,
151 * points into the Data field at the end of the structure
153 * Identifies the class of this device. FIXME: can it be GUID_NULL?
155 * Is a combination of:
157 * the unique ID needs to be generated
158 * - DICD_INHERIT_CLASSDRVS
159 * inherit driver of the device info set (== same pointer)
163 PCWSTR DeviceDescription
;
167 /* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
168 /* If the driver is not searched/detected, this list is empty */
169 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
171 /* List of interfaces implemented by this device */
172 LIST_ENTRY InterfaceListHead
; /* List of struct DeviceInterface */
177 struct DeviceInfoSet
/* HDEVINFO */
179 DWORD magic
; /* SETUP_DEV_INFO_SET_MAGIC */
180 GUID ClassGuid
; /* If != GUID_NULL, only devices of this class can be in the device info set */
181 HKEY HKLM
; /* Local or distant HKEY_LOCAL_MACHINE registry key */
183 /* Reserved Field points to a struct DriverInfoElement */
184 SP_DEVINSTALL_PARAMS_W InstallParams
;
186 /* If the driver is not searched/detected, this list is empty */
187 LIST_ENTRY DriverListHead
; /* List of struct DriverInfoElement */
189 LIST_ENTRY ListHead
; /* List of struct DeviceInfoElement */
192 /***********************************************************************
193 * SetupDiBuildClassInfoList (SETUPAPI.@)
195 BOOL WINAPI
SetupDiBuildClassInfoList(
197 LPGUID ClassGuidList
,
198 DWORD ClassGuidListSize
,
202 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
203 ClassGuidListSize
, RequiredSize
,
207 /***********************************************************************
208 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
210 BOOL WINAPI
SetupDiBuildClassInfoListExA(
212 LPGUID ClassGuidList
,
213 DWORD ClassGuidListSize
,
218 LPWSTR MachineNameW
= NULL
;
225 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
226 if (MachineNameW
== NULL
) return FALSE
;
229 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
230 ClassGuidListSize
, RequiredSize
,
231 MachineNameW
, Reserved
);
234 MyFree(MachineNameW
);
239 /***********************************************************************
240 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
242 BOOL WINAPI
SetupDiBuildClassInfoListExW(
244 LPGUID ClassGuidList
,
245 DWORD ClassGuidListSize
,
250 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
256 DWORD dwGuidListIndex
= 0;
260 if (RequiredSize
!= NULL
)
263 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
268 if (hClassesKey
== INVALID_HANDLE_VALUE
)
273 for (dwIndex
= 0; ; dwIndex
++)
275 dwLength
= MAX_GUID_STRING_LEN
+ 1;
276 lError
= RegEnumKeyExW(hClassesKey
,
284 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
285 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
287 TRACE("Key name: %p\n", szKeyName
);
289 if (RegOpenKeyExW(hClassesKey
,
295 RegCloseKey(hClassesKey
);
299 if (!RegQueryValueExW(hClassKey
,
306 TRACE("'NoUseClass' value found!\n");
307 RegCloseKey(hClassKey
);
311 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
312 (!RegQueryValueExW(hClassKey
,
319 TRACE("'NoInstallClass' value found!\n");
320 RegCloseKey(hClassKey
);
324 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
325 (!RegQueryValueExW(hClassKey
,
332 TRACE("'NoDisplayClass' value found!\n");
333 RegCloseKey(hClassKey
);
337 RegCloseKey(hClassKey
);
339 TRACE("Guid: %p\n", szKeyName
);
340 if (dwGuidListIndex
< ClassGuidListSize
)
342 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
346 TRACE("Guid: %p\n", &szKeyName
[1]);
348 UuidFromStringW(&szKeyName
[1],
349 &ClassGuidList
[dwGuidListIndex
]);
355 if (lError
!= ERROR_SUCCESS
)
359 RegCloseKey(hClassesKey
);
361 if (RequiredSize
!= NULL
)
362 *RequiredSize
= dwGuidListIndex
;
364 if (ClassGuidListSize
< dwGuidListIndex
)
366 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
373 /***********************************************************************
374 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
376 BOOL WINAPI
SetupDiClassGuidsFromNameA(
378 LPGUID ClassGuidList
,
379 DWORD ClassGuidListSize
,
382 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
383 ClassGuidListSize
, RequiredSize
,
387 /***********************************************************************
388 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
390 BOOL WINAPI
SetupDiClassGuidsFromNameW(
392 LPGUID ClassGuidList
,
393 DWORD ClassGuidListSize
,
396 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
397 ClassGuidListSize
, RequiredSize
,
401 /***********************************************************************
402 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
404 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
406 LPGUID ClassGuidList
,
407 DWORD ClassGuidListSize
,
412 LPWSTR ClassNameW
= NULL
;
413 LPWSTR MachineNameW
= NULL
;
418 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
419 if (ClassNameW
== NULL
)
424 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
425 if (MachineNameW
== NULL
)
432 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
433 ClassGuidListSize
, RequiredSize
,
434 MachineNameW
, Reserved
);
437 MyFree(MachineNameW
);
444 /***********************************************************************
445 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
447 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
449 LPGUID ClassGuidList
,
450 DWORD ClassGuidListSize
,
455 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
456 WCHAR szClassName
[256];
462 DWORD dwGuidListIndex
= 0;
464 if (RequiredSize
!= NULL
)
467 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
468 KEY_ENUMERATE_SUB_KEYS
,
472 if (hClassesKey
== INVALID_HANDLE_VALUE
)
477 for (dwIndex
= 0; ; dwIndex
++)
479 dwLength
= MAX_GUID_STRING_LEN
+ 1;
480 lError
= RegEnumKeyExW(hClassesKey
,
488 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
489 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
491 TRACE("Key name: %p\n", szKeyName
);
493 if (RegOpenKeyExW(hClassesKey
,
499 RegCloseKey(hClassesKey
);
503 dwLength
= 256 * sizeof(WCHAR
);
504 if (!RegQueryValueExW(hClassKey
,
511 TRACE("Class name: %p\n", szClassName
);
513 if (strcmpiW(szClassName
, ClassName
) == 0)
515 TRACE("Found matching class name\n");
517 TRACE("Guid: %p\n", szKeyName
);
518 if (dwGuidListIndex
< ClassGuidListSize
)
520 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
524 TRACE("Guid: %p\n", &szKeyName
[1]);
526 UuidFromStringW(&szKeyName
[1],
527 &ClassGuidList
[dwGuidListIndex
]);
534 RegCloseKey(hClassKey
);
537 if (lError
!= ERROR_SUCCESS
)
541 RegCloseKey(hClassesKey
);
543 if (RequiredSize
!= NULL
)
544 *RequiredSize
= dwGuidListIndex
;
546 if (ClassGuidListSize
< dwGuidListIndex
)
548 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
555 /***********************************************************************
556 * SetupDiClassNameFromGuidA (SETUPAPI.@)
558 BOOL WINAPI
SetupDiClassNameFromGuidA(
559 const GUID
* ClassGuid
,
564 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
565 ClassNameSize
, RequiredSize
,
569 /***********************************************************************
570 * SetupDiClassNameFromGuidW (SETUPAPI.@)
572 BOOL WINAPI
SetupDiClassNameFromGuidW(
573 const GUID
* ClassGuid
,
578 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
579 ClassNameSize
, RequiredSize
,
583 /***********************************************************************
584 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
586 BOOL WINAPI
SetupDiClassNameFromGuidExA(
587 const GUID
* ClassGuid
,
594 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
595 LPWSTR MachineNameW
= NULL
;
599 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
600 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
601 NULL
, MachineNameW
, Reserved
);
604 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
605 ClassNameSize
, NULL
, NULL
);
607 if (!ClassNameSize
&& RequiredSize
)
610 MyFree(MachineNameW
);
614 /***********************************************************************
615 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
617 BOOL WINAPI
SetupDiClassNameFromGuidExW(
618 const GUID
* ClassGuid
,
629 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
634 if (hKey
== INVALID_HANDLE_VALUE
)
639 if (RequiredSize
!= NULL
)
642 rc
= RegQueryValueExW(hKey
,
648 if (rc
!= ERROR_SUCCESS
)
655 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
658 dwLength
= ClassNameSize
* sizeof(WCHAR
);
659 rc
= RegQueryValueExW(hKey
,
665 if (rc
!= ERROR_SUCCESS
)
677 /***********************************************************************
678 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
681 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
684 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
687 /***********************************************************************
688 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
691 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
696 LPWSTR MachineNameW
= NULL
;
699 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
703 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
704 if (MachineNameW
== NULL
)
705 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
708 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
709 MachineNameW
, Reserved
);
712 MyFree(MachineNameW
);
717 /***********************************************************************
718 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
721 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
726 struct DeviceInfoSet
*list
;
729 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
731 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
734 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
735 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
737 memset(list
, 0, sizeof(struct DeviceInfoSet
));
739 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
742 ClassGuid
? ClassGuid
: &GUID_NULL
,
743 sizeof(list
->ClassGuid
));
744 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
745 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
746 list
->InstallParams
.hwndParent
= hwndParent
;
749 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
750 if (rc
!= ERROR_SUCCESS
)
753 HeapFree(GetProcessHeap(), 0, list
);
754 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
759 list
->HKLM
= HKEY_LOCAL_MACHINE
;
761 InitializeListHead(&list
->DriverListHead
);
762 InitializeListHead(&list
->ListHead
);
763 return (HDEVINFO
)list
;
766 /***********************************************************************
767 * SetupDiEnumDeviceInfo (SETUPAPI.@)
769 BOOL WINAPI
SetupDiEnumDeviceInfo(
770 HDEVINFO DeviceInfoSet
,
772 PSP_DEVINFO_DATA DeviceInfoData
)
776 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
778 SetLastError(ERROR_INVALID_PARAMETER
);
779 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
781 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
783 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
784 SetLastError(ERROR_INVALID_HANDLE
);
785 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
786 SetLastError(ERROR_INVALID_USER_BUFFER
);
789 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
790 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
791 ItemList
= ItemList
->Flink
;
792 if (ItemList
== &list
->ListHead
)
793 SetLastError(ERROR_NO_MORE_ITEMS
);
796 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
797 memcpy(&DeviceInfoData
->ClassGuid
,
800 DeviceInfoData
->DevInst
= 0; /* FIXME */
801 /* Note: this appears to be dangerous, passing a private
802 * pointer a heap-allocated datum to the caller. However, the
803 * expected lifetime of the device data is the same as the
804 * HDEVINFO; once that is closed, the data are no longer valid.
806 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
812 SetLastError(ERROR_INVALID_HANDLE
);
816 /***********************************************************************
817 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
819 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
821 PCSTR InfSectionName
,
822 PSTR InfSectionWithExt
,
823 DWORD InfSectionWithExtSize
,
827 LPWSTR InfSectionNameW
= NULL
;
828 PWSTR InfSectionWithExtW
= NULL
;
830 BOOL bResult
= FALSE
;
836 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
837 if (InfSectionNameW
== NULL
) goto end
;
839 if (InfSectionWithExt
)
841 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
842 if (InfSectionWithExtW
== NULL
) goto end
;
845 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
846 InfSectionWithExt
? InfSectionNameW
: NULL
,
847 InfSectionWithExtSize
, RequiredSize
,
848 Extension
? &ExtensionW
: NULL
);
850 if (bResult
&& InfSectionWithExt
)
852 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
853 InfSectionWithExtSize
, NULL
, NULL
) != 0;
855 if (bResult
&& Extension
)
857 if (ExtensionW
== NULL
)
860 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
864 if (InfSectionNameW
) MyFree(InfSectionNameW
);
865 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
870 /***********************************************************************
871 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
873 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
875 PCWSTR InfSectionName
,
876 PWSTR InfSectionWithExt
,
877 DWORD InfSectionWithExtSize
,
881 WCHAR szBuffer
[MAX_PATH
];
884 LONG lLineCount
= -1;
886 lstrcpyW(szBuffer
, InfSectionName
);
887 dwLength
= lstrlenW(szBuffer
);
889 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
891 /* Test section name with '.NTx86' extension */
892 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
893 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
895 if (lLineCount
== -1)
897 /* Test section name with '.NT' extension */
898 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
899 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
904 /* Test section name with '.Win' extension */
905 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
906 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
909 if (lLineCount
== -1)
911 /* Test section name without extension */
912 szBuffer
[dwLength
] = 0;
913 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
916 if (lLineCount
== -1)
918 SetLastError(ERROR_INVALID_PARAMETER
);
922 dwFullLength
= lstrlenW(szBuffer
);
924 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
926 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
928 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
932 lstrcpyW(InfSectionWithExt
, szBuffer
);
933 if (Extension
!= NULL
)
935 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
939 if (RequiredSize
!= NULL
)
941 *RequiredSize
= dwFullLength
+ 1;
947 /***********************************************************************
948 * SetupDiGetClassDescriptionA (SETUPAPI.@)
950 BOOL WINAPI
SetupDiGetClassDescriptionA(
951 const GUID
* ClassGuid
,
952 PSTR ClassDescription
,
953 DWORD ClassDescriptionSize
,
956 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
957 ClassDescriptionSize
,
958 RequiredSize
, NULL
, NULL
);
961 /***********************************************************************
962 * SetupDiGetClassDescriptionW (SETUPAPI.@)
964 BOOL WINAPI
SetupDiGetClassDescriptionW(
965 const GUID
* ClassGuid
,
966 PWSTR ClassDescription
,
967 DWORD ClassDescriptionSize
,
970 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
971 ClassDescriptionSize
,
972 RequiredSize
, NULL
, NULL
);
975 /***********************************************************************
976 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
978 BOOL WINAPI
SetupDiGetClassDescriptionExA(
979 const GUID
* ClassGuid
,
980 PSTR ClassDescription
,
981 DWORD ClassDescriptionSize
,
986 PWCHAR ClassDescriptionW
;
987 LPWSTR MachineNameW
= NULL
;
991 if (ClassDescriptionSize
> 0)
993 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
994 if (!ClassDescriptionW
)
996 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1002 ClassDescriptionW
= NULL
;
1006 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1009 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1015 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1016 NULL
, MachineNameW
, Reserved
);
1019 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1020 ClassDescriptionSize
, NULL
, NULL
);
1022 if (!ClassDescriptionSize
&& RequiredSize
)
1023 *RequiredSize
= len
;
1027 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1028 MyFree(MachineNameW
);
1032 /***********************************************************************
1033 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1035 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1036 const GUID
* ClassGuid
,
1037 PWSTR ClassDescription
,
1038 DWORD ClassDescriptionSize
,
1039 PDWORD RequiredSize
,
1046 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1051 if (hKey
== INVALID_HANDLE_VALUE
)
1053 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1057 if (RequiredSize
!= NULL
)
1060 if (RegQueryValueExW(hKey
,
1071 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1074 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1075 if (RegQueryValueExW(hKey
,
1079 (LPBYTE
)ClassDescription
,
1091 /***********************************************************************
1092 * SetupDiGetClassDevsA (SETUPAPI.@)
1094 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1100 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1101 flags
, NULL
, NULL
, NULL
);
1104 /***********************************************************************
1105 * SetupDiGetClassDevsW (SETUPAPI.@)
1107 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1113 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1114 flags
, NULL
, NULL
, NULL
);
1117 /***********************************************************************
1118 * SetupDiGetClassDevsExA (SETUPAPI.@)
1120 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1130 LPWSTR enumstrW
= NULL
;
1131 LPWSTR machineW
= NULL
;
1135 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1136 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1139 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1142 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1146 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1147 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1150 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1153 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1155 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1158 HeapFree(GetProcessHeap(), 0, enumstrW
);
1159 HeapFree(GetProcessHeap(), 0, machineW
);
1164 CreateDeviceInfoElement(
1165 IN LPCWSTR InstancePath
,
1166 IN LPCGUID pClassGuid
,
1167 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1170 struct DeviceInfoElement
*deviceInfo
;
1172 *pDeviceInfo
= NULL
;
1174 size
= sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1175 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1178 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1181 memset(deviceInfo
, 0, size
);
1182 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1183 wcscpy(deviceInfo
->Data
, InstancePath
);
1184 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1185 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1186 deviceInfo
->DeviceDescription
= NULL
;
1187 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1188 deviceInfo
->CreationFlags
= 0;
1189 InitializeListHead(&deviceInfo
->DriverListHead
);
1190 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1192 *pDeviceInfo
= deviceInfo
;
1197 CreateDeviceInterface(
1198 IN
struct DeviceInfoElement
* deviceInfo
,
1199 IN LPCWSTR SymbolicLink
,
1200 IN LPCGUID pInterfaceGuid
,
1201 OUT
struct DeviceInterface
**pDeviceInterface
)
1203 struct DeviceInterface
*deviceInterface
;
1205 *pDeviceInterface
= NULL
;
1207 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1208 if (!deviceInterface
)
1210 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1213 deviceInterface
->DeviceInfo
= deviceInfo
;
1214 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1215 deviceInterface
->Flags
= 0; /* FIXME */
1216 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1218 *pDeviceInterface
= deviceInterface
;
1222 static LONG
SETUP_CreateDevListFromEnumerator(
1223 struct DeviceInfoSet
*list
,
1224 LPCGUID pClassGuid OPTIONAL
,
1226 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1228 HKEY hDeviceIdKey
, hInstanceIdKey
;
1229 WCHAR KeyBuffer
[MAX_PATH
];
1230 WCHAR InstancePath
[MAX_PATH
];
1231 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1232 struct DeviceInfoElement
*deviceInfo
;
1234 DWORD dwLength
, dwRegType
;
1237 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1240 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1241 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1242 if (rc
== ERROR_NO_MORE_ITEMS
)
1244 if (rc
!= ERROR_SUCCESS
)
1248 /* Open device id sub key */
1249 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1250 if (rc
!= ERROR_SUCCESS
)
1252 wcscpy(InstancePath
, Enumerator
);
1253 wcscat(InstancePath
, L
"\\");
1254 wcscat(InstancePath
, KeyBuffer
);
1255 wcscat(InstancePath
, L
"\\");
1256 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1258 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1264 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1265 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1266 if (rc
== ERROR_NO_MORE_ITEMS
)
1268 if (rc
!= ERROR_SUCCESS
)
1270 RegCloseKey(hDeviceIdKey
);
1275 /* Open instance id sub key */
1276 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1277 if (rc
!= ERROR_SUCCESS
)
1279 RegCloseKey(hDeviceIdKey
);
1282 *pEndOfInstancePath
= '\0';
1283 wcscat(InstancePath
, KeyBuffer
);
1285 /* Read ClassGUID value */
1286 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1287 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1288 RegCloseKey(hInstanceIdKey
);
1289 if (rc
== ERROR_FILE_NOT_FOUND
)
1292 /* Skip this bad entry as we can't verify it */
1295 else if (rc
!= ERROR_SUCCESS
)
1297 RegCloseKey(hDeviceIdKey
);
1300 else if (dwRegType
!= REG_SZ
)
1302 RegCloseKey(hDeviceIdKey
);
1303 return ERROR_GEN_FAILURE
;
1306 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1307 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1309 RegCloseKey(hDeviceIdKey
);
1310 return GetLastError();
1312 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1314 /* Skip this entry as it is not the right device class */
1318 /* Add the entry to the list */
1319 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1321 RegCloseKey(hDeviceIdKey
);
1322 return GetLastError();
1324 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1325 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1327 RegCloseKey(hDeviceIdKey
);
1330 return ERROR_SUCCESS
;
1333 static LONG
SETUP_CreateDevList(
1334 struct DeviceInfoSet
*list
,
1335 PCWSTR MachineName OPTIONAL
,
1336 LPGUID
class OPTIONAL
,
1337 PCWSTR Enumerator OPTIONAL
)
1339 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1340 WCHAR KeyBuffer
[MAX_PATH
];
1345 if (IsEqualIID(class, &GUID_NULL
))
1349 if (MachineName
!= NULL
)
1351 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1352 if (rc
!= ERROR_SUCCESS
)
1356 HKLM
= HKEY_LOCAL_MACHINE
;
1358 rc
= RegOpenKeyExW(HKLM
,
1361 KEY_ENUMERATE_SUB_KEYS
,
1363 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1364 if (rc
!= ERROR_SUCCESS
)
1367 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1368 * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
1377 KEY_ENUMERATE_SUB_KEYS
,
1379 RegCloseKey(hEnumKey
);
1380 if (rc
!= ERROR_SUCCESS
)
1382 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1383 RegCloseKey(hEnumeratorKey
);
1388 /* Enumerate enumerators */
1392 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1393 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1394 if (rc
== ERROR_NO_MORE_ITEMS
)
1396 if (rc
!= ERROR_SUCCESS
)
1398 RegCloseKey(hEnumKey
);
1404 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1405 if (rc
!= ERROR_SUCCESS
)
1407 RegCloseKey(hEnumKey
);
1411 /* Call SETUP_CreateDevListFromEnumerator */
1412 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1413 RegCloseKey(hEnumeratorKey
);
1414 if (rc
!= ERROR_SUCCESS
)
1416 RegCloseKey(hEnumKey
);
1420 RegCloseKey(hEnumKey
);
1421 return ERROR_SUCCESS
;
1426 static LONG
SETUP_CreateSerialDeviceList(
1427 struct DeviceInfoSet
*list
,
1429 LPGUID InterfaceGuid
,
1430 PCWSTR DeviceInstanceW
)
1432 static const size_t initialSize
= 100;
1434 WCHAR buf
[initialSize
];
1436 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1438 struct DeviceInfoElement
*deviceInfo
;
1441 WARN("'MachineName' is ignored on Wine!\n");
1442 if (DeviceInstanceW
)
1443 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1449 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1451 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1455 HeapFree(GetProcessHeap(), 0, devices
);
1456 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1458 return ERROR_NOT_ENOUGH_MEMORY
;
1464 HeapFree(GetProcessHeap(), 0, devices
);
1465 return GetLastError();
1469 /* 'devices' is a MULTI_SZ string */
1470 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1472 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1474 /* We have found a device */
1475 struct DeviceInterface
*interfaceInfo
;
1476 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1477 /* Step 1. Create a device info element */
1478 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1481 HeapFree(GetProcessHeap(), 0, devices
);
1482 return GetLastError();
1484 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1486 /* Step 2. Create an interface list for this element */
1487 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1490 HeapFree(GetProcessHeap(), 0, devices
);
1491 return GetLastError();
1493 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1497 HeapFree(GetProcessHeap(), 0, devices
);
1498 return ERROR_SUCCESS
;
1501 #else /* __REACTOS__ */
1503 static LONG
SETUP_CreateInterfaceList(
1504 struct DeviceInfoSet
*list
,
1506 LPGUID InterfaceGuid
,
1507 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1509 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1510 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1511 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1512 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1513 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1515 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1518 DWORD dwLength
, dwInstancePathLength
;
1521 struct DeviceInfoElement
*deviceInfo
;
1523 /* Open registry key related to this interface */
1524 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1525 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1526 return GetLastError();
1528 /* Enumerate sub keys of hInterfaceKey */
1532 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1533 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1534 if (rc
== ERROR_NO_MORE_ITEMS
)
1536 if (rc
!= ERROR_SUCCESS
)
1538 RegCloseKey(hInterfaceKey
);
1544 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1545 if (rc
!= ERROR_SUCCESS
)
1547 RegCloseKey(hInterfaceKey
);
1551 /* Read DeviceInstance */
1552 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1553 if (rc
!= ERROR_SUCCESS
)
1555 RegCloseKey(hDeviceInstanceKey
);
1556 RegCloseKey(hInterfaceKey
);
1559 if (dwRegType
!= REG_SZ
)
1561 RegCloseKey(hDeviceInstanceKey
);
1562 RegCloseKey(hInterfaceKey
);
1563 return ERROR_GEN_FAILURE
;
1565 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1568 RegCloseKey(hDeviceInstanceKey
);
1569 RegCloseKey(hInterfaceKey
);
1570 return ERROR_NOT_ENOUGH_MEMORY
;
1572 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1573 if (rc
!= ERROR_SUCCESS
)
1575 HeapFree(GetProcessHeap(), 0, InstancePath
);
1576 RegCloseKey(hDeviceInstanceKey
);
1577 RegCloseKey(hInterfaceKey
);
1580 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1581 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1583 if (DeviceInstanceW
)
1585 /* Check if device enumerator is not the right one */
1586 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1588 HeapFree(GetProcessHeap(), 0, InstancePath
);
1589 RegCloseKey(hDeviceInstanceKey
);
1594 /* Find class GUID associated to the device instance */
1599 KEY_ENUMERATE_SUB_KEYS
,
1601 if (rc
!= ERROR_SUCCESS
)
1603 HeapFree(GetProcessHeap(), 0, InstancePath
);
1604 RegCloseKey(hDeviceInstanceKey
);
1605 RegCloseKey(hInterfaceKey
);
1614 RegCloseKey(hEnumKey
);
1615 if (rc
!= ERROR_SUCCESS
)
1617 HeapFree(GetProcessHeap(), 0, InstancePath
);
1618 RegCloseKey(hDeviceInstanceKey
);
1619 RegCloseKey(hInterfaceKey
);
1622 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1623 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1625 if (rc
!= ERROR_SUCCESS
)
1627 HeapFree(GetProcessHeap(), 0, InstancePath
);
1628 RegCloseKey(hDeviceInstanceKey
);
1629 RegCloseKey(hInterfaceKey
);
1632 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1633 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1634 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1636 HeapFree(GetProcessHeap(), 0, InstancePath
);
1637 RegCloseKey(hDeviceInstanceKey
);
1638 RegCloseKey(hInterfaceKey
);
1639 return ERROR_GEN_FAILURE
;
1641 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1643 /* If current device doesn't match the list GUID (if any), skip this entry */
1644 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1646 HeapFree(GetProcessHeap(), 0, InstancePath
);
1647 RegCloseKey(hDeviceInstanceKey
);
1651 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1655 LPWSTR pSymbolicLink
;
1656 struct DeviceInterface
*interfaceInfo
;
1658 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1659 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1660 if (rc
== ERROR_NO_MORE_ITEMS
)
1662 if (rc
!= ERROR_SUCCESS
)
1664 HeapFree(GetProcessHeap(), 0, InstancePath
);
1665 RegCloseKey(hDeviceInstanceKey
);
1666 RegCloseKey(hInterfaceKey
);
1670 if (KeyBuffer
[0] != '#')
1671 /* This entry doesn't represent an interesting entry */
1675 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1676 if (rc
!= ERROR_SUCCESS
)
1678 RegCloseKey(hDeviceInstanceKey
);
1679 RegCloseKey(hInterfaceKey
);
1683 /* Read SymbolicLink value */
1684 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1685 if (rc
!= ERROR_SUCCESS
)
1687 RegCloseKey(hReferenceKey
);
1688 RegCloseKey(hDeviceInstanceKey
);
1689 RegCloseKey(hInterfaceKey
);
1692 if (dwRegType
!= REG_SZ
)
1694 RegCloseKey(hReferenceKey
);
1695 RegCloseKey(hDeviceInstanceKey
);
1696 RegCloseKey(hInterfaceKey
);
1697 return ERROR_GEN_FAILURE
;
1700 /* We have found a device */
1701 /* Step 1. Create a device info element */
1702 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1704 RegCloseKey(hReferenceKey
);
1705 RegCloseKey(hDeviceInstanceKey
);
1706 RegCloseKey(hInterfaceKey
);
1707 return GetLastError();
1709 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1710 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1712 /* Step 2. Create an interface list for this element */
1713 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1716 RegCloseKey(hReferenceKey
);
1717 RegCloseKey(hDeviceInstanceKey
);
1718 RegCloseKey(hInterfaceKey
);
1719 return ERROR_NOT_ENOUGH_MEMORY
;
1721 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1722 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1723 RegCloseKey(hReferenceKey
);
1724 if (rc
!= ERROR_SUCCESS
)
1726 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1727 RegCloseKey(hDeviceInstanceKey
);
1728 RegCloseKey(hInterfaceKey
);
1731 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1733 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1734 RegCloseKey(hDeviceInstanceKey
);
1735 RegCloseKey(hInterfaceKey
);
1736 return GetLastError();
1738 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1739 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1740 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1742 RegCloseKey(hDeviceInstanceKey
);
1744 RegCloseKey(hInterfaceKey
);
1745 return ERROR_SUCCESS
;
1747 #endif /* __REACTOS__ */
1749 /***********************************************************************
1750 * SetupDiGetClassDevsExW (SETUPAPI.@)
1752 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1761 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1762 struct DeviceInfoSet
*list
;
1766 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1767 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1769 /* Create the deviceset if not set */
1772 list
= (struct DeviceInfoSet
*)deviceset
;
1773 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1775 SetLastError(ERROR_INVALID_HANDLE
);
1776 return INVALID_HANDLE_VALUE
;
1778 hDeviceInfo
= deviceset
;
1782 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1783 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1784 NULL
, machine
, NULL
);
1785 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1786 return INVALID_HANDLE_VALUE
;
1787 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1790 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1793 pClassGuid
= &list
->ClassGuid
;
1795 if (flags
& DIGCF_PRESENT
)
1796 FIXME(": flag DIGCF_PRESENT ignored\n");
1797 if (flags
& DIGCF_PROFILE
)
1798 FIXME(": flag DIGCF_PROFILE ignored\n");
1800 if (flags
& DIGCF_ALLCLASSES
)
1802 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1803 if (rc
!= ERROR_SUCCESS
)
1807 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1808 return INVALID_HANDLE_VALUE
;
1812 else if (flags
& DIGCF_DEVICEINTERFACE
)
1816 SetLastError(ERROR_INVALID_PARAMETER
);
1818 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1819 return INVALID_HANDLE_VALUE
;
1823 /* Special case: find serial ports by calling QueryDosDevice */
1824 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1825 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1826 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1827 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1830 ERR("Wine can only enumerate serial devices at the moment!\n");
1831 rc
= ERROR_INVALID_PARAMETER
;
1833 #else /* __REACTOS__ */
1834 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1835 #endif /* __REACTOS__ */
1836 if (rc
!= ERROR_SUCCESS
)
1840 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1841 return INVALID_HANDLE_VALUE
;
1847 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1848 if (rc
!= ERROR_SUCCESS
)
1852 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1853 return INVALID_HANDLE_VALUE
;
1859 /***********************************************************************
1860 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1862 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1863 HDEVINFO DeviceInfoSet
,
1864 PSP_DEVINFO_DATA DeviceInfoData
,
1865 CONST GUID
* InterfaceClassGuid
,
1867 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1871 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1872 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1874 if (!DeviceInterfaceData
)
1875 SetLastError(ERROR_INVALID_PARAMETER
);
1876 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1877 SetLastError(ERROR_INVALID_USER_BUFFER
);
1878 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1880 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1882 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1884 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1886 while (ItemList
!= &list
->ListHead
&& !Found
)
1888 PLIST_ENTRY InterfaceListEntry
;
1889 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1890 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1892 /* We are not searching for this element */
1893 ItemList
= ItemList
->Flink
;
1896 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1897 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1899 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1900 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1902 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1905 if (MemberIndex
-- == 0)
1907 /* return this item */
1908 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1909 &DevItf
->InterfaceClassGuid
,
1911 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1912 /* Note: this appears to be dangerous, passing a private
1913 * pointer a heap-allocated datum to the caller. However, the
1914 * expected lifetime of the device data is the same as the
1915 * HDEVINFO; once that is closed, the data are no longer valid.
1917 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1920 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1922 ItemList
= ItemList
->Flink
;
1925 SetLastError(ERROR_NO_MORE_ITEMS
);
1930 SetLastError(ERROR_INVALID_HANDLE
);
1933 SetLastError(ERROR_INVALID_HANDLE
);
1937 /***********************************************************************
1938 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1940 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1944 TRACE("%p\n", devinfo
);
1945 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1947 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1949 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1951 PLIST_ENTRY ListEntry
, InterfaceEntry
;
1952 struct DeviceInfoElement
*deviceInfo
;
1953 while (!IsListEmpty(&list
->ListHead
))
1955 ListEntry
= RemoveHeadList(&list
->ListHead
);
1956 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1957 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1959 InterfaceEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1960 HeapFree(GetProcessHeap(), 0, InterfaceEntry
);
1962 HeapFree(GetProcessHeap(), 0, ListEntry
);
1964 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1965 RegCloseKey(list
->HKLM
);
1966 HeapFree(GetProcessHeap(), 0, list
);
1970 SetLastError(ERROR_INVALID_HANDLE
);
1973 SetLastError(ERROR_INVALID_HANDLE
);
1975 TRACE("Returning %d\n", ret
);
1979 /***********************************************************************
1980 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1982 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1983 HDEVINFO DeviceInfoSet
,
1984 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1985 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1986 DWORD DeviceInterfaceDetailDataSize
,
1987 PDWORD RequiredSize
,
1988 PSP_DEVINFO_DATA DeviceInfoData
)
1990 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
1991 DWORD sizeW
= 0, sizeA
;
1994 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
1995 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1996 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1998 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
1999 SetLastError(ERROR_INVALID_USER_BUFFER
);
2000 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2001 SetLastError(ERROR_INVALID_PARAMETER
);
2002 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2003 SetLastError(ERROR_INVALID_PARAMETER
);
2006 if (DeviceInterfaceDetailData
!= NULL
)
2008 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2009 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2010 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2011 if (!DeviceInterfaceDetailDataW
)
2013 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2016 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2018 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2019 ret
= SetupDiGetDeviceInterfaceDetailW(
2021 DeviceInterfaceData
,
2022 DeviceInterfaceDetailDataW
,
2026 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2027 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2029 *RequiredSize
= sizeA
;
2030 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2032 if (!WideCharToMultiByte(
2034 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2035 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2042 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2045 TRACE("Returning %d\n", ret
);
2049 /***********************************************************************
2050 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2052 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2053 HDEVINFO DeviceInfoSet
,
2054 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2055 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2056 DWORD DeviceInterfaceDetailDataSize
,
2057 PDWORD RequiredSize
,
2058 PSP_DEVINFO_DATA DeviceInfoData
)
2062 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2063 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2064 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2066 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2067 SetLastError(ERROR_INVALID_PARAMETER
);
2068 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2069 SetLastError(ERROR_INVALID_HANDLE
);
2070 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2071 SetLastError(ERROR_INVALID_HANDLE
);
2072 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2073 SetLastError(ERROR_INVALID_USER_BUFFER
);
2074 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2075 SetLastError(ERROR_INVALID_USER_BUFFER
);
2076 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2077 SetLastError(ERROR_INVALID_USER_BUFFER
);
2078 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2079 SetLastError(ERROR_INVALID_PARAMETER
);
2080 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2081 SetLastError(ERROR_INVALID_PARAMETER
);
2084 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2085 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2086 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2087 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2089 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2091 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2093 *RequiredSize
= sizeRequired
;
2097 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2098 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2101 memcpy(&DeviceInfoData
->ClassGuid
,
2102 &deviceInterface
->DeviceInfo
->ClassGuid
,
2104 DeviceInfoData
->DevInst
= 0; /* FIXME */
2105 /* Note: this appears to be dangerous, passing a private
2106 * pointer a heap-allocated datum to the caller. However, the
2107 * expected lifetime of the device data is the same as the
2108 * HDEVINFO; once that is closed, the data are no longer valid.
2110 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2116 TRACE("Returning %d\n", ret
);
2120 /***********************************************************************
2121 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2123 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2125 PSP_DEVINFO_DATA DeviceInfoData
,
2127 PDWORD PropertyRegDataType
,
2128 PBYTE PropertyBuffer
,
2129 DWORD PropertyBufferSize
,
2130 PDWORD RequiredSize
)
2133 BOOL bIsStringProperty
;
2135 DWORD RequiredSizeA
, RequiredSizeW
;
2136 DWORD PropertyBufferSizeW
;
2137 PBYTE PropertyBufferW
;
2139 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2140 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2143 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2144 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2146 bResult
= SetupDiGetDeviceRegistryPropertyW(
2152 PropertyBufferSizeW
,
2155 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2157 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2159 if (bIsStringProperty
)
2160 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2162 RequiredSizeA
= RequiredSizeW
;
2164 *RequiredSize
= RequiredSizeA
;
2165 if (PropertyRegDataType
)
2166 *PropertyRegDataType
= RegType
;
2171 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2175 if (RequiredSizeA
<= PropertyBufferSize
)
2177 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2179 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2181 /* Last error is already set by WideCharToMultiByte */
2186 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2190 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2194 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2198 /***********************************************************************
2199 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2201 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2202 HDEVINFO DeviceInfoSet
,
2203 PSP_DEVINFO_DATA DeviceInfoData
,
2205 PDWORD PropertyRegDataType
,
2206 PBYTE PropertyBuffer
,
2207 DWORD PropertyBufferSize
,
2208 PDWORD RequiredSize
)
2210 HKEY hEnumKey
, hKey
;
2214 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2215 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2218 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2219 SetLastError(ERROR_INVALID_HANDLE
);
2220 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2221 SetLastError(ERROR_INVALID_HANDLE
);
2222 else if (!DeviceInfoData
)
2223 SetLastError(ERROR_INVALID_PARAMETER
);
2224 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2225 SetLastError(ERROR_INVALID_USER_BUFFER
);
2226 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2227 SetLastError(ERROR_INVALID_PARAMETER
);
2230 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2231 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2235 case SPDRP_CAPABILITIES
:
2237 case SPDRP_CLASSGUID
:
2238 case SPDRP_COMPATIBLEIDS
:
2239 case SPDRP_CONFIGFLAGS
:
2240 case SPDRP_DEVICEDESC
:
2242 case SPDRP_FRIENDLYNAME
:
2243 case SPDRP_HARDWAREID
:
2244 case SPDRP_LOCATION_INFORMATION
:
2245 case SPDRP_LOWERFILTERS
:
2247 case SPDRP_SECURITY
:
2249 case SPDRP_UI_NUMBER
:
2250 case SPDRP_UPPERFILTERS
:
2252 LPCWSTR RegistryPropertyName
;
2257 case SPDRP_CAPABILITIES
:
2258 RegistryPropertyName
= L
"Capabilities"; break;
2260 RegistryPropertyName
= L
"Class"; break;
2261 case SPDRP_CLASSGUID
:
2262 RegistryPropertyName
= L
"ClassGUID"; break;
2263 case SPDRP_COMPATIBLEIDS
:
2264 RegistryPropertyName
= L
"CompatibleIDs"; break;
2265 case SPDRP_CONFIGFLAGS
:
2266 RegistryPropertyName
= L
"ConfigFlags"; break;
2267 case SPDRP_DEVICEDESC
:
2268 RegistryPropertyName
= L
"DeviceDesc"; break;
2270 RegistryPropertyName
= L
"Driver"; break;
2271 case SPDRP_FRIENDLYNAME
:
2272 RegistryPropertyName
= L
"FriendlyName"; break;
2273 case SPDRP_HARDWAREID
:
2274 RegistryPropertyName
= L
"HardwareID"; break;
2275 case SPDRP_LOCATION_INFORMATION
:
2276 RegistryPropertyName
= L
"LocationInformation"; break;
2277 case SPDRP_LOWERFILTERS
:
2278 RegistryPropertyName
= L
"LowerFilters"; break;
2280 RegistryPropertyName
= L
"Mfg"; break;
2281 case SPDRP_SECURITY
:
2282 RegistryPropertyName
= L
"Security"; break;
2284 RegistryPropertyName
= L
"Service"; break;
2285 case SPDRP_UI_NUMBER
:
2286 RegistryPropertyName
= L
"UINumber"; break;
2287 case SPDRP_UPPERFILTERS
:
2288 RegistryPropertyName
= L
"UpperFilters"; break;
2290 /* Should not happen */
2291 RegistryPropertyName
= NULL
; break;
2294 /* Open registry key name */
2299 KEY_ENUMERATE_SUB_KEYS
,
2301 if (rc
!= ERROR_SUCCESS
)
2312 RegCloseKey(hEnumKey
);
2313 if (rc
!= ERROR_SUCCESS
)
2318 /* Read registry entry */
2319 BufferSize
= PropertyBufferSize
;
2320 rc
= RegQueryValueExW(
2322 RegistryPropertyName
,
2323 NULL
, /* Reserved */
2324 PropertyRegDataType
,
2328 *RequiredSize
= BufferSize
;
2333 case ERROR_MORE_DATA
:
2334 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2343 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2345 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2347 if (PropertyRegDataType
)
2348 *PropertyRegDataType
= REG_SZ
;
2350 *RequiredSize
= required
;
2351 if (PropertyBufferSize
>= required
)
2353 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2357 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2361 /*case SPDRP_BUSTYPEGUID:
2362 case SPDRP_LEGACYBUSTYPE:
2363 case SPDRP_BUSNUMBER:
2364 case SPDRP_ENUMERATOR_NAME:
2365 case SPDRP_SECURITY_SDS:
2367 case SPDRP_EXCLUSIVE:
2368 case SPDRP_CHARACTERISTICS:
2370 case SPDRP_UI_NUMBER_DESC_FORMAT:
2371 case SPDRP_DEVICE_POWER_DATA:*/
2372 #if (WINVER >= 0x501)
2373 /*case SPDRP_REMOVAL_POLICY:
2374 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2375 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2376 case SPDRP_INSTALL_STATE:*/
2381 FIXME("Property 0x%lx not implemented\n", Property
);
2382 SetLastError(ERROR_NOT_SUPPORTED
);
2387 TRACE("Returning %d\n", ret
);
2392 /***********************************************************************
2393 * SetupDiInstallClassA (SETUPAPI.@)
2395 BOOL WINAPI
SetupDiInstallClassA(
2401 UNICODE_STRING FileNameW
;
2404 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2406 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2410 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2412 RtlFreeUnicodeString(&FileNameW
);
2417 static HKEY
CreateClassKey(HINF hInf
)
2419 WCHAR FullBuffer
[MAX_PATH
];
2420 WCHAR Buffer
[MAX_PATH
];
2425 if (!SetupGetLineTextW(NULL
,
2433 return INVALID_HANDLE_VALUE
;
2436 lstrcpyW(FullBuffer
, ControlClass
);
2437 lstrcatW(FullBuffer
, Buffer
);
2440 if (!SetupGetLineTextW(NULL
,
2448 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2449 return INVALID_HANDLE_VALUE
;
2452 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2456 REG_OPTION_NON_VOLATILE
,
2462 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2463 return INVALID_HANDLE_VALUE
;
2466 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2471 RequiredSize
* sizeof(WCHAR
)))
2473 RegCloseKey(hClassKey
);
2474 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2475 return INVALID_HANDLE_VALUE
;
2481 /***********************************************************************
2482 * SetupDiInstallClassW (SETUPAPI.@)
2484 BOOL WINAPI
SetupDiInstallClassW(
2490 WCHAR SectionName
[MAX_PATH
];
2491 DWORD SectionNameLength
= 0;
2493 BOOL bFileQueueCreated
= FALSE
;
2496 FIXME("not fully implemented\n");
2498 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2500 SetLastError(ERROR_INVALID_PARAMETER
);
2504 /* Open the .inf file */
2505 hInf
= SetupOpenInfFileW(InfFileName
,
2509 if (hInf
== INVALID_HANDLE_VALUE
)
2515 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2516 hClassKey
= CreateClassKey(hInf
);
2517 if (hClassKey
== INVALID_HANDLE_VALUE
)
2519 SetupCloseInfFile(hInf
);
2525 /* Try to append a layout file */
2527 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2530 /* Retrieve the actual section name */
2531 SetupDiGetActualSectionToInstallW(hInf
,
2539 if (!(Flags
& DI_NOVCP
))
2541 FileQueue
= SetupOpenFileQueue();
2542 if (FileQueue
== INVALID_HANDLE_VALUE
)
2544 SetupCloseInfFile(hInf
);
2545 RegCloseKey(hClassKey
);
2549 bFileQueueCreated
= TRUE
;
2554 SetupInstallFromInfSectionW(NULL
,
2563 INVALID_HANDLE_VALUE
,
2566 /* FIXME: More code! */
2568 if (bFileQueueCreated
)
2569 SetupCloseFileQueue(FileQueue
);
2571 SetupCloseInfFile(hInf
);
2573 RegCloseKey(hClassKey
);
2578 /***********************************************************************
2579 * SetupDiOpenClassRegKey (SETUPAPI.@)
2581 HKEY WINAPI
SetupDiOpenClassRegKey(
2582 const GUID
* ClassGuid
,
2585 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2586 DIOCR_INSTALLER
, NULL
, NULL
);
2590 /***********************************************************************
2591 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2593 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2594 const GUID
* ClassGuid
,
2600 PWSTR MachineNameW
= NULL
;
2607 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2608 if (MachineNameW
== NULL
)
2609 return INVALID_HANDLE_VALUE
;
2612 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2613 Flags
, MachineNameW
, Reserved
);
2616 MyFree(MachineNameW
);
2622 /***********************************************************************
2623 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2625 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2626 const GUID
* ClassGuid
,
2632 LPWSTR lpGuidString
;
2633 LPWSTR lpFullGuidString
;
2641 if (Flags
== DIOCR_INSTALLER
)
2643 lpKeyName
= ControlClass
;
2645 else if (Flags
== DIOCR_INTERFACE
)
2647 lpKeyName
= DeviceClasses
;
2651 ERR("Invalid Flags parameter!\n");
2652 SetLastError(ERROR_INVALID_PARAMETER
);
2653 return INVALID_HANDLE_VALUE
;
2656 if (MachineName
!= NULL
)
2658 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2659 if (rc
!= ERROR_SUCCESS
)
2662 return INVALID_HANDLE_VALUE
;
2666 HKLM
= HKEY_LOCAL_MACHINE
;
2668 rc
= RegOpenKeyExW(HKLM
,
2673 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2674 if (rc
!= ERROR_SUCCESS
)
2677 return INVALID_HANDLE_VALUE
;
2680 if (ClassGuid
== NULL
)
2683 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2685 SetLastError(ERROR_GEN_FAILURE
);
2686 RegCloseKey(hClassesKey
);
2687 return INVALID_HANDLE_VALUE
;
2690 dwLength
= lstrlenW(lpGuidString
);
2691 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2692 if (!lpFullGuidString
)
2694 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2695 RpcStringFreeW(&lpGuidString
);
2696 return INVALID_HANDLE_VALUE
;
2698 lpFullGuidString
[0] = '{';
2699 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2700 lpFullGuidString
[dwLength
+ 1] = '}';
2701 lpFullGuidString
[dwLength
+ 2] = '\0';
2702 RpcStringFreeW(&lpGuidString
);
2704 rc
= RegOpenKeyExW(hClassesKey
,
2709 if (rc
!= ERROR_SUCCESS
)
2712 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2713 RegCloseKey(hClassesKey
);
2714 return INVALID_HANDLE_VALUE
;
2717 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2718 RegCloseKey(hClassesKey
);
2723 /***********************************************************************
2724 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2726 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2727 HDEVINFO DeviceInfoSet
,
2730 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2732 FIXME("%p %s %08lx %p\n",
2733 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2737 /***********************************************************************
2738 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2740 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2741 HDEVINFO DeviceInfoSet
,
2744 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2746 LPWSTR DevicePathW
= NULL
;
2749 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2751 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2752 if (DevicePathW
== NULL
)
2755 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2756 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2758 MyFree(DevicePathW
);
2763 /***********************************************************************
2764 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2766 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2767 HDEVINFO DeviceInfoSet
,
2768 PSP_DEVINFO_DATA DeviceInfoData
,
2769 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2770 DWORD ClassInstallParamsSize
)
2772 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2773 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2779 IN PWSTR InstallerName
,
2780 OUT HMODULE
* ModulePointer
,
2781 OUT PVOID
* FunctionPointer
)
2783 HMODULE hModule
= NULL
;
2784 LPSTR FunctionNameA
= NULL
;
2788 *ModulePointer
= NULL
;
2789 *FunctionPointer
= NULL
;
2791 Comma
= strchrW(InstallerName
, ',');
2794 rc
= ERROR_INVALID_PARAMETER
;
2798 /* W->A conversion for function name */
2799 FunctionNameA
= UnicodeToMultiByte(Comma
+ 1, CP_ACP
);
2802 rc
= GetLastError();
2808 hModule
= LoadLibraryW(InstallerName
);
2812 rc
= GetLastError();
2816 /* Search function */
2817 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
2818 if (!*FunctionPointer
)
2820 rc
= GetLastError();
2824 *ModulePointer
= hModule
;
2828 if (rc
!= ERROR_SUCCESS
&& hModule
)
2829 FreeLibrary(hModule
);
2830 MyFree(FunctionNameA
);
2835 FreeFunctionPointer(
2836 IN HMODULE ModulePointer
,
2837 IN PVOID FunctionPointer
)
2839 if (ModulePointer
== NULL
)
2840 return ERROR_SUCCESS
;
2841 if (FreeLibrary(ModulePointer
))
2842 return ERROR_SUCCESS
;
2844 return GetLastError();
2847 /***********************************************************************
2848 * SetupDiCallClassInstaller (SETUPAPI.@)
2850 BOOL WINAPI
SetupDiCallClassInstaller(
2851 IN DI_FUNCTION InstallFunction
,
2852 IN HDEVINFO DeviceInfoSet
,
2853 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2857 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2860 SetLastError(ERROR_INVALID_PARAMETER
);
2861 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2862 SetLastError(ERROR_INVALID_HANDLE
);
2863 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2864 SetLastError(ERROR_INVALID_HANDLE
);
2865 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2866 SetLastError(ERROR_INVALID_HANDLE
);
2867 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2868 SetLastError(ERROR_INVALID_USER_BUFFER
);
2871 SP_DEVINSTALL_PARAMS_W InstallParams
;
2872 #define CLASS_COINSTALLER 0x1
2873 #define DEVICE_COINSTALLER 0x2
2874 #define CLASS_INSTALLER 0x4
2875 UCHAR CanHandle
= 0;
2876 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
2878 switch (InstallFunction
)
2880 case DIF_ALLOW_INSTALL
:
2881 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2883 case DIF_DESTROYPRIVATEDATA
:
2884 CanHandle
= CLASS_INSTALLER
;
2886 case DIF_INSTALLDEVICE
:
2887 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2888 DefaultHandler
= SetupDiInstallDevice
;
2890 case DIF_INSTALLDEVICEFILES
:
2891 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2892 DefaultHandler
= SetupDiInstallDriverFiles
;
2894 case DIF_INSTALLINTERFACES
:
2895 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2896 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
2898 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
2899 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
2901 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
2902 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2904 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
2905 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2907 case DIF_REGISTER_COINSTALLERS
:
2908 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2909 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
2911 case DIF_SELECTBESTCOMPATDRV
:
2912 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
2913 DefaultHandler
= SetupDiSelectBestCompatDrv
;
2916 FIXME("Install function %ld not implemented\n", InstallFunction
);
2917 SetLastError(ERROR_INVALID_PARAMETER
);
2920 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2921 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
2922 /* Don't process this call, as a parameter is invalid */
2927 LIST_ENTRY ClassCoInstallersListHead
;
2928 LIST_ENTRY DeviceCoInstallersListHead
;
2929 HMODULE ClassInstallerLibrary
= NULL
;
2930 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
2931 COINSTALLER_CONTEXT_DATA Context
;
2932 PLIST_ENTRY ListEntry
;
2934 DWORD dwRegType
, dwLength
;
2935 DWORD rc
= NO_ERROR
;
2937 InitializeListHead(&ClassCoInstallersListHead
);
2938 InitializeListHead(&DeviceCoInstallersListHead
);
2940 if (CanHandle
& DEVICE_COINSTALLER
)
2942 FIXME("Doesn't use Device co-installers at the moment\n");
2944 if (CanHandle
& CLASS_COINSTALLER
)
2948 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
2952 if (rc
== ERROR_SUCCESS
)
2954 LPWSTR lpGuidString
;
2955 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
2957 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
2958 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2960 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2961 if (KeyBuffer
!= NULL
)
2963 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2964 if (rc
== ERROR_SUCCESS
)
2967 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
2969 /* Add coinstaller to ClassCoInstallersListHead list */
2970 FIXME("Class coinstaller is '%S'. UNIMPLEMENTED!\n", ptr
);
2973 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
2976 RpcStringFreeW(&lpGuidString
);
2981 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
2983 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
2984 if (hKey
!= INVALID_HANDLE_VALUE
)
2986 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2987 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2989 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2990 if (KeyBuffer
!= NULL
)
2992 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
2993 if (rc
== ERROR_SUCCESS
)
2995 /* Get ClassInstaller function pointer */
2996 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
2998 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
2999 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3002 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3009 /* Call Class co-installers */
3010 Context
.PostProcessing
= FALSE
;
3012 ListEntry
= ClassCoInstallersListHead
.Flink
;
3013 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3015 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3016 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3017 coinstaller
->PrivateData
= Context
.PrivateData
;
3018 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3020 coinstaller
->DoPostProcessing
= TRUE
;
3023 ListEntry
= ListEntry
->Flink
;
3026 /* Call Device co-installers */
3027 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3028 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3030 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3031 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3032 coinstaller
->PrivateData
= Context
.PrivateData
;
3033 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3035 coinstaller
->DoPostProcessing
= TRUE
;
3038 ListEntry
= ListEntry
->Flink
;
3041 /* Call Class installer */
3044 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3045 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3048 rc
= ERROR_DI_DO_DEFAULT
;
3050 /* Call default handler */
3051 if (rc
== ERROR_DI_DO_DEFAULT
)
3053 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3055 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3058 rc
= GetLastError();
3064 /* Call Class co-installers that required postprocessing */
3065 Context
.PostProcessing
= TRUE
;
3066 ListEntry
= ClassCoInstallersListHead
.Flink
;
3067 while (ListEntry
!= &ClassCoInstallersListHead
)
3069 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3070 if (coinstaller
->DoPostProcessing
)
3072 Context
.InstallResult
= rc
;
3073 Context
.PrivateData
= coinstaller
->PrivateData
;
3074 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3076 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3077 ListEntry
= ListEntry
->Flink
;
3080 /* Call Device co-installers that required postprocessing */
3081 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3082 while (ListEntry
!= &DeviceCoInstallersListHead
)
3084 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3085 if (coinstaller
->DoPostProcessing
)
3087 Context
.InstallResult
= rc
;
3088 Context
.PrivateData
= coinstaller
->PrivateData
;
3089 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3091 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3092 ListEntry
= ListEntry
->Flink
;
3095 /* Free allocated memory */
3096 while (!IsListEmpty(&ClassCoInstallersListHead
))
3098 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3099 HeapFree(GetProcessHeap(), 0, ListEntry
);
3101 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3103 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3104 HeapFree(GetProcessHeap(), 0, ListEntry
);
3107 ret
= (rc
== NO_ERROR
);
3111 TRACE("Returning %d\n", ret
);
3115 /***********************************************************************
3116 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3118 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3119 IN HDEVINFO DeviceInfoSet
,
3120 IN PSP_DEVINFO_DATA DeviceInfoData
,
3121 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3123 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3126 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3128 if (DeviceInstallParams
== NULL
)
3129 SetLastError(ERROR_INVALID_PARAMETER
);
3130 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3131 SetLastError(ERROR_INVALID_USER_BUFFER
);
3134 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3135 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3139 /* Do W->A conversion */
3141 DeviceInstallParams
,
3142 &deviceInstallParamsW
,
3143 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3144 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3145 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3147 DeviceInstallParams
->DriverPath
[0] = '\0';
3153 TRACE("Returning %d\n", ret
);
3157 /***********************************************************************
3158 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3160 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3161 IN HDEVINFO DeviceInfoSet
,
3162 IN PSP_DEVINFO_DATA DeviceInfoData
,
3163 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3165 struct DeviceInfoSet
*list
;
3168 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3171 SetLastError(ERROR_INVALID_HANDLE
);
3172 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3173 SetLastError(ERROR_INVALID_HANDLE
);
3174 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3175 SetLastError(ERROR_INVALID_USER_BUFFER
);
3176 else if (!DeviceInstallParams
)
3177 SetLastError(ERROR_INVALID_PARAMETER
);
3178 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3179 SetLastError(ERROR_INVALID_USER_BUFFER
);
3182 PSP_DEVINSTALL_PARAMS_W Source
;
3185 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3187 Source
= &list
->InstallParams
;
3188 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3192 TRACE("Returning %d\n", ret
);
3196 /***********************************************************************
3197 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3199 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3200 IN HDEVINFO DeviceInfoSet
,
3201 IN PSP_DEVINFO_DATA DeviceInfoData
,
3202 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3204 struct DeviceInfoSet
*list
;
3207 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3210 SetLastError(ERROR_INVALID_HANDLE
);
3211 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3212 SetLastError(ERROR_INVALID_HANDLE
);
3213 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3214 SetLastError(ERROR_INVALID_USER_BUFFER
);
3215 else if (!DeviceInstallParams
)
3216 SetLastError(ERROR_INVALID_PARAMETER
);
3217 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3218 SetLastError(ERROR_INVALID_USER_BUFFER
);
3221 PSP_DEVINSTALL_PARAMS_W Destination
;
3223 /* FIXME: Validate parameters */
3226 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3228 Destination
= &list
->InstallParams
;
3229 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3233 TRACE("Returning %d\n", ret
);
3237 /***********************************************************************
3238 * SetupDiCreateDevRegKey (SETUPAPI.@)
3240 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3241 IN HDEVINFO DeviceInfoSet
,
3242 IN PSP_DEVINFO_DATA DeviceInfoData
,
3246 IN HINF InfHandle OPTIONAL
,
3247 IN PCWSTR InfSectionName OPTIONAL
)
3249 struct DeviceInfoSet
*list
;
3250 HKEY ret
= INVALID_HANDLE_VALUE
;
3252 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3253 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3256 SetLastError(ERROR_INVALID_HANDLE
);
3257 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3258 SetLastError(ERROR_INVALID_HANDLE
);
3259 else if (!DeviceInfoData
)
3260 SetLastError(ERROR_INVALID_PARAMETER
);
3261 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3262 SetLastError(ERROR_INVALID_USER_BUFFER
);
3263 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3264 SetLastError(ERROR_INVALID_PARAMETER
);
3265 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3266 SetLastError(ERROR_INVALID_PARAMETER
);
3267 else if (InfHandle
&& !InfSectionName
)
3268 SetLastError(ERROR_INVALID_PARAMETER
);
3269 else if (!InfHandle
&& InfSectionName
)
3270 SetLastError(ERROR_INVALID_PARAMETER
);
3273 LPWSTR lpGuidString
= NULL
;
3274 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3275 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3276 DWORD Index
; /* Index used in the DriverKey name */
3278 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3279 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3280 HKEY hKey
= INVALID_HANDLE_VALUE
;
3282 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3284 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3288 if (KeyType
== DIREG_DEV
)
3290 FIXME("DIREG_DEV case unimplemented\n");
3292 else /* KeyType == DIREG_DRV */
3294 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3296 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3297 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3300 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3303 wcscpy(DriverKey
, L
"{");
3304 wcscat(DriverKey
, lpGuidString
);
3305 wcscat(DriverKey
, L
"}\\");
3306 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3307 rc
= RegOpenKeyExW(list
->HKLM
,
3312 if (rc
!= ERROR_SUCCESS
)
3318 /* Try all values for Index between 0 and 9999 */
3320 while (Index
<= 9999)
3323 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3324 rc
= RegCreateKeyEx(hClassKey
,
3328 REG_OPTION_NON_VOLATILE
,
3329 KEY_READ
| KEY_WRITE
,
3333 if (rc
!= ERROR_SUCCESS
)
3338 if (Disposition
== REG_CREATED_NEW_KEY
)
3341 hKey
= INVALID_HANDLE_VALUE
;
3346 /* Unable to create more than 9999 devices within the same class */
3347 SetLastError(ERROR_GEN_FAILURE
);
3351 /* Open device key, to write Driver value */
3352 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3353 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3355 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3356 if (rc
!= ERROR_SUCCESS
)
3363 /* Do installation of the specified section */
3366 FIXME("Need to install section %s in file %p\n",
3367 debugstr_w(InfSectionName
), InfHandle
);
3373 RpcStringFreeW(&lpGuidString
);
3374 HeapFree(GetProcessHeap(), 0, DriverKey
);
3375 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3376 RegCloseKey(hClassKey
);
3377 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3378 RegCloseKey(hDeviceKey
);
3379 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3383 TRACE("Returning 0x%p\n", ret
);
3387 /***********************************************************************
3388 * SetupDiOpenDevRegKey (SETUPAPI.@)
3390 HKEY WINAPI
SetupDiOpenDevRegKey(
3391 HDEVINFO DeviceInfoSet
,
3392 PSP_DEVINFO_DATA DeviceInfoData
,
3398 struct DeviceInfoSet
*list
;
3399 HKEY ret
= INVALID_HANDLE_VALUE
;
3401 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3402 Scope
, HwProfile
, KeyType
, samDesired
);
3405 SetLastError(ERROR_INVALID_HANDLE
);
3406 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3407 SetLastError(ERROR_INVALID_HANDLE
);
3408 else if (!DeviceInfoData
)
3409 SetLastError(ERROR_INVALID_PARAMETER
);
3410 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3411 SetLastError(ERROR_INVALID_USER_BUFFER
);
3412 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3413 SetLastError(ERROR_INVALID_PARAMETER
);
3414 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3415 SetLastError(ERROR_INVALID_PARAMETER
);
3418 HKEY hKey
= INVALID_HANDLE_VALUE
;
3419 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3420 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3421 LPWSTR DriverKey
= NULL
;
3426 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3428 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3430 else /* Scope == DICS_FLAG_GLOBAL */
3436 KEY_ENUMERATE_SUB_KEYS
,
3438 if (rc
!= ERROR_SUCCESS
)
3445 deviceInfo
->DeviceName
,
3447 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3449 RegCloseKey(hRootKey
);
3450 hRootKey
= INVALID_HANDLE_VALUE
;
3451 if (rc
!= ERROR_SUCCESS
)
3456 if (KeyType
== DIREG_DEV
)
3458 /* We're done. Just return the hKey handle */
3462 /* Read the 'Driver' key */
3463 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3464 if (rc
!= ERROR_SUCCESS
)
3469 if (dwRegType
!= REG_SZ
)
3471 SetLastError(ERROR_GEN_FAILURE
);
3474 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3477 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3480 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3481 if (rc
!= ERROR_SUCCESS
)
3487 hKey
= INVALID_HANDLE_VALUE
;
3488 /* Need to open the driver key */
3493 KEY_ENUMERATE_SUB_KEYS
,
3495 if (rc
!= ERROR_SUCCESS
)
3506 if (rc
!= ERROR_SUCCESS
)
3514 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3515 RegCloseKey(hRootKey
);
3516 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3520 TRACE("Returning 0x%p\n", ret
);
3524 /***********************************************************************
3525 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3527 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3528 HDEVINFO DeviceInfoSet
,
3530 CONST GUID
*ClassGuid
,
3531 PCSTR DeviceDescription
,
3533 DWORD CreationFlags
,
3534 PSP_DEVINFO_DATA DeviceInfoData
)
3536 LPWSTR DeviceNameW
= NULL
;
3537 LPWSTR DeviceDescriptionW
= NULL
;
3544 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3545 if (DeviceNameW
== NULL
) return FALSE
;
3547 if (DeviceDescription
)
3549 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3550 if (DeviceDescriptionW
== NULL
)
3552 if (DeviceNameW
) MyFree(DeviceNameW
);
3557 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3558 ClassGuid
, DeviceDescriptionW
,
3559 hwndParent
, CreationFlags
,
3562 if (DeviceNameW
) MyFree(DeviceNameW
);
3563 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3568 /***********************************************************************
3569 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3571 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3572 HDEVINFO DeviceInfoSet
,
3574 CONST GUID
*ClassGuid
,
3575 PCWSTR DeviceDescription
,
3577 DWORD CreationFlags
,
3578 PSP_DEVINFO_DATA DeviceInfoData
)
3580 struct DeviceInfoSet
*list
;
3583 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3584 debugstr_guid(ClassGuid
), DeviceDescription
,
3585 hwndParent
, CreationFlags
, DeviceInfoData
);
3588 SetLastError(ERROR_INVALID_HANDLE
);
3589 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3590 SetLastError(ERROR_INVALID_HANDLE
);
3591 else if (!ClassGuid
)
3592 SetLastError(ERROR_INVALID_PARAMETER
);
3593 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3594 SetLastError(ERROR_CLASS_MISMATCH
);
3595 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3597 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3598 SetLastError(ERROR_INVALID_PARAMETER
);
3602 SP_DEVINFO_DATA DevInfo
;
3604 if (CreationFlags
& DICD_GENERATE_ID
)
3606 /* Generate a new unique ID for this device */
3607 SetLastError(ERROR_GEN_FAILURE
);
3608 FIXME("not implemented\n");
3612 /* Device name is fully qualified. Try to open it */
3615 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3616 rc
= SetupDiOpenDeviceInfoW(
3619 NULL
, /* hwndParent */
3620 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3625 /* SetupDiOpenDeviceInfoW has already added
3626 * the device info to the device info set
3628 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3630 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3632 struct DeviceInfoElement
*deviceInfo
;
3634 /* FIXME: ClassGuid can be NULL */
3635 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3637 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3639 if (!DeviceInfoData
)
3643 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3645 SetLastError(ERROR_INVALID_USER_BUFFER
);
3649 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3650 DeviceInfoData
->DevInst
= 0; /* FIXME */
3651 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3660 TRACE("Returning %d\n", ret
);
3664 /***********************************************************************
3665 * Helper functions for SetupDiBuildDriverInfoList
3669 IN PLIST_ENTRY DriverListHead
,
3670 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3671 IN LPGUID ClassGuid
,
3672 IN INFCONTEXT ContextDevice
,
3674 IN LPCWSTR ProviderName
,
3675 IN LPCWSTR ManufacturerName
,
3676 IN LPCWSTR MatchingId
,
3677 FILETIME DriverDate
,
3678 DWORDLONG DriverVersion
,
3681 struct DriverInfoElement
*driverInfo
= NULL
;
3682 HANDLE hFile
= INVALID_HANDLE_VALUE
;
3683 DWORD RequiredSize
= 128; /* Initial buffer size */
3684 BOOL Result
= FALSE
;
3685 PLIST_ENTRY PreviousEntry
;
3686 LPWSTR InfInstallSection
= NULL
;
3689 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3692 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3695 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3697 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
3698 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
3700 /* Copy InfFileName field */
3701 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
);
3703 /* Fill InfDate field */
3704 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3705 GENERIC_READ, FILE_SHARE_READ,
3706 NULL, OPEN_EXISTING, 0, NULL);
3707 if (hFile == INVALID_HANDLE_VALUE)
3709 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
3713 /* Fill SectionName field */
3714 Result
= SetupGetStringFieldW(
3717 driverInfo
->Details
.SectionName
, LINE_LEN
,
3722 /* Fill DrvDescription field */
3723 Result
= SetupGetStringFieldW(
3725 0, /* Field index */
3726 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
3729 /* Copy MatchingId information */
3730 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3731 if (!driverInfo
->MatchingId
)
3733 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3736 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3738 /* Get inf install section */
3740 RequiredSize
= 128; /* Initial buffer size */
3741 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3742 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3744 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3745 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3746 if (!InfInstallSection
)
3748 Result
= SetupGetStringFieldW(
3750 1, /* Field index */
3751 InfInstallSection
, RequiredSize
,
3757 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3758 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
3760 driverInfo
->DriverRank
= Rank
;
3761 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3762 driverInfo
->Info
.DriverType
= DriverType
;
3763 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3764 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
3765 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3766 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3767 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3770 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3771 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3774 driverInfo
->Info
.ProviderName
[0] = '\0';
3775 driverInfo
->Info
.DriverDate
= DriverDate
;
3776 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3778 /* Insert current driver in driver list, according to its rank */
3779 PreviousEntry
= DriverListHead
->Flink
;
3780 while (PreviousEntry
!= DriverListHead
)
3782 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3784 /* Insert before the current item */
3785 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
3789 if (PreviousEntry
== DriverListHead
)
3791 /* Insert at the end of the list */
3792 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
3801 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
3802 HeapFree(GetProcessHeap(), 0, driverInfo
);
3804 if (hFile
!= INVALID_HANDLE_VALUE
)
3806 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3812 GetVersionInformationFromInfFile(
3814 OUT LPGUID ClassGuid
,
3815 OUT LPWSTR
* pProviderName
,
3816 OUT FILETIME
* DriverDate
,
3817 OUT DWORDLONG
* DriverVersion
)
3820 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
3821 LPWSTR DriverVer
= NULL
;
3822 LPWSTR ProviderName
= NULL
;
3823 LPWSTR pComma
; /* Points into DriverVer */
3824 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
3825 SYSTEMTIME SystemTime
;
3827 BOOL ret
= FALSE
; /* Final result */
3829 /* Get class Guid */
3830 if (!SetupGetLineTextW(
3833 L
"Version", L
"ClassGUID",
3834 guidW
, sizeof(guidW
),
3835 NULL
/* Required size */))
3839 guidW
[37] = '\0'; /* Replace the } by a NULL character */
3840 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
3842 SetLastError(ERROR_GEN_FAILURE
);
3846 /* Get provider name */
3847 Result
= SetupGetLineTextW(
3849 hInf
, L
"Version", L
"Provider",
3854 /* We know know the needed buffer size */
3855 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3858 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3861 Result
= SetupGetLineTextW(
3863 hInf
, L
"Version", L
"Provider",
3864 ProviderName
, RequiredSize
,
3869 *pProviderName
= ProviderName
;
3871 /* Read the "DriverVer" value */
3872 Result
= SetupGetLineTextW(
3874 hInf
, L
"Version", L
"DriverVer",
3879 /* We know know the needed buffer size */
3880 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3883 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3886 Result
= SetupGetLineTextW(
3888 hInf
, L
"Version", L
"DriverVer",
3889 DriverVer
, RequiredSize
,
3895 /* Get driver date and driver version, by analyzing the "DriverVer" value */
3896 pComma
= wcschr(DriverVer
, ',');
3899 *pComma
= UNICODE_NULL
;
3900 pVersion
= pComma
+ 1;
3902 /* Get driver date version. Invalid date = 00/00/00 */
3903 memset(DriverDate
, 0, sizeof(FILETIME
));
3904 if (wcslen(DriverVer
) == 10
3905 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
3906 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
3908 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
3909 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
3910 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
3911 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
3912 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
3913 SystemTimeToFileTime(&SystemTime
, DriverDate
);
3915 /* Get driver version. Invalid version = 0.0.0.0 */
3917 /* FIXME: use pVersion to fill DriverVersion variable */
3923 HeapFree(GetProcessHeap(), 0, ProviderName
);
3924 HeapFree(GetProcessHeap(), 0, DriverVer
);
3926 TRACE("Returning %d\n", ret
);
3930 /***********************************************************************
3931 * SetupDiBuildDriverInfoList (SETUPAPI.@)
3934 SetupDiBuildDriverInfoList(
3935 IN HDEVINFO DeviceInfoSet
,
3936 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3937 IN DWORD DriverType
)
3939 struct DeviceInfoSet
*list
;
3940 SP_DEVINSTALL_PARAMS_W InstallParams
;
3941 PVOID Buffer
= NULL
;
3942 HINF hInf
= INVALID_HANDLE_VALUE
;
3943 LPWSTR ProviderName
= NULL
;
3944 LPWSTR ManufacturerName
= NULL
;
3945 LPWSTR ManufacturerSection
= NULL
;
3946 LPWSTR HardwareIDs
= NULL
;
3947 LPWSTR CompatibleIDs
= NULL
;
3948 FILETIME DriverDate
;
3949 DWORDLONG DriverVersion
= 0;
3953 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
3956 SetLastError(ERROR_INVALID_HANDLE
);
3957 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3958 SetLastError(ERROR_INVALID_HANDLE
);
3959 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
3960 SetLastError(ERROR_INVALID_HANDLE
);
3961 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
3962 SetLastError(ERROR_INVALID_PARAMETER
);
3963 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
3964 SetLastError(ERROR_INVALID_PARAMETER
);
3965 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
3966 SetLastError(ERROR_INVALID_PARAMETER
);
3967 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3968 SetLastError(ERROR_INVALID_USER_BUFFER
);
3973 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3974 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3978 if (DriverType
== SPDIT_COMPATDRIVER
)
3980 /* Get hardware IDs list */
3982 RequiredSize
= 512; /* Initial buffer size */
3983 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3984 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3986 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
3987 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
3990 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3993 Result
= SetupDiGetDeviceRegistryPropertyW(
4005 /* Get compatible IDs list */
4007 RequiredSize
= 512; /* Initial buffer size */
4008 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4009 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4011 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4012 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4015 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4018 Result
= SetupDiGetDeviceRegistryPropertyW(
4021 SPDRP_COMPATIBLEIDS
,
4023 (PBYTE
)CompatibleIDs
,
4026 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4028 /* No compatible ID for this device */
4029 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4030 CompatibleIDs
= NULL
;
4038 /* Enumerate .inf files */
4040 RequiredSize
= 32768; /* Initial buffer size */
4041 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4042 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4044 HeapFree(GetProcessHeap(), 0, Buffer
);
4045 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4049 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4052 Result
= SetupGetInfFileListW(
4053 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4055 Buffer
, RequiredSize
,
4062 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4064 INFCONTEXT ContextManufacturer
, ContextDevice
;
4066 TRACE("Opening file %S\n", filename
);
4068 hInf
= SetupOpenInfFileW(filename
, NULL
, INF_STYLE_WIN4
, NULL
);
4069 if (hInf
== INVALID_HANDLE_VALUE
)
4072 if (!GetVersionInformationFromInfFile(
4079 SetupCloseInfFile(hInf
);
4080 hInf
= INVALID_HANDLE_VALUE
;
4084 if (DriverType
== SPDIT_CLASSDRIVER
)
4086 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4087 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4093 /* Get the manufacturers list */
4094 Result
= SetupFindFirstLineW(hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4097 Result
= SetupGetStringFieldW(
4098 &ContextManufacturer
,
4099 0, /* Field index */
4104 /* We got the needed size for the buffer */
4105 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4106 if (!ManufacturerName
)
4108 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4111 Result
= SetupGetStringFieldW(
4112 &ContextManufacturer
,
4113 0, /* Field index */
4114 ManufacturerName
, RequiredSize
,
4117 Result
= SetupGetStringFieldW(
4118 &ContextManufacturer
,
4119 1, /* Field index */
4124 /* We got the needed size for the buffer */
4125 ManufacturerSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4126 if (!ManufacturerSection
)
4128 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4131 Result
= SetupGetStringFieldW(
4132 &ContextManufacturer
,
4133 1, /* Field index */
4134 ManufacturerSection
, RequiredSize
,
4138 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4139 Result
= SetupFindFirstLineW(hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4142 if (DriverType
== SPDIT_CLASSDRIVER
)
4144 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4145 if (!AddDriverToList(
4146 &list
->DriverListHead
,
4154 DriverDate
, DriverVersion
,
4160 else /* DriverType = SPDIT_COMPATDRIVER */
4162 /* 1. Get all fields */
4163 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4167 BOOL DriverAlreadyAdded
;
4169 for (i
= 2; i
<= FieldCount
; i
++)
4171 LPWSTR DeviceId
= NULL
;
4173 RequiredSize
= 128; /* Initial buffer size */
4174 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4175 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4177 HeapFree(GetProcessHeap(), 0, DeviceId
);
4178 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4181 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4184 Result
= SetupGetStringFieldW(
4187 DeviceId
, RequiredSize
,
4192 HeapFree(GetProcessHeap(), 0, DeviceId
);
4195 DriverAlreadyAdded
= FALSE
;
4196 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4198 if (wcscmp(DeviceId
, currentId
) == 0)
4201 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4209 DriverDate
, DriverVersion
,
4210 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4211 DriverAlreadyAdded
= TRUE
;
4216 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4218 if (wcscmp(DeviceId
, currentId
) == 0)
4221 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4229 DriverDate
, DriverVersion
,
4230 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4231 DriverAlreadyAdded
= TRUE
;
4235 HeapFree(GetProcessHeap(), 0, DeviceId
);
4238 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4241 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4242 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
4243 ManufacturerName
= ManufacturerSection
= NULL
;
4244 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4249 HeapFree(GetProcessHeap(), 0, ProviderName
);
4250 ProviderName
= NULL
;
4252 SetupCloseInfFile(hInf
);
4253 hInf
= INVALID_HANDLE_VALUE
;
4264 InstallParams
.Flags
|= DI_DIDCOMPAT
;
4265 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
4269 InstallParams
.Flags
|= DI_DIDCLASS
;
4270 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
4272 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4275 HeapFree(GetProcessHeap(), 0, ProviderName
);
4276 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4277 HeapFree(GetProcessHeap(), 0, ManufacturerSection
);
4278 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4279 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4280 if (hInf
!= INVALID_HANDLE_VALUE
)
4281 SetupCloseInfFile(hInf
);
4282 HeapFree(GetProcessHeap(), 0, Buffer
);
4284 TRACE("Returning %d\n", ret
);
4288 /***********************************************************************
4289 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4292 SetupDiDeleteDeviceInfo(
4293 IN HDEVINFO DeviceInfoSet
,
4294 IN PSP_DEVINFO_DATA DeviceInfoData
)
4296 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4298 FIXME("not implemented\n");
4299 SetLastError(ERROR_GEN_FAILURE
);
4304 /***********************************************************************
4305 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4308 SetupDiDestroyDriverInfoList(
4309 IN HDEVINFO DeviceInfoSet
,
4310 IN PSP_DEVINFO_DATA DeviceInfoData
,
4311 IN DWORD DriverType
)
4313 struct DeviceInfoSet
*list
;
4316 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
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 (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4323 SetLastError(ERROR_INVALID_PARAMETER
);
4324 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4325 SetLastError(ERROR_INVALID_PARAMETER
);
4326 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4327 SetLastError(ERROR_INVALID_USER_BUFFER
);
4330 PLIST_ENTRY ListEntry
;
4331 struct DriverInfoElement
*driverInfo
;
4332 SP_DEVINSTALL_PARAMS_W InstallParams
;
4334 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4335 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4338 if (!DeviceInfoData
)
4339 /* Fall back to destroying class driver list */
4340 DriverType
= SPDIT_CLASSDRIVER
;
4341 if (DriverType
== SPDIT_CLASSDRIVER
)
4343 if (!(InstallParams
.Flags
& DI_DIDCLASS
))
4344 /* The list was not created */
4347 else if (DriverType
== SPDIT_COMPATDRIVER
)
4349 if (!(InstallParams
.Flags
& DI_DIDCOMPAT
))
4350 /* The list was not created */
4354 if (DriverType
== SPDIT_CLASSDRIVER
)
4356 while (!IsListEmpty(&list
->DriverListHead
))
4358 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
4359 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4360 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4361 HeapFree(GetProcessHeap(), 0, driverInfo
);
4363 InstallParams
.Reserved
= 0;
4364 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
4365 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
4366 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
4370 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
4371 struct DeviceInfoElement
*deviceInfo
;
4373 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4374 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
4376 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4377 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
4379 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
4380 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4381 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
4383 InstallParamsSet
.Reserved
= 0;
4384 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
4386 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4387 HeapFree(GetProcessHeap(), 0, driverInfo
);
4389 InstallParams
.Reserved
= 0;
4390 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
4391 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
4392 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4397 TRACE("Returning %d\n", ret
);
4402 /***********************************************************************
4403 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4406 SetupDiOpenDeviceInfoA(
4407 IN HDEVINFO DeviceInfoSet
,
4408 IN PCSTR DeviceInstanceId
,
4409 IN HWND hwndParent OPTIONAL
,
4411 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4413 LPWSTR DeviceInstanceIdW
= NULL
;
4416 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4418 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4419 if (DeviceInstanceIdW
== NULL
)
4422 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4423 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4425 MyFree(DeviceInstanceIdW
);
4431 /***********************************************************************
4432 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4435 SetupDiOpenDeviceInfoW(
4436 IN HDEVINFO DeviceInfoSet
,
4437 IN PCWSTR DeviceInstanceId
,
4438 IN HWND hwndParent OPTIONAL
,
4440 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4442 struct DeviceInfoSet
*list
;
4443 HKEY hEnumKey
, hKey
;
4447 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4449 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4450 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4453 SetLastError(ERROR_INVALID_HANDLE
);
4454 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4455 SetLastError(ERROR_INVALID_HANDLE
);
4456 else if (!DeviceInstanceId
)
4457 SetLastError(ERROR_INVALID_PARAMETER
);
4458 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4460 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4461 SetLastError(ERROR_INVALID_PARAMETER
);
4463 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4464 SetLastError(ERROR_INVALID_USER_BUFFER
);
4467 struct DeviceInfoElement
*deviceInfo
= NULL
;
4468 /* Search if device already exists in DeviceInfoSet.
4469 * If yes, return the existing element
4470 * If no, create a new element using informations in registry
4472 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4473 while (ItemList
!= &list
->ListHead
)
4478 FIXME("not implemented\n");
4479 ItemList
= ItemList
->Flink
;
4484 /* good one found */
4489 /* Open supposed registry key */
4494 KEY_ENUMERATE_SUB_KEYS
,
4496 if (rc
!= ERROR_SUCCESS
)
4507 RegCloseKey(hEnumKey
);
4508 if (rc
!= ERROR_SUCCESS
)
4514 /* FIXME: GUID_NULL is not allowed */
4515 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
/* FIXME */, &deviceInfo
))
4520 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4526 if (ret
&& deviceInfo
&& DeviceInfoData
)
4528 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4529 DeviceInfoData
->DevInst
= 0; /* FIXME */
4530 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4538 /***********************************************************************
4539 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4542 SetupDiEnumDriverInfoA(
4543 IN HDEVINFO DeviceInfoSet
,
4544 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4545 IN DWORD DriverType
,
4546 IN DWORD MemberIndex
,
4547 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4549 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4552 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4553 DriverType
, MemberIndex
, DriverInfoData
);
4555 if (DriverInfoData
== NULL
)
4556 SetLastError(ERROR_INVALID_PARAMETER
);
4557 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4558 SetLastError(ERROR_INVALID_USER_BUFFER
);
4561 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4562 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4563 DriverType
, MemberIndex
, &driverInfoData2W
);
4567 /* Do W->A conversion */
4568 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4569 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4570 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4571 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4573 DriverInfoData
->Description
[0] = '\0';
4576 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4577 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4579 DriverInfoData
->MfgName
[0] = '\0';
4582 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4583 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4585 DriverInfoData
->ProviderName
[0] = '\0';
4588 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4590 /* Copy more fields */
4591 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4592 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4597 TRACE("Returning %d\n", ret
);
4602 /***********************************************************************
4603 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4606 SetupDiEnumDriverInfoW(
4607 IN HDEVINFO DeviceInfoSet
,
4608 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4609 IN DWORD DriverType
,
4610 IN DWORD MemberIndex
,
4611 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4613 PLIST_ENTRY ListHead
;
4616 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4617 DriverType
, MemberIndex
, DriverInfoData
);
4619 if (!DeviceInfoSet
|| !DriverInfoData
)
4620 SetLastError(ERROR_INVALID_PARAMETER
);
4621 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4622 SetLastError(ERROR_INVALID_HANDLE
);
4623 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4624 SetLastError(ERROR_INVALID_HANDLE
);
4625 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4626 SetLastError(ERROR_INVALID_PARAMETER
);
4627 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4628 SetLastError(ERROR_INVALID_PARAMETER
);
4629 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4630 SetLastError(ERROR_INVALID_PARAMETER
);
4631 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4632 SetLastError(ERROR_INVALID_USER_BUFFER
);
4635 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4636 PLIST_ENTRY ItemList
;
4637 if (DriverType
== SPDIT_CLASSDRIVER
||
4638 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4640 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4644 ListHead
= &devInfo
->DriverListHead
;
4647 ItemList
= ListHead
->Flink
;
4648 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4649 ItemList
= ItemList
->Flink
;
4650 if (ItemList
== ListHead
)
4651 SetLastError(ERROR_NO_MORE_ITEMS
);
4654 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4657 &DriverInfoData
->DriverType
,
4658 &DrvInfo
->Info
.DriverType
,
4659 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4664 TRACE("Returning %d\n", ret
);
4668 /***********************************************************************
4669 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4672 SetupDiGetSelectedDriverW(
4673 IN HDEVINFO DeviceInfoSet
,
4674 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4675 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4679 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4681 if (!DeviceInfoSet
|| !DriverInfoData
)
4682 SetLastError(ERROR_INVALID_PARAMETER
);
4683 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4684 SetLastError(ERROR_INVALID_HANDLE
);
4685 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4686 SetLastError(ERROR_INVALID_HANDLE
);
4687 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4688 SetLastError(ERROR_INVALID_USER_BUFFER
);
4689 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4690 SetLastError(ERROR_INVALID_USER_BUFFER
);
4693 SP_DEVINSTALL_PARAMS InstallParams
;
4695 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4696 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4698 struct DriverInfoElement
*driverInfo
;
4699 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
4700 if (driverInfo
== NULL
)
4701 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4705 &DriverInfoData
->DriverType
,
4706 &driverInfo
->Info
.DriverType
,
4707 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4713 TRACE("Returning %d\n", ret
);
4717 /***********************************************************************
4718 * SetupDiSetSelectedDriverW (SETUPAPI.@)
4721 SetupDiSetSelectedDriverW(
4722 IN HDEVINFO DeviceInfoSet
,
4723 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4724 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
4728 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4731 SetLastError(ERROR_INVALID_PARAMETER
);
4732 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4733 SetLastError(ERROR_INVALID_HANDLE
);
4734 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4735 SetLastError(ERROR_INVALID_HANDLE
);
4736 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4737 SetLastError(ERROR_INVALID_USER_BUFFER
);
4738 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4739 SetLastError(ERROR_INVALID_USER_BUFFER
);
4742 struct DriverInfoElement
**pDriverInfo
;
4743 PLIST_ENTRY ListHead
, ItemList
;
4747 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
4748 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
4752 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
4753 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4756 if (!DriverInfoData
)
4758 *pDriverInfo
= NULL
;
4763 /* Search selected driver in list */
4764 ItemList
= ListHead
->Flink
;
4765 while (ItemList
!= ListHead
)
4767 if (DriverInfoData
->Reserved
!= 0)
4769 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
4774 /* The caller wants to compare only DriverType, Description and ProviderName fields */
4775 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
4776 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
4777 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
4778 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
4784 if (ItemList
== ListHead
)
4785 SetLastError(ERROR_INVALID_PARAMETER
);
4788 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
4789 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
4791 TRACE("Choosing driver whose rank is 0x%lx\n",
4792 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
4794 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
4799 TRACE("Returning %d\n", ret
);
4803 /***********************************************************************
4804 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
4807 SetupDiGetDriverInfoDetailA(
4808 IN HDEVINFO DeviceInfoSet
,
4809 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4810 IN PSP_DRVINFO_DATA_A DriverInfoData
,
4811 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
4812 IN DWORD DriverInfoDetailDataSize
,
4813 OUT PDWORD RequiredSize OPTIONAL
)
4815 FIXME("%p %p %p %p 0x%lx %p\n", DeviceInfoSet
, DeviceInfoData
,
4816 DriverInfoData
, DriverInfoDetailData
, DriverInfoDetailDataSize
,
4818 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4822 /***********************************************************************
4823 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
4826 SetupDiGetDriverInfoDetailW(
4827 IN HDEVINFO DeviceInfoSet
,
4828 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4829 IN PSP_DRVINFO_DATA_W DriverInfoData
,
4830 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
4831 IN DWORD DriverInfoDetailDataSize
,
4832 OUT PDWORD RequiredSize OPTIONAL
)
4837 SetLastError(ERROR_INVALID_PARAMETER
);
4838 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4839 SetLastError(ERROR_INVALID_HANDLE
);
4840 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4841 SetLastError(ERROR_INVALID_HANDLE
);
4842 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4843 SetLastError(ERROR_INVALID_USER_BUFFER
);
4844 else if (!DriverInfoData
)
4845 SetLastError(ERROR_INVALID_PARAMETER
);
4846 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
4847 SetLastError(ERROR_INVALID_PARAMETER
);
4848 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
4849 SetLastError(ERROR_INVALID_PARAMETER
);
4850 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
4851 SetLastError(ERROR_INVALID_USER_BUFFER
);
4852 else if (DriverInfoDetailData
&& DriverInfoDetailData
->Reserved
== 0)
4853 SetLastError(ERROR_INVALID_PARAMETER
);
4856 struct DriverInfoElement
*driverInfoElement
;
4857 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
4860 DriverInfoDetailData
,
4861 &driverInfoElement
->Details
,
4862 driverInfoElement
->Details
.cbSize
);
4863 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
4864 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
4869 TRACE("Returning %d\n", ret
);
4873 /***********************************************************************
4874 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
4877 SetupDiSelectBestCompatDrv(
4878 IN HDEVINFO DeviceInfoSet
,
4879 IN PSP_DEVINFO_DATA DeviceInfoData
)
4881 SP_DRVINFO_DATA_W drvInfoData
;
4884 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4886 /* Drivers are sorted by rank in the driver list, so
4887 * the first driver in the list is the best one.
4889 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
4890 ret
= SetupDiEnumDriverInfoW(
4894 0, /* Member index */
4899 ret
= SetupDiSetSelectedDriverW(
4905 TRACE("Returning %d\n", ret
);
4909 /***********************************************************************
4910 * SetupDiInstallDriverFiles (SETUPAPI.@)
4913 SetupDiInstallDriverFiles(
4914 IN HDEVINFO DeviceInfoSet
,
4915 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4919 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4922 SetLastError(ERROR_INVALID_PARAMETER
);
4923 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4924 SetLastError(ERROR_INVALID_HANDLE
);
4925 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4926 SetLastError(ERROR_INVALID_HANDLE
);
4927 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4928 SetLastError(ERROR_INVALID_USER_BUFFER
);
4929 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
4930 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4931 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
4932 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4935 SP_DEVINSTALL_PARAMS_W InstallParams
;
4936 HINF hInf
= INVALID_HANDLE_VALUE
;
4937 struct DriverInfoElement
*SelectedDriver
;
4938 WCHAR SectionName
[MAX_PATH
];
4939 DWORD SectionNameLength
= 0;
4941 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4942 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4946 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
4947 if (!SelectedDriver
)
4949 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4953 hInf
= SetupOpenInfFileW(SelectedDriver
->Details
.InfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
4954 if (hInf
== INVALID_HANDLE_VALUE
)
4957 ret
= SetupDiGetActualSectionToInstallW(hInf
, SelectedDriver
->Details
.SectionName
,
4958 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4962 if (InstallParams
.InstallMsgHandler
)
4964 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
, hInf
, SectionName
,
4965 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
4966 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
4967 DeviceInfoSet
, DeviceInfoData
);
4971 PVOID callback_context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
4972 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
, hInf
, SectionName
,
4973 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
4974 SetupDefaultQueueCallbackW
, callback_context
,
4975 DeviceInfoSet
, DeviceInfoData
);
4976 SetupTermDefaultQueueCallback(callback_context
);
4979 if (hInf
!= INVALID_HANDLE_VALUE
)
4980 SetupCloseInfFile(hInf
);
4983 InstallParams
.Flags
|= DI_NOFILECOPY
;
4984 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4988 TRACE("Returning %d\n", ret
);
4992 /***********************************************************************
4993 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4996 SetupDiRegisterCoDeviceInstallers(
4997 IN HDEVINFO DeviceInfoSet
,
4998 IN PSP_DEVINFO_DATA DeviceInfoData
)
5000 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5002 FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
5003 //SetLastError(ERROR_GEN_FAILURE);
5008 /***********************************************************************
5009 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5012 SetupDiInstallDeviceInterfaces(
5013 IN HDEVINFO DeviceInfoSet
,
5014 IN PSP_DEVINFO_DATA DeviceInfoData
)
5016 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5018 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5019 //SetLastError(ERROR_GEN_FAILURE);
5024 /***********************************************************************
5025 * SetupDiInstallDevice (SETUPAPI.@)
5028 SetupDiInstallDevice(
5029 IN HDEVINFO DeviceInfoSet
,
5030 IN PSP_DEVINFO_DATA DeviceInfoData
)
5032 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5033 SP_DEVINSTALL_PARAMS_W InstallParams
;
5034 struct DriverInfoElement
*SelectedDriver
;
5035 SYSTEMTIME DriverDate
;
5036 WCHAR SectionName
[MAX_PATH
];
5038 DWORD SectionNameLength
= 0;
5039 BOOL Result
= FALSE
;
5040 INFCONTEXT ContextService
;
5044 HINF hInf
= INVALID_HANDLE_VALUE
;
5045 LPCWSTR AssociatedService
= NULL
;
5046 LPWSTR pSectionName
= NULL
;
5047 LPWSTR ClassName
= NULL
;
5049 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5050 BOOL RebootRequired
= FALSE
;
5051 HKEY hKey
= INVALID_HANDLE_VALUE
;
5052 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
5054 BOOL ret
= FALSE
; /* Return value */
5056 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5059 SetLastError(ERROR_INVALID_PARAMETER
);
5060 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5061 SetLastError(ERROR_INVALID_HANDLE
);
5062 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5063 SetLastError(ERROR_INVALID_HANDLE
);
5064 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5065 SetLastError(ERROR_INVALID_USER_BUFFER
);
5071 /* One parameter is bad */
5075 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5076 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5080 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5082 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5086 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5087 if (SelectedDriver
== NULL
)
5089 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5093 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5095 hInf
= SetupOpenInfFileW(SelectedDriver
->Details
.InfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5096 if (hInf
== INVALID_HANDLE_VALUE
)
5099 Result
= SetupDiGetActualSectionToInstallW(hInf
, SelectedDriver
->Details
.SectionName
,
5100 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5101 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
5103 pSectionName
= &SectionName
[wcslen(SectionName
)];
5105 /* Get information from [Version] section */
5108 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
5110 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
5112 ClassName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5115 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5118 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, RequiredSize
, &RequiredSize
))
5121 /* Format ClassGuid to a string */
5122 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5124 RequiredSize
= lstrlenW(lpGuidString
);
5125 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5126 if (!lpFullGuidString
)
5128 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5131 lpFullGuidString
[0] = '{';
5132 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5133 lpFullGuidString
[RequiredSize
+ 1] = '}';
5134 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5136 /* Open/Create driver key information */
5137 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_SET_VALUE
);
5138 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5139 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5140 if (hKey
== INVALID_HANDLE_VALUE
)
5143 /* Install main section */
5144 DoAction
= SPINST_REGISTRY
;
5145 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5146 DoAction
|= SPINST_FILES
;
5147 /* Files have already been copied in SetupDiInstallDriverFiles.
5148 * Process only registry entries. */
5149 *pSectionName
= '\0';
5150 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
, hInf
, SectionName
,
5151 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5152 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5153 DeviceInfoSet
, DeviceInfoData
);
5156 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
5158 Result
= SetupCommitFileQueueW(InstallParams
.hwndParent
,
5159 InstallParams
.FileQueue
,
5160 InstallParams
.InstallMsgHandler
,
5161 InstallParams
.InstallMsgHandlerContext
);
5163 InstallParams
.Flags
|= DI_NOFILECOPY
;
5164 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5166 /* Write information to driver key */
5167 *pSectionName
= UNICODE_NULL
;
5168 TRACE("Write information to driver key\n");
5169 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5170 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5171 TRACE("DriverVersion : '%u.%u.%u.%u'\n", SelectedDriver
->Info
.DriverVersion
& 0xff, (SelectedDriver
->Info
.DriverVersion
>> 8) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 16) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 24) & 0xff);
5172 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
5173 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
5174 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
5175 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
5176 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
5177 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5178 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5179 if (rc
== ERROR_SUCCESS
)
5180 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5181 if (rc
== ERROR_SUCCESS
)
5182 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5183 if (rc
== ERROR_SUCCESS
)
5185 swprintf(Buffer
, L
"%u.%u.%u.%u", SelectedDriver
->Info
.DriverVersion
& 0xff, (SelectedDriver
->Info
.DriverVersion
>> 8) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 16) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 24) & 0xff);
5186 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5188 if (rc
== ERROR_SUCCESS
)
5189 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
5190 if (rc
== ERROR_SUCCESS
)
5191 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5192 if (rc
== ERROR_SUCCESS
)
5193 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5194 if (rc
== ERROR_SUCCESS
)
5195 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5196 if (rc
== ERROR_SUCCESS
)
5197 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5198 if (rc
!= ERROR_SUCCESS
)
5204 hKey
= INVALID_HANDLE_VALUE
;
5206 /* FIXME: Process .LogConfigOverride section */
5208 /* Install .Services section */
5209 wcscpy(pSectionName
, L
".Services");
5210 Result
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
5213 LPWSTR ServiceName
= NULL
;
5214 LPWSTR ServiceSection
= NULL
;
5216 Result
= SetupGetStringFieldW(
5218 1, /* Field index */
5223 if (RequiredSize
> 0)
5225 /* We got the needed size for the buffer */
5226 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5229 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5232 Result
= SetupGetStringFieldW(
5234 1, /* Field index */
5235 ServiceName
, RequiredSize
,
5240 Result
= SetupGetIntField(
5242 2, /* Field index */
5246 /* The field may be empty. Ignore the error */
5249 Result
= SetupGetStringFieldW(
5251 3, /* Field index */
5256 if (RequiredSize
> 0)
5258 /* We got the needed size for the buffer */
5259 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5260 if (!ServiceSection
)
5262 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5265 Result
= SetupGetStringFieldW(
5267 3, /* Field index */
5268 ServiceSection
, RequiredSize
,
5273 SetLastError(ERROR_SUCCESS
);
5274 Result
= SetupInstallServicesFromInfSectionExW(hInf
, ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
5275 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
5277 AssociatedService
= ServiceName
;
5279 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5280 RebootRequired
= TRUE
;
5283 HeapFree(GetProcessHeap(), 0, ServiceName
);
5284 HeapFree(GetProcessHeap(), 0, ServiceSection
);
5287 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
5290 /* Copy .inf file to Inf\ directory */
5291 FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
5293 /* Open device registry key */
5294 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5295 if (hKey
== INVALID_HANDLE_VALUE
)
5298 /* Install .HW section */
5299 wcscpy(pSectionName
, L
".HW");
5300 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
, hInf
, SectionName
,
5301 SPINST_REGISTRY
, hKey
, NULL
, 0,
5302 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5303 DeviceInfoSet
, DeviceInfoData
);
5307 /* Write information to enum key */
5308 TRACE("Write information to enum key\n");
5309 TRACE("Service : '%S'\n", AssociatedService
);
5310 TRACE("Class : '%S'\n", ClassName
);
5311 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
5312 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5313 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
5314 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
5315 if (rc
== ERROR_SUCCESS
)
5316 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
5317 if (rc
== ERROR_SUCCESS
)
5318 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5319 if (rc
== ERROR_SUCCESS
)
5320 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5321 if (rc
== ERROR_SUCCESS
)
5322 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5323 if (rc
!= ERROR_SUCCESS
)
5329 /* Start the device */
5330 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5332 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
5334 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
5335 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
5336 ret
= NT_SUCCESS(Status
);
5342 /* End of installation */
5343 if (hClassKey
!= INVALID_HANDLE_VALUE
)
5344 RegCloseKey(hClassKey
);
5345 if (hKey
!= INVALID_HANDLE_VALUE
)
5348 RpcStringFreeW(&lpGuidString
);
5349 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
5350 HeapFree(GetProcessHeap(), 0, ClassName
);
5351 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5352 if (hInf
!= INVALID_HANDLE_VALUE
)
5353 SetupCloseInfFile(hInf
);
5355 TRACE("Returning %d\n", ret
);