2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
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 "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
32 static const WCHAR NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
33 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
34 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
35 static const WCHAR NtExtension
[] = {'.','N','T',0};
36 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
37 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
38 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
39 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
41 /* Registry key and value names */
42 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
43 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
44 'C','o','n','t','r','o','l','\\',
45 'C','l','a','s','s',0};
47 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
48 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
49 'C','o','n','t','r','o','l','\\',
50 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
52 static const WCHAR EnumKeyName
[] = {'S','y','s','t','e','m','\\',
53 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
57 /* FIXME: header mess */
58 DEFINE_GUID(GUID_NULL
,
59 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
61 (CALLBACK
* CLASS_INSTALL_PROC
) (
62 IN DI_FUNCTION InstallFunction
,
63 IN HDEVINFO DeviceInfoSet
,
64 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
66 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
67 IN HDEVINFO DeviceInfoSet
,
68 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
70 (CALLBACK
* COINSTALLER_PROC
) (
71 IN DI_FUNCTION InstallFunction
,
72 IN HDEVINFO DeviceInfoSet
,
73 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
74 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
76 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
77 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
78 IN LPFNADDPROPSHEETPAGE fAddFunc
,
81 struct CoInstallerElement
86 COINSTALLER_PROC Function
;
87 BOOL DoPostProcessing
;
91 /***********************************************************************
92 * SetupDiBuildClassInfoList (SETUPAPI.@)
94 BOOL WINAPI
SetupDiBuildClassInfoList(
97 DWORD ClassGuidListSize
,
101 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
102 ClassGuidListSize
, RequiredSize
,
106 /***********************************************************************
107 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
109 BOOL WINAPI
SetupDiBuildClassInfoListExA(
111 LPGUID ClassGuidList
,
112 DWORD ClassGuidListSize
,
117 LPWSTR MachineNameW
= NULL
;
124 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
125 if (MachineNameW
== NULL
) return FALSE
;
128 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
129 ClassGuidListSize
, RequiredSize
,
130 MachineNameW
, Reserved
);
133 MyFree(MachineNameW
);
138 /***********************************************************************
139 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
141 BOOL WINAPI
SetupDiBuildClassInfoListExW(
143 LPGUID ClassGuidList
,
144 DWORD ClassGuidListSize
,
149 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
155 DWORD dwGuidListIndex
= 0;
157 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
158 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
160 if (RequiredSize
!= NULL
)
163 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
164 KEY_ENUMERATE_SUB_KEYS
,
168 if (hClassesKey
== INVALID_HANDLE_VALUE
)
173 for (dwIndex
= 0; ; dwIndex
++)
175 dwLength
= MAX_GUID_STRING_LEN
+ 1;
176 lError
= RegEnumKeyExW(hClassesKey
,
184 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
185 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
187 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
189 if (RegOpenKeyExW(hClassesKey
,
195 RegCloseKey(hClassesKey
);
199 if (!RegQueryValueExW(hClassKey
,
206 TRACE("'NoUseClass' value found!\n");
207 RegCloseKey(hClassKey
);
211 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
212 (!RegQueryValueExW(hClassKey
,
219 TRACE("'NoInstallClass' value found!\n");
220 RegCloseKey(hClassKey
);
224 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
225 (!RegQueryValueExW(hClassKey
,
232 TRACE("'NoDisplayClass' value found!\n");
233 RegCloseKey(hClassKey
);
237 RegCloseKey(hClassKey
);
239 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
240 if (dwGuidListIndex
< ClassGuidListSize
)
242 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
246 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
248 UuidFromStringW(&szKeyName
[1],
249 &ClassGuidList
[dwGuidListIndex
]);
255 if (lError
!= ERROR_SUCCESS
)
259 RegCloseKey(hClassesKey
);
261 if (RequiredSize
!= NULL
)
262 *RequiredSize
= dwGuidListIndex
;
264 if (ClassGuidListSize
< dwGuidListIndex
)
266 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
273 /***********************************************************************
274 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
276 BOOL WINAPI
SetupDiClassGuidsFromNameA(
278 LPGUID ClassGuidList
,
279 DWORD ClassGuidListSize
,
282 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
283 ClassGuidListSize
, RequiredSize
,
287 /***********************************************************************
288 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
290 BOOL WINAPI
SetupDiClassGuidsFromNameW(
292 LPGUID ClassGuidList
,
293 DWORD ClassGuidListSize
,
296 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
297 ClassGuidListSize
, RequiredSize
,
301 /***********************************************************************
302 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
304 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
306 LPGUID ClassGuidList
,
307 DWORD ClassGuidListSize
,
312 LPWSTR ClassNameW
= NULL
;
313 LPWSTR MachineNameW
= NULL
;
318 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
319 if (ClassNameW
== NULL
)
324 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
325 if (MachineNameW
== NULL
)
332 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
333 ClassGuidListSize
, RequiredSize
,
334 MachineNameW
, Reserved
);
337 MyFree(MachineNameW
);
344 /***********************************************************************
345 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
347 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
349 LPGUID ClassGuidList
,
350 DWORD ClassGuidListSize
,
355 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
356 WCHAR szClassName
[256];
362 DWORD dwGuidListIndex
= 0;
364 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
365 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
367 if (RequiredSize
!= NULL
)
370 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
371 KEY_ENUMERATE_SUB_KEYS
,
375 if (hClassesKey
== INVALID_HANDLE_VALUE
)
380 for (dwIndex
= 0; ; dwIndex
++)
382 dwLength
= MAX_GUID_STRING_LEN
+ 1;
383 lError
= RegEnumKeyExW(hClassesKey
,
391 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
392 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
394 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
396 if (RegOpenKeyExW(hClassesKey
,
402 RegCloseKey(hClassesKey
);
406 dwLength
= 256 * sizeof(WCHAR
);
407 if (!RegQueryValueExW(hClassKey
,
414 TRACE("Class name: %s\n", debugstr_w(szClassName
));
416 if (strcmpiW(szClassName
, ClassName
) == 0)
418 TRACE("Found matching class name\n");
420 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
421 if (dwGuidListIndex
< ClassGuidListSize
)
423 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
427 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
429 UuidFromStringW(&szKeyName
[1],
430 &ClassGuidList
[dwGuidListIndex
]);
437 RegCloseKey(hClassKey
);
440 if (lError
!= ERROR_SUCCESS
)
444 RegCloseKey(hClassesKey
);
446 if (RequiredSize
!= NULL
)
447 *RequiredSize
= dwGuidListIndex
;
449 if (ClassGuidListSize
< dwGuidListIndex
)
451 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
458 /***********************************************************************
459 * SetupDiClassNameFromGuidA (SETUPAPI.@)
461 BOOL WINAPI
SetupDiClassNameFromGuidA(
462 const GUID
* ClassGuid
,
467 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
468 ClassNameSize
, RequiredSize
,
472 /***********************************************************************
473 * SetupDiClassNameFromGuidW (SETUPAPI.@)
475 BOOL WINAPI
SetupDiClassNameFromGuidW(
476 const GUID
* ClassGuid
,
481 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
482 ClassNameSize
, RequiredSize
,
486 /***********************************************************************
487 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
489 BOOL WINAPI
SetupDiClassNameFromGuidExA(
490 const GUID
* ClassGuid
,
497 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
498 LPWSTR MachineNameW
= NULL
;
502 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
503 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
504 NULL
, MachineNameW
, Reserved
);
507 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
508 ClassNameSize
, NULL
, NULL
);
510 if (!ClassNameSize
&& RequiredSize
)
513 MyFree(MachineNameW
);
517 /***********************************************************************
518 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
520 BOOL WINAPI
SetupDiClassNameFromGuidExW(
521 const GUID
* ClassGuid
,
532 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
533 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
535 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
540 if (hKey
== INVALID_HANDLE_VALUE
)
545 if (RequiredSize
!= NULL
)
548 rc
= RegQueryValueExW(hKey
,
554 if (rc
!= ERROR_SUCCESS
)
561 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
564 dwLength
= ClassNameSize
* sizeof(WCHAR
);
565 rc
= RegQueryValueExW(hKey
,
571 if (rc
!= ERROR_SUCCESS
)
583 /***********************************************************************
584 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
587 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
590 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
593 /***********************************************************************
594 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
597 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
602 LPWSTR MachineNameW
= NULL
;
605 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
606 debugstr_a(MachineName
), Reserved
);
610 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
611 if (MachineNameW
== NULL
)
612 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
615 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
616 MachineNameW
, Reserved
);
619 MyFree(MachineNameW
);
625 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
629 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
630 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
631 case CR_SUCCESS
: return ERROR_SUCCESS
;
634 return ERROR_GEN_FAILURE
;
637 /* Does not happen */
640 /***********************************************************************
641 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
644 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
649 struct DeviceInfoSet
*list
;
650 LPWSTR UNCServerName
= NULL
;
654 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
656 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
657 debugstr_w(MachineName
), Reserved
);
659 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
661 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
662 list
= HeapAlloc(GetProcessHeap(), 0, size
);
665 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
668 memset(list
, 0, sizeof(struct DeviceInfoSet
));
670 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
673 ClassGuid
? ClassGuid
: &GUID_NULL
,
674 sizeof(list
->ClassGuid
));
675 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
676 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
677 list
->InstallParams
.hwndParent
= hwndParent
;
680 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
681 if (rc
!= ERROR_SUCCESS
)
686 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
689 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
693 strcpyW(UNCServerName
+ 2, MachineName
);
694 list
->szData
[0] = list
->szData
[1] = '\\';
695 strcpyW(list
->szData
+ 2, MachineName
);
696 list
->MachineName
= list
->szData
;
700 DWORD Size
= MAX_PATH
;
701 list
->HKLM
= HKEY_LOCAL_MACHINE
;
702 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
705 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
708 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
710 list
->MachineName
= NULL
;
713 UNCServerName
[0] = UNCServerName
[1] = '\\';
714 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
715 if (cr
!= CR_SUCCESS
)
717 SetLastError(GetErrorCodeFromCrCode(cr
));
721 InitializeListHead(&list
->DriverListHead
);
722 InitializeListHead(&list
->ListHead
);
724 ret
= (HDEVINFO
)list
;
727 if (ret
== INVALID_HANDLE_VALUE
)
729 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
730 RegCloseKey(list
->HKLM
);
731 HeapFree(GetProcessHeap(), 0, list
);
733 HeapFree(GetProcessHeap(), 0, UNCServerName
);
737 /***********************************************************************
738 * SetupDiEnumDeviceInfo (SETUPAPI.@)
740 BOOL WINAPI
SetupDiEnumDeviceInfo(
741 HDEVINFO DeviceInfoSet
,
743 PSP_DEVINFO_DATA DeviceInfoData
)
747 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
749 SetLastError(ERROR_INVALID_PARAMETER
);
750 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
752 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
754 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
755 SetLastError(ERROR_INVALID_HANDLE
);
756 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
757 SetLastError(ERROR_INVALID_USER_BUFFER
);
760 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
761 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
762 ItemList
= ItemList
->Flink
;
763 if (ItemList
== &list
->ListHead
)
764 SetLastError(ERROR_NO_MORE_ITEMS
);
767 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
768 memcpy(&DeviceInfoData
->ClassGuid
,
771 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
772 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
778 SetLastError(ERROR_INVALID_HANDLE
);
782 /***********************************************************************
783 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
785 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
787 PCSTR InfSectionName
,
788 PSTR InfSectionWithExt
,
789 DWORD InfSectionWithExtSize
,
793 LPWSTR InfSectionNameW
= NULL
;
794 PWSTR InfSectionWithExtW
= NULL
;
796 BOOL bResult
= FALSE
;
802 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
803 if (InfSectionNameW
== NULL
) goto end
;
805 if (InfSectionWithExt
)
807 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
808 if (InfSectionWithExtW
== NULL
) goto end
;
811 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
812 InfSectionWithExt
? InfSectionNameW
: NULL
,
813 InfSectionWithExtSize
, RequiredSize
,
814 Extension
? &ExtensionW
: NULL
);
816 if (bResult
&& InfSectionWithExt
)
818 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
819 InfSectionWithExtSize
, NULL
, NULL
) != 0;
821 if (bResult
&& Extension
)
823 if (ExtensionW
== NULL
)
826 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
830 if (InfSectionNameW
) MyFree(InfSectionNameW
);
831 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
836 /***********************************************************************
837 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
839 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
841 PCWSTR InfSectionName
,
842 PWSTR InfSectionWithExt
,
843 DWORD InfSectionWithExtSize
,
847 WCHAR szBuffer
[MAX_PATH
];
850 LONG lLineCount
= -1;
852 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
853 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
855 lstrcpyW(szBuffer
, InfSectionName
);
856 dwLength
= lstrlenW(szBuffer
);
858 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
860 /* Test section name with '.NTx86' extension */
861 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
862 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
864 if (lLineCount
== -1)
866 /* Test section name with '.NT' extension */
867 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
868 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
873 /* Test section name with '.Win' extension */
874 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
875 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
878 if (lLineCount
== -1)
880 /* Test section name without extension */
881 szBuffer
[dwLength
] = 0;
882 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
885 if (lLineCount
== -1)
887 SetLastError(ERROR_INVALID_PARAMETER
);
891 dwFullLength
= lstrlenW(szBuffer
);
893 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
895 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
897 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
901 lstrcpyW(InfSectionWithExt
, szBuffer
);
902 if (Extension
!= NULL
)
904 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
908 if (RequiredSize
!= NULL
)
910 *RequiredSize
= dwFullLength
+ 1;
916 /***********************************************************************
917 * SetupDiGetClassDescriptionA (SETUPAPI.@)
919 BOOL WINAPI
SetupDiGetClassDescriptionA(
920 const GUID
* ClassGuid
,
921 PSTR ClassDescription
,
922 DWORD ClassDescriptionSize
,
925 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
926 ClassDescriptionSize
,
927 RequiredSize
, NULL
, NULL
);
930 /***********************************************************************
931 * SetupDiGetClassDescriptionW (SETUPAPI.@)
933 BOOL WINAPI
SetupDiGetClassDescriptionW(
934 const GUID
* ClassGuid
,
935 PWSTR ClassDescription
,
936 DWORD ClassDescriptionSize
,
939 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
940 ClassDescriptionSize
,
941 RequiredSize
, NULL
, NULL
);
944 /***********************************************************************
945 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
947 BOOL WINAPI
SetupDiGetClassDescriptionExA(
948 const GUID
* ClassGuid
,
949 PSTR ClassDescription
,
950 DWORD ClassDescriptionSize
,
955 PWCHAR ClassDescriptionW
;
956 LPWSTR MachineNameW
= NULL
;
960 if (ClassDescriptionSize
> 0)
962 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
963 if (!ClassDescriptionW
)
965 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
971 ClassDescriptionW
= NULL
;
975 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
978 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
984 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
985 NULL
, MachineNameW
, Reserved
);
988 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
989 ClassDescriptionSize
, NULL
, NULL
);
991 if (!ClassDescriptionSize
&& RequiredSize
)
996 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
997 MyFree(MachineNameW
);
1001 /***********************************************************************
1002 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1004 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1005 const GUID
* ClassGuid
,
1006 PWSTR ClassDescription
,
1007 DWORD ClassDescriptionSize
,
1008 PDWORD RequiredSize
,
1015 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1016 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1018 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1023 if (hKey
== INVALID_HANDLE_VALUE
)
1025 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1029 if (RequiredSize
!= NULL
)
1032 if (RegQueryValueExW(hKey
,
1043 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1046 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1047 if (RegQueryValueExW(hKey
,
1051 (LPBYTE
)ClassDescription
,
1063 /***********************************************************************
1064 * SetupDiGetClassDevsA (SETUPAPI.@)
1066 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1072 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1073 flags
, NULL
, NULL
, NULL
);
1076 /***********************************************************************
1077 * SetupDiGetClassDevsW (SETUPAPI.@)
1079 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1085 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1086 flags
, NULL
, NULL
, NULL
);
1089 /***********************************************************************
1090 * SetupDiGetClassDevsExA (SETUPAPI.@)
1092 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1102 LPWSTR enumstrW
= NULL
;
1103 LPWSTR machineW
= NULL
;
1107 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1108 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1111 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1114 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1118 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1119 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1122 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1125 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1127 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1130 HeapFree(GetProcessHeap(), 0, enumstrW
);
1131 HeapFree(GetProcessHeap(), 0, machineW
);
1136 CreateDeviceInfoElement(
1137 IN
struct DeviceInfoSet
*list
,
1138 IN LPCWSTR InstancePath
,
1139 IN LPCGUID pClassGuid
,
1140 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1144 struct DeviceInfoElement
*deviceInfo
;
1146 *pDeviceInfo
= NULL
;
1148 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1149 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1152 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1155 memset(deviceInfo
, 0, size
);
1157 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1158 if (cr
!= CR_SUCCESS
)
1160 SetLastError(GetErrorCodeFromCrCode(cr
));
1164 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1165 wcscpy(deviceInfo
->Data
, InstancePath
);
1166 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1167 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1168 deviceInfo
->DeviceDescription
= NULL
;
1169 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1170 deviceInfo
->CreationFlags
= 0;
1171 InitializeListHead(&deviceInfo
->DriverListHead
);
1172 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1174 *pDeviceInfo
= deviceInfo
;
1179 CreateDeviceInterface(
1180 IN
struct DeviceInfoElement
* deviceInfo
,
1181 IN LPCWSTR SymbolicLink
,
1182 IN LPCGUID pInterfaceGuid
,
1183 OUT
struct DeviceInterface
**pDeviceInterface
)
1185 struct DeviceInterface
*deviceInterface
;
1187 *pDeviceInterface
= NULL
;
1189 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1190 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1191 if (!deviceInterface
)
1193 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1196 deviceInterface
->DeviceInfo
= deviceInfo
;
1197 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1198 deviceInterface
->Flags
= 0; /* FIXME */
1199 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1201 *pDeviceInterface
= deviceInterface
;
1205 static LONG
SETUP_CreateDevListFromEnumerator(
1206 struct DeviceInfoSet
*list
,
1207 LPCGUID pClassGuid OPTIONAL
,
1209 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1211 HKEY hDeviceIdKey
, hInstanceIdKey
;
1212 WCHAR KeyBuffer
[MAX_PATH
];
1213 WCHAR InstancePath
[MAX_PATH
];
1214 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1215 struct DeviceInfoElement
*deviceInfo
;
1217 DWORD dwLength
, dwRegType
;
1220 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1223 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1224 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1225 if (rc
== ERROR_NO_MORE_ITEMS
)
1227 if (rc
!= ERROR_SUCCESS
)
1231 /* Open device id sub key */
1232 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1233 if (rc
!= ERROR_SUCCESS
)
1235 wcscpy(InstancePath
, Enumerator
);
1236 wcscat(InstancePath
, L
"\\");
1237 wcscat(InstancePath
, KeyBuffer
);
1238 wcscat(InstancePath
, L
"\\");
1239 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1241 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1247 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1248 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1249 if (rc
== ERROR_NO_MORE_ITEMS
)
1251 if (rc
!= ERROR_SUCCESS
)
1253 RegCloseKey(hDeviceIdKey
);
1258 /* Open instance id sub key */
1259 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1260 if (rc
!= ERROR_SUCCESS
)
1262 RegCloseKey(hDeviceIdKey
);
1265 *pEndOfInstancePath
= '\0';
1266 wcscat(InstancePath
, KeyBuffer
);
1268 /* Read ClassGUID value */
1269 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1270 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1271 RegCloseKey(hInstanceIdKey
);
1272 if (rc
== ERROR_FILE_NOT_FOUND
)
1275 /* Skip this bad entry as we can't verify it */
1277 /* Set a default GUID for this device */
1278 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1280 else if (rc
!= ERROR_SUCCESS
)
1282 RegCloseKey(hDeviceIdKey
);
1285 else if (dwRegType
!= REG_SZ
)
1287 RegCloseKey(hDeviceIdKey
);
1288 return ERROR_GEN_FAILURE
;
1292 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1293 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1294 /* Bad GUID, skip the entry */
1298 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1300 /* Skip this entry as it is not the right device class */
1304 /* Add the entry to the list */
1305 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1307 RegCloseKey(hDeviceIdKey
);
1308 return GetLastError();
1310 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1311 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1313 RegCloseKey(hDeviceIdKey
);
1316 return ERROR_SUCCESS
;
1319 static LONG
SETUP_CreateDevList(
1320 struct DeviceInfoSet
*list
,
1321 PCWSTR MachineName OPTIONAL
,
1322 LPGUID
class OPTIONAL
,
1323 PCWSTR Enumerator OPTIONAL
)
1325 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1326 WCHAR KeyBuffer
[MAX_PATH
];
1331 if (class && IsEqualIID(class, &GUID_NULL
))
1335 if (MachineName
!= NULL
)
1337 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1338 if (rc
!= ERROR_SUCCESS
)
1342 HKLM
= HKEY_LOCAL_MACHINE
;
1344 rc
= RegOpenKeyExW(HKLM
,
1347 KEY_ENUMERATE_SUB_KEYS
,
1349 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1350 if (rc
!= ERROR_SUCCESS
)
1353 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1354 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1363 KEY_ENUMERATE_SUB_KEYS
,
1365 RegCloseKey(hEnumKey
);
1366 if (rc
!= ERROR_SUCCESS
)
1368 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1369 RegCloseKey(hEnumeratorKey
);
1374 /* Enumerate enumerators */
1378 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1379 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1380 if (rc
== ERROR_NO_MORE_ITEMS
)
1382 if (rc
!= ERROR_SUCCESS
)
1384 RegCloseKey(hEnumKey
);
1390 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1391 if (rc
!= ERROR_SUCCESS
)
1393 RegCloseKey(hEnumKey
);
1397 /* Call SETUP_CreateDevListFromEnumerator */
1398 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1399 RegCloseKey(hEnumeratorKey
);
1400 if (rc
!= ERROR_SUCCESS
)
1402 RegCloseKey(hEnumKey
);
1406 RegCloseKey(hEnumKey
);
1407 return ERROR_SUCCESS
;
1412 static LONG
SETUP_CreateSerialDeviceList(
1413 struct DeviceInfoSet
*list
,
1415 LPGUID InterfaceGuid
,
1416 PCWSTR DeviceInstanceW
)
1418 static const size_t initialSize
= 100;
1420 WCHAR buf
[initialSize
];
1422 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1424 struct DeviceInfoElement
*deviceInfo
;
1427 WARN("'MachineName' is ignored on Wine!\n");
1428 if (DeviceInstanceW
)
1429 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1435 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1437 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1441 HeapFree(GetProcessHeap(), 0, devices
);
1442 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1444 return ERROR_NOT_ENOUGH_MEMORY
;
1450 HeapFree(GetProcessHeap(), 0, devices
);
1451 return GetLastError();
1455 /* 'devices' is a MULTI_SZ string */
1456 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1458 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1460 /* We have found a device */
1461 struct DeviceInterface
*interfaceInfo
;
1462 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1463 /* Step 1. Create a device info element */
1464 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1467 HeapFree(GetProcessHeap(), 0, devices
);
1468 return GetLastError();
1470 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1472 /* Step 2. Create an interface list for this element */
1473 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1476 HeapFree(GetProcessHeap(), 0, devices
);
1477 return GetLastError();
1479 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1483 HeapFree(GetProcessHeap(), 0, devices
);
1484 return ERROR_SUCCESS
;
1487 #else /* __REACTOS__ */
1489 static LONG
SETUP_CreateInterfaceList(
1490 struct DeviceInfoSet
*list
,
1492 LPGUID InterfaceGuid
,
1493 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1495 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1496 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1497 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1498 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1499 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1501 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1504 DWORD dwLength
, dwInstancePathLength
;
1507 struct DeviceInfoElement
*deviceInfo
;
1509 /* Open registry key related to this interface */
1510 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1511 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1512 return GetLastError();
1514 /* Enumerate sub keys of hInterfaceKey */
1518 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1519 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1520 if (rc
== ERROR_NO_MORE_ITEMS
)
1522 if (rc
!= ERROR_SUCCESS
)
1524 RegCloseKey(hInterfaceKey
);
1530 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1531 if (rc
!= ERROR_SUCCESS
)
1533 RegCloseKey(hInterfaceKey
);
1537 /* Read DeviceInstance */
1538 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1539 if (rc
!= ERROR_SUCCESS
)
1541 RegCloseKey(hDeviceInstanceKey
);
1542 RegCloseKey(hInterfaceKey
);
1545 if (dwRegType
!= REG_SZ
)
1547 RegCloseKey(hDeviceInstanceKey
);
1548 RegCloseKey(hInterfaceKey
);
1549 return ERROR_GEN_FAILURE
;
1551 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1554 RegCloseKey(hDeviceInstanceKey
);
1555 RegCloseKey(hInterfaceKey
);
1556 return ERROR_NOT_ENOUGH_MEMORY
;
1558 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1559 if (rc
!= ERROR_SUCCESS
)
1561 HeapFree(GetProcessHeap(), 0, InstancePath
);
1562 RegCloseKey(hDeviceInstanceKey
);
1563 RegCloseKey(hInterfaceKey
);
1566 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1567 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1569 if (DeviceInstanceW
)
1571 /* Check if device enumerator is not the right one */
1572 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1574 HeapFree(GetProcessHeap(), 0, InstancePath
);
1575 RegCloseKey(hDeviceInstanceKey
);
1580 /* Find class GUID associated to the device instance */
1585 KEY_ENUMERATE_SUB_KEYS
,
1587 if (rc
!= ERROR_SUCCESS
)
1589 HeapFree(GetProcessHeap(), 0, InstancePath
);
1590 RegCloseKey(hDeviceInstanceKey
);
1591 RegCloseKey(hInterfaceKey
);
1600 RegCloseKey(hEnumKey
);
1601 if (rc
!= ERROR_SUCCESS
)
1603 HeapFree(GetProcessHeap(), 0, InstancePath
);
1604 RegCloseKey(hDeviceInstanceKey
);
1605 RegCloseKey(hInterfaceKey
);
1608 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1609 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1611 if (rc
!= ERROR_SUCCESS
)
1613 HeapFree(GetProcessHeap(), 0, InstancePath
);
1614 RegCloseKey(hDeviceInstanceKey
);
1615 RegCloseKey(hInterfaceKey
);
1618 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1619 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1620 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1622 HeapFree(GetProcessHeap(), 0, InstancePath
);
1623 RegCloseKey(hDeviceInstanceKey
);
1624 RegCloseKey(hInterfaceKey
);
1625 return ERROR_GEN_FAILURE
;
1627 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1629 /* If current device doesn't match the list GUID (if any), skip this entry */
1630 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1632 HeapFree(GetProcessHeap(), 0, InstancePath
);
1633 RegCloseKey(hDeviceInstanceKey
);
1637 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1641 LPWSTR pSymbolicLink
;
1642 struct DeviceInterface
*interfaceInfo
;
1644 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1645 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1646 if (rc
== ERROR_NO_MORE_ITEMS
)
1648 if (rc
!= ERROR_SUCCESS
)
1650 HeapFree(GetProcessHeap(), 0, InstancePath
);
1651 RegCloseKey(hDeviceInstanceKey
);
1652 RegCloseKey(hInterfaceKey
);
1656 if (KeyBuffer
[0] != '#')
1657 /* This entry doesn't represent an interesting entry */
1661 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1662 if (rc
!= ERROR_SUCCESS
)
1664 RegCloseKey(hDeviceInstanceKey
);
1665 RegCloseKey(hInterfaceKey
);
1669 /* Read SymbolicLink value */
1670 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1671 if (rc
!= ERROR_SUCCESS
)
1673 RegCloseKey(hReferenceKey
);
1674 RegCloseKey(hDeviceInstanceKey
);
1675 RegCloseKey(hInterfaceKey
);
1678 if (dwRegType
!= REG_SZ
)
1680 RegCloseKey(hReferenceKey
);
1681 RegCloseKey(hDeviceInstanceKey
);
1682 RegCloseKey(hInterfaceKey
);
1683 return ERROR_GEN_FAILURE
;
1686 /* We have found a device */
1687 /* Step 1. Create a device info element */
1688 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1690 RegCloseKey(hReferenceKey
);
1691 RegCloseKey(hDeviceInstanceKey
);
1692 RegCloseKey(hInterfaceKey
);
1693 return GetLastError();
1695 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1696 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1698 /* Step 2. Create an interface list for this element */
1699 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1702 RegCloseKey(hReferenceKey
);
1703 RegCloseKey(hDeviceInstanceKey
);
1704 RegCloseKey(hInterfaceKey
);
1705 return ERROR_NOT_ENOUGH_MEMORY
;
1707 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1708 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1709 RegCloseKey(hReferenceKey
);
1710 if (rc
!= ERROR_SUCCESS
)
1712 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1713 RegCloseKey(hDeviceInstanceKey
);
1714 RegCloseKey(hInterfaceKey
);
1717 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1719 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1720 RegCloseKey(hDeviceInstanceKey
);
1721 RegCloseKey(hInterfaceKey
);
1722 return GetLastError();
1724 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1725 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1726 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1728 RegCloseKey(hDeviceInstanceKey
);
1730 RegCloseKey(hInterfaceKey
);
1731 return ERROR_SUCCESS
;
1733 #endif /* __REACTOS__ */
1735 /***********************************************************************
1736 * SetupDiGetClassDevsExW (SETUPAPI.@)
1738 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1747 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1748 struct DeviceInfoSet
*list
;
1752 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1753 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1755 /* Create the deviceset if not set */
1758 list
= (struct DeviceInfoSet
*)deviceset
;
1759 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1761 SetLastError(ERROR_INVALID_HANDLE
);
1762 return INVALID_HANDLE_VALUE
;
1764 hDeviceInfo
= deviceset
;
1768 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1769 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1770 NULL
, machine
, NULL
);
1771 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1772 return INVALID_HANDLE_VALUE
;
1773 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1776 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1779 pClassGuid
= &list
->ClassGuid
;
1781 if (flags
& DIGCF_PRESENT
)
1782 FIXME(": flag DIGCF_PRESENT ignored\n");
1783 if (flags
& DIGCF_PROFILE
)
1784 FIXME(": flag DIGCF_PROFILE ignored\n");
1786 if (flags
& DIGCF_ALLCLASSES
)
1788 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1789 if (rc
!= ERROR_SUCCESS
)
1793 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1794 return INVALID_HANDLE_VALUE
;
1798 else if (flags
& DIGCF_DEVICEINTERFACE
)
1802 SetLastError(ERROR_INVALID_PARAMETER
);
1804 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1805 return INVALID_HANDLE_VALUE
;
1809 /* Special case: find serial ports by calling QueryDosDevice */
1810 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1811 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1812 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1813 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1816 ERR("Wine can only enumerate serial devices at the moment!\n");
1817 rc
= ERROR_INVALID_PARAMETER
;
1819 #else /* __REACTOS__ */
1820 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1821 #endif /* __REACTOS__ */
1822 if (rc
!= ERROR_SUCCESS
)
1826 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1827 return INVALID_HANDLE_VALUE
;
1833 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1834 if (rc
!= ERROR_SUCCESS
)
1838 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1839 return INVALID_HANDLE_VALUE
;
1845 /***********************************************************************
1846 * SetupDiGetClassImageIndex (SETUPAPI.@)
1849 static BOOL
GetIconIndex(
1851 OUT PINT ImageIndex
)
1853 LPWSTR Buffer
= NULL
;
1854 DWORD dwRegType
, dwLength
;
1858 /* Read "Icon" registry key */
1859 rc
= RegQueryValueExW(hClassKey
, L
"Icon", NULL
, &dwRegType
, NULL
, &dwLength
);
1860 if (rc
!= ERROR_SUCCESS
)
1864 } else if (dwRegType
!= REG_SZ
)
1866 SetLastError(ERROR_INVALID_INDEX
);
1869 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1872 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1875 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1876 rc
= RegQueryValueExW(hClassKey
, L
"Icon", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1877 if (rc
!= ERROR_SUCCESS
)
1883 /* Transform "Icon" value to a INT */
1884 *ImageIndex
= atoiW(Buffer
);
1892 BOOL WINAPI
SetupDiGetClassImageIndex(
1893 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1894 IN CONST GUID
*ClassGuid
,
1895 OUT PINT ImageIndex
)
1897 struct ClassImageList
*list
;
1900 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
1902 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
1903 SetLastError(ERROR_INVALID_PARAMETER
);
1904 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1905 SetLastError(ERROR_INVALID_USER_BUFFER
);
1906 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
1907 SetLastError(ERROR_INVALID_USER_BUFFER
);
1908 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
1909 SetLastError(ERROR_INVALID_USER_BUFFER
);
1910 else if (!ImageIndex
)
1911 SetLastError(ERROR_INVALID_PARAMETER
);
1914 HKEY hKey
= INVALID_HANDLE_VALUE
;
1917 /* Read Icon registry entry into Buffer */
1918 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
1919 if (hKey
== INVALID_HANDLE_VALUE
)
1921 if (!GetIconIndex(hKey
, &iconIndex
))
1926 SetLastError(ERROR_INVALID_INDEX
);
1930 *ImageIndex
= -iconIndex
;
1934 if (hKey
!= INVALID_HANDLE_VALUE
)
1938 TRACE("Returning %d\n", ret
);
1942 /***********************************************************************
1943 * SetupDiGetClassImageList(SETUPAPI.@)
1945 BOOL WINAPI
SetupDiGetClassImageList(
1946 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
1948 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
1951 /***********************************************************************
1952 * SetupDiGetClassImageListExA(SETUPAPI.@)
1954 BOOL WINAPI
SetupDiGetClassImageListExA(
1955 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1956 IN PCSTR MachineName OPTIONAL
,
1959 PWSTR MachineNameW
= NULL
;
1964 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1965 if (MachineNameW
== NULL
)
1969 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
1972 MyFree(MachineNameW
);
1977 /***********************************************************************
1978 * SetupDiGetClassImageListExW(SETUPAPI.@)
1980 BOOL WINAPI
SetupDiGetClassImageListExW(
1981 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1982 IN PCWSTR MachineName OPTIONAL
,
1987 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
1989 if (!ClassImageListData
)
1990 SetLastError(ERROR_INVALID_PARAMETER
);
1991 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1992 SetLastError(ERROR_INVALID_USER_BUFFER
);
1994 SetLastError(ERROR_INVALID_PARAMETER
);
1997 struct ClassImageList
*list
= NULL
;
2000 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2002 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2003 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2006 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2009 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2012 list
->szData
[0] = list
->szData
[1] = '\\';
2013 strcpyW(list
->szData
+ 2, MachineName
);
2014 list
->MachineName
= list
->szData
;
2018 list
->MachineName
= NULL
;
2021 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2029 TRACE("Returning %d\n", ret
);
2033 /***********************************************************************
2034 * SetupDiLoadClassIcon(SETUPAPI.@)
2036 BOOL WINAPI
SetupDiLoadClassIcon(
2037 IN CONST GUID
*ClassGuid
,
2038 OUT HICON
*LargeIcon OPTIONAL
,
2039 OUT PINT MiniIconIndex OPTIONAL
)
2044 SetLastError(ERROR_INVALID_PARAMETER
);
2047 LPWSTR Buffer
= NULL
;
2050 HKEY hKey
= INVALID_HANDLE_VALUE
;
2052 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2053 if (hKey
== INVALID_HANDLE_VALUE
)
2056 if (!GetIconIndex(hKey
, &iconIndex
))
2061 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2064 DWORD dwRegType
, dwLength
;
2065 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2066 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2068 Buffer
= MyMalloc(dwLength
);
2071 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2074 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2075 if (rc
!= ERROR_SUCCESS
)
2082 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
))
2083 && dwRegType
== REG_SZ
)
2085 Buffer
= MyMalloc(dwLength
);
2088 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2091 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2092 if (rc
!= ERROR_SUCCESS
)
2100 /* Unable to find where to load the icon */
2101 SetLastError(ERROR_FILE_NOT_FOUND
);
2104 Comma
= strchrW(Buffer
, ',');
2107 SetLastError(ERROR_GEN_FAILURE
);
2114 /* Look up icon in setupapi.dll */
2115 DllName
= L
"setupapi.dll";
2116 iconIndex
= -iconIndex
;
2119 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2122 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2124 SetLastError(ERROR_INVALID_INDEX
);
2129 *MiniIconIndex
= iconIndex
;
2133 if (hKey
!= INVALID_HANDLE_VALUE
)
2138 TRACE("Returning %d\n", ret
);
2142 /***********************************************************************
2143 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2145 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2146 HDEVINFO DeviceInfoSet
,
2147 PSP_DEVINFO_DATA DeviceInfoData
,
2148 CONST GUID
* InterfaceClassGuid
,
2150 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2154 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2155 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2157 if (!DeviceInterfaceData
)
2158 SetLastError(ERROR_INVALID_PARAMETER
);
2159 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2160 SetLastError(ERROR_INVALID_USER_BUFFER
);
2161 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2163 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2165 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2167 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2169 while (ItemList
!= &list
->ListHead
&& !Found
)
2171 PLIST_ENTRY InterfaceListEntry
;
2172 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2173 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2175 /* We are not searching for this element */
2176 ItemList
= ItemList
->Flink
;
2179 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2180 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2182 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2183 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2185 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2188 if (MemberIndex
-- == 0)
2190 /* return this item */
2191 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2192 &DevItf
->InterfaceClassGuid
,
2194 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2195 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2198 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2200 ItemList
= ItemList
->Flink
;
2203 SetLastError(ERROR_NO_MORE_ITEMS
);
2208 SetLastError(ERROR_INVALID_HANDLE
);
2211 SetLastError(ERROR_INVALID_HANDLE
);
2215 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2217 InterlockedIncrement(&infFile
->References
);
2220 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2222 if (InterlockedDecrement(&infFile
->References
) == 0)
2224 SetupCloseInfFile(infFile
->hInf
);
2225 HeapFree(GetProcessHeap(), 0, infFile
);
2229 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2231 DereferenceInfFile(driverInfo
->InfFileDetails
);
2232 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2233 HeapFree(GetProcessHeap(), 0, driverInfo
);
2237 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2239 PLIST_ENTRY ListEntry
;
2240 struct DriverInfoElement
*driverInfo
;
2242 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2244 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2245 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2246 if (!DestroyDriverInfoElement(driverInfo
))
2249 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2251 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2252 HeapFree(GetProcessHeap(), 0, ListEntry
);
2254 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2258 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2260 PLIST_ENTRY ListEntry
;
2261 struct DeviceInfoElement
*deviceInfo
;
2263 while (!IsListEmpty(&list
->ListHead
))
2265 ListEntry
= RemoveHeadList(&list
->ListHead
);
2266 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2267 if (!DestroyDeviceInfoElement(deviceInfo
))
2270 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2271 RegCloseKey(list
->HKLM
);
2272 CM_Disconnect_Machine(list
->hMachine
);
2273 HeapFree(GetProcessHeap(), 0, list
);
2277 /***********************************************************************
2278 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2280 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2284 TRACE("%p\n", devinfo
);
2285 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2287 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2289 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2290 ret
= DestroyDeviceInfoSet(list
);
2292 SetLastError(ERROR_INVALID_HANDLE
);
2295 SetLastError(ERROR_INVALID_HANDLE
);
2297 TRACE("Returning %d\n", ret
);
2301 /***********************************************************************
2302 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2304 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2305 HDEVINFO DeviceInfoSet
,
2306 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2307 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2308 DWORD DeviceInterfaceDetailDataSize
,
2309 PDWORD RequiredSize
,
2310 PSP_DEVINFO_DATA DeviceInfoData
)
2312 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2313 DWORD sizeW
= 0, sizeA
;
2316 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2317 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2318 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2320 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2321 SetLastError(ERROR_INVALID_USER_BUFFER
);
2322 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2323 SetLastError(ERROR_INVALID_PARAMETER
);
2324 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2325 SetLastError(ERROR_INVALID_PARAMETER
);
2328 if (DeviceInterfaceDetailData
!= NULL
)
2330 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2331 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2332 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2333 if (!DeviceInterfaceDetailDataW
)
2335 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2338 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2340 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2341 ret
= SetupDiGetDeviceInterfaceDetailW(
2343 DeviceInterfaceData
,
2344 DeviceInterfaceDetailDataW
,
2348 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2349 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2351 *RequiredSize
= sizeA
;
2352 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2354 if (!WideCharToMultiByte(
2356 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2357 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2364 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2367 TRACE("Returning %d\n", ret
);
2371 /***********************************************************************
2372 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2374 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2375 HDEVINFO DeviceInfoSet
,
2376 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2377 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2378 DWORD DeviceInterfaceDetailDataSize
,
2379 PDWORD RequiredSize
,
2380 PSP_DEVINFO_DATA DeviceInfoData
)
2384 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2385 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2386 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2388 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2389 SetLastError(ERROR_INVALID_PARAMETER
);
2390 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2391 SetLastError(ERROR_INVALID_HANDLE
);
2392 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2393 SetLastError(ERROR_INVALID_HANDLE
);
2394 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2395 SetLastError(ERROR_INVALID_USER_BUFFER
);
2396 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2397 SetLastError(ERROR_INVALID_USER_BUFFER
);
2398 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2399 SetLastError(ERROR_INVALID_USER_BUFFER
);
2400 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2401 SetLastError(ERROR_INVALID_PARAMETER
);
2402 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2403 SetLastError(ERROR_INVALID_PARAMETER
);
2406 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2407 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2408 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2409 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2411 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2413 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2415 *RequiredSize
= sizeRequired
;
2419 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2420 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2423 memcpy(&DeviceInfoData
->ClassGuid
,
2424 &deviceInterface
->DeviceInfo
->ClassGuid
,
2426 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2427 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2433 TRACE("Returning %d\n", ret
);
2437 /***********************************************************************
2438 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2440 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2442 PSP_DEVINFO_DATA DeviceInfoData
,
2444 PDWORD PropertyRegDataType
,
2445 PBYTE PropertyBuffer
,
2446 DWORD PropertyBufferSize
,
2447 PDWORD RequiredSize
)
2450 BOOL bIsStringProperty
;
2452 DWORD RequiredSizeA
, RequiredSizeW
;
2453 DWORD PropertyBufferSizeW
;
2454 PBYTE PropertyBufferW
;
2456 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2457 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2460 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2461 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2463 bResult
= SetupDiGetDeviceRegistryPropertyW(
2469 PropertyBufferSizeW
,
2472 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2474 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2476 if (bIsStringProperty
)
2477 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2479 RequiredSizeA
= RequiredSizeW
;
2481 *RequiredSize
= RequiredSizeA
;
2482 if (PropertyRegDataType
)
2483 *PropertyRegDataType
= RegType
;
2488 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2492 if (RequiredSizeA
<= PropertyBufferSize
)
2494 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2496 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2498 /* Last error is already set by WideCharToMultiByte */
2503 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2507 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2511 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2515 /***********************************************************************
2516 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2518 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2519 HDEVINFO DeviceInfoSet
,
2520 PSP_DEVINFO_DATA DeviceInfoData
,
2522 PDWORD PropertyRegDataType
,
2523 PBYTE PropertyBuffer
,
2524 DWORD PropertyBufferSize
,
2525 PDWORD RequiredSize
)
2527 HKEY hEnumKey
, hKey
;
2531 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2532 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2535 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2536 SetLastError(ERROR_INVALID_HANDLE
);
2537 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2538 SetLastError(ERROR_INVALID_HANDLE
);
2539 else if (!DeviceInfoData
)
2540 SetLastError(ERROR_INVALID_PARAMETER
);
2541 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2542 SetLastError(ERROR_INVALID_USER_BUFFER
);
2543 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2544 SetLastError(ERROR_INVALID_PARAMETER
);
2547 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2548 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2552 case SPDRP_CAPABILITIES
:
2554 case SPDRP_CLASSGUID
:
2555 case SPDRP_COMPATIBLEIDS
:
2556 case SPDRP_CONFIGFLAGS
:
2557 case SPDRP_DEVICEDESC
:
2559 case SPDRP_FRIENDLYNAME
:
2560 case SPDRP_HARDWAREID
:
2561 case SPDRP_LOCATION_INFORMATION
:
2562 case SPDRP_LOWERFILTERS
:
2564 case SPDRP_SECURITY
:
2566 case SPDRP_UI_NUMBER
:
2567 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2568 case SPDRP_UPPERFILTERS
:
2570 LPCWSTR RegistryPropertyName
;
2575 case SPDRP_CAPABILITIES
:
2576 RegistryPropertyName
= L
"Capabilities"; break;
2578 RegistryPropertyName
= L
"Class"; break;
2579 case SPDRP_CLASSGUID
:
2580 RegistryPropertyName
= L
"ClassGUID"; break;
2581 case SPDRP_COMPATIBLEIDS
:
2582 RegistryPropertyName
= L
"CompatibleIDs"; break;
2583 case SPDRP_CONFIGFLAGS
:
2584 RegistryPropertyName
= L
"ConfigFlags"; break;
2585 case SPDRP_DEVICEDESC
:
2586 RegistryPropertyName
= L
"DeviceDesc"; break;
2588 RegistryPropertyName
= L
"Driver"; break;
2589 case SPDRP_FRIENDLYNAME
:
2590 RegistryPropertyName
= L
"FriendlyName"; break;
2591 case SPDRP_HARDWAREID
:
2592 RegistryPropertyName
= L
"HardwareID"; break;
2593 case SPDRP_LOCATION_INFORMATION
:
2594 RegistryPropertyName
= L
"LocationInformation"; break;
2595 case SPDRP_LOWERFILTERS
:
2596 RegistryPropertyName
= L
"LowerFilters"; break;
2598 RegistryPropertyName
= L
"Mfg"; break;
2599 case SPDRP_SECURITY
:
2600 RegistryPropertyName
= L
"Security"; break;
2602 RegistryPropertyName
= L
"Service"; break;
2603 case SPDRP_UI_NUMBER
:
2604 RegistryPropertyName
= L
"UINumber"; break;
2605 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2606 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2607 case SPDRP_UPPERFILTERS
:
2608 RegistryPropertyName
= L
"UpperFilters"; break;
2610 /* Should not happen */
2611 RegistryPropertyName
= NULL
; break;
2614 /* Open registry key name */
2619 KEY_ENUMERATE_SUB_KEYS
,
2621 if (rc
!= ERROR_SUCCESS
)
2632 RegCloseKey(hEnumKey
);
2633 if (rc
!= ERROR_SUCCESS
)
2638 /* Read registry entry */
2639 BufferSize
= PropertyBufferSize
;
2640 rc
= RegQueryValueExW(
2642 RegistryPropertyName
,
2643 NULL
, /* Reserved */
2644 PropertyRegDataType
,
2648 *RequiredSize
= BufferSize
;
2651 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2654 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2656 case ERROR_MORE_DATA
:
2657 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2666 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2668 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2670 if (PropertyRegDataType
)
2671 *PropertyRegDataType
= REG_SZ
;
2673 *RequiredSize
= required
;
2674 if (PropertyBufferSize
>= required
)
2676 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2680 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2684 /*case SPDRP_BUSTYPEGUID:
2685 case SPDRP_LEGACYBUSTYPE:
2686 case SPDRP_BUSNUMBER:
2687 case SPDRP_ENUMERATOR_NAME:
2688 case SPDRP_SECURITY_SDS:
2690 case SPDRP_EXCLUSIVE:
2691 case SPDRP_CHARACTERISTICS:
2693 case SPDRP_DEVICE_POWER_DATA:*/
2694 #if (WINVER >= 0x501)
2695 /*case SPDRP_REMOVAL_POLICY:
2696 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2697 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2698 case SPDRP_INSTALL_STATE:*/
2703 ERR("Property 0x%lx not implemented\n", Property
);
2704 SetLastError(ERROR_NOT_SUPPORTED
);
2709 TRACE("Returning %d\n", ret
);
2713 /***********************************************************************
2714 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2716 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2717 IN HDEVINFO DeviceInfoSet
,
2718 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2720 IN CONST BYTE
*PropertyBuffer
,
2721 IN DWORD PropertyBufferSize
)
2723 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2724 Property
, PropertyBuffer
, PropertyBufferSize
);
2725 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2729 /***********************************************************************
2730 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2732 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2733 IN HDEVINFO DeviceInfoSet
,
2734 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2736 IN
const BYTE
*PropertyBuffer
,
2737 IN DWORD PropertyBufferSize
)
2739 struct DeviceInfoSet
*list
;
2742 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2743 Property
, PropertyBuffer
, PropertyBufferSize
);
2746 SetLastError(ERROR_INVALID_HANDLE
);
2747 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2748 SetLastError(ERROR_INVALID_HANDLE
);
2749 else if (DeviceInfoData
)
2750 SetLastError(ERROR_INVALID_HANDLE
);
2751 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2752 SetLastError(ERROR_INVALID_USER_BUFFER
);
2757 case SPDRP_COMPATIBLEIDS
:
2758 case SPDRP_CONFIGFLAGS
:
2759 case SPDRP_FRIENDLYNAME
:
2760 case SPDRP_HARDWAREID
:
2761 case SPDRP_LOCATION_INFORMATION
:
2762 case SPDRP_LOWERFILTERS
:
2763 case SPDRP_SECURITY
:
2765 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2766 case SPDRP_UPPERFILTERS
:
2768 LPCWSTR RegistryPropertyName
;
2769 DWORD RegistryDataType
;
2775 case SPDRP_COMPATIBLEIDS
:
2776 RegistryPropertyName
= L
"CompatibleIDs";
2777 RegistryDataType
= REG_MULTI_SZ
;
2779 case SPDRP_CONFIGFLAGS
:
2780 RegistryPropertyName
= L
"ConfigFlags";
2781 RegistryDataType
= REG_DWORD
;
2783 case SPDRP_FRIENDLYNAME
:
2784 RegistryPropertyName
= L
"FriendlyName";
2785 RegistryDataType
= REG_SZ
;
2787 case SPDRP_HARDWAREID
:
2788 RegistryPropertyName
= L
"HardwareID";
2789 RegistryDataType
= REG_MULTI_SZ
;
2791 case SPDRP_LOCATION_INFORMATION
:
2792 RegistryPropertyName
= L
"LocationInformation";
2793 RegistryDataType
= REG_SZ
;
2795 case SPDRP_LOWERFILTERS
:
2796 RegistryPropertyName
= L
"LowerFilters";
2797 RegistryDataType
= REG_MULTI_SZ
;
2799 case SPDRP_SECURITY
:
2800 RegistryPropertyName
= L
"Security";
2801 RegistryDataType
= REG_BINARY
;
2804 RegistryPropertyName
= L
"Service";
2805 RegistryDataType
= REG_SZ
;
2807 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2808 RegistryPropertyName
= L
"UINumberDescFormat";
2809 RegistryDataType
= REG_SZ
;
2811 case SPDRP_UPPERFILTERS
:
2812 RegistryPropertyName
= L
"UpperFilters";
2813 RegistryDataType
= REG_MULTI_SZ
;
2816 /* Should not happen */
2817 RegistryPropertyName
= NULL
;
2818 RegistryDataType
= REG_BINARY
;
2821 /* Open device registry key */
2822 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2823 if (hKey
!= INVALID_HANDLE_VALUE
)
2825 /* Write new data */
2826 rc
= RegSetValueExW(
2828 RegistryPropertyName
,
2832 PropertyBufferSize
);
2833 if (rc
== ERROR_SUCCESS
)
2842 /*case SPDRP_CHARACTERISTICS:
2844 case SPDRP_EXCLUSIVE:*/
2845 #if (WINVER >= 0x501)
2846 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2848 //case SPDRP_SECURITY_SDS:
2852 ERR("Property 0x%lx not implemented\n", Property
);
2853 SetLastError(ERROR_NOT_SUPPORTED
);
2858 TRACE("Returning %d\n", ret
);
2862 /***********************************************************************
2863 * SetupDiInstallClassA (SETUPAPI.@)
2865 BOOL WINAPI
SetupDiInstallClassA(
2871 UNICODE_STRING FileNameW
;
2874 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2876 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2880 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2882 RtlFreeUnicodeString(&FileNameW
);
2887 static HKEY
CreateClassKey(HINF hInf
)
2889 WCHAR FullBuffer
[MAX_PATH
];
2890 WCHAR Buffer
[MAX_PATH
];
2895 if (!SetupGetLineTextW(NULL
,
2903 return INVALID_HANDLE_VALUE
;
2906 lstrcpyW(FullBuffer
, ControlClass
);
2907 lstrcatW(FullBuffer
, Buffer
);
2910 if (!SetupGetLineTextW(NULL
,
2918 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2919 return INVALID_HANDLE_VALUE
;
2922 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2926 REG_OPTION_NON_VOLATILE
,
2932 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2933 return INVALID_HANDLE_VALUE
;
2936 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2941 RequiredSize
* sizeof(WCHAR
)))
2943 RegCloseKey(hClassKey
);
2944 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2945 return INVALID_HANDLE_VALUE
;
2951 /***********************************************************************
2952 * SetupDiInstallClassW (SETUPAPI.@)
2954 BOOL WINAPI
SetupDiInstallClassW(
2960 WCHAR SectionName
[MAX_PATH
];
2961 DWORD SectionNameLength
= 0;
2963 BOOL bFileQueueCreated
= FALSE
;
2966 TRACE("%p %s 0x%lx %p\n", hwndParent
, debugstr_w(InfFileName
),
2969 FIXME("not fully implemented\n");
2971 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2973 SetLastError(ERROR_INVALID_PARAMETER
);
2977 /* Open the .inf file */
2978 hInf
= SetupOpenInfFileW(InfFileName
,
2982 if (hInf
== INVALID_HANDLE_VALUE
)
2988 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2989 hClassKey
= CreateClassKey(hInf
);
2990 if (hClassKey
== INVALID_HANDLE_VALUE
)
2992 SetupCloseInfFile(hInf
);
2998 /* Try to append a layout file */
3000 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3003 /* Retrieve the actual section name */
3004 SetupDiGetActualSectionToInstallW(hInf
,
3012 if (!(Flags
& DI_NOVCP
))
3014 FileQueue
= SetupOpenFileQueue();
3015 if (FileQueue
== INVALID_HANDLE_VALUE
)
3017 SetupCloseInfFile(hInf
);
3018 RegCloseKey(hClassKey
);
3022 bFileQueueCreated
= TRUE
;
3027 SetupInstallFromInfSectionW(NULL
,
3036 INVALID_HANDLE_VALUE
,
3039 /* FIXME: More code! */
3041 if (bFileQueueCreated
)
3042 SetupCloseFileQueue(FileQueue
);
3044 SetupCloseInfFile(hInf
);
3046 RegCloseKey(hClassKey
);
3051 /***********************************************************************
3052 * SetupDiOpenClassRegKey (SETUPAPI.@)
3054 HKEY WINAPI
SetupDiOpenClassRegKey(
3055 const GUID
* ClassGuid
,
3058 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3059 DIOCR_INSTALLER
, NULL
, NULL
);
3063 /***********************************************************************
3064 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3066 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3067 const GUID
* ClassGuid OPTIONAL
,
3070 PCSTR MachineName OPTIONAL
,
3073 PWSTR MachineNameW
= NULL
;
3080 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3081 if (MachineNameW
== NULL
)
3082 return INVALID_HANDLE_VALUE
;
3085 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3086 Flags
, MachineNameW
, Reserved
);
3089 MyFree(MachineNameW
);
3095 /***********************************************************************
3096 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3098 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3099 const GUID
* ClassGuid OPTIONAL
,
3102 PCWSTR MachineName OPTIONAL
,
3105 LPWSTR lpGuidString
;
3106 LPWSTR lpFullGuidString
;
3114 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3115 Flags
, debugstr_w(MachineName
), Reserved
);
3117 if (Flags
== DIOCR_INSTALLER
)
3119 lpKeyName
= ControlClass
;
3121 else if (Flags
== DIOCR_INTERFACE
)
3123 lpKeyName
= DeviceClasses
;
3127 ERR("Invalid Flags parameter!\n");
3128 SetLastError(ERROR_INVALID_FLAGS
);
3129 return INVALID_HANDLE_VALUE
;
3132 if (MachineName
!= NULL
)
3134 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3135 if (rc
!= ERROR_SUCCESS
)
3138 return INVALID_HANDLE_VALUE
;
3142 HKLM
= HKEY_LOCAL_MACHINE
;
3144 rc
= RegOpenKeyExW(HKLM
,
3147 ClassGuid
? KEY_ENUMERATE_SUB_KEYS
: samDesired
,
3149 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3150 if (rc
!= ERROR_SUCCESS
)
3153 return INVALID_HANDLE_VALUE
;
3156 if (ClassGuid
== NULL
)
3159 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3161 SetLastError(ERROR_GEN_FAILURE
);
3162 RegCloseKey(hClassesKey
);
3163 return INVALID_HANDLE_VALUE
;
3166 dwLength
= lstrlenW(lpGuidString
);
3167 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3168 if (!lpFullGuidString
)
3170 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3171 RpcStringFreeW(&lpGuidString
);
3172 return INVALID_HANDLE_VALUE
;
3174 lpFullGuidString
[0] = '{';
3175 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3176 lpFullGuidString
[dwLength
+ 1] = '}';
3177 lpFullGuidString
[dwLength
+ 2] = '\0';
3178 RpcStringFreeW(&lpGuidString
);
3180 rc
= RegOpenKeyExW(hClassesKey
,
3185 if (rc
!= ERROR_SUCCESS
)
3188 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3189 RegCloseKey(hClassesKey
);
3190 return INVALID_HANDLE_VALUE
;
3193 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3194 RegCloseKey(hClassesKey
);
3199 /***********************************************************************
3200 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3202 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3203 HDEVINFO DeviceInfoSet
,
3206 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3208 FIXME("%p %s %08lx %p\n",
3209 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3213 /***********************************************************************
3214 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3216 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3217 HDEVINFO DeviceInfoSet
,
3220 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3222 LPWSTR DevicePathW
= NULL
;
3225 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3227 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3228 if (DevicePathW
== NULL
)
3231 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3232 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3234 MyFree(DevicePathW
);
3239 /***********************************************************************
3240 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3242 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3243 HDEVINFO DeviceInfoSet
,
3244 PSP_DEVINFO_DATA DeviceInfoData
,
3245 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3246 DWORD ClassInstallParamsSize
)
3248 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3249 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3253 /***********************************************************************
3254 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3256 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3257 HDEVINFO DeviceInfoSet
,
3258 PSP_DEVINFO_DATA DeviceInfoData
,
3259 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3260 DWORD ClassInstallParamsSize
)
3262 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3263 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3269 IN PWSTR InstallerName
,
3270 OUT HMODULE
* ModulePointer
,
3271 OUT PVOID
* FunctionPointer
)
3273 HMODULE hModule
= NULL
;
3274 LPSTR FunctionNameA
= NULL
;
3278 *ModulePointer
= NULL
;
3279 *FunctionPointer
= NULL
;
3281 Comma
= strchrW(InstallerName
, ',');
3284 rc
= ERROR_INVALID_PARAMETER
;
3290 hModule
= LoadLibraryW(InstallerName
);
3294 rc
= GetLastError();
3298 /* Skip comma spaces */
3299 while (*Comma
== ',' || isspaceW(*Comma
))
3302 /* W->A conversion for function name */
3303 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3306 rc
= GetLastError();
3310 /* Search function */
3311 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3312 if (!*FunctionPointer
)
3314 rc
= GetLastError();
3318 *ModulePointer
= hModule
;
3322 if (rc
!= ERROR_SUCCESS
&& hModule
)
3323 FreeLibrary(hModule
);
3324 MyFree(FunctionNameA
);
3329 FreeFunctionPointer(
3330 IN HMODULE ModulePointer
,
3331 IN PVOID FunctionPointer
)
3333 if (ModulePointer
== NULL
)
3334 return ERROR_SUCCESS
;
3335 if (FreeLibrary(ModulePointer
))
3336 return ERROR_SUCCESS
;
3338 return GetLastError();
3341 /***********************************************************************
3342 * SetupDiCallClassInstaller (SETUPAPI.@)
3344 BOOL WINAPI
SetupDiCallClassInstaller(
3345 IN DI_FUNCTION InstallFunction
,
3346 IN HDEVINFO DeviceInfoSet
,
3347 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3351 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3354 SetLastError(ERROR_INVALID_PARAMETER
);
3355 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3356 SetLastError(ERROR_INVALID_HANDLE
);
3357 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3358 SetLastError(ERROR_INVALID_HANDLE
);
3359 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3360 SetLastError(ERROR_INVALID_HANDLE
);
3361 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3362 SetLastError(ERROR_INVALID_USER_BUFFER
);
3365 SP_DEVINSTALL_PARAMS_W InstallParams
;
3366 #define CLASS_COINSTALLER 0x1
3367 #define DEVICE_COINSTALLER 0x2
3368 #define CLASS_INSTALLER 0x4
3369 UCHAR CanHandle
= 0;
3370 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3372 switch (InstallFunction
)
3374 case DIF_ALLOW_INSTALL
:
3375 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3377 case DIF_DESTROYPRIVATEDATA
:
3378 CanHandle
= CLASS_INSTALLER
;
3380 case DIF_INSTALLDEVICE
:
3381 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3382 DefaultHandler
= SetupDiInstallDevice
;
3384 case DIF_INSTALLDEVICEFILES
:
3385 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3386 DefaultHandler
= SetupDiInstallDriverFiles
;
3388 case DIF_INSTALLINTERFACES
:
3389 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3390 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3392 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3393 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3395 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3396 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3398 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3399 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3401 case DIF_REGISTER_COINSTALLERS
:
3402 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3403 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3405 case DIF_SELECTBESTCOMPATDRV
:
3406 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3407 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3410 ERR("Install function %u not supported\n", InstallFunction
);
3411 SetLastError(ERROR_NOT_SUPPORTED
);
3414 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3415 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3416 /* Don't process this call, as a parameter is invalid */
3421 LIST_ENTRY ClassCoInstallersListHead
;
3422 LIST_ENTRY DeviceCoInstallersListHead
;
3423 HMODULE ClassInstallerLibrary
= NULL
;
3424 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3425 COINSTALLER_CONTEXT_DATA Context
;
3426 PLIST_ENTRY ListEntry
;
3428 DWORD dwRegType
, dwLength
;
3429 DWORD rc
= NO_ERROR
;
3431 InitializeListHead(&ClassCoInstallersListHead
);
3432 InitializeListHead(&DeviceCoInstallersListHead
);
3434 if (CanHandle
& DEVICE_COINSTALLER
)
3436 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3437 if (hKey
!= INVALID_HANDLE_VALUE
)
3439 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3440 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3442 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3443 if (KeyBuffer
!= NULL
)
3445 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3446 if (rc
== ERROR_SUCCESS
)
3449 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3451 /* Add coinstaller to DeviceCoInstallersListHead list */
3452 struct CoInstallerElement
*coinstaller
;
3453 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3454 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3457 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3458 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3459 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3461 HeapFree(GetProcessHeap(), 0, coinstaller
);
3464 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3470 if (CanHandle
& CLASS_COINSTALLER
)
3474 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3478 if (rc
== ERROR_SUCCESS
)
3480 LPWSTR lpGuidString
;
3481 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3483 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3484 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3486 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3487 if (KeyBuffer
!= NULL
)
3489 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3490 if (rc
== ERROR_SUCCESS
)
3493 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3495 /* Add coinstaller to ClassCoInstallersListHead list */
3496 struct CoInstallerElement
*coinstaller
;
3497 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3498 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3501 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3502 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3503 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3505 HeapFree(GetProcessHeap(), 0, coinstaller
);
3508 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3511 RpcStringFreeW(&lpGuidString
);
3516 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3518 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3519 if (hKey
!= INVALID_HANDLE_VALUE
)
3521 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3522 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3524 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3525 if (KeyBuffer
!= NULL
)
3527 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3528 if (rc
== ERROR_SUCCESS
)
3530 /* Get ClassInstaller function pointer */
3531 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3532 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3534 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3535 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3538 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3545 /* Call Class co-installers */
3546 Context
.PostProcessing
= FALSE
;
3548 ListEntry
= ClassCoInstallersListHead
.Flink
;
3549 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3551 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3552 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3553 coinstaller
->PrivateData
= Context
.PrivateData
;
3554 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3556 coinstaller
->DoPostProcessing
= TRUE
;
3559 ListEntry
= ListEntry
->Flink
;
3562 /* Call Device co-installers */
3563 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3564 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3566 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3567 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3568 coinstaller
->PrivateData
= Context
.PrivateData
;
3569 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3571 coinstaller
->DoPostProcessing
= TRUE
;
3574 ListEntry
= ListEntry
->Flink
;
3577 /* Call Class installer */
3580 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3581 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3584 rc
= ERROR_DI_DO_DEFAULT
;
3586 /* Call default handler */
3587 if (rc
== ERROR_DI_DO_DEFAULT
)
3589 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3591 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3594 rc
= GetLastError();
3600 /* Call Class co-installers that required postprocessing */
3601 Context
.PostProcessing
= TRUE
;
3602 ListEntry
= ClassCoInstallersListHead
.Flink
;
3603 while (ListEntry
!= &ClassCoInstallersListHead
)
3605 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3606 if (coinstaller
->DoPostProcessing
)
3608 Context
.InstallResult
= rc
;
3609 Context
.PrivateData
= coinstaller
->PrivateData
;
3610 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3612 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3613 ListEntry
= ListEntry
->Flink
;
3616 /* Call Device co-installers that required postprocessing */
3617 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3618 while (ListEntry
!= &DeviceCoInstallersListHead
)
3620 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3621 if (coinstaller
->DoPostProcessing
)
3623 Context
.InstallResult
= rc
;
3624 Context
.PrivateData
= coinstaller
->PrivateData
;
3625 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3627 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3628 ListEntry
= ListEntry
->Flink
;
3631 /* Free allocated memory */
3632 while (!IsListEmpty(&ClassCoInstallersListHead
))
3634 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3635 HeapFree(GetProcessHeap(), 0, ListEntry
);
3637 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3639 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3640 HeapFree(GetProcessHeap(), 0, ListEntry
);
3643 ret
= (rc
== NO_ERROR
);
3647 TRACE("Returning %d\n", ret
);
3651 /***********************************************************************
3652 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3654 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
3655 IN HDEVINFO DeviceInfoSet
,
3656 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
3658 struct DeviceInfoSet
*list
;
3661 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
3664 SetLastError(ERROR_INVALID_HANDLE
);
3665 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3666 SetLastError(ERROR_INVALID_HANDLE
);
3667 else if (!DeviceInfoListDetailData
)
3668 SetLastError(ERROR_INVALID_PARAMETER
);
3669 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
3670 SetLastError(ERROR_INVALID_USER_BUFFER
);
3674 &DeviceInfoListDetailData
->ClassGuid
,
3677 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
3678 if (list
->MachineName
)
3679 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
3681 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
3686 TRACE("Returning %d\n", ret
);
3690 /***********************************************************************
3691 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3693 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3694 IN HDEVINFO DeviceInfoSet
,
3695 IN PSP_DEVINFO_DATA DeviceInfoData
,
3696 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3698 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3701 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3703 if (DeviceInstallParams
== NULL
)
3704 SetLastError(ERROR_INVALID_PARAMETER
);
3705 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3706 SetLastError(ERROR_INVALID_USER_BUFFER
);
3709 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3710 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3714 /* Do W->A conversion */
3716 DeviceInstallParams
,
3717 &deviceInstallParamsW
,
3718 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3719 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3720 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3722 DeviceInstallParams
->DriverPath
[0] = '\0';
3728 TRACE("Returning %d\n", ret
);
3732 /***********************************************************************
3733 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3735 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3736 IN HDEVINFO DeviceInfoSet
,
3737 IN PSP_DEVINFO_DATA DeviceInfoData
,
3738 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3740 struct DeviceInfoSet
*list
;
3743 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3746 SetLastError(ERROR_INVALID_HANDLE
);
3747 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3748 SetLastError(ERROR_INVALID_HANDLE
);
3749 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3750 SetLastError(ERROR_INVALID_USER_BUFFER
);
3751 else if (!DeviceInstallParams
)
3752 SetLastError(ERROR_INVALID_PARAMETER
);
3753 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3754 SetLastError(ERROR_INVALID_USER_BUFFER
);
3757 PSP_DEVINSTALL_PARAMS_W Source
;
3760 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3762 Source
= &list
->InstallParams
;
3763 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3767 TRACE("Returning %d\n", ret
);
3771 /***********************************************************************
3772 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3774 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3775 IN HDEVINFO DeviceInfoSet
,
3776 IN PSP_DEVINFO_DATA DeviceInfoData
,
3777 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3779 struct DeviceInfoSet
*list
;
3782 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3785 SetLastError(ERROR_INVALID_HANDLE
);
3786 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3787 SetLastError(ERROR_INVALID_HANDLE
);
3788 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3789 SetLastError(ERROR_INVALID_USER_BUFFER
);
3790 else if (!DeviceInstallParams
)
3791 SetLastError(ERROR_INVALID_PARAMETER
);
3792 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3793 SetLastError(ERROR_INVALID_USER_BUFFER
);
3796 PSP_DEVINSTALL_PARAMS_W Destination
;
3798 /* FIXME: Validate parameters */
3801 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3803 Destination
= &list
->InstallParams
;
3804 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3808 TRACE("Returning %d\n", ret
);
3812 /***********************************************************************
3813 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
3815 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
3816 IN HDEVINFO DeviceInfoSet
,
3817 IN PSP_DEVINFO_DATA DeviceInfoData
,
3818 OUT PSTR DeviceInstanceId OPTIONAL
,
3819 IN DWORD DeviceInstanceIdSize
,
3820 OUT PDWORD RequiredSize OPTIONAL
)
3822 PWSTR DeviceInstanceIdW
= NULL
;
3825 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
3826 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
3828 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
3829 SetLastError(ERROR_INVALID_PARAMETER
);
3832 if (DeviceInstanceIdSize
!= 0)
3834 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
3835 if (DeviceInstanceIdW
== NULL
)
3839 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
3840 DeviceInstanceIdW
, DeviceInstanceIdSize
,
3843 if (ret
&& DeviceInstanceIdW
!= NULL
)
3845 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
3846 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
3848 DeviceInstanceId
[0] = '\0';
3854 TRACE("Returning %d\n", ret
);
3858 /***********************************************************************
3859 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
3861 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
3862 IN HDEVINFO DeviceInfoSet
,
3863 IN PSP_DEVINFO_DATA DeviceInfoData
,
3864 OUT PWSTR DeviceInstanceId OPTIONAL
,
3865 IN DWORD DeviceInstanceIdSize
,
3866 OUT PDWORD RequiredSize OPTIONAL
)
3870 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
3871 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
3874 SetLastError(ERROR_INVALID_HANDLE
);
3875 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3876 SetLastError(ERROR_INVALID_HANDLE
);
3877 else if (!DeviceInfoData
)
3878 SetLastError(ERROR_INVALID_PARAMETER
);
3879 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3880 SetLastError(ERROR_INVALID_USER_BUFFER
);
3881 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
3882 SetLastError(ERROR_INVALID_PARAMETER
);
3883 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
3884 SetLastError(ERROR_INVALID_PARAMETER
);
3887 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3890 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
3892 *RequiredSize
= required
;
3894 if (required
<= DeviceInstanceIdSize
)
3896 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
3900 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3903 TRACE("Returning %d\n", ret
);
3907 /***********************************************************************
3908 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
3910 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
3911 IN HDEVINFO DeviceInfoSet
,
3912 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3913 IN LPPROPSHEETHEADERA PropertySheetHeader
,
3914 IN DWORD PropertySheetHeaderPageListSize
,
3915 OUT PDWORD RequiredSize OPTIONAL
,
3916 IN DWORD PropertySheetType
)
3918 PROPSHEETHEADERW psh
;
3921 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3922 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
3923 RequiredSize
, PropertySheetType
);
3925 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
3926 psh
.phpage
= PropertySheetHeader
->phpage
;
3927 psh
.nPages
= PropertySheetHeader
->nPages
;
3929 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
3930 PropertySheetHeaderPageListSize
, RequiredSize
,
3934 PropertySheetHeader
->nPages
= psh
.nPages
;
3937 TRACE("Returning %d\n", ret
);
3941 struct ClassDevPropertySheetsData
3943 HPROPSHEETPAGE
*PropertySheetPages
;
3944 DWORD MaximumNumberOfPages
;
3945 DWORD NumberOfPages
;
3948 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
3949 IN HPROPSHEETPAGE hPropSheetPage
,
3950 IN OUT LPARAM lParam
)
3952 struct ClassDevPropertySheetsData
*PropPageData
;
3954 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
3956 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
3958 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
3959 PropPageData
->PropertySheetPages
++;
3962 PropPageData
->NumberOfPages
++;
3966 /***********************************************************************
3967 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
3969 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
3970 IN HDEVINFO DeviceInfoSet
,
3971 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3972 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
3973 IN DWORD PropertySheetHeaderPageListSize
,
3974 OUT PDWORD RequiredSize OPTIONAL
,
3975 IN DWORD PropertySheetType
)
3977 struct DeviceInfoSet
*list
;
3980 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3981 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
3982 RequiredSize
, PropertySheetType
);
3985 SetLastError(ERROR_INVALID_HANDLE
);
3986 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3987 SetLastError(ERROR_INVALID_HANDLE
);
3988 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3989 SetLastError(ERROR_INVALID_HANDLE
);
3990 else if (!PropertySheetHeader
)
3991 SetLastError(ERROR_INVALID_PARAMETER
);
3992 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
3993 SetLastError(ERROR_INVALID_FLAGS
);
3994 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3995 SetLastError(ERROR_INVALID_USER_BUFFER
);
3996 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
3997 SetLastError(ERROR_INVALID_PARAMETER
);
3998 else if (!PropertySheetHeader
)
3999 SetLastError(ERROR_INVALID_PARAMETER
);
4000 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4001 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4002 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4003 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4004 SetLastError(ERROR_INVALID_PARAMETER
);
4007 HKEY hKey
= INVALID_HANDLE_VALUE
;
4008 SP_PROPSHEETPAGE_REQUEST Request
;
4009 LPWSTR PropPageProvider
= NULL
;
4010 HMODULE hModule
= NULL
;
4011 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4012 struct ClassDevPropertySheetsData PropPageData
;
4013 DWORD dwLength
, dwRegType
;
4017 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4020 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4021 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4023 if (hKey
== INVALID_HANDLE_VALUE
)
4026 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
);
4027 if (rc
== ERROR_FILE_NOT_FOUND
)
4029 /* No registry key. As it is optional, don't say it's a bad error */
4035 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4041 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4042 if (!PropPageProvider
)
4044 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4047 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4048 if (rc
!= ERROR_SUCCESS
)
4053 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4055 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4056 if (rc
!= ERROR_SUCCESS
)
4058 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4062 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4063 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4064 Request
.DeviceInfoSet
= DeviceInfoSet
;
4065 Request
.DeviceInfoData
= DeviceInfoData
;
4066 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4067 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4068 PropPageData
.NumberOfPages
= 0;
4069 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4074 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4075 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4077 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4082 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4083 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4087 if (hKey
!= INVALID_HANDLE_VALUE
)
4089 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4090 FreeFunctionPointer(hModule
, pPropPageProvider
);
4093 TRACE("Returning %d\n", ret
);
4097 /***********************************************************************
4098 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4100 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4101 IN HDEVINFO DeviceInfoSet
,
4102 IN PSP_DEVINFO_DATA DeviceInfoData
,
4106 IN HINF InfHandle OPTIONAL
,
4107 IN PCSTR InfSectionName OPTIONAL
)
4109 PCWSTR InfSectionNameW
= NULL
;
4110 HKEY ret
= INVALID_HANDLE_VALUE
;
4114 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4115 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4118 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4126 if (InfSectionNameW
!= NULL
)
4127 MyFree((PVOID
)InfSectionNameW
);
4132 /***********************************************************************
4133 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4135 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4136 IN HDEVINFO DeviceInfoSet
,
4137 IN PSP_DEVINFO_DATA DeviceInfoData
,
4141 IN HINF InfHandle OPTIONAL
,
4142 IN PCWSTR InfSectionName OPTIONAL
)
4144 struct DeviceInfoSet
*list
;
4145 HKEY ret
= INVALID_HANDLE_VALUE
;
4147 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4148 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4151 SetLastError(ERROR_INVALID_HANDLE
);
4152 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4153 SetLastError(ERROR_INVALID_HANDLE
);
4154 else if (!DeviceInfoData
)
4155 SetLastError(ERROR_INVALID_PARAMETER
);
4156 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4157 SetLastError(ERROR_INVALID_USER_BUFFER
);
4158 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4159 SetLastError(ERROR_INVALID_PARAMETER
);
4160 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4161 SetLastError(ERROR_INVALID_PARAMETER
);
4162 else if (InfHandle
&& !InfSectionName
)
4163 SetLastError(ERROR_INVALID_PARAMETER
);
4164 else if (!InfHandle
&& InfSectionName
)
4165 SetLastError(ERROR_INVALID_PARAMETER
);
4168 LPWSTR lpGuidString
= NULL
;
4169 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4170 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4171 DWORD Index
; /* Index used in the DriverKey name */
4173 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4174 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4175 HKEY hKey
= INVALID_HANDLE_VALUE
;
4177 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
4179 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4183 if (KeyType
== DIREG_DEV
)
4185 FIXME("DIREG_DEV case unimplemented\n");
4187 else /* KeyType == DIREG_DRV */
4189 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4191 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
4192 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4195 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4198 wcscpy(DriverKey
, L
"{");
4199 wcscat(DriverKey
, lpGuidString
);
4200 wcscat(DriverKey
, L
"}\\");
4201 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4202 rc
= RegOpenKeyExW(list
->HKLM
,
4207 if (rc
!= ERROR_SUCCESS
)
4213 /* Try all values for Index between 0 and 9999 */
4215 while (Index
<= 9999)
4218 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4219 rc
= RegCreateKeyEx(hClassKey
,
4223 REG_OPTION_NON_VOLATILE
,
4224 #if _WIN32_WINNT >= 0x502
4225 KEY_READ
| KEY_WRITE
,
4232 if (rc
!= ERROR_SUCCESS
)
4237 if (Disposition
== REG_CREATED_NEW_KEY
)
4240 hKey
= INVALID_HANDLE_VALUE
;
4245 /* Unable to create more than 9999 devices within the same class */
4246 SetLastError(ERROR_GEN_FAILURE
);
4250 /* Open device key, to write Driver value */
4251 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4252 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4254 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4255 if (rc
!= ERROR_SUCCESS
)
4262 /* Do installation of the specified section */
4265 FIXME("Need to install section %s in file %p\n",
4266 debugstr_w(InfSectionName
), InfHandle
);
4272 RpcStringFreeW(&lpGuidString
);
4273 HeapFree(GetProcessHeap(), 0, DriverKey
);
4274 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4275 RegCloseKey(hClassKey
);
4276 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4277 RegCloseKey(hDeviceKey
);
4278 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4282 TRACE("Returning 0x%p\n", ret
);
4286 /***********************************************************************
4287 * SetupDiOpenDevRegKey (SETUPAPI.@)
4289 HKEY WINAPI
SetupDiOpenDevRegKey(
4290 HDEVINFO DeviceInfoSet
,
4291 PSP_DEVINFO_DATA DeviceInfoData
,
4297 struct DeviceInfoSet
*list
;
4298 HKEY ret
= INVALID_HANDLE_VALUE
;
4300 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4301 Scope
, HwProfile
, KeyType
, samDesired
);
4304 SetLastError(ERROR_INVALID_HANDLE
);
4305 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4306 SetLastError(ERROR_INVALID_HANDLE
);
4307 else if (!DeviceInfoData
)
4308 SetLastError(ERROR_INVALID_PARAMETER
);
4309 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4310 SetLastError(ERROR_INVALID_USER_BUFFER
);
4311 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4312 SetLastError(ERROR_INVALID_PARAMETER
);
4313 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4314 SetLastError(ERROR_INVALID_PARAMETER
);
4317 HKEY hKey
= INVALID_HANDLE_VALUE
;
4318 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
4319 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4320 LPWSTR DriverKey
= NULL
;
4325 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
4327 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4329 else /* Scope == DICS_FLAG_GLOBAL */
4335 KEY_ENUMERATE_SUB_KEYS
,
4337 if (rc
!= ERROR_SUCCESS
)
4344 deviceInfo
->DeviceName
,
4346 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4348 RegCloseKey(hRootKey
);
4349 hRootKey
= INVALID_HANDLE_VALUE
;
4350 if (rc
!= ERROR_SUCCESS
)
4355 if (KeyType
== DIREG_DEV
)
4357 /* We're done. Just return the hKey handle */
4361 /* Read the 'Driver' key */
4362 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
4363 if (rc
!= ERROR_SUCCESS
)
4368 if (dwRegType
!= REG_SZ
)
4370 SetLastError(ERROR_GEN_FAILURE
);
4373 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4376 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4379 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4380 if (rc
!= ERROR_SUCCESS
)
4386 hKey
= INVALID_HANDLE_VALUE
;
4387 /* Need to open the driver key */
4392 KEY_ENUMERATE_SUB_KEYS
,
4394 if (rc
!= ERROR_SUCCESS
)
4405 if (rc
!= ERROR_SUCCESS
)
4413 if (hRootKey
!= INVALID_HANDLE_VALUE
)
4414 RegCloseKey(hRootKey
);
4415 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4419 TRACE("Returning 0x%p\n", ret
);
4423 /***********************************************************************
4424 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4426 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4427 HDEVINFO DeviceInfoSet
,
4429 CONST GUID
*ClassGuid
,
4430 PCSTR DeviceDescription
,
4432 DWORD CreationFlags
,
4433 PSP_DEVINFO_DATA DeviceInfoData
)
4435 LPWSTR DeviceNameW
= NULL
;
4436 LPWSTR DeviceDescriptionW
= NULL
;
4443 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4444 if (DeviceNameW
== NULL
) return FALSE
;
4446 if (DeviceDescription
)
4448 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4449 if (DeviceDescriptionW
== NULL
)
4451 if (DeviceNameW
) MyFree(DeviceNameW
);
4456 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4457 ClassGuid
, DeviceDescriptionW
,
4458 hwndParent
, CreationFlags
,
4461 if (DeviceNameW
) MyFree(DeviceNameW
);
4462 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4467 /***********************************************************************
4468 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4470 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4471 HDEVINFO DeviceInfoSet
,
4473 CONST GUID
*ClassGuid
,
4474 PCWSTR DeviceDescription
,
4476 DWORD CreationFlags
,
4477 PSP_DEVINFO_DATA DeviceInfoData
)
4479 struct DeviceInfoSet
*list
;
4482 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4483 debugstr_guid(ClassGuid
), DeviceDescription
,
4484 hwndParent
, CreationFlags
, DeviceInfoData
);
4487 SetLastError(ERROR_INVALID_HANDLE
);
4488 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4489 SetLastError(ERROR_INVALID_HANDLE
);
4490 else if (!ClassGuid
)
4491 SetLastError(ERROR_INVALID_PARAMETER
);
4492 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4493 SetLastError(ERROR_CLASS_MISMATCH
);
4494 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4496 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4497 SetLastError(ERROR_INVALID_FLAGS
);
4501 SP_DEVINFO_DATA DevInfo
;
4503 if (CreationFlags
& DICD_GENERATE_ID
)
4505 /* Generate a new unique ID for this device */
4506 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4507 FIXME("not implemented\n");
4511 /* Device name is fully qualified. Try to open it */
4514 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4515 rc
= SetupDiOpenDeviceInfoW(
4518 NULL
, /* hwndParent */
4519 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
4524 /* SetupDiOpenDeviceInfoW has already added
4525 * the device info to the device info set
4527 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
4529 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
4531 struct DeviceInfoElement
*deviceInfo
;
4533 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
4535 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4537 if (!DeviceInfoData
)
4541 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
4543 SetLastError(ERROR_INVALID_USER_BUFFER
);
4547 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4548 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4549 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4558 TRACE("Returning %d\n", ret
);
4562 /***********************************************************************
4563 * Helper functions for SetupDiBuildDriverInfoList
4567 IN PLIST_ENTRY DriverListHead
,
4568 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4569 IN LPGUID ClassGuid
,
4570 IN INFCONTEXT ContextDevice
,
4571 IN
struct InfFileDetails
*InfFileDetails
,
4573 IN LPCWSTR ProviderName
,
4574 IN LPCWSTR ManufacturerName
,
4575 IN LPCWSTR MatchingId
,
4576 FILETIME DriverDate
,
4577 DWORDLONG DriverVersion
,
4580 struct DriverInfoElement
*driverInfo
= NULL
;
4581 HANDLE hFile
= INVALID_HANDLE_VALUE
;
4582 DWORD RequiredSize
= 128; /* Initial buffer size */
4583 BOOL Result
= FALSE
;
4584 PLIST_ENTRY PreviousEntry
;
4585 LPWSTR InfInstallSection
= NULL
;
4588 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
4591 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4594 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
4596 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
4597 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
4599 /* Copy InfFileName field */
4600 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
4601 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
4603 /* Fill InfDate field */
4604 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4605 GENERIC_READ, FILE_SHARE_READ,
4606 NULL, OPEN_EXISTING, 0, NULL);
4607 if (hFile == INVALID_HANDLE_VALUE)
4609 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4613 /* Fill SectionName field */
4614 Result
= SetupGetStringFieldW(
4617 driverInfo
->Details
.SectionName
, LINE_LEN
,
4622 /* Fill DrvDescription field */
4623 Result
= SetupGetStringFieldW(
4625 0, /* Field index */
4626 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
4629 /* Copy MatchingId information */
4630 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4631 if (!driverInfo
->MatchingId
)
4633 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4636 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4638 /* Get inf install section */
4640 RequiredSize
= 128; /* Initial buffer size */
4641 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4642 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4644 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4645 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4646 if (!InfInstallSection
)
4648 Result
= SetupGetStringFieldW(
4650 1, /* Field index */
4651 InfInstallSection
, RequiredSize
,
4657 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4658 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4660 driverInfo
->DriverRank
= Rank
;
4661 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
4662 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4663 driverInfo
->Info
.DriverType
= DriverType
;
4664 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4665 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4666 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4667 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4668 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4671 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4672 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4675 driverInfo
->Info
.ProviderName
[0] = '\0';
4676 driverInfo
->Info
.DriverDate
= DriverDate
;
4677 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4678 ReferenceInfFile(InfFileDetails
);
4679 driverInfo
->InfFileDetails
= InfFileDetails
;
4681 /* Insert current driver in driver list, according to its rank */
4682 PreviousEntry
= DriverListHead
->Flink
;
4683 while (PreviousEntry
!= DriverListHead
)
4685 struct DriverInfoElement
*CurrentDriver
;
4686 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
4687 if (CurrentDriver
->DriverRank
> Rank
||
4688 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
4690 /* Insert before the current item */
4691 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4694 PreviousEntry
= PreviousEntry
->Flink
;
4696 if (PreviousEntry
== DriverListHead
)
4698 /* Insert at the end of the list */
4699 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4708 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4709 HeapFree(GetProcessHeap(), 0, driverInfo
);
4711 if (hFile
!= INVALID_HANDLE_VALUE
)
4713 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4719 GetVersionInformationFromInfFile(
4721 OUT LPGUID ClassGuid
,
4722 OUT LPWSTR
* pProviderName
,
4723 OUT FILETIME
* DriverDate
,
4724 OUT DWORDLONG
* DriverVersion
)
4727 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4728 LPWSTR DriverVer
= NULL
;
4729 LPWSTR ProviderName
= NULL
;
4730 LPWSTR pComma
; /* Points into DriverVer */
4731 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4732 SYSTEMTIME SystemTime
;
4734 BOOL ret
= FALSE
; /* Final result */
4736 /* Get class Guid */
4737 if (!SetupGetLineTextW(
4740 L
"Version", L
"ClassGUID",
4741 guidW
, sizeof(guidW
),
4742 NULL
/* Required size */))
4746 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4747 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4749 SetLastError(ERROR_GEN_FAILURE
);
4753 /* Get provider name */
4754 Result
= SetupGetLineTextW(
4756 hInf
, L
"Version", L
"Provider",
4761 /* We know know the needed buffer size */
4762 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4765 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4768 Result
= SetupGetLineTextW(
4770 hInf
, L
"Version", L
"Provider",
4771 ProviderName
, RequiredSize
,
4776 *pProviderName
= ProviderName
;
4778 /* Read the "DriverVer" value */
4779 Result
= SetupGetLineTextW(
4781 hInf
, L
"Version", L
"DriverVer",
4786 /* We know know the needed buffer size */
4787 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4790 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4793 Result
= SetupGetLineTextW(
4795 hInf
, L
"Version", L
"DriverVer",
4796 DriverVer
, RequiredSize
,
4802 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4803 pComma
= wcschr(DriverVer
, ',');
4806 *pComma
= UNICODE_NULL
;
4807 pVersion
= pComma
+ 1;
4809 /* Get driver date version. Invalid date = 00/00/00 */
4810 memset(DriverDate
, 0, sizeof(FILETIME
));
4811 if (wcslen(DriverVer
) == 10
4812 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4813 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4815 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4816 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4817 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4818 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4819 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4820 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4822 /* Get driver version. Invalid version = 0.0.0.0 */
4826 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
4827 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
4828 LARGE_INTEGER fullVersion
;
4830 pMinor
= strchrW(pVersion
, '.');
4834 pRevision
= strchrW(++pMinor
, '.');
4835 Minor
= atoiW(pMinor
);
4840 pBuild
= strchrW(++pRevision
, '.');
4841 Revision
= atoiW(pRevision
);
4847 Build
= atoiW(pBuild
);
4849 Major
= atoiW(pVersion
);
4850 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
4851 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
4852 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
4859 HeapFree(GetProcessHeap(), 0, ProviderName
);
4860 HeapFree(GetProcessHeap(), 0, DriverVer
);
4865 /***********************************************************************
4866 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4869 SetupDiBuildDriverInfoList(
4870 IN HDEVINFO DeviceInfoSet
,
4871 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4872 IN DWORD DriverType
)
4874 struct DeviceInfoSet
*list
;
4875 SP_DEVINSTALL_PARAMS_W InstallParams
;
4876 PVOID Buffer
= NULL
;
4877 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4878 LPWSTR ProviderName
= NULL
;
4879 LPWSTR ManufacturerName
= NULL
;
4880 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4881 LPWSTR HardwareIDs
= NULL
;
4882 LPWSTR CompatibleIDs
= NULL
;
4883 LPWSTR FullInfFileName
= NULL
;
4884 FILETIME DriverDate
;
4885 DWORDLONG DriverVersion
= 0;
4889 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4892 SetLastError(ERROR_INVALID_HANDLE
);
4893 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4894 SetLastError(ERROR_INVALID_HANDLE
);
4895 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4896 SetLastError(ERROR_INVALID_HANDLE
);
4897 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4898 SetLastError(ERROR_INVALID_PARAMETER
);
4899 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4900 SetLastError(ERROR_INVALID_PARAMETER
);
4901 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4902 SetLastError(ERROR_INVALID_PARAMETER
);
4903 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4904 SetLastError(ERROR_INVALID_USER_BUFFER
);
4909 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4910 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4914 if (DriverType
== SPDIT_COMPATDRIVER
)
4916 /* Get hardware IDs list */
4918 RequiredSize
= 512; /* Initial buffer size */
4919 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4920 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4922 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4923 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4926 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4929 Result
= SetupDiGetDeviceRegistryPropertyW(
4941 /* Get compatible IDs list */
4943 RequiredSize
= 512; /* Initial buffer size */
4944 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4945 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4947 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4948 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4951 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4954 Result
= SetupDiGetDeviceRegistryPropertyW(
4957 SPDRP_COMPATIBLEIDS
,
4959 (PBYTE
)CompatibleIDs
,
4962 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4964 /* No compatible ID for this device */
4965 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4966 CompatibleIDs
= NULL
;
4974 /* Enumerate .inf files */
4976 RequiredSize
= 32768; /* Initial buffer size */
4977 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4978 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4980 HeapFree(GetProcessHeap(), 0, Buffer
);
4981 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4985 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4988 Result
= SetupGetInfFileListW(
4989 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4991 Buffer
, RequiredSize
,
4994 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4996 /* No .inf file in specified directory. So, we should
4997 * success as we created an empty driver info list.
5005 LPWSTR pFullFilename
;
5007 if (*InstallParams
.DriverPath
)
5010 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5013 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5014 if (!FullInfFileName
)
5016 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5019 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5020 wcscat(FullInfFileName
, L
"\\");
5021 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5025 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5026 if (!FullInfFileName
)
5028 pFullFilename
= &FullInfFileName
[0];
5031 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5033 INFCONTEXT ContextManufacturer
, ContextDevice
;
5036 wcscpy(pFullFilename
, filename
);
5037 TRACE("Opening file %S\n", FullInfFileName
);
5039 currentInfFileDetails
= HeapAlloc(
5042 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5043 if (!currentInfFileDetails
)
5045 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5046 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5048 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5049 ReferenceInfFile(currentInfFileDetails
);
5050 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5052 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5053 currentInfFileDetails
= NULL
;
5057 if (!GetVersionInformationFromInfFile(
5058 currentInfFileDetails
->hInf
,
5064 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5065 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5066 currentInfFileDetails
= NULL
;
5070 if (DriverType
== SPDIT_CLASSDRIVER
)
5072 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5073 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5079 /* Get the manufacturers list */
5080 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5083 Result
= SetupGetStringFieldW(
5084 &ContextManufacturer
,
5085 0, /* Field index */
5090 /* We got the needed size for the buffer */
5091 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5092 if (!ManufacturerName
)
5094 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5097 Result
= SetupGetStringFieldW(
5098 &ContextManufacturer
,
5099 0, /* Field index */
5100 ManufacturerName
, RequiredSize
,
5103 /* Get manufacturer section name */
5104 Result
= SetupGetStringFieldW(
5105 &ContextManufacturer
,
5106 1, /* Field index */
5107 ManufacturerSection
, LINE_LEN
,
5111 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5112 /* Add (possible) extension to manufacturer section name */
5113 Result
= SetupDiGetActualSectionToInstallW(
5114 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5117 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5118 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5123 if (DriverType
== SPDIT_CLASSDRIVER
)
5125 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5126 if (!AddDriverToList(
5127 &list
->DriverListHead
,
5131 currentInfFileDetails
,
5136 DriverDate
, DriverVersion
,
5142 else /* DriverType = SPDIT_COMPATDRIVER */
5144 /* 1. Get all fields */
5145 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5149 BOOL DriverAlreadyAdded
;
5151 for (i
= 2; i
<= FieldCount
; i
++)
5153 LPWSTR DeviceId
= NULL
;
5155 RequiredSize
= 128; /* Initial buffer size */
5156 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5157 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5159 HeapFree(GetProcessHeap(), 0, DeviceId
);
5160 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5163 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5166 Result
= SetupGetStringFieldW(
5169 DeviceId
, RequiredSize
,
5174 HeapFree(GetProcessHeap(), 0, DeviceId
);
5177 DriverAlreadyAdded
= FALSE
;
5178 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5180 if (wcsicmp(DeviceId
, currentId
) == 0)
5183 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5187 currentInfFileDetails
,
5192 DriverDate
, DriverVersion
,
5193 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5194 DriverAlreadyAdded
= TRUE
;
5199 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5201 if (wcsicmp(DeviceId
, currentId
) == 0)
5204 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5208 currentInfFileDetails
,
5213 DriverDate
, DriverVersion
,
5214 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5215 DriverAlreadyAdded
= TRUE
;
5219 HeapFree(GetProcessHeap(), 0, DeviceId
);
5222 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5225 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5226 ManufacturerName
= NULL
;
5227 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5232 HeapFree(GetProcessHeap(), 0, ProviderName
);
5233 ProviderName
= NULL
;
5235 DereferenceInfFile(currentInfFileDetails
);
5236 currentInfFileDetails
= NULL
;
5247 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5248 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5252 InstallParams
.Flags
|= DI_DIDCLASS
;
5253 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5255 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5258 HeapFree(GetProcessHeap(), 0, ProviderName
);
5259 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5260 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5261 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5262 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5263 if (currentInfFileDetails
)
5264 DereferenceInfFile(currentInfFileDetails
);
5265 HeapFree(GetProcessHeap(), 0, Buffer
);
5267 TRACE("Returning %d\n", ret
);
5271 /***********************************************************************
5272 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5275 SetupDiDeleteDeviceInfo(
5276 IN HDEVINFO DeviceInfoSet
,
5277 IN PSP_DEVINFO_DATA DeviceInfoData
)
5279 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5281 FIXME("not implemented\n");
5282 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5287 /***********************************************************************
5288 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5291 SetupDiDestroyDriverInfoList(
5292 IN HDEVINFO DeviceInfoSet
,
5293 IN PSP_DEVINFO_DATA DeviceInfoData
,
5294 IN DWORD DriverType
)
5296 struct DeviceInfoSet
*list
;
5299 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5302 SetLastError(ERROR_INVALID_HANDLE
);
5303 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5304 SetLastError(ERROR_INVALID_HANDLE
);
5305 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5306 SetLastError(ERROR_INVALID_PARAMETER
);
5307 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5308 SetLastError(ERROR_INVALID_PARAMETER
);
5309 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5310 SetLastError(ERROR_INVALID_USER_BUFFER
);
5313 PLIST_ENTRY ListEntry
;
5314 struct DriverInfoElement
*driverInfo
;
5315 SP_DEVINSTALL_PARAMS_W InstallParams
;
5317 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5318 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5321 if (!DeviceInfoData
)
5322 /* Fall back to destroying class driver list */
5323 DriverType
= SPDIT_CLASSDRIVER
;
5325 if (DriverType
== SPDIT_CLASSDRIVER
)
5327 while (!IsListEmpty(&list
->DriverListHead
))
5329 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5330 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5331 DestroyDriverInfoElement(driverInfo
);
5333 InstallParams
.Reserved
= 0;
5334 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5335 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5336 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5340 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5341 struct DeviceInfoElement
*deviceInfo
;
5343 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5344 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5346 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5347 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5349 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5350 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5351 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5353 InstallParamsSet
.Reserved
= 0;
5354 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5356 DestroyDriverInfoElement(driverInfo
);
5358 InstallParams
.Reserved
= 0;
5359 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5360 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5361 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5366 TRACE("Returning %d\n", ret
);
5371 /***********************************************************************
5372 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5375 SetupDiOpenDeviceInfoA(
5376 IN HDEVINFO DeviceInfoSet
,
5377 IN PCSTR DeviceInstanceId
,
5378 IN HWND hwndParent OPTIONAL
,
5380 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5382 LPWSTR DeviceInstanceIdW
= NULL
;
5385 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5387 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5388 if (DeviceInstanceIdW
== NULL
)
5391 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5392 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5394 MyFree(DeviceInstanceIdW
);
5400 /***********************************************************************
5401 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5404 SetupDiOpenDeviceInfoW(
5405 IN HDEVINFO DeviceInfoSet
,
5406 IN PCWSTR DeviceInstanceId
,
5407 IN HWND hwndParent OPTIONAL
,
5409 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5411 struct DeviceInfoSet
*list
;
5412 HKEY hEnumKey
, hKey
;
5416 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5418 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5419 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5422 SetLastError(ERROR_INVALID_HANDLE
);
5423 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5424 SetLastError(ERROR_INVALID_HANDLE
);
5425 else if (!DeviceInstanceId
)
5426 SetLastError(ERROR_INVALID_PARAMETER
);
5427 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5429 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5430 SetLastError(ERROR_INVALID_FLAGS
);
5432 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5433 SetLastError(ERROR_INVALID_USER_BUFFER
);
5436 struct DeviceInfoElement
*deviceInfo
= NULL
;
5437 /* Search if device already exists in DeviceInfoSet.
5438 * If yes, return the existing element
5439 * If no, create a new element using informations in registry
5441 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5442 while (ItemList
!= &list
->ListHead
)
5447 FIXME("not implemented\n");
5448 ItemList
= ItemList
->Flink
;
5453 /* good one found */
5458 /* Open supposed registry key */
5463 KEY_ENUMERATE_SUB_KEYS
,
5465 if (rc
!= ERROR_SUCCESS
)
5476 RegCloseKey(hEnumKey
);
5477 if (rc
!= ERROR_SUCCESS
)
5479 if (rc
== ERROR_FILE_NOT_FOUND
)
5480 rc
= ERROR_NO_SUCH_DEVINST
;
5485 /* FIXME: try to get ClassGUID from registry, instead of
5486 * sending GUID_NULL to CreateDeviceInfoElement
5488 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
5493 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5499 if (ret
&& deviceInfo
&& DeviceInfoData
)
5501 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5502 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5503 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5511 /***********************************************************************
5512 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5515 SetupDiEnumDriverInfoA(
5516 IN HDEVINFO DeviceInfoSet
,
5517 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5518 IN DWORD DriverType
,
5519 IN DWORD MemberIndex
,
5520 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5522 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5525 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5526 DriverType
, MemberIndex
, DriverInfoData
);
5528 if (DriverInfoData
== NULL
)
5529 SetLastError(ERROR_INVALID_PARAMETER
);
5530 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5531 SetLastError(ERROR_INVALID_USER_BUFFER
);
5534 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5535 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
5536 DriverType
, MemberIndex
, &driverInfoData2W
);
5540 /* Do W->A conversion */
5541 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5542 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5543 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5544 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5546 DriverInfoData
->Description
[0] = '\0';
5549 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5550 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5552 DriverInfoData
->MfgName
[0] = '\0';
5555 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5556 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5558 DriverInfoData
->ProviderName
[0] = '\0';
5561 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5563 /* Copy more fields */
5564 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5565 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5570 TRACE("Returning %d\n", ret
);
5575 /***********************************************************************
5576 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5579 SetupDiEnumDriverInfoW(
5580 IN HDEVINFO DeviceInfoSet
,
5581 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5582 IN DWORD DriverType
,
5583 IN DWORD MemberIndex
,
5584 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5586 PLIST_ENTRY ListHead
;
5589 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5590 DriverType
, MemberIndex
, DriverInfoData
);
5592 if (!DeviceInfoSet
|| !DriverInfoData
)
5593 SetLastError(ERROR_INVALID_PARAMETER
);
5594 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5595 SetLastError(ERROR_INVALID_HANDLE
);
5596 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5597 SetLastError(ERROR_INVALID_HANDLE
);
5598 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5599 SetLastError(ERROR_INVALID_PARAMETER
);
5600 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5601 SetLastError(ERROR_INVALID_PARAMETER
);
5602 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5603 SetLastError(ERROR_INVALID_PARAMETER
);
5604 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5605 SetLastError(ERROR_INVALID_USER_BUFFER
);
5608 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5609 PLIST_ENTRY ItemList
;
5610 if (DriverType
== SPDIT_CLASSDRIVER
||
5611 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
5613 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5617 ListHead
= &devInfo
->DriverListHead
;
5620 ItemList
= ListHead
->Flink
;
5621 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
5622 ItemList
= ItemList
->Flink
;
5623 if (ItemList
== ListHead
)
5624 SetLastError(ERROR_NO_MORE_ITEMS
);
5627 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
5630 &DriverInfoData
->DriverType
,
5631 &DrvInfo
->Info
.DriverType
,
5632 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5637 TRACE("Returning %d\n", ret
);
5642 /***********************************************************************
5643 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5646 SetupDiGetSelectedDriverA(
5647 IN HDEVINFO DeviceInfoSet
,
5648 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5649 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5651 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5654 if (DriverInfoData
== NULL
)
5655 SetLastError(ERROR_INVALID_PARAMETER
);
5656 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5657 SetLastError(ERROR_INVALID_USER_BUFFER
);
5660 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5662 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5668 /* Do W->A conversion */
5669 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5670 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5671 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5672 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5674 DriverInfoData
->Description
[0] = '\0';
5677 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5678 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5680 DriverInfoData
->MfgName
[0] = '\0';
5683 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5684 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5686 DriverInfoData
->ProviderName
[0] = '\0';
5689 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5691 /* Copy more fields */
5692 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5693 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5702 /***********************************************************************
5703 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5706 SetupDiGetSelectedDriverW(
5707 IN HDEVINFO DeviceInfoSet
,
5708 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5709 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5713 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5715 if (!DeviceInfoSet
|| !DriverInfoData
)
5716 SetLastError(ERROR_INVALID_PARAMETER
);
5717 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5718 SetLastError(ERROR_INVALID_HANDLE
);
5719 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5720 SetLastError(ERROR_INVALID_HANDLE
);
5721 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5722 SetLastError(ERROR_INVALID_USER_BUFFER
);
5723 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5724 SetLastError(ERROR_INVALID_USER_BUFFER
);
5727 SP_DEVINSTALL_PARAMS InstallParams
;
5729 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5730 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5732 struct DriverInfoElement
*driverInfo
;
5733 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5734 if (driverInfo
== NULL
)
5735 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5739 &DriverInfoData
->DriverType
,
5740 &driverInfo
->Info
.DriverType
,
5741 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5747 TRACE("Returning %d\n", ret
);
5752 /***********************************************************************
5753 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5756 SetupDiSetSelectedDriverA(
5757 IN HDEVINFO DeviceInfoSet
,
5758 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5759 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5761 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5762 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5765 if (DriverInfoData
!= NULL
)
5767 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5768 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5770 SetLastError(ERROR_INVALID_PARAMETER
);
5774 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5775 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5777 if (DriverInfoDataW
.Reserved
== 0)
5779 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5781 /* convert the strings to unicode */
5782 if (!MultiByteToWideChar(CP_ACP
,
5784 DriverInfoData
->Description
,
5786 DriverInfoDataW
.Description
,
5788 !MultiByteToWideChar(CP_ACP
,
5790 DriverInfoData
->ProviderName
,
5792 DriverInfoDataW
.ProviderName
,
5799 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5802 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5806 if (ret
&& pDriverInfoDataW
!= NULL
)
5808 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5815 /***********************************************************************
5816 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5819 SetupDiSetSelectedDriverW(
5820 IN HDEVINFO DeviceInfoSet
,
5821 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5822 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5826 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5829 SetLastError(ERROR_INVALID_PARAMETER
);
5830 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5831 SetLastError(ERROR_INVALID_HANDLE
);
5832 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5833 SetLastError(ERROR_INVALID_HANDLE
);
5834 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5835 SetLastError(ERROR_INVALID_USER_BUFFER
);
5836 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5837 SetLastError(ERROR_INVALID_USER_BUFFER
);
5840 struct DriverInfoElement
**pDriverInfo
;
5841 PLIST_ENTRY ListHead
, ItemList
;
5845 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5846 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5850 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5851 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5854 if (!DriverInfoData
)
5856 *pDriverInfo
= NULL
;
5861 /* Search selected driver in list */
5862 ItemList
= ListHead
->Flink
;
5863 while (ItemList
!= ListHead
)
5865 if (DriverInfoData
->Reserved
!= 0)
5867 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5872 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5873 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5874 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5875 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5876 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5882 if (ItemList
== ListHead
)
5883 SetLastError(ERROR_INVALID_PARAMETER
);
5886 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5887 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5889 TRACE("Choosing driver whose rank is 0x%lx\n",
5890 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5892 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5897 TRACE("Returning %d\n", ret
);
5901 /***********************************************************************
5902 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5905 SetupDiGetDriverInfoDetailA(
5906 IN HDEVINFO DeviceInfoSet
,
5907 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5908 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5909 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5910 IN DWORD DriverInfoDetailDataSize
,
5911 OUT PDWORD RequiredSize OPTIONAL
)
5913 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5914 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5916 DWORD HardwareIDLen
= 0;
5919 /* do some sanity checks, the unicode version might do more thorough checks */
5920 if (DriverInfoData
== NULL
||
5921 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5922 (DriverInfoDetailData
!= NULL
&&
5923 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5924 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5926 SetLastError(ERROR_INVALID_PARAMETER
);
5930 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5931 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5933 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5935 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5937 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5941 SetLastError(ERROR_INVALID_PARAMETER
);
5944 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5945 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5947 /* convert the strings to unicode */
5948 if (MultiByteToWideChar(CP_ACP
,
5950 DriverInfoData
->Description
,
5952 DriverInfoDataW
.Description
,
5954 MultiByteToWideChar(CP_ACP
,
5956 DriverInfoData
->MfgName
,
5958 DriverInfoDataW
.MfgName
,
5960 MultiByteToWideChar(CP_ACP
,
5962 DriverInfoData
->ProviderName
,
5964 DriverInfoDataW
.ProviderName
,
5967 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5969 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5970 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5973 if (DriverInfoDetailData
!= NULL
)
5975 /* calculate the unicode buffer size from the ansi buffer size */
5976 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5977 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5978 (HardwareIDLen
* sizeof(WCHAR
));
5980 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5981 if (DriverInfoDetailDataW
== NULL
)
5983 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5987 /* initialize the buffer */
5988 ZeroMemory(DriverInfoDetailDataW
,
5990 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5993 /* call the unicode version */
5994 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5997 DriverInfoDetailDataW
,
6003 if (DriverInfoDetailDataW
!= NULL
)
6005 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6006 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6007 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6008 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6009 if (WideCharToMultiByte(CP_ACP
,
6011 DriverInfoDetailDataW
->SectionName
,
6013 DriverInfoDetailData
->SectionName
,
6017 WideCharToMultiByte(CP_ACP
,
6019 DriverInfoDetailDataW
->InfFileName
,
6021 DriverInfoDetailData
->InfFileName
,
6025 WideCharToMultiByte(CP_ACP
,
6027 DriverInfoDetailDataW
->DrvDescription
,
6029 DriverInfoDetailData
->DrvDescription
,
6033 WideCharToMultiByte(CP_ACP
,
6035 DriverInfoDetailDataW
->HardwareID
,
6037 DriverInfoDetailData
->HardwareID
,
6043 DWORD hwidlen
= HardwareIDLen
;
6044 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6046 /* count the strings in the list */
6049 len
= lstrlenA(s
) + 1;
6058 /* looks like the string list wasn't terminated... */
6059 SetLastError(ERROR_INVALID_USER_BUFFER
);
6065 /* make sure CompatIDsOffset points to the second string in the
6069 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6070 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6071 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6075 DriverInfoDetailData
->CompatIDsOffset
= 0;
6076 DriverInfoDetailData
->CompatIDsLength
= 0;
6085 if (RequiredSize
!= NULL
)
6087 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6088 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6094 if (DriverInfoDetailDataW
!= NULL
)
6096 MyFree(DriverInfoDetailDataW
);
6102 /***********************************************************************
6103 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6106 SetupDiGetDriverInfoDetailW(
6107 IN HDEVINFO DeviceInfoSet
,
6108 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6109 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6110 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6111 IN DWORD DriverInfoDetailDataSize
,
6112 OUT PDWORD RequiredSize OPTIONAL
)
6116 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6117 DriverInfoData
, DriverInfoDetailData
,
6118 DriverInfoDetailDataSize
, RequiredSize
);
6121 SetLastError(ERROR_INVALID_PARAMETER
);
6122 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6123 SetLastError(ERROR_INVALID_HANDLE
);
6124 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6125 SetLastError(ERROR_INVALID_HANDLE
);
6126 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6127 SetLastError(ERROR_INVALID_USER_BUFFER
);
6128 else if (!DriverInfoData
)
6129 SetLastError(ERROR_INVALID_PARAMETER
);
6130 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6131 SetLastError(ERROR_INVALID_PARAMETER
);
6132 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6133 SetLastError(ERROR_INVALID_PARAMETER
);
6134 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6135 SetLastError(ERROR_INVALID_USER_BUFFER
);
6136 else if (DriverInfoData
->Reserved
== 0)
6137 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6140 struct DriverInfoElement
*driverInfoElement
;
6141 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6144 DriverInfoDetailData
,
6145 &driverInfoElement
->Details
,
6146 driverInfoElement
->Details
.cbSize
);
6147 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6148 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6153 TRACE("Returning %d\n", ret
);
6157 /***********************************************************************
6158 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6161 SetupDiSelectBestCompatDrv(
6162 IN HDEVINFO DeviceInfoSet
,
6163 IN PSP_DEVINFO_DATA DeviceInfoData
)
6165 SP_DRVINFO_DATA_W drvInfoData
;
6168 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6170 /* Drivers are sorted by rank in the driver list, so
6171 * the first driver in the list is the best one.
6173 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6174 ret
= SetupDiEnumDriverInfoW(
6178 0, /* Member index */
6183 ret
= SetupDiSetSelectedDriverW(
6189 TRACE("Returning %d\n", ret
);
6193 /***********************************************************************
6194 * SetupDiInstallDriverFiles (SETUPAPI.@)
6197 SetupDiInstallDriverFiles(
6198 IN HDEVINFO DeviceInfoSet
,
6199 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6203 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6206 SetLastError(ERROR_INVALID_PARAMETER
);
6207 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6208 SetLastError(ERROR_INVALID_HANDLE
);
6209 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6210 SetLastError(ERROR_INVALID_HANDLE
);
6211 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6212 SetLastError(ERROR_INVALID_USER_BUFFER
);
6213 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
6214 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6215 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
6216 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6219 SP_DEVINSTALL_PARAMS_W InstallParams
;
6220 struct DriverInfoElement
*SelectedDriver
;
6221 WCHAR SectionName
[MAX_PATH
];
6222 DWORD SectionNameLength
= 0;
6224 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6225 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6229 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6230 if (!SelectedDriver
)
6232 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6236 ret
= SetupDiGetActualSectionToInstallW(
6237 SelectedDriver
->InfFileDetails
->hInf
,
6238 SelectedDriver
->Details
.SectionName
,
6239 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6243 if (!InstallParams
.InstallMsgHandler
)
6245 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6246 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6247 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6249 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6250 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6251 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
6252 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6253 DeviceInfoSet
, DeviceInfoData
);
6257 TRACE("Returning %d\n", ret
);
6261 /***********************************************************************
6262 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6265 SetupDiRegisterCoDeviceInstallers(
6266 IN HDEVINFO DeviceInfoSet
,
6267 IN PSP_DEVINFO_DATA DeviceInfoData
)
6269 BOOL ret
= FALSE
; /* Return value */
6271 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6274 SetLastError(ERROR_INVALID_PARAMETER
);
6275 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6276 SetLastError(ERROR_INVALID_HANDLE
);
6277 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6278 SetLastError(ERROR_INVALID_HANDLE
);
6279 else if (!DeviceInfoData
)
6280 SetLastError(ERROR_INVALID_PARAMETER
);
6281 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6282 SetLastError(ERROR_INVALID_USER_BUFFER
);
6285 SP_DEVINSTALL_PARAMS_W InstallParams
;
6286 struct DriverInfoElement
*SelectedDriver
;
6289 WCHAR SectionName
[MAX_PATH
];
6290 DWORD SectionNameLength
= 0;
6291 HKEY hKey
= INVALID_HANDLE_VALUE
;
6293 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6294 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6298 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6299 if (SelectedDriver
== NULL
)
6301 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6305 /* Get .CoInstallers section name */
6306 Result
= SetupDiGetActualSectionToInstallW(
6307 SelectedDriver
->InfFileDetails
->hInf
,
6308 SelectedDriver
->Details
.SectionName
,
6309 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6310 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
6312 wcscat(SectionName
, L
".CoInstallers");
6314 /* Open/Create driver key information */
6315 #if _WIN32_WINNT >= 0x502
6316 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6318 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6320 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6321 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6322 if (hKey
== INVALID_HANDLE_VALUE
)
6325 /* Install .CoInstallers section */
6326 DoAction
= SPINST_REGISTRY
;
6327 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6329 DoAction
|= SPINST_FILES
;
6330 if (!InstallParams
.InstallMsgHandler
)
6332 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6333 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6334 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6337 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6338 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6339 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6340 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6341 DeviceInfoSet
, DeviceInfoData
);
6348 if (hKey
!= INVALID_HANDLE_VALUE
)
6352 TRACE("Returning %d\n", ret
);
6356 /***********************************************************************
6357 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
6360 SetupDiInstallDeviceInterfaces(
6361 IN HDEVINFO DeviceInfoSet
,
6362 IN PSP_DEVINFO_DATA DeviceInfoData
)
6364 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6366 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
6367 //SetLastError(ERROR_GEN_FAILURE);
6373 InfIsFromOEMLocation(
6375 OUT LPBOOL IsOEMLocation
)
6379 last
= strrchrW(FullName
, '\\');
6382 /* No directory specified */
6383 *IsOEMLocation
= FALSE
;
6387 WCHAR Windir
[MAX_PATH
];
6390 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
6391 if (ret
== 0 || ret
>= MAX_PATH
)
6393 SetLastError(ERROR_GEN_FAILURE
);
6397 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
6399 /* The path is %SYSTEMROOT%\Inf */
6400 *IsOEMLocation
= FALSE
;
6404 /* The file is in another place */
6405 *IsOEMLocation
= TRUE
;
6411 /***********************************************************************
6412 * SetupDiInstallDevice (SETUPAPI.@)
6415 SetupDiInstallDevice(
6416 IN HDEVINFO DeviceInfoSet
,
6417 IN PSP_DEVINFO_DATA DeviceInfoData
)
6419 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6420 SP_DEVINSTALL_PARAMS_W InstallParams
;
6421 struct DriverInfoElement
*SelectedDriver
;
6422 SYSTEMTIME DriverDate
;
6423 WCHAR SectionName
[MAX_PATH
];
6425 DWORD SectionNameLength
= 0;
6426 BOOL Result
= FALSE
;
6427 INFCONTEXT ContextService
;
6431 LPCWSTR AssociatedService
= NULL
;
6432 LPWSTR pSectionName
= NULL
;
6433 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
6435 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
6436 BOOL RebootRequired
= FALSE
;
6437 HKEY hKey
= INVALID_HANDLE_VALUE
;
6438 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
6439 BOOL NeedtoCopyFile
;
6440 LARGE_INTEGER fullVersion
;
6442 BOOL ret
= FALSE
; /* Return value */
6444 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6447 SetLastError(ERROR_INVALID_PARAMETER
);
6448 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6449 SetLastError(ERROR_INVALID_HANDLE
);
6450 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6451 SetLastError(ERROR_INVALID_HANDLE
);
6452 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6453 SetLastError(ERROR_INVALID_USER_BUFFER
);
6459 /* One parameter is bad */
6463 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6464 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6468 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
6470 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6474 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6475 if (SelectedDriver
== NULL
)
6477 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6481 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
6483 Result
= SetupDiGetActualSectionToInstallW(
6484 SelectedDriver
->InfFileDetails
->hInf
,
6485 SelectedDriver
->Details
.SectionName
,
6486 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6487 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
6489 pSectionName
= &SectionName
[wcslen(SectionName
)];
6491 /* Get information from [Version] section */
6492 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
6494 /* Format ClassGuid to a string */
6495 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
6497 RequiredSize
= lstrlenW(lpGuidString
);
6498 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
6499 if (!lpFullGuidString
)
6501 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6504 lpFullGuidString
[0] = '{';
6505 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
6506 lpFullGuidString
[RequiredSize
+ 1] = '}';
6507 lpFullGuidString
[RequiredSize
+ 2] = '\0';
6509 /* Open/Create driver key information */
6510 #if _WIN32_WINNT >= 0x502
6511 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6513 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6515 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6516 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6517 if (hKey
== INVALID_HANDLE_VALUE
)
6520 /* Install main section */
6521 DoAction
= SPINST_REGISTRY
;
6522 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6524 DoAction
|= SPINST_FILES
;
6525 if (!InstallParams
.InstallMsgHandler
)
6527 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6528 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6529 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6532 *pSectionName
= '\0';
6533 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6534 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6535 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6536 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6537 DeviceInfoSet
, DeviceInfoData
);
6540 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
6542 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
6544 /* Delete resources allocated by SetupInitDefaultQueueCallback */
6545 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
6548 InstallParams
.Flags
|= DI_NOFILECOPY
;
6549 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6551 /* Write information to driver key */
6552 *pSectionName
= UNICODE_NULL
;
6553 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
6554 TRACE("Write information to driver key\n");
6555 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6556 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6557 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
6558 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
6559 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
6560 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
6561 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
6562 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
6563 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6564 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
6565 if (rc
== ERROR_SUCCESS
)
6566 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
6567 if (rc
== ERROR_SUCCESS
)
6568 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6569 if (rc
== ERROR_SUCCESS
)
6571 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
6572 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
6574 if (rc
== ERROR_SUCCESS
)
6575 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
6576 if (rc
== ERROR_SUCCESS
)
6577 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
6578 if (rc
== ERROR_SUCCESS
)
6579 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
6580 if (rc
== ERROR_SUCCESS
)
6581 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
6582 if (rc
== ERROR_SUCCESS
)
6583 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
6584 if (rc
!= ERROR_SUCCESS
)
6590 hKey
= INVALID_HANDLE_VALUE
;
6592 /* FIXME: Process .LogConfigOverride section */
6594 /* Install .Services section */
6595 wcscpy(pSectionName
, L
".Services");
6596 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
6599 LPWSTR ServiceName
= NULL
;
6600 LPWSTR ServiceSection
= NULL
;
6602 Result
= SetupGetStringFieldW(
6604 1, /* Field index */
6609 if (RequiredSize
> 0)
6611 /* We got the needed size for the buffer */
6612 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6615 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6618 Result
= SetupGetStringFieldW(
6620 1, /* Field index */
6621 ServiceName
, RequiredSize
,
6626 Result
= SetupGetIntField(
6628 2, /* Field index */
6632 /* The field may be empty. Ignore the error */
6635 Result
= SetupGetStringFieldW(
6637 3, /* Field index */
6642 if (GetLastError() == ERROR_INVALID_PARAMETER
)
6644 /* This first is probably missing. It is not
6645 * required, so ignore the error */
6652 if (RequiredSize
> 0)
6654 /* We got the needed size for the buffer */
6655 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6656 if (!ServiceSection
)
6658 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6661 Result
= SetupGetStringFieldW(
6663 3, /* Field index */
6664 ServiceSection
, RequiredSize
,
6669 SetLastError(ERROR_SUCCESS
);
6670 Result
= SetupInstallServicesFromInfSectionExW(
6671 SelectedDriver
->InfFileDetails
->hInf
,
6672 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
6674 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
6676 AssociatedService
= ServiceName
;
6678 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
6679 RebootRequired
= TRUE
;
6682 HeapFree(GetProcessHeap(), 0, ServiceName
);
6683 HeapFree(GetProcessHeap(), 0, ServiceSection
);
6686 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
6689 /* Copy .inf file to Inf\ directory (if needed) */
6690 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
6695 Result
= SetupCopyOEMInfW(
6696 SelectedDriver
->InfFileDetails
->FullInfFileName
,
6699 SP_COPY_NOOVERWRITE
,
6705 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6706 * to release use of current InfFile */
6709 /* Open device registry key */
6710 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
6711 if (hKey
== INVALID_HANDLE_VALUE
)
6714 /* Install .HW section */
6715 wcscpy(pSectionName
, L
".HW");
6716 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6717 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6718 SPINST_REGISTRY
, hKey
, NULL
, 0,
6719 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6720 DeviceInfoSet
, DeviceInfoData
);
6724 /* Write information to enum key */
6725 TRACE("Write information to enum key\n");
6726 TRACE("Class : '%S'\n", ClassName
);
6727 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
6728 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6729 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
6730 TRACE("Service : '%S'\n", AssociatedService
);
6731 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
6732 if (rc
== ERROR_SUCCESS
)
6733 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
6734 if (rc
== ERROR_SUCCESS
)
6735 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6736 if (rc
== ERROR_SUCCESS
)
6737 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
6738 if (rc
== ERROR_SUCCESS
&& *AssociatedService
)
6739 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
6740 if (rc
!= ERROR_SUCCESS
)
6746 /* Start the device */
6747 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
6749 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6751 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
6752 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6753 ret
= NT_SUCCESS(Status
);
6759 /* End of installation */
6760 if (hClassKey
!= INVALID_HANDLE_VALUE
)
6761 RegCloseKey(hClassKey
);
6762 if (hKey
!= INVALID_HANDLE_VALUE
)
6765 RpcStringFreeW(&lpGuidString
);
6766 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
6767 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6769 TRACE("Returning %d\n", ret
);