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, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1190 if (!deviceInterface
)
1192 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1195 deviceInterface
->DeviceInfo
= deviceInfo
;
1196 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1197 deviceInterface
->Flags
= 0; /* FIXME */
1198 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1200 *pDeviceInterface
= deviceInterface
;
1204 static LONG
SETUP_CreateDevListFromEnumerator(
1205 struct DeviceInfoSet
*list
,
1206 LPCGUID pClassGuid OPTIONAL
,
1208 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1210 HKEY hDeviceIdKey
, hInstanceIdKey
;
1211 WCHAR KeyBuffer
[MAX_PATH
];
1212 WCHAR InstancePath
[MAX_PATH
];
1213 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1214 struct DeviceInfoElement
*deviceInfo
;
1216 DWORD dwLength
, dwRegType
;
1219 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1222 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1223 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1224 if (rc
== ERROR_NO_MORE_ITEMS
)
1226 if (rc
!= ERROR_SUCCESS
)
1230 /* Open device id sub key */
1231 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1232 if (rc
!= ERROR_SUCCESS
)
1234 wcscpy(InstancePath
, Enumerator
);
1235 wcscat(InstancePath
, L
"\\");
1236 wcscat(InstancePath
, KeyBuffer
);
1237 wcscat(InstancePath
, L
"\\");
1238 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1240 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1246 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1247 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1248 if (rc
== ERROR_NO_MORE_ITEMS
)
1250 if (rc
!= ERROR_SUCCESS
)
1252 RegCloseKey(hDeviceIdKey
);
1257 /* Open instance id sub key */
1258 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1259 if (rc
!= ERROR_SUCCESS
)
1261 RegCloseKey(hDeviceIdKey
);
1264 *pEndOfInstancePath
= '\0';
1265 wcscat(InstancePath
, KeyBuffer
);
1267 /* Read ClassGUID value */
1268 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1269 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1270 RegCloseKey(hInstanceIdKey
);
1271 if (rc
== ERROR_FILE_NOT_FOUND
)
1274 /* Skip this bad entry as we can't verify it */
1276 /* Set a default GUID for this device */
1277 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1279 else if (rc
!= ERROR_SUCCESS
)
1281 RegCloseKey(hDeviceIdKey
);
1284 else if (dwRegType
!= REG_SZ
)
1286 RegCloseKey(hDeviceIdKey
);
1287 return ERROR_GEN_FAILURE
;
1291 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1292 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1293 /* Bad GUID, skip the entry */
1297 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1299 /* Skip this entry as it is not the right device class */
1303 /* Add the entry to the list */
1304 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1306 RegCloseKey(hDeviceIdKey
);
1307 return GetLastError();
1309 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1310 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1312 RegCloseKey(hDeviceIdKey
);
1315 return ERROR_SUCCESS
;
1318 static LONG
SETUP_CreateDevList(
1319 struct DeviceInfoSet
*list
,
1320 PCWSTR MachineName OPTIONAL
,
1321 LPGUID
class OPTIONAL
,
1322 PCWSTR Enumerator OPTIONAL
)
1324 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1325 WCHAR KeyBuffer
[MAX_PATH
];
1330 if (class && IsEqualIID(class, &GUID_NULL
))
1334 if (MachineName
!= NULL
)
1336 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1337 if (rc
!= ERROR_SUCCESS
)
1341 HKLM
= HKEY_LOCAL_MACHINE
;
1343 rc
= RegOpenKeyExW(HKLM
,
1346 KEY_ENUMERATE_SUB_KEYS
,
1348 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1349 if (rc
!= ERROR_SUCCESS
)
1352 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1353 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1362 KEY_ENUMERATE_SUB_KEYS
,
1364 RegCloseKey(hEnumKey
);
1365 if (rc
!= ERROR_SUCCESS
)
1367 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1368 RegCloseKey(hEnumeratorKey
);
1373 /* Enumerate enumerators */
1377 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1378 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1379 if (rc
== ERROR_NO_MORE_ITEMS
)
1381 if (rc
!= ERROR_SUCCESS
)
1383 RegCloseKey(hEnumKey
);
1389 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1390 if (rc
!= ERROR_SUCCESS
)
1392 RegCloseKey(hEnumKey
);
1396 /* Call SETUP_CreateDevListFromEnumerator */
1397 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1398 RegCloseKey(hEnumeratorKey
);
1399 if (rc
!= ERROR_SUCCESS
)
1401 RegCloseKey(hEnumKey
);
1405 RegCloseKey(hEnumKey
);
1406 return ERROR_SUCCESS
;
1411 static LONG
SETUP_CreateSerialDeviceList(
1412 struct DeviceInfoSet
*list
,
1414 LPGUID InterfaceGuid
,
1415 PCWSTR DeviceInstanceW
)
1417 static const size_t initialSize
= 100;
1419 WCHAR buf
[initialSize
];
1421 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1423 struct DeviceInfoElement
*deviceInfo
;
1426 WARN("'MachineName' is ignored on Wine!\n");
1427 if (DeviceInstanceW
)
1428 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1434 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1436 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1440 HeapFree(GetProcessHeap(), 0, devices
);
1441 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1443 return ERROR_NOT_ENOUGH_MEMORY
;
1449 HeapFree(GetProcessHeap(), 0, devices
);
1450 return GetLastError();
1454 /* 'devices' is a MULTI_SZ string */
1455 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1457 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1459 /* We have found a device */
1460 struct DeviceInterface
*interfaceInfo
;
1461 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1462 /* Step 1. Create a device info element */
1463 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1466 HeapFree(GetProcessHeap(), 0, devices
);
1467 return GetLastError();
1469 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1471 /* Step 2. Create an interface list for this element */
1472 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1475 HeapFree(GetProcessHeap(), 0, devices
);
1476 return GetLastError();
1478 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1482 HeapFree(GetProcessHeap(), 0, devices
);
1483 return ERROR_SUCCESS
;
1486 #else /* __REACTOS__ */
1488 static LONG
SETUP_CreateInterfaceList(
1489 struct DeviceInfoSet
*list
,
1491 LPGUID InterfaceGuid
,
1492 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1494 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1495 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1496 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1497 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1498 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1500 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1503 DWORD dwLength
, dwInstancePathLength
;
1506 struct DeviceInfoElement
*deviceInfo
;
1508 /* Open registry key related to this interface */
1509 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1510 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1511 return GetLastError();
1513 /* Enumerate sub keys of hInterfaceKey */
1517 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1518 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1519 if (rc
== ERROR_NO_MORE_ITEMS
)
1521 if (rc
!= ERROR_SUCCESS
)
1523 RegCloseKey(hInterfaceKey
);
1529 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1530 if (rc
!= ERROR_SUCCESS
)
1532 RegCloseKey(hInterfaceKey
);
1536 /* Read DeviceInstance */
1537 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1538 if (rc
!= ERROR_SUCCESS
)
1540 RegCloseKey(hDeviceInstanceKey
);
1541 RegCloseKey(hInterfaceKey
);
1544 if (dwRegType
!= REG_SZ
)
1546 RegCloseKey(hDeviceInstanceKey
);
1547 RegCloseKey(hInterfaceKey
);
1548 return ERROR_GEN_FAILURE
;
1550 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1553 RegCloseKey(hDeviceInstanceKey
);
1554 RegCloseKey(hInterfaceKey
);
1555 return ERROR_NOT_ENOUGH_MEMORY
;
1557 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1558 if (rc
!= ERROR_SUCCESS
)
1560 HeapFree(GetProcessHeap(), 0, InstancePath
);
1561 RegCloseKey(hDeviceInstanceKey
);
1562 RegCloseKey(hInterfaceKey
);
1565 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1566 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1568 if (DeviceInstanceW
)
1570 /* Check if device enumerator is not the right one */
1571 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1573 HeapFree(GetProcessHeap(), 0, InstancePath
);
1574 RegCloseKey(hDeviceInstanceKey
);
1579 /* Find class GUID associated to the device instance */
1584 KEY_ENUMERATE_SUB_KEYS
,
1586 if (rc
!= ERROR_SUCCESS
)
1588 HeapFree(GetProcessHeap(), 0, InstancePath
);
1589 RegCloseKey(hDeviceInstanceKey
);
1590 RegCloseKey(hInterfaceKey
);
1599 RegCloseKey(hEnumKey
);
1600 if (rc
!= ERROR_SUCCESS
)
1602 HeapFree(GetProcessHeap(), 0, InstancePath
);
1603 RegCloseKey(hDeviceInstanceKey
);
1604 RegCloseKey(hInterfaceKey
);
1607 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1608 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1610 if (rc
!= ERROR_SUCCESS
)
1612 HeapFree(GetProcessHeap(), 0, InstancePath
);
1613 RegCloseKey(hDeviceInstanceKey
);
1614 RegCloseKey(hInterfaceKey
);
1617 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1618 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1619 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1621 HeapFree(GetProcessHeap(), 0, InstancePath
);
1622 RegCloseKey(hDeviceInstanceKey
);
1623 RegCloseKey(hInterfaceKey
);
1624 return ERROR_GEN_FAILURE
;
1626 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1628 /* If current device doesn't match the list GUID (if any), skip this entry */
1629 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1631 HeapFree(GetProcessHeap(), 0, InstancePath
);
1632 RegCloseKey(hDeviceInstanceKey
);
1636 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1640 LPWSTR pSymbolicLink
;
1641 struct DeviceInterface
*interfaceInfo
;
1643 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1644 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1645 if (rc
== ERROR_NO_MORE_ITEMS
)
1647 if (rc
!= ERROR_SUCCESS
)
1649 HeapFree(GetProcessHeap(), 0, InstancePath
);
1650 RegCloseKey(hDeviceInstanceKey
);
1651 RegCloseKey(hInterfaceKey
);
1655 if (KeyBuffer
[0] != '#')
1656 /* This entry doesn't represent an interesting entry */
1660 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1661 if (rc
!= ERROR_SUCCESS
)
1663 RegCloseKey(hDeviceInstanceKey
);
1664 RegCloseKey(hInterfaceKey
);
1668 /* Read SymbolicLink value */
1669 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1670 if (rc
!= ERROR_SUCCESS
)
1672 RegCloseKey(hReferenceKey
);
1673 RegCloseKey(hDeviceInstanceKey
);
1674 RegCloseKey(hInterfaceKey
);
1677 if (dwRegType
!= REG_SZ
)
1679 RegCloseKey(hReferenceKey
);
1680 RegCloseKey(hDeviceInstanceKey
);
1681 RegCloseKey(hInterfaceKey
);
1682 return ERROR_GEN_FAILURE
;
1685 /* We have found a device */
1686 /* Step 1. Create a device info element */
1687 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1689 RegCloseKey(hReferenceKey
);
1690 RegCloseKey(hDeviceInstanceKey
);
1691 RegCloseKey(hInterfaceKey
);
1692 return GetLastError();
1694 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1695 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1697 /* Step 2. Create an interface list for this element */
1698 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1701 RegCloseKey(hReferenceKey
);
1702 RegCloseKey(hDeviceInstanceKey
);
1703 RegCloseKey(hInterfaceKey
);
1704 return ERROR_NOT_ENOUGH_MEMORY
;
1706 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1707 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1708 RegCloseKey(hReferenceKey
);
1709 if (rc
!= ERROR_SUCCESS
)
1711 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1712 RegCloseKey(hDeviceInstanceKey
);
1713 RegCloseKey(hInterfaceKey
);
1716 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1718 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1719 RegCloseKey(hDeviceInstanceKey
);
1720 RegCloseKey(hInterfaceKey
);
1721 return GetLastError();
1723 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1724 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1725 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1727 RegCloseKey(hDeviceInstanceKey
);
1729 RegCloseKey(hInterfaceKey
);
1730 return ERROR_SUCCESS
;
1732 #endif /* __REACTOS__ */
1734 /***********************************************************************
1735 * SetupDiGetClassDevsExW (SETUPAPI.@)
1737 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1746 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1747 struct DeviceInfoSet
*list
;
1751 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1752 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1754 /* Create the deviceset if not set */
1757 list
= (struct DeviceInfoSet
*)deviceset
;
1758 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1760 SetLastError(ERROR_INVALID_HANDLE
);
1761 return INVALID_HANDLE_VALUE
;
1763 hDeviceInfo
= deviceset
;
1767 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1768 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1769 NULL
, machine
, NULL
);
1770 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1771 return INVALID_HANDLE_VALUE
;
1772 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1775 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1778 pClassGuid
= &list
->ClassGuid
;
1780 if (flags
& DIGCF_PRESENT
)
1781 FIXME(": flag DIGCF_PRESENT ignored\n");
1782 if (flags
& DIGCF_PROFILE
)
1783 FIXME(": flag DIGCF_PROFILE ignored\n");
1785 if (flags
& DIGCF_ALLCLASSES
)
1787 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1788 if (rc
!= ERROR_SUCCESS
)
1792 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1793 return INVALID_HANDLE_VALUE
;
1797 else if (flags
& DIGCF_DEVICEINTERFACE
)
1801 SetLastError(ERROR_INVALID_PARAMETER
);
1803 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1804 return INVALID_HANDLE_VALUE
;
1808 /* Special case: find serial ports by calling QueryDosDevice */
1809 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1810 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1811 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1812 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1815 ERR("Wine can only enumerate serial devices at the moment!\n");
1816 rc
= ERROR_INVALID_PARAMETER
;
1818 #else /* __REACTOS__ */
1819 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1820 #endif /* __REACTOS__ */
1821 if (rc
!= ERROR_SUCCESS
)
1825 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1826 return INVALID_HANDLE_VALUE
;
1832 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1833 if (rc
!= ERROR_SUCCESS
)
1837 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1838 return INVALID_HANDLE_VALUE
;
1844 /***********************************************************************
1845 * SetupDiGetClassImageIndex (SETUPAPI.@)
1848 static BOOL
GetIconIndex(
1850 OUT PINT ImageIndex
)
1852 LPWSTR Buffer
= NULL
;
1853 DWORD dwRegType
, dwLength
;
1857 /* Read "Icon" registry key */
1858 rc
= RegQueryValueExW(hClassKey
, L
"Icon", NULL
, &dwRegType
, NULL
, &dwLength
);
1859 if (rc
!= ERROR_SUCCESS
)
1863 } else if (dwRegType
!= REG_SZ
)
1865 SetLastError(ERROR_INVALID_INDEX
);
1868 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1871 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1874 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1875 rc
= RegQueryValueExW(hClassKey
, L
"Icon", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1876 if (rc
!= ERROR_SUCCESS
)
1882 /* Transform "Icon" value to a INT */
1883 *ImageIndex
= atoiW(Buffer
);
1891 BOOL WINAPI
SetupDiGetClassImageIndex(
1892 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1893 IN CONST GUID
*ClassGuid
,
1894 OUT PINT ImageIndex
)
1896 struct ClassImageList
*list
;
1899 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
1901 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
1902 SetLastError(ERROR_INVALID_PARAMETER
);
1903 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1904 SetLastError(ERROR_INVALID_USER_BUFFER
);
1905 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
1906 SetLastError(ERROR_INVALID_USER_BUFFER
);
1907 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
1908 SetLastError(ERROR_INVALID_USER_BUFFER
);
1909 else if (!ImageIndex
)
1910 SetLastError(ERROR_INVALID_PARAMETER
);
1913 HKEY hKey
= INVALID_HANDLE_VALUE
;
1916 /* Read Icon registry entry into Buffer */
1917 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
1918 if (hKey
== INVALID_HANDLE_VALUE
)
1920 if (!GetIconIndex(hKey
, &iconIndex
))
1925 SetLastError(ERROR_INVALID_INDEX
);
1929 *ImageIndex
= -iconIndex
;
1933 if (hKey
!= INVALID_HANDLE_VALUE
)
1937 TRACE("Returning %d\n", ret
);
1941 /***********************************************************************
1942 * SetupDiGetClassImageList(SETUPAPI.@)
1944 BOOL WINAPI
SetupDiGetClassImageList(
1945 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
1947 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
1950 /***********************************************************************
1951 * SetupDiGetClassImageListExA(SETUPAPI.@)
1953 BOOL WINAPI
SetupDiGetClassImageListExA(
1954 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1955 IN PCSTR MachineName OPTIONAL
,
1958 PWSTR MachineNameW
= NULL
;
1963 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1964 if (MachineNameW
== NULL
)
1968 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
1971 MyFree(MachineNameW
);
1976 /***********************************************************************
1977 * SetupDiGetClassImageListExW(SETUPAPI.@)
1979 BOOL WINAPI
SetupDiGetClassImageListExW(
1980 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1981 IN PCWSTR MachineName OPTIONAL
,
1986 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
1988 if (!ClassImageListData
)
1989 SetLastError(ERROR_INVALID_PARAMETER
);
1990 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1991 SetLastError(ERROR_INVALID_USER_BUFFER
);
1993 SetLastError(ERROR_INVALID_PARAMETER
);
1996 struct ClassImageList
*list
= NULL
;
1999 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2001 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2002 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2005 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2008 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2011 list
->szData
[0] = list
->szData
[1] = '\\';
2012 strcpyW(list
->szData
+ 2, MachineName
);
2013 list
->MachineName
= list
->szData
;
2017 list
->MachineName
= NULL
;
2020 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2028 TRACE("Returning %d\n", ret
);
2032 /***********************************************************************
2033 * SetupDiLoadClassIcon(SETUPAPI.@)
2035 BOOL WINAPI
SetupDiLoadClassIcon(
2036 IN CONST GUID
*ClassGuid
,
2037 OUT HICON
*LargeIcon OPTIONAL
,
2038 OUT PINT MiniIconIndex OPTIONAL
)
2043 SetLastError(ERROR_INVALID_PARAMETER
);
2046 LPWSTR Buffer
= NULL
;
2049 HKEY hKey
= INVALID_HANDLE_VALUE
;
2051 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2052 if (hKey
== INVALID_HANDLE_VALUE
)
2055 if (!GetIconIndex(hKey
, &iconIndex
))
2060 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2063 DWORD dwRegType
, dwLength
;
2064 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2065 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2067 Buffer
= MyMalloc(dwLength
);
2070 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2073 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2074 if (rc
!= ERROR_SUCCESS
)
2081 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
))
2082 && dwRegType
== REG_SZ
)
2084 Buffer
= MyMalloc(dwLength
);
2087 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2090 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2091 if (rc
!= ERROR_SUCCESS
)
2099 /* Unable to find where to load the icon */
2100 SetLastError(ERROR_FILE_NOT_FOUND
);
2103 Comma
= strchrW(Buffer
, ',');
2106 SetLastError(ERROR_GEN_FAILURE
);
2113 /* Look up icon in setupapi.dll */
2114 DllName
= L
"setupapi.dll";
2115 iconIndex
= -iconIndex
;
2118 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2121 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2123 SetLastError(ERROR_INVALID_INDEX
);
2128 *MiniIconIndex
= iconIndex
;
2132 if (hKey
!= INVALID_HANDLE_VALUE
)
2137 TRACE("Returning %d\n", ret
);
2141 /***********************************************************************
2142 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2144 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2145 HDEVINFO DeviceInfoSet
,
2146 PSP_DEVINFO_DATA DeviceInfoData
,
2147 CONST GUID
* InterfaceClassGuid
,
2149 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2153 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2154 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2156 if (!DeviceInterfaceData
)
2157 SetLastError(ERROR_INVALID_PARAMETER
);
2158 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2159 SetLastError(ERROR_INVALID_USER_BUFFER
);
2160 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2162 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2164 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2166 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2168 while (ItemList
!= &list
->ListHead
&& !Found
)
2170 PLIST_ENTRY InterfaceListEntry
;
2171 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2172 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2174 /* We are not searching for this element */
2175 ItemList
= ItemList
->Flink
;
2178 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2179 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2181 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2182 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2184 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2187 if (MemberIndex
-- == 0)
2189 /* return this item */
2190 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2191 &DevItf
->InterfaceClassGuid
,
2193 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2194 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2197 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2199 ItemList
= ItemList
->Flink
;
2202 SetLastError(ERROR_NO_MORE_ITEMS
);
2207 SetLastError(ERROR_INVALID_HANDLE
);
2210 SetLastError(ERROR_INVALID_HANDLE
);
2214 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2216 InterlockedIncrement(&infFile
->References
);
2219 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2221 if (InterlockedDecrement(&infFile
->References
) == 0)
2223 SetupCloseInfFile(infFile
->hInf
);
2224 HeapFree(GetProcessHeap(), 0, infFile
);
2228 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2230 DereferenceInfFile(driverInfo
->InfFileDetails
);
2231 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2232 HeapFree(GetProcessHeap(), 0, driverInfo
);
2236 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2238 PLIST_ENTRY ListEntry
;
2239 struct DriverInfoElement
*driverInfo
;
2241 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2243 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2244 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2245 if (!DestroyDriverInfoElement(driverInfo
))
2248 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2250 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2251 HeapFree(GetProcessHeap(), 0, ListEntry
);
2253 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2257 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2259 PLIST_ENTRY ListEntry
;
2260 struct DeviceInfoElement
*deviceInfo
;
2262 while (!IsListEmpty(&list
->ListHead
))
2264 ListEntry
= RemoveHeadList(&list
->ListHead
);
2265 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2266 if (!DestroyDeviceInfoElement(deviceInfo
))
2269 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2270 RegCloseKey(list
->HKLM
);
2271 CM_Disconnect_Machine(list
->hMachine
);
2272 HeapFree(GetProcessHeap(), 0, list
);
2276 /***********************************************************************
2277 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2279 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2283 TRACE("%p\n", devinfo
);
2284 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2286 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2288 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2289 ret
= DestroyDeviceInfoSet(list
);
2291 SetLastError(ERROR_INVALID_HANDLE
);
2294 SetLastError(ERROR_INVALID_HANDLE
);
2296 TRACE("Returning %d\n", ret
);
2300 /***********************************************************************
2301 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2303 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2304 HDEVINFO DeviceInfoSet
,
2305 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2306 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2307 DWORD DeviceInterfaceDetailDataSize
,
2308 PDWORD RequiredSize
,
2309 PSP_DEVINFO_DATA DeviceInfoData
)
2311 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2312 DWORD sizeW
= 0, sizeA
;
2315 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2316 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2317 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2319 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2320 SetLastError(ERROR_INVALID_USER_BUFFER
);
2321 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2322 SetLastError(ERROR_INVALID_PARAMETER
);
2323 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2324 SetLastError(ERROR_INVALID_PARAMETER
);
2327 if (DeviceInterfaceDetailData
!= NULL
)
2329 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2330 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2331 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2332 if (!DeviceInterfaceDetailDataW
)
2334 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2337 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2339 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2340 ret
= SetupDiGetDeviceInterfaceDetailW(
2342 DeviceInterfaceData
,
2343 DeviceInterfaceDetailDataW
,
2347 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2348 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2350 *RequiredSize
= sizeA
;
2351 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2353 if (!WideCharToMultiByte(
2355 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2356 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2363 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2366 TRACE("Returning %d\n", ret
);
2370 /***********************************************************************
2371 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2373 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2374 HDEVINFO DeviceInfoSet
,
2375 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2376 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2377 DWORD DeviceInterfaceDetailDataSize
,
2378 PDWORD RequiredSize
,
2379 PSP_DEVINFO_DATA DeviceInfoData
)
2383 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2384 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2385 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2387 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2388 SetLastError(ERROR_INVALID_PARAMETER
);
2389 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2390 SetLastError(ERROR_INVALID_HANDLE
);
2391 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2392 SetLastError(ERROR_INVALID_HANDLE
);
2393 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2394 SetLastError(ERROR_INVALID_USER_BUFFER
);
2395 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2396 SetLastError(ERROR_INVALID_USER_BUFFER
);
2397 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2398 SetLastError(ERROR_INVALID_USER_BUFFER
);
2399 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2400 SetLastError(ERROR_INVALID_PARAMETER
);
2401 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2402 SetLastError(ERROR_INVALID_PARAMETER
);
2405 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2406 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2407 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2408 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2410 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2412 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2414 *RequiredSize
= sizeRequired
;
2418 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2419 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2422 memcpy(&DeviceInfoData
->ClassGuid
,
2423 &deviceInterface
->DeviceInfo
->ClassGuid
,
2425 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2426 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2432 TRACE("Returning %d\n", ret
);
2436 /***********************************************************************
2437 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2439 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2441 PSP_DEVINFO_DATA DeviceInfoData
,
2443 PDWORD PropertyRegDataType
,
2444 PBYTE PropertyBuffer
,
2445 DWORD PropertyBufferSize
,
2446 PDWORD RequiredSize
)
2449 BOOL bIsStringProperty
;
2451 DWORD RequiredSizeA
, RequiredSizeW
;
2452 DWORD PropertyBufferSizeW
;
2453 PBYTE PropertyBufferW
;
2455 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2456 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2459 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2460 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2462 bResult
= SetupDiGetDeviceRegistryPropertyW(
2468 PropertyBufferSizeW
,
2471 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2473 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2475 if (bIsStringProperty
)
2476 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2478 RequiredSizeA
= RequiredSizeW
;
2480 *RequiredSize
= RequiredSizeA
;
2481 if (PropertyRegDataType
)
2482 *PropertyRegDataType
= RegType
;
2487 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2491 if (RequiredSizeA
<= PropertyBufferSize
)
2493 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2495 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2497 /* Last error is already set by WideCharToMultiByte */
2502 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2506 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2510 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2514 /***********************************************************************
2515 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2517 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2518 HDEVINFO DeviceInfoSet
,
2519 PSP_DEVINFO_DATA DeviceInfoData
,
2521 PDWORD PropertyRegDataType
,
2522 PBYTE PropertyBuffer
,
2523 DWORD PropertyBufferSize
,
2524 PDWORD RequiredSize
)
2526 HKEY hEnumKey
, hKey
;
2530 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2531 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2534 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2535 SetLastError(ERROR_INVALID_HANDLE
);
2536 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2537 SetLastError(ERROR_INVALID_HANDLE
);
2538 else if (!DeviceInfoData
)
2539 SetLastError(ERROR_INVALID_PARAMETER
);
2540 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2541 SetLastError(ERROR_INVALID_USER_BUFFER
);
2542 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2543 SetLastError(ERROR_INVALID_PARAMETER
);
2546 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2547 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2551 case SPDRP_CAPABILITIES
:
2553 case SPDRP_CLASSGUID
:
2554 case SPDRP_COMPATIBLEIDS
:
2555 case SPDRP_CONFIGFLAGS
:
2556 case SPDRP_DEVICEDESC
:
2558 case SPDRP_FRIENDLYNAME
:
2559 case SPDRP_HARDWAREID
:
2560 case SPDRP_LOCATION_INFORMATION
:
2561 case SPDRP_LOWERFILTERS
:
2563 case SPDRP_SECURITY
:
2565 case SPDRP_UI_NUMBER
:
2566 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2567 case SPDRP_UPPERFILTERS
:
2569 LPCWSTR RegistryPropertyName
;
2574 case SPDRP_CAPABILITIES
:
2575 RegistryPropertyName
= L
"Capabilities"; break;
2577 RegistryPropertyName
= L
"Class"; break;
2578 case SPDRP_CLASSGUID
:
2579 RegistryPropertyName
= L
"ClassGUID"; break;
2580 case SPDRP_COMPATIBLEIDS
:
2581 RegistryPropertyName
= L
"CompatibleIDs"; break;
2582 case SPDRP_CONFIGFLAGS
:
2583 RegistryPropertyName
= L
"ConfigFlags"; break;
2584 case SPDRP_DEVICEDESC
:
2585 RegistryPropertyName
= L
"DeviceDesc"; break;
2587 RegistryPropertyName
= L
"Driver"; break;
2588 case SPDRP_FRIENDLYNAME
:
2589 RegistryPropertyName
= L
"FriendlyName"; break;
2590 case SPDRP_HARDWAREID
:
2591 RegistryPropertyName
= L
"HardwareID"; break;
2592 case SPDRP_LOCATION_INFORMATION
:
2593 RegistryPropertyName
= L
"LocationInformation"; break;
2594 case SPDRP_LOWERFILTERS
:
2595 RegistryPropertyName
= L
"LowerFilters"; break;
2597 RegistryPropertyName
= L
"Mfg"; break;
2598 case SPDRP_SECURITY
:
2599 RegistryPropertyName
= L
"Security"; break;
2601 RegistryPropertyName
= L
"Service"; break;
2602 case SPDRP_UI_NUMBER
:
2603 RegistryPropertyName
= L
"UINumber"; break;
2604 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2605 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2606 case SPDRP_UPPERFILTERS
:
2607 RegistryPropertyName
= L
"UpperFilters"; break;
2609 /* Should not happen */
2610 RegistryPropertyName
= NULL
; break;
2613 /* Open registry key name */
2618 KEY_ENUMERATE_SUB_KEYS
,
2620 if (rc
!= ERROR_SUCCESS
)
2631 RegCloseKey(hEnumKey
);
2632 if (rc
!= ERROR_SUCCESS
)
2637 /* Read registry entry */
2638 BufferSize
= PropertyBufferSize
;
2639 rc
= RegQueryValueExW(
2641 RegistryPropertyName
,
2642 NULL
, /* Reserved */
2643 PropertyRegDataType
,
2647 *RequiredSize
= BufferSize
;
2650 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2653 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2655 case ERROR_MORE_DATA
:
2656 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2665 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2667 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2669 if (PropertyRegDataType
)
2670 *PropertyRegDataType
= REG_SZ
;
2672 *RequiredSize
= required
;
2673 if (PropertyBufferSize
>= required
)
2675 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2679 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2683 /*case SPDRP_BUSTYPEGUID:
2684 case SPDRP_LEGACYBUSTYPE:
2685 case SPDRP_BUSNUMBER:
2686 case SPDRP_ENUMERATOR_NAME:
2687 case SPDRP_SECURITY_SDS:
2689 case SPDRP_EXCLUSIVE:
2690 case SPDRP_CHARACTERISTICS:
2692 case SPDRP_DEVICE_POWER_DATA:*/
2693 #if (WINVER >= 0x501)
2694 /*case SPDRP_REMOVAL_POLICY:
2695 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2696 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2697 case SPDRP_INSTALL_STATE:*/
2702 ERR("Property 0x%lx not implemented\n", Property
);
2703 SetLastError(ERROR_NOT_SUPPORTED
);
2708 TRACE("Returning %d\n", ret
);
2712 /***********************************************************************
2713 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2715 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2716 IN HDEVINFO DeviceInfoSet
,
2717 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2719 IN CONST BYTE
*PropertyBuffer
,
2720 IN DWORD PropertyBufferSize
)
2722 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2723 Property
, PropertyBuffer
, PropertyBufferSize
);
2724 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2728 /***********************************************************************
2729 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2731 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2732 IN HDEVINFO DeviceInfoSet
,
2733 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2735 IN
const BYTE
*PropertyBuffer
,
2736 IN DWORD PropertyBufferSize
)
2738 struct DeviceInfoSet
*list
;
2741 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2742 Property
, PropertyBuffer
, PropertyBufferSize
);
2745 SetLastError(ERROR_INVALID_HANDLE
);
2746 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2747 SetLastError(ERROR_INVALID_HANDLE
);
2748 else if (DeviceInfoData
)
2749 SetLastError(ERROR_INVALID_HANDLE
);
2750 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2751 SetLastError(ERROR_INVALID_USER_BUFFER
);
2756 case SPDRP_COMPATIBLEIDS
:
2757 case SPDRP_CONFIGFLAGS
:
2758 case SPDRP_FRIENDLYNAME
:
2759 case SPDRP_HARDWAREID
:
2760 case SPDRP_LOCATION_INFORMATION
:
2761 case SPDRP_LOWERFILTERS
:
2762 case SPDRP_SECURITY
:
2764 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2765 case SPDRP_UPPERFILTERS
:
2767 LPCWSTR RegistryPropertyName
;
2768 DWORD RegistryDataType
;
2774 case SPDRP_COMPATIBLEIDS
:
2775 RegistryPropertyName
= L
"CompatibleIDs";
2776 RegistryDataType
= REG_MULTI_SZ
;
2778 case SPDRP_CONFIGFLAGS
:
2779 RegistryPropertyName
= L
"ConfigFlags";
2780 RegistryDataType
= REG_DWORD
;
2782 case SPDRP_FRIENDLYNAME
:
2783 RegistryPropertyName
= L
"FriendlyName";
2784 RegistryDataType
= REG_SZ
;
2786 case SPDRP_HARDWAREID
:
2787 RegistryPropertyName
= L
"HardwareID";
2788 RegistryDataType
= REG_MULTI_SZ
;
2790 case SPDRP_LOCATION_INFORMATION
:
2791 RegistryPropertyName
= L
"LocationInformation";
2792 RegistryDataType
= REG_SZ
;
2794 case SPDRP_LOWERFILTERS
:
2795 RegistryPropertyName
= L
"LowerFilters";
2796 RegistryDataType
= REG_MULTI_SZ
;
2798 case SPDRP_SECURITY
:
2799 RegistryPropertyName
= L
"Security";
2800 RegistryDataType
= REG_BINARY
;
2803 RegistryPropertyName
= L
"Service";
2804 RegistryDataType
= REG_SZ
;
2806 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2807 RegistryPropertyName
= L
"UINumberDescFormat";
2808 RegistryDataType
= REG_SZ
;
2810 case SPDRP_UPPERFILTERS
:
2811 RegistryPropertyName
= L
"UpperFilters";
2812 RegistryDataType
= REG_MULTI_SZ
;
2815 /* Should not happen */
2816 RegistryPropertyName
= NULL
;
2817 RegistryDataType
= REG_BINARY
;
2820 /* Open device registry key */
2821 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2822 if (hKey
!= INVALID_HANDLE_VALUE
)
2824 /* Write new data */
2825 rc
= RegSetValueExW(
2827 RegistryPropertyName
,
2831 PropertyBufferSize
);
2832 if (rc
== ERROR_SUCCESS
)
2841 /*case SPDRP_CHARACTERISTICS:
2843 case SPDRP_EXCLUSIVE:*/
2844 #if (WINVER >= 0x501)
2845 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2847 //case SPDRP_SECURITY_SDS:
2851 ERR("Property 0x%lx not implemented\n", Property
);
2852 SetLastError(ERROR_NOT_SUPPORTED
);
2857 TRACE("Returning %d\n", ret
);
2861 /***********************************************************************
2862 * SetupDiInstallClassA (SETUPAPI.@)
2864 BOOL WINAPI
SetupDiInstallClassA(
2870 UNICODE_STRING FileNameW
;
2873 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2875 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2879 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2881 RtlFreeUnicodeString(&FileNameW
);
2886 static HKEY
CreateClassKey(HINF hInf
)
2888 WCHAR FullBuffer
[MAX_PATH
];
2889 WCHAR Buffer
[MAX_PATH
];
2894 if (!SetupGetLineTextW(NULL
,
2902 return INVALID_HANDLE_VALUE
;
2905 lstrcpyW(FullBuffer
, ControlClass
);
2906 lstrcatW(FullBuffer
, Buffer
);
2909 if (!SetupGetLineTextW(NULL
,
2917 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2918 return INVALID_HANDLE_VALUE
;
2921 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2925 REG_OPTION_NON_VOLATILE
,
2931 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2932 return INVALID_HANDLE_VALUE
;
2935 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2940 RequiredSize
* sizeof(WCHAR
)))
2942 RegCloseKey(hClassKey
);
2943 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2944 return INVALID_HANDLE_VALUE
;
2950 /***********************************************************************
2951 * SetupDiInstallClassW (SETUPAPI.@)
2953 BOOL WINAPI
SetupDiInstallClassW(
2959 WCHAR SectionName
[MAX_PATH
];
2960 DWORD SectionNameLength
= 0;
2962 BOOL bFileQueueCreated
= FALSE
;
2965 TRACE("%p %s 0x%lx %p\n", hwndParent
, debugstr_w(InfFileName
),
2968 FIXME("not fully implemented\n");
2970 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2972 SetLastError(ERROR_INVALID_PARAMETER
);
2976 /* Open the .inf file */
2977 hInf
= SetupOpenInfFileW(InfFileName
,
2981 if (hInf
== INVALID_HANDLE_VALUE
)
2987 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2988 hClassKey
= CreateClassKey(hInf
);
2989 if (hClassKey
== INVALID_HANDLE_VALUE
)
2991 SetupCloseInfFile(hInf
);
2997 /* Try to append a layout file */
2999 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3002 /* Retrieve the actual section name */
3003 SetupDiGetActualSectionToInstallW(hInf
,
3011 if (!(Flags
& DI_NOVCP
))
3013 FileQueue
= SetupOpenFileQueue();
3014 if (FileQueue
== INVALID_HANDLE_VALUE
)
3016 SetupCloseInfFile(hInf
);
3017 RegCloseKey(hClassKey
);
3021 bFileQueueCreated
= TRUE
;
3026 SetupInstallFromInfSectionW(NULL
,
3035 INVALID_HANDLE_VALUE
,
3038 /* FIXME: More code! */
3040 if (bFileQueueCreated
)
3041 SetupCloseFileQueue(FileQueue
);
3043 SetupCloseInfFile(hInf
);
3045 RegCloseKey(hClassKey
);
3050 /***********************************************************************
3051 * SetupDiOpenClassRegKey (SETUPAPI.@)
3053 HKEY WINAPI
SetupDiOpenClassRegKey(
3054 const GUID
* ClassGuid
,
3057 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3058 DIOCR_INSTALLER
, NULL
, NULL
);
3062 /***********************************************************************
3063 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3065 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3066 const GUID
* ClassGuid OPTIONAL
,
3069 PCSTR MachineName OPTIONAL
,
3072 PWSTR MachineNameW
= NULL
;
3079 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3080 if (MachineNameW
== NULL
)
3081 return INVALID_HANDLE_VALUE
;
3084 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3085 Flags
, MachineNameW
, Reserved
);
3088 MyFree(MachineNameW
);
3094 /***********************************************************************
3095 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3097 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3098 const GUID
* ClassGuid OPTIONAL
,
3101 PCWSTR MachineName OPTIONAL
,
3104 LPWSTR lpGuidString
;
3105 LPWSTR lpFullGuidString
;
3113 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3114 Flags
, debugstr_w(MachineName
), Reserved
);
3116 if (Flags
== DIOCR_INSTALLER
)
3118 lpKeyName
= ControlClass
;
3120 else if (Flags
== DIOCR_INTERFACE
)
3122 lpKeyName
= DeviceClasses
;
3126 ERR("Invalid Flags parameter!\n");
3127 SetLastError(ERROR_INVALID_FLAGS
);
3128 return INVALID_HANDLE_VALUE
;
3131 if (MachineName
!= NULL
)
3133 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3134 if (rc
!= ERROR_SUCCESS
)
3137 return INVALID_HANDLE_VALUE
;
3141 HKLM
= HKEY_LOCAL_MACHINE
;
3143 rc
= RegOpenKeyExW(HKLM
,
3146 ClassGuid
? KEY_ENUMERATE_SUB_KEYS
: samDesired
,
3148 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3149 if (rc
!= ERROR_SUCCESS
)
3152 return INVALID_HANDLE_VALUE
;
3155 if (ClassGuid
== NULL
)
3158 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3160 SetLastError(ERROR_GEN_FAILURE
);
3161 RegCloseKey(hClassesKey
);
3162 return INVALID_HANDLE_VALUE
;
3165 dwLength
= lstrlenW(lpGuidString
);
3166 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3167 if (!lpFullGuidString
)
3169 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3170 RpcStringFreeW(&lpGuidString
);
3171 return INVALID_HANDLE_VALUE
;
3173 lpFullGuidString
[0] = '{';
3174 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3175 lpFullGuidString
[dwLength
+ 1] = '}';
3176 lpFullGuidString
[dwLength
+ 2] = '\0';
3177 RpcStringFreeW(&lpGuidString
);
3179 rc
= RegOpenKeyExW(hClassesKey
,
3184 if (rc
!= ERROR_SUCCESS
)
3187 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3188 RegCloseKey(hClassesKey
);
3189 return INVALID_HANDLE_VALUE
;
3192 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3193 RegCloseKey(hClassesKey
);
3198 /***********************************************************************
3199 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3201 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3202 HDEVINFO DeviceInfoSet
,
3205 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3207 FIXME("%p %s %08lx %p\n",
3208 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3212 /***********************************************************************
3213 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3215 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3216 HDEVINFO DeviceInfoSet
,
3219 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3221 LPWSTR DevicePathW
= NULL
;
3224 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3226 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3227 if (DevicePathW
== NULL
)
3230 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3231 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3233 MyFree(DevicePathW
);
3238 /***********************************************************************
3239 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3241 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3242 HDEVINFO DeviceInfoSet
,
3243 PSP_DEVINFO_DATA DeviceInfoData
,
3244 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3245 DWORD ClassInstallParamsSize
)
3247 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3248 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3252 /***********************************************************************
3253 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3255 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3256 HDEVINFO DeviceInfoSet
,
3257 PSP_DEVINFO_DATA DeviceInfoData
,
3258 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3259 DWORD ClassInstallParamsSize
)
3261 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3262 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3268 IN PWSTR InstallerName
,
3269 OUT HMODULE
* ModulePointer
,
3270 OUT PVOID
* FunctionPointer
)
3272 HMODULE hModule
= NULL
;
3273 LPSTR FunctionNameA
= NULL
;
3277 *ModulePointer
= NULL
;
3278 *FunctionPointer
= NULL
;
3280 Comma
= strchrW(InstallerName
, ',');
3283 rc
= ERROR_INVALID_PARAMETER
;
3289 hModule
= LoadLibraryW(InstallerName
);
3293 rc
= GetLastError();
3297 /* Skip comma spaces */
3298 while (*Comma
== ',' || isspaceW(*Comma
))
3301 /* W->A conversion for function name */
3302 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3305 rc
= GetLastError();
3309 /* Search function */
3310 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3311 if (!*FunctionPointer
)
3313 rc
= GetLastError();
3317 *ModulePointer
= hModule
;
3321 if (rc
!= ERROR_SUCCESS
&& hModule
)
3322 FreeLibrary(hModule
);
3323 MyFree(FunctionNameA
);
3328 FreeFunctionPointer(
3329 IN HMODULE ModulePointer
,
3330 IN PVOID FunctionPointer
)
3332 if (ModulePointer
== NULL
)
3333 return ERROR_SUCCESS
;
3334 if (FreeLibrary(ModulePointer
))
3335 return ERROR_SUCCESS
;
3337 return GetLastError();
3340 /***********************************************************************
3341 * SetupDiCallClassInstaller (SETUPAPI.@)
3343 BOOL WINAPI
SetupDiCallClassInstaller(
3344 IN DI_FUNCTION InstallFunction
,
3345 IN HDEVINFO DeviceInfoSet
,
3346 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3350 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3353 SetLastError(ERROR_INVALID_PARAMETER
);
3354 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3355 SetLastError(ERROR_INVALID_HANDLE
);
3356 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3357 SetLastError(ERROR_INVALID_HANDLE
);
3358 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3359 SetLastError(ERROR_INVALID_HANDLE
);
3360 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3361 SetLastError(ERROR_INVALID_USER_BUFFER
);
3364 SP_DEVINSTALL_PARAMS_W InstallParams
;
3365 #define CLASS_COINSTALLER 0x1
3366 #define DEVICE_COINSTALLER 0x2
3367 #define CLASS_INSTALLER 0x4
3368 UCHAR CanHandle
= 0;
3369 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3371 switch (InstallFunction
)
3373 case DIF_ALLOW_INSTALL
:
3374 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3376 case DIF_DESTROYPRIVATEDATA
:
3377 CanHandle
= CLASS_INSTALLER
;
3379 case DIF_INSTALLDEVICE
:
3380 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3381 DefaultHandler
= SetupDiInstallDevice
;
3383 case DIF_INSTALLDEVICEFILES
:
3384 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3385 DefaultHandler
= SetupDiInstallDriverFiles
;
3387 case DIF_INSTALLINTERFACES
:
3388 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3389 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3391 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3392 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3394 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3395 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3397 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3398 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3400 case DIF_REGISTER_COINSTALLERS
:
3401 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3402 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3404 case DIF_SELECTBESTCOMPATDRV
:
3405 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3406 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3409 ERR("Install function %u not supported\n", InstallFunction
);
3410 SetLastError(ERROR_NOT_SUPPORTED
);
3413 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3414 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3415 /* Don't process this call, as a parameter is invalid */
3420 LIST_ENTRY ClassCoInstallersListHead
;
3421 LIST_ENTRY DeviceCoInstallersListHead
;
3422 HMODULE ClassInstallerLibrary
= NULL
;
3423 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3424 COINSTALLER_CONTEXT_DATA Context
;
3425 PLIST_ENTRY ListEntry
;
3427 DWORD dwRegType
, dwLength
;
3428 DWORD rc
= NO_ERROR
;
3430 InitializeListHead(&ClassCoInstallersListHead
);
3431 InitializeListHead(&DeviceCoInstallersListHead
);
3433 if (CanHandle
& DEVICE_COINSTALLER
)
3435 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3436 if (hKey
!= INVALID_HANDLE_VALUE
)
3438 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3439 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3441 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3442 if (KeyBuffer
!= NULL
)
3444 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3445 if (rc
== ERROR_SUCCESS
)
3448 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3450 /* Add coinstaller to DeviceCoInstallersListHead list */
3451 struct CoInstallerElement
*coinstaller
;
3452 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3453 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3456 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3457 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3458 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3460 HeapFree(GetProcessHeap(), 0, coinstaller
);
3463 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3469 if (CanHandle
& CLASS_COINSTALLER
)
3473 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3477 if (rc
== ERROR_SUCCESS
)
3479 LPWSTR lpGuidString
;
3480 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3482 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3483 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3485 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3486 if (KeyBuffer
!= NULL
)
3488 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3489 if (rc
== ERROR_SUCCESS
)
3492 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3494 /* Add coinstaller to ClassCoInstallersListHead list */
3495 struct CoInstallerElement
*coinstaller
;
3496 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3497 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3500 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3501 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3502 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3504 HeapFree(GetProcessHeap(), 0, coinstaller
);
3507 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3510 RpcStringFreeW(&lpGuidString
);
3515 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3517 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3518 if (hKey
!= INVALID_HANDLE_VALUE
)
3520 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3521 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3523 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3524 if (KeyBuffer
!= NULL
)
3526 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3527 if (rc
== ERROR_SUCCESS
)
3529 /* Get ClassInstaller function pointer */
3530 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3531 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3533 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3534 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3537 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3544 /* Call Class co-installers */
3545 Context
.PostProcessing
= FALSE
;
3547 ListEntry
= ClassCoInstallersListHead
.Flink
;
3548 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3550 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3551 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3552 coinstaller
->PrivateData
= Context
.PrivateData
;
3553 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3555 coinstaller
->DoPostProcessing
= TRUE
;
3558 ListEntry
= ListEntry
->Flink
;
3561 /* Call Device co-installers */
3562 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3563 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3565 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3566 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3567 coinstaller
->PrivateData
= Context
.PrivateData
;
3568 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3570 coinstaller
->DoPostProcessing
= TRUE
;
3573 ListEntry
= ListEntry
->Flink
;
3576 /* Call Class installer */
3579 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3580 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3583 rc
= ERROR_DI_DO_DEFAULT
;
3585 /* Call default handler */
3586 if (rc
== ERROR_DI_DO_DEFAULT
)
3588 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3590 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3593 rc
= GetLastError();
3599 /* Call Class co-installers that required postprocessing */
3600 Context
.PostProcessing
= TRUE
;
3601 ListEntry
= ClassCoInstallersListHead
.Flink
;
3602 while (ListEntry
!= &ClassCoInstallersListHead
)
3604 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3605 if (coinstaller
->DoPostProcessing
)
3607 Context
.InstallResult
= rc
;
3608 Context
.PrivateData
= coinstaller
->PrivateData
;
3609 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3611 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3612 ListEntry
= ListEntry
->Flink
;
3615 /* Call Device co-installers that required postprocessing */
3616 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3617 while (ListEntry
!= &DeviceCoInstallersListHead
)
3619 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3620 if (coinstaller
->DoPostProcessing
)
3622 Context
.InstallResult
= rc
;
3623 Context
.PrivateData
= coinstaller
->PrivateData
;
3624 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3626 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3627 ListEntry
= ListEntry
->Flink
;
3630 /* Free allocated memory */
3631 while (!IsListEmpty(&ClassCoInstallersListHead
))
3633 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3634 HeapFree(GetProcessHeap(), 0, ListEntry
);
3636 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3638 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3639 HeapFree(GetProcessHeap(), 0, ListEntry
);
3642 ret
= (rc
== NO_ERROR
);
3646 TRACE("Returning %d\n", ret
);
3650 /***********************************************************************
3651 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3653 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
3654 IN HDEVINFO DeviceInfoSet
,
3655 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
3657 struct DeviceInfoSet
*list
;
3660 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
3663 SetLastError(ERROR_INVALID_HANDLE
);
3664 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3665 SetLastError(ERROR_INVALID_HANDLE
);
3666 else if (!DeviceInfoListDetailData
)
3667 SetLastError(ERROR_INVALID_PARAMETER
);
3668 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
3669 SetLastError(ERROR_INVALID_USER_BUFFER
);
3673 &DeviceInfoListDetailData
->ClassGuid
,
3676 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
3677 if (list
->MachineName
)
3678 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
3680 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
3685 TRACE("Returning %d\n", ret
);
3689 /***********************************************************************
3690 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3692 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3693 IN HDEVINFO DeviceInfoSet
,
3694 IN PSP_DEVINFO_DATA DeviceInfoData
,
3695 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3697 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3700 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3702 if (DeviceInstallParams
== NULL
)
3703 SetLastError(ERROR_INVALID_PARAMETER
);
3704 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3705 SetLastError(ERROR_INVALID_USER_BUFFER
);
3708 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3709 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3713 /* Do W->A conversion */
3715 DeviceInstallParams
,
3716 &deviceInstallParamsW
,
3717 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3718 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3719 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3721 DeviceInstallParams
->DriverPath
[0] = '\0';
3727 TRACE("Returning %d\n", ret
);
3731 /***********************************************************************
3732 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3734 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3735 IN HDEVINFO DeviceInfoSet
,
3736 IN PSP_DEVINFO_DATA DeviceInfoData
,
3737 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3739 struct DeviceInfoSet
*list
;
3742 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3745 SetLastError(ERROR_INVALID_HANDLE
);
3746 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3747 SetLastError(ERROR_INVALID_HANDLE
);
3748 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3749 SetLastError(ERROR_INVALID_USER_BUFFER
);
3750 else if (!DeviceInstallParams
)
3751 SetLastError(ERROR_INVALID_PARAMETER
);
3752 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3753 SetLastError(ERROR_INVALID_USER_BUFFER
);
3756 PSP_DEVINSTALL_PARAMS_W Source
;
3759 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3761 Source
= &list
->InstallParams
;
3762 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3766 TRACE("Returning %d\n", ret
);
3770 /***********************************************************************
3771 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3773 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3774 IN HDEVINFO DeviceInfoSet
,
3775 IN PSP_DEVINFO_DATA DeviceInfoData
,
3776 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3778 struct DeviceInfoSet
*list
;
3781 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3784 SetLastError(ERROR_INVALID_HANDLE
);
3785 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3786 SetLastError(ERROR_INVALID_HANDLE
);
3787 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3788 SetLastError(ERROR_INVALID_USER_BUFFER
);
3789 else if (!DeviceInstallParams
)
3790 SetLastError(ERROR_INVALID_PARAMETER
);
3791 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3792 SetLastError(ERROR_INVALID_USER_BUFFER
);
3795 PSP_DEVINSTALL_PARAMS_W Destination
;
3797 /* FIXME: Validate parameters */
3800 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3802 Destination
= &list
->InstallParams
;
3803 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3807 TRACE("Returning %d\n", ret
);
3811 /***********************************************************************
3812 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
3814 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
3815 IN HDEVINFO DeviceInfoSet
,
3816 IN PSP_DEVINFO_DATA DeviceInfoData
,
3817 OUT PSTR DeviceInstanceId OPTIONAL
,
3818 IN DWORD DeviceInstanceIdSize
,
3819 OUT PDWORD RequiredSize OPTIONAL
)
3821 PWSTR DeviceInstanceIdW
= NULL
;
3824 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
3825 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
3827 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
3828 SetLastError(ERROR_INVALID_PARAMETER
);
3831 if (DeviceInstanceIdSize
!= 0)
3833 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
3834 if (DeviceInstanceIdW
== NULL
)
3838 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
3839 DeviceInstanceIdW
, DeviceInstanceIdSize
,
3842 if (ret
&& DeviceInstanceIdW
!= NULL
)
3844 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
3845 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
3847 DeviceInstanceId
[0] = '\0';
3853 TRACE("Returning %d\n", ret
);
3857 /***********************************************************************
3858 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
3860 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
3861 IN HDEVINFO DeviceInfoSet
,
3862 IN PSP_DEVINFO_DATA DeviceInfoData
,
3863 OUT PWSTR DeviceInstanceId OPTIONAL
,
3864 IN DWORD DeviceInstanceIdSize
,
3865 OUT PDWORD RequiredSize OPTIONAL
)
3869 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
3870 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
3873 SetLastError(ERROR_INVALID_HANDLE
);
3874 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3875 SetLastError(ERROR_INVALID_HANDLE
);
3876 else if (!DeviceInfoData
)
3877 SetLastError(ERROR_INVALID_PARAMETER
);
3878 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3879 SetLastError(ERROR_INVALID_USER_BUFFER
);
3880 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
3881 SetLastError(ERROR_INVALID_PARAMETER
);
3882 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
3883 SetLastError(ERROR_INVALID_PARAMETER
);
3886 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3889 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
3891 *RequiredSize
= required
;
3893 if (required
<= DeviceInstanceIdSize
)
3895 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
3899 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3902 TRACE("Returning %d\n", ret
);
3906 /***********************************************************************
3907 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
3909 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
3910 IN HDEVINFO DeviceInfoSet
,
3911 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3912 IN LPPROPSHEETHEADERA PropertySheetHeader
,
3913 IN DWORD PropertySheetHeaderPageListSize
,
3914 OUT PDWORD RequiredSize OPTIONAL
,
3915 IN DWORD PropertySheetType
)
3917 PROPSHEETHEADERW psh
;
3920 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3921 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
3922 RequiredSize
, PropertySheetType
);
3924 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
3925 psh
.phpage
= PropertySheetHeader
->phpage
;
3926 psh
.nPages
= PropertySheetHeader
->nPages
;
3928 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
3929 PropertySheetHeaderPageListSize
, RequiredSize
,
3933 PropertySheetHeader
->nPages
= psh
.nPages
;
3936 TRACE("Returning %d\n", ret
);
3940 struct ClassDevPropertySheetsData
3942 HPROPSHEETPAGE
*PropertySheetPages
;
3943 DWORD MaximumNumberOfPages
;
3944 DWORD NumberOfPages
;
3947 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
3948 IN HPROPSHEETPAGE hPropSheetPage
,
3949 IN OUT LPARAM lParam
)
3951 struct ClassDevPropertySheetsData
*PropPageData
;
3953 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
3955 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
3957 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
3958 PropPageData
->PropertySheetPages
++;
3961 PropPageData
->NumberOfPages
++;
3965 /***********************************************************************
3966 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
3968 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
3969 IN HDEVINFO DeviceInfoSet
,
3970 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3971 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
3972 IN DWORD PropertySheetHeaderPageListSize
,
3973 OUT PDWORD RequiredSize OPTIONAL
,
3974 IN DWORD PropertySheetType
)
3976 struct DeviceInfoSet
*list
;
3979 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3980 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
3981 RequiredSize
, PropertySheetType
);
3984 SetLastError(ERROR_INVALID_HANDLE
);
3985 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3986 SetLastError(ERROR_INVALID_HANDLE
);
3987 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3988 SetLastError(ERROR_INVALID_HANDLE
);
3989 else if (!PropertySheetHeader
)
3990 SetLastError(ERROR_INVALID_PARAMETER
);
3991 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
3992 SetLastError(ERROR_INVALID_FLAGS
);
3993 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3994 SetLastError(ERROR_INVALID_USER_BUFFER
);
3995 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
3996 SetLastError(ERROR_INVALID_PARAMETER
);
3997 else if (!PropertySheetHeader
)
3998 SetLastError(ERROR_INVALID_PARAMETER
);
3999 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4000 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4001 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4002 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4003 SetLastError(ERROR_INVALID_PARAMETER
);
4006 HKEY hKey
= INVALID_HANDLE_VALUE
;
4007 SP_PROPSHEETPAGE_REQUEST Request
;
4008 LPWSTR PropPageProvider
= NULL
;
4009 HMODULE hModule
= NULL
;
4010 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4011 struct ClassDevPropertySheetsData PropPageData
;
4012 DWORD dwLength
, dwRegType
;
4016 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4019 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4020 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4022 if (hKey
== INVALID_HANDLE_VALUE
)
4025 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
);
4026 if (rc
== ERROR_FILE_NOT_FOUND
)
4028 /* No registry key. As it is optional, don't say it's a bad error */
4034 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4040 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4041 if (!PropPageProvider
)
4043 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4046 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4047 if (rc
!= ERROR_SUCCESS
)
4052 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4054 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4055 if (rc
!= ERROR_SUCCESS
)
4057 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4061 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4062 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4063 Request
.DeviceInfoSet
= DeviceInfoSet
;
4064 Request
.DeviceInfoData
= DeviceInfoData
;
4065 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4066 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4067 PropPageData
.NumberOfPages
= 0;
4068 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4073 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4074 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4076 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4081 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4082 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4086 if (hKey
!= INVALID_HANDLE_VALUE
)
4088 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4089 FreeFunctionPointer(hModule
, pPropPageProvider
);
4092 TRACE("Returning %d\n", ret
);
4096 /***********************************************************************
4097 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4099 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4100 IN HDEVINFO DeviceInfoSet
,
4101 IN PSP_DEVINFO_DATA DeviceInfoData
,
4105 IN HINF InfHandle OPTIONAL
,
4106 IN PCSTR InfSectionName OPTIONAL
)
4108 PCWSTR InfSectionNameW
= NULL
;
4109 HKEY ret
= INVALID_HANDLE_VALUE
;
4113 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4114 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4117 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4125 if (InfSectionNameW
!= NULL
)
4126 MyFree((PVOID
)InfSectionNameW
);
4131 /***********************************************************************
4132 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4134 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4135 IN HDEVINFO DeviceInfoSet
,
4136 IN PSP_DEVINFO_DATA DeviceInfoData
,
4140 IN HINF InfHandle OPTIONAL
,
4141 IN PCWSTR InfSectionName OPTIONAL
)
4143 struct DeviceInfoSet
*list
;
4144 HKEY ret
= INVALID_HANDLE_VALUE
;
4146 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4147 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4150 SetLastError(ERROR_INVALID_HANDLE
);
4151 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4152 SetLastError(ERROR_INVALID_HANDLE
);
4153 else if (!DeviceInfoData
)
4154 SetLastError(ERROR_INVALID_PARAMETER
);
4155 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4156 SetLastError(ERROR_INVALID_USER_BUFFER
);
4157 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4158 SetLastError(ERROR_INVALID_PARAMETER
);
4159 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4160 SetLastError(ERROR_INVALID_PARAMETER
);
4161 else if (InfHandle
&& !InfSectionName
)
4162 SetLastError(ERROR_INVALID_PARAMETER
);
4163 else if (!InfHandle
&& InfSectionName
)
4164 SetLastError(ERROR_INVALID_PARAMETER
);
4167 LPWSTR lpGuidString
= NULL
;
4168 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4169 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4170 DWORD Index
; /* Index used in the DriverKey name */
4172 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4173 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4174 HKEY hKey
= INVALID_HANDLE_VALUE
;
4176 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
4178 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4182 if (KeyType
== DIREG_DEV
)
4184 FIXME("DIREG_DEV case unimplemented\n");
4186 else /* KeyType == DIREG_DRV */
4188 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4190 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
4191 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4194 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4197 wcscpy(DriverKey
, L
"{");
4198 wcscat(DriverKey
, lpGuidString
);
4199 wcscat(DriverKey
, L
"}\\");
4200 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4201 rc
= RegOpenKeyExW(list
->HKLM
,
4206 if (rc
!= ERROR_SUCCESS
)
4212 /* Try all values for Index between 0 and 9999 */
4214 while (Index
<= 9999)
4217 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4218 rc
= RegCreateKeyEx(hClassKey
,
4222 REG_OPTION_NON_VOLATILE
,
4223 #if _WIN32_WINNT >= 0x502
4224 KEY_READ
| KEY_WRITE
,
4231 if (rc
!= ERROR_SUCCESS
)
4236 if (Disposition
== REG_CREATED_NEW_KEY
)
4239 hKey
= INVALID_HANDLE_VALUE
;
4244 /* Unable to create more than 9999 devices within the same class */
4245 SetLastError(ERROR_GEN_FAILURE
);
4249 /* Open device key, to write Driver value */
4250 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4251 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4253 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4254 if (rc
!= ERROR_SUCCESS
)
4261 /* Do installation of the specified section */
4264 FIXME("Need to install section %s in file %p\n",
4265 debugstr_w(InfSectionName
), InfHandle
);
4271 RpcStringFreeW(&lpGuidString
);
4272 HeapFree(GetProcessHeap(), 0, DriverKey
);
4273 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4274 RegCloseKey(hClassKey
);
4275 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4276 RegCloseKey(hDeviceKey
);
4277 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4281 TRACE("Returning 0x%p\n", ret
);
4285 /***********************************************************************
4286 * SetupDiOpenDevRegKey (SETUPAPI.@)
4288 HKEY WINAPI
SetupDiOpenDevRegKey(
4289 HDEVINFO DeviceInfoSet
,
4290 PSP_DEVINFO_DATA DeviceInfoData
,
4296 struct DeviceInfoSet
*list
;
4297 HKEY ret
= INVALID_HANDLE_VALUE
;
4299 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4300 Scope
, HwProfile
, KeyType
, samDesired
);
4303 SetLastError(ERROR_INVALID_HANDLE
);
4304 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4305 SetLastError(ERROR_INVALID_HANDLE
);
4306 else if (!DeviceInfoData
)
4307 SetLastError(ERROR_INVALID_PARAMETER
);
4308 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4309 SetLastError(ERROR_INVALID_USER_BUFFER
);
4310 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4311 SetLastError(ERROR_INVALID_PARAMETER
);
4312 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4313 SetLastError(ERROR_INVALID_PARAMETER
);
4316 HKEY hKey
= INVALID_HANDLE_VALUE
;
4317 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
4318 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4319 LPWSTR DriverKey
= NULL
;
4324 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
4326 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4328 else /* Scope == DICS_FLAG_GLOBAL */
4334 KEY_ENUMERATE_SUB_KEYS
,
4336 if (rc
!= ERROR_SUCCESS
)
4343 deviceInfo
->DeviceName
,
4345 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4347 RegCloseKey(hRootKey
);
4348 hRootKey
= INVALID_HANDLE_VALUE
;
4349 if (rc
!= ERROR_SUCCESS
)
4354 if (KeyType
== DIREG_DEV
)
4356 /* We're done. Just return the hKey handle */
4360 /* Read the 'Driver' key */
4361 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
4362 if (rc
!= ERROR_SUCCESS
)
4367 if (dwRegType
!= REG_SZ
)
4369 SetLastError(ERROR_GEN_FAILURE
);
4372 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4375 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4378 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4379 if (rc
!= ERROR_SUCCESS
)
4385 hKey
= INVALID_HANDLE_VALUE
;
4386 /* Need to open the driver key */
4391 KEY_ENUMERATE_SUB_KEYS
,
4393 if (rc
!= ERROR_SUCCESS
)
4404 if (rc
!= ERROR_SUCCESS
)
4412 if (hRootKey
!= INVALID_HANDLE_VALUE
)
4413 RegCloseKey(hRootKey
);
4414 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4418 TRACE("Returning 0x%p\n", ret
);
4422 /***********************************************************************
4423 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4425 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4426 HDEVINFO DeviceInfoSet
,
4428 CONST GUID
*ClassGuid
,
4429 PCSTR DeviceDescription
,
4431 DWORD CreationFlags
,
4432 PSP_DEVINFO_DATA DeviceInfoData
)
4434 LPWSTR DeviceNameW
= NULL
;
4435 LPWSTR DeviceDescriptionW
= NULL
;
4442 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4443 if (DeviceNameW
== NULL
) return FALSE
;
4445 if (DeviceDescription
)
4447 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4448 if (DeviceDescriptionW
== NULL
)
4450 if (DeviceNameW
) MyFree(DeviceNameW
);
4455 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4456 ClassGuid
, DeviceDescriptionW
,
4457 hwndParent
, CreationFlags
,
4460 if (DeviceNameW
) MyFree(DeviceNameW
);
4461 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4466 /***********************************************************************
4467 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4469 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4470 HDEVINFO DeviceInfoSet
,
4472 CONST GUID
*ClassGuid
,
4473 PCWSTR DeviceDescription
,
4475 DWORD CreationFlags
,
4476 PSP_DEVINFO_DATA DeviceInfoData
)
4478 struct DeviceInfoSet
*list
;
4481 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4482 debugstr_guid(ClassGuid
), DeviceDescription
,
4483 hwndParent
, CreationFlags
, DeviceInfoData
);
4486 SetLastError(ERROR_INVALID_HANDLE
);
4487 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4488 SetLastError(ERROR_INVALID_HANDLE
);
4489 else if (!ClassGuid
)
4490 SetLastError(ERROR_INVALID_PARAMETER
);
4491 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4492 SetLastError(ERROR_CLASS_MISMATCH
);
4493 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4495 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4496 SetLastError(ERROR_INVALID_FLAGS
);
4500 SP_DEVINFO_DATA DevInfo
;
4502 if (CreationFlags
& DICD_GENERATE_ID
)
4504 /* Generate a new unique ID for this device */
4505 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4506 FIXME("not implemented\n");
4510 /* Device name is fully qualified. Try to open it */
4513 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4514 rc
= SetupDiOpenDeviceInfoW(
4517 NULL
, /* hwndParent */
4518 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
4523 /* SetupDiOpenDeviceInfoW has already added
4524 * the device info to the device info set
4526 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
4528 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
4530 struct DeviceInfoElement
*deviceInfo
;
4532 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
4534 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4536 if (!DeviceInfoData
)
4540 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
4542 SetLastError(ERROR_INVALID_USER_BUFFER
);
4546 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4547 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4548 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4557 TRACE("Returning %d\n", ret
);
4561 /***********************************************************************
4562 * Helper functions for SetupDiBuildDriverInfoList
4566 IN PLIST_ENTRY DriverListHead
,
4567 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4568 IN LPGUID ClassGuid
,
4569 IN INFCONTEXT ContextDevice
,
4570 IN
struct InfFileDetails
*InfFileDetails
,
4572 IN LPCWSTR ProviderName
,
4573 IN LPCWSTR ManufacturerName
,
4574 IN LPCWSTR MatchingId
,
4575 FILETIME DriverDate
,
4576 DWORDLONG DriverVersion
,
4579 struct DriverInfoElement
*driverInfo
= NULL
;
4580 HANDLE hFile
= INVALID_HANDLE_VALUE
;
4581 DWORD RequiredSize
= 128; /* Initial buffer size */
4582 BOOL Result
= FALSE
;
4583 PLIST_ENTRY PreviousEntry
;
4584 LPWSTR InfInstallSection
= NULL
;
4587 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
4590 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4593 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
4595 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
4596 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
4598 /* Copy InfFileName field */
4599 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
4600 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
4602 /* Fill InfDate field */
4603 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4604 GENERIC_READ, FILE_SHARE_READ,
4605 NULL, OPEN_EXISTING, 0, NULL);
4606 if (hFile == INVALID_HANDLE_VALUE)
4608 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4612 /* Fill SectionName field */
4613 Result
= SetupGetStringFieldW(
4616 driverInfo
->Details
.SectionName
, LINE_LEN
,
4621 /* Fill DrvDescription field */
4622 Result
= SetupGetStringFieldW(
4624 0, /* Field index */
4625 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
4628 /* Copy MatchingId information */
4629 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4630 if (!driverInfo
->MatchingId
)
4632 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4635 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4637 /* Get inf install section */
4639 RequiredSize
= 128; /* Initial buffer size */
4640 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4641 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4643 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4644 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4645 if (!InfInstallSection
)
4647 Result
= SetupGetStringFieldW(
4649 1, /* Field index */
4650 InfInstallSection
, RequiredSize
,
4656 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4657 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4659 driverInfo
->DriverRank
= Rank
;
4660 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4661 driverInfo
->Info
.DriverType
= DriverType
;
4662 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4663 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4664 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4665 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4666 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4669 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4670 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4673 driverInfo
->Info
.ProviderName
[0] = '\0';
4674 driverInfo
->Info
.DriverDate
= DriverDate
;
4675 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4676 ReferenceInfFile(InfFileDetails
);
4677 driverInfo
->InfFileDetails
= InfFileDetails
;
4679 /* Insert current driver in driver list, according to its rank */
4680 PreviousEntry
= DriverListHead
->Flink
;
4681 while (PreviousEntry
!= DriverListHead
)
4683 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
4685 /* Insert before the current item */
4686 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4689 PreviousEntry
= PreviousEntry
->Flink
;
4691 if (PreviousEntry
== DriverListHead
)
4693 /* Insert at the end of the list */
4694 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4703 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4704 HeapFree(GetProcessHeap(), 0, driverInfo
);
4706 if (hFile
!= INVALID_HANDLE_VALUE
)
4708 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4714 GetVersionInformationFromInfFile(
4716 OUT LPGUID ClassGuid
,
4717 OUT LPWSTR
* pProviderName
,
4718 OUT FILETIME
* DriverDate
,
4719 OUT DWORDLONG
* DriverVersion
)
4722 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4723 LPWSTR DriverVer
= NULL
;
4724 LPWSTR ProviderName
= NULL
;
4725 LPWSTR pComma
; /* Points into DriverVer */
4726 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4727 SYSTEMTIME SystemTime
;
4729 BOOL ret
= FALSE
; /* Final result */
4731 /* Get class Guid */
4732 if (!SetupGetLineTextW(
4735 L
"Version", L
"ClassGUID",
4736 guidW
, sizeof(guidW
),
4737 NULL
/* Required size */))
4741 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4742 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4744 SetLastError(ERROR_GEN_FAILURE
);
4748 /* Get provider name */
4749 Result
= SetupGetLineTextW(
4751 hInf
, L
"Version", L
"Provider",
4756 /* We know know the needed buffer size */
4757 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4760 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4763 Result
= SetupGetLineTextW(
4765 hInf
, L
"Version", L
"Provider",
4766 ProviderName
, RequiredSize
,
4771 *pProviderName
= ProviderName
;
4773 /* Read the "DriverVer" value */
4774 Result
= SetupGetLineTextW(
4776 hInf
, L
"Version", L
"DriverVer",
4781 /* We know know the needed buffer size */
4782 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4785 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4788 Result
= SetupGetLineTextW(
4790 hInf
, L
"Version", L
"DriverVer",
4791 DriverVer
, RequiredSize
,
4797 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4798 pComma
= wcschr(DriverVer
, ',');
4801 *pComma
= UNICODE_NULL
;
4802 pVersion
= pComma
+ 1;
4804 /* Get driver date version. Invalid date = 00/00/00 */
4805 memset(DriverDate
, 0, sizeof(FILETIME
));
4806 if (wcslen(DriverVer
) == 10
4807 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4808 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4810 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4811 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4812 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4813 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4814 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4815 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4817 /* Get driver version. Invalid version = 0.0.0.0 */
4819 /* FIXME: use pVersion to fill DriverVersion variable */
4825 HeapFree(GetProcessHeap(), 0, ProviderName
);
4826 HeapFree(GetProcessHeap(), 0, DriverVer
);
4831 /***********************************************************************
4832 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4835 SetupDiBuildDriverInfoList(
4836 IN HDEVINFO DeviceInfoSet
,
4837 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4838 IN DWORD DriverType
)
4840 struct DeviceInfoSet
*list
;
4841 SP_DEVINSTALL_PARAMS_W InstallParams
;
4842 PVOID Buffer
= NULL
;
4843 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4844 LPWSTR ProviderName
= NULL
;
4845 LPWSTR ManufacturerName
= NULL
;
4846 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4847 LPWSTR HardwareIDs
= NULL
;
4848 LPWSTR CompatibleIDs
= NULL
;
4849 LPWSTR FullInfFileName
= NULL
;
4850 FILETIME DriverDate
;
4851 DWORDLONG DriverVersion
= 0;
4855 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4858 SetLastError(ERROR_INVALID_HANDLE
);
4859 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4860 SetLastError(ERROR_INVALID_HANDLE
);
4861 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4862 SetLastError(ERROR_INVALID_HANDLE
);
4863 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4864 SetLastError(ERROR_INVALID_PARAMETER
);
4865 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4866 SetLastError(ERROR_INVALID_PARAMETER
);
4867 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4868 SetLastError(ERROR_INVALID_PARAMETER
);
4869 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4870 SetLastError(ERROR_INVALID_USER_BUFFER
);
4875 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4876 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4880 if (DriverType
== SPDIT_COMPATDRIVER
)
4882 /* Get hardware IDs list */
4884 RequiredSize
= 512; /* Initial buffer size */
4885 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4886 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4888 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4889 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4892 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4895 Result
= SetupDiGetDeviceRegistryPropertyW(
4907 /* Get compatible IDs list */
4909 RequiredSize
= 512; /* Initial buffer size */
4910 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4911 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4913 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4914 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4917 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4920 Result
= SetupDiGetDeviceRegistryPropertyW(
4923 SPDRP_COMPATIBLEIDS
,
4925 (PBYTE
)CompatibleIDs
,
4928 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4930 /* No compatible ID for this device */
4931 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4932 CompatibleIDs
= NULL
;
4940 /* Enumerate .inf files */
4942 RequiredSize
= 32768; /* Initial buffer size */
4943 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4944 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4946 HeapFree(GetProcessHeap(), 0, Buffer
);
4947 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4951 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4954 Result
= SetupGetInfFileListW(
4955 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4957 Buffer
, RequiredSize
,
4960 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4962 /* No .inf file in specified directory. So, we should
4963 * success as we created an empty driver info list.
4971 LPWSTR pFullFilename
;
4973 if (*InstallParams
.DriverPath
)
4976 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
4979 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
4980 if (!FullInfFileName
)
4982 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
4985 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
4986 wcscat(FullInfFileName
, L
"\\");
4987 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
4991 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
4992 if (!FullInfFileName
)
4994 pFullFilename
= &FullInfFileName
[0];
4997 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4999 INFCONTEXT ContextManufacturer
, ContextDevice
;
5002 wcscpy(pFullFilename
, filename
);
5003 TRACE("Opening file %S\n", FullInfFileName
);
5005 currentInfFileDetails
= HeapAlloc(
5008 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5009 if (!currentInfFileDetails
)
5011 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5012 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5014 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5015 ReferenceInfFile(currentInfFileDetails
);
5016 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5018 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5019 currentInfFileDetails
= NULL
;
5023 if (!GetVersionInformationFromInfFile(
5024 currentInfFileDetails
->hInf
,
5030 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5031 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5032 currentInfFileDetails
= NULL
;
5036 if (DriverType
== SPDIT_CLASSDRIVER
)
5038 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5039 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5045 /* Get the manufacturers list */
5046 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5049 Result
= SetupGetStringFieldW(
5050 &ContextManufacturer
,
5051 0, /* Field index */
5056 /* We got the needed size for the buffer */
5057 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5058 if (!ManufacturerName
)
5060 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5063 Result
= SetupGetStringFieldW(
5064 &ContextManufacturer
,
5065 0, /* Field index */
5066 ManufacturerName
, RequiredSize
,
5069 /* Get manufacturer section name */
5070 Result
= SetupGetStringFieldW(
5071 &ContextManufacturer
,
5072 1, /* Field index */
5073 ManufacturerSection
, LINE_LEN
,
5077 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5078 /* Add (possible) extension to manufacturer section name */
5079 Result
= SetupDiGetActualSectionToInstallW(
5080 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5083 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5084 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5089 if (DriverType
== SPDIT_CLASSDRIVER
)
5091 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5092 if (!AddDriverToList(
5093 &list
->DriverListHead
,
5097 currentInfFileDetails
,
5102 DriverDate
, DriverVersion
,
5108 else /* DriverType = SPDIT_COMPATDRIVER */
5110 /* 1. Get all fields */
5111 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5115 BOOL DriverAlreadyAdded
;
5117 for (i
= 2; i
<= FieldCount
; i
++)
5119 LPWSTR DeviceId
= NULL
;
5121 RequiredSize
= 128; /* Initial buffer size */
5122 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5123 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5125 HeapFree(GetProcessHeap(), 0, DeviceId
);
5126 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5129 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5132 Result
= SetupGetStringFieldW(
5135 DeviceId
, RequiredSize
,
5140 HeapFree(GetProcessHeap(), 0, DeviceId
);
5143 DriverAlreadyAdded
= FALSE
;
5144 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5146 if (wcsicmp(DeviceId
, currentId
) == 0)
5149 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5153 currentInfFileDetails
,
5158 DriverDate
, DriverVersion
,
5159 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5160 DriverAlreadyAdded
= TRUE
;
5165 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5167 if (wcsicmp(DeviceId
, currentId
) == 0)
5170 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5174 currentInfFileDetails
,
5179 DriverDate
, DriverVersion
,
5180 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5181 DriverAlreadyAdded
= TRUE
;
5185 HeapFree(GetProcessHeap(), 0, DeviceId
);
5188 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5191 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5192 ManufacturerName
= NULL
;
5193 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5198 HeapFree(GetProcessHeap(), 0, ProviderName
);
5199 ProviderName
= NULL
;
5201 DereferenceInfFile(currentInfFileDetails
);
5202 currentInfFileDetails
= NULL
;
5213 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5214 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5218 InstallParams
.Flags
|= DI_DIDCLASS
;
5219 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5221 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5224 HeapFree(GetProcessHeap(), 0, ProviderName
);
5225 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5226 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5227 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5228 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5229 if (currentInfFileDetails
)
5230 DereferenceInfFile(currentInfFileDetails
);
5231 HeapFree(GetProcessHeap(), 0, Buffer
);
5233 TRACE("Returning %d\n", ret
);
5237 /***********************************************************************
5238 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5241 SetupDiDeleteDeviceInfo(
5242 IN HDEVINFO DeviceInfoSet
,
5243 IN PSP_DEVINFO_DATA DeviceInfoData
)
5245 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5247 FIXME("not implemented\n");
5248 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5253 /***********************************************************************
5254 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5257 SetupDiDestroyDriverInfoList(
5258 IN HDEVINFO DeviceInfoSet
,
5259 IN PSP_DEVINFO_DATA DeviceInfoData
,
5260 IN DWORD DriverType
)
5262 struct DeviceInfoSet
*list
;
5265 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5268 SetLastError(ERROR_INVALID_HANDLE
);
5269 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5270 SetLastError(ERROR_INVALID_HANDLE
);
5271 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5272 SetLastError(ERROR_INVALID_PARAMETER
);
5273 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5274 SetLastError(ERROR_INVALID_PARAMETER
);
5275 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5276 SetLastError(ERROR_INVALID_USER_BUFFER
);
5279 PLIST_ENTRY ListEntry
;
5280 struct DriverInfoElement
*driverInfo
;
5281 SP_DEVINSTALL_PARAMS_W InstallParams
;
5283 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5284 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5287 if (!DeviceInfoData
)
5288 /* Fall back to destroying class driver list */
5289 DriverType
= SPDIT_CLASSDRIVER
;
5291 if (DriverType
== SPDIT_CLASSDRIVER
)
5293 while (!IsListEmpty(&list
->DriverListHead
))
5295 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5296 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5297 DestroyDriverInfoElement(driverInfo
);
5299 InstallParams
.Reserved
= 0;
5300 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5301 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5302 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5306 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5307 struct DeviceInfoElement
*deviceInfo
;
5309 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5310 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5312 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5313 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5315 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5316 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5317 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5319 InstallParamsSet
.Reserved
= 0;
5320 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5322 DestroyDriverInfoElement(driverInfo
);
5324 InstallParams
.Reserved
= 0;
5325 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5326 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5327 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5332 TRACE("Returning %d\n", ret
);
5337 /***********************************************************************
5338 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5341 SetupDiOpenDeviceInfoA(
5342 IN HDEVINFO DeviceInfoSet
,
5343 IN PCSTR DeviceInstanceId
,
5344 IN HWND hwndParent OPTIONAL
,
5346 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5348 LPWSTR DeviceInstanceIdW
= NULL
;
5351 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5353 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5354 if (DeviceInstanceIdW
== NULL
)
5357 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5358 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5360 MyFree(DeviceInstanceIdW
);
5366 /***********************************************************************
5367 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5370 SetupDiOpenDeviceInfoW(
5371 IN HDEVINFO DeviceInfoSet
,
5372 IN PCWSTR DeviceInstanceId
,
5373 IN HWND hwndParent OPTIONAL
,
5375 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5377 struct DeviceInfoSet
*list
;
5378 HKEY hEnumKey
, hKey
;
5382 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5384 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5385 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5388 SetLastError(ERROR_INVALID_HANDLE
);
5389 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5390 SetLastError(ERROR_INVALID_HANDLE
);
5391 else if (!DeviceInstanceId
)
5392 SetLastError(ERROR_INVALID_PARAMETER
);
5393 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5395 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5396 SetLastError(ERROR_INVALID_FLAGS
);
5398 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5399 SetLastError(ERROR_INVALID_USER_BUFFER
);
5402 struct DeviceInfoElement
*deviceInfo
= NULL
;
5403 /* Search if device already exists in DeviceInfoSet.
5404 * If yes, return the existing element
5405 * If no, create a new element using informations in registry
5407 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5408 while (ItemList
!= &list
->ListHead
)
5413 FIXME("not implemented\n");
5414 ItemList
= ItemList
->Flink
;
5419 /* good one found */
5424 /* Open supposed registry key */
5429 KEY_ENUMERATE_SUB_KEYS
,
5431 if (rc
!= ERROR_SUCCESS
)
5442 RegCloseKey(hEnumKey
);
5443 if (rc
!= ERROR_SUCCESS
)
5445 if (rc
== ERROR_FILE_NOT_FOUND
)
5446 rc
= ERROR_NO_SUCH_DEVINST
;
5451 /* FIXME: try to get ClassGUID from registry, instead of
5452 * sending GUID_NULL to CreateDeviceInfoElement
5454 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
5459 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5465 if (ret
&& deviceInfo
&& DeviceInfoData
)
5467 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5468 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5469 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5477 /***********************************************************************
5478 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5481 SetupDiEnumDriverInfoA(
5482 IN HDEVINFO DeviceInfoSet
,
5483 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5484 IN DWORD DriverType
,
5485 IN DWORD MemberIndex
,
5486 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5488 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5491 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5492 DriverType
, MemberIndex
, DriverInfoData
);
5494 if (DriverInfoData
== NULL
)
5495 SetLastError(ERROR_INVALID_PARAMETER
);
5496 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5497 SetLastError(ERROR_INVALID_USER_BUFFER
);
5500 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5501 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
5502 DriverType
, MemberIndex
, &driverInfoData2W
);
5506 /* Do W->A conversion */
5507 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5508 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5509 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5510 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5512 DriverInfoData
->Description
[0] = '\0';
5515 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5516 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5518 DriverInfoData
->MfgName
[0] = '\0';
5521 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5522 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5524 DriverInfoData
->ProviderName
[0] = '\0';
5527 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5529 /* Copy more fields */
5530 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5531 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5536 TRACE("Returning %d\n", ret
);
5541 /***********************************************************************
5542 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5545 SetupDiEnumDriverInfoW(
5546 IN HDEVINFO DeviceInfoSet
,
5547 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5548 IN DWORD DriverType
,
5549 IN DWORD MemberIndex
,
5550 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5552 PLIST_ENTRY ListHead
;
5555 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5556 DriverType
, MemberIndex
, DriverInfoData
);
5558 if (!DeviceInfoSet
|| !DriverInfoData
)
5559 SetLastError(ERROR_INVALID_PARAMETER
);
5560 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5561 SetLastError(ERROR_INVALID_HANDLE
);
5562 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5563 SetLastError(ERROR_INVALID_HANDLE
);
5564 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5565 SetLastError(ERROR_INVALID_PARAMETER
);
5566 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5567 SetLastError(ERROR_INVALID_PARAMETER
);
5568 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5569 SetLastError(ERROR_INVALID_PARAMETER
);
5570 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5571 SetLastError(ERROR_INVALID_USER_BUFFER
);
5574 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5575 PLIST_ENTRY ItemList
;
5576 if (DriverType
== SPDIT_CLASSDRIVER
||
5577 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
5579 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5583 ListHead
= &devInfo
->DriverListHead
;
5586 ItemList
= ListHead
->Flink
;
5587 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
5588 ItemList
= ItemList
->Flink
;
5589 if (ItemList
== ListHead
)
5590 SetLastError(ERROR_NO_MORE_ITEMS
);
5593 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
5596 &DriverInfoData
->DriverType
,
5597 &DrvInfo
->Info
.DriverType
,
5598 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5603 TRACE("Returning %d\n", ret
);
5608 /***********************************************************************
5609 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5612 SetupDiGetSelectedDriverA(
5613 IN HDEVINFO DeviceInfoSet
,
5614 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5615 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5617 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5620 if (DriverInfoData
== NULL
)
5621 SetLastError(ERROR_INVALID_PARAMETER
);
5622 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5623 SetLastError(ERROR_INVALID_USER_BUFFER
);
5626 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5628 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5634 /* Do W->A conversion */
5635 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5636 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5637 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5638 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5640 DriverInfoData
->Description
[0] = '\0';
5643 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5644 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5646 DriverInfoData
->MfgName
[0] = '\0';
5649 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5650 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5652 DriverInfoData
->ProviderName
[0] = '\0';
5655 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5657 /* Copy more fields */
5658 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5659 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5668 /***********************************************************************
5669 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5672 SetupDiGetSelectedDriverW(
5673 IN HDEVINFO DeviceInfoSet
,
5674 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5675 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5679 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5681 if (!DeviceInfoSet
|| !DriverInfoData
)
5682 SetLastError(ERROR_INVALID_PARAMETER
);
5683 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5684 SetLastError(ERROR_INVALID_HANDLE
);
5685 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5686 SetLastError(ERROR_INVALID_HANDLE
);
5687 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5688 SetLastError(ERROR_INVALID_USER_BUFFER
);
5689 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5690 SetLastError(ERROR_INVALID_USER_BUFFER
);
5693 SP_DEVINSTALL_PARAMS InstallParams
;
5695 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5696 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5698 struct DriverInfoElement
*driverInfo
;
5699 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5700 if (driverInfo
== NULL
)
5701 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5705 &DriverInfoData
->DriverType
,
5706 &driverInfo
->Info
.DriverType
,
5707 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5713 TRACE("Returning %d\n", ret
);
5718 /***********************************************************************
5719 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5722 SetupDiSetSelectedDriverA(
5723 IN HDEVINFO DeviceInfoSet
,
5724 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5725 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5727 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5728 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5731 if (DriverInfoData
!= NULL
)
5733 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5734 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5736 SetLastError(ERROR_INVALID_PARAMETER
);
5740 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5741 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5743 if (DriverInfoDataW
.Reserved
== 0)
5745 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5747 /* convert the strings to unicode */
5748 if (!MultiByteToWideChar(CP_ACP
,
5750 DriverInfoData
->Description
,
5752 DriverInfoDataW
.Description
,
5754 !MultiByteToWideChar(CP_ACP
,
5756 DriverInfoData
->ProviderName
,
5758 DriverInfoDataW
.ProviderName
,
5765 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5768 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5772 if (ret
&& pDriverInfoDataW
!= NULL
)
5774 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5781 /***********************************************************************
5782 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5785 SetupDiSetSelectedDriverW(
5786 IN HDEVINFO DeviceInfoSet
,
5787 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5788 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5792 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5795 SetLastError(ERROR_INVALID_PARAMETER
);
5796 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5797 SetLastError(ERROR_INVALID_HANDLE
);
5798 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5799 SetLastError(ERROR_INVALID_HANDLE
);
5800 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5801 SetLastError(ERROR_INVALID_USER_BUFFER
);
5802 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5803 SetLastError(ERROR_INVALID_USER_BUFFER
);
5806 struct DriverInfoElement
**pDriverInfo
;
5807 PLIST_ENTRY ListHead
, ItemList
;
5811 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5812 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5816 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5817 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5820 if (!DriverInfoData
)
5822 *pDriverInfo
= NULL
;
5827 /* Search selected driver in list */
5828 ItemList
= ListHead
->Flink
;
5829 while (ItemList
!= ListHead
)
5831 if (DriverInfoData
->Reserved
!= 0)
5833 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5838 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5839 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5840 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5841 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5842 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5848 if (ItemList
== ListHead
)
5849 SetLastError(ERROR_INVALID_PARAMETER
);
5852 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5853 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5855 TRACE("Choosing driver whose rank is 0x%lx\n",
5856 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5858 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5863 TRACE("Returning %d\n", ret
);
5867 /***********************************************************************
5868 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5871 SetupDiGetDriverInfoDetailA(
5872 IN HDEVINFO DeviceInfoSet
,
5873 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5874 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5875 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5876 IN DWORD DriverInfoDetailDataSize
,
5877 OUT PDWORD RequiredSize OPTIONAL
)
5879 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5880 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5882 DWORD HardwareIDLen
= 0;
5885 /* do some sanity checks, the unicode version might do more thorough checks */
5886 if (DriverInfoData
== NULL
||
5887 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5888 (DriverInfoDetailData
!= NULL
&&
5889 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5890 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5892 SetLastError(ERROR_INVALID_PARAMETER
);
5896 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5897 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5899 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5901 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5903 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5907 SetLastError(ERROR_INVALID_PARAMETER
);
5910 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5911 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5913 /* convert the strings to unicode */
5914 if (MultiByteToWideChar(CP_ACP
,
5916 DriverInfoData
->Description
,
5918 DriverInfoDataW
.Description
,
5920 MultiByteToWideChar(CP_ACP
,
5922 DriverInfoData
->MfgName
,
5924 DriverInfoDataW
.MfgName
,
5926 MultiByteToWideChar(CP_ACP
,
5928 DriverInfoData
->ProviderName
,
5930 DriverInfoDataW
.ProviderName
,
5933 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5935 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5936 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5939 if (DriverInfoDetailData
!= NULL
)
5941 /* calculate the unicode buffer size from the ansi buffer size */
5942 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5943 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5944 (HardwareIDLen
* sizeof(WCHAR
));
5946 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5947 if (DriverInfoDetailDataW
== NULL
)
5949 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5953 /* initialize the buffer */
5954 ZeroMemory(DriverInfoDetailDataW
,
5956 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5959 /* call the unicode version */
5960 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5963 DriverInfoDetailDataW
,
5969 if (DriverInfoDetailDataW
!= NULL
)
5971 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5972 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
5973 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
5974 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
5975 if (WideCharToMultiByte(CP_ACP
,
5977 DriverInfoDetailDataW
->SectionName
,
5979 DriverInfoDetailData
->SectionName
,
5983 WideCharToMultiByte(CP_ACP
,
5985 DriverInfoDetailDataW
->InfFileName
,
5987 DriverInfoDetailData
->InfFileName
,
5991 WideCharToMultiByte(CP_ACP
,
5993 DriverInfoDetailDataW
->DrvDescription
,
5995 DriverInfoDetailData
->DrvDescription
,
5999 WideCharToMultiByte(CP_ACP
,
6001 DriverInfoDetailDataW
->HardwareID
,
6003 DriverInfoDetailData
->HardwareID
,
6009 DWORD hwidlen
= HardwareIDLen
;
6010 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6012 /* count the strings in the list */
6015 len
= lstrlenA(s
) + 1;
6024 /* looks like the string list wasn't terminated... */
6025 SetLastError(ERROR_INVALID_USER_BUFFER
);
6031 /* make sure CompatIDsOffset points to the second string in the
6035 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6036 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6037 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6041 DriverInfoDetailData
->CompatIDsOffset
= 0;
6042 DriverInfoDetailData
->CompatIDsLength
= 0;
6051 if (RequiredSize
!= NULL
)
6053 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6054 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6060 if (DriverInfoDetailDataW
!= NULL
)
6062 MyFree(DriverInfoDetailDataW
);
6068 /***********************************************************************
6069 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6072 SetupDiGetDriverInfoDetailW(
6073 IN HDEVINFO DeviceInfoSet
,
6074 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6075 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6076 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6077 IN DWORD DriverInfoDetailDataSize
,
6078 OUT PDWORD RequiredSize OPTIONAL
)
6082 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6083 DriverInfoData
, DriverInfoDetailData
,
6084 DriverInfoDetailDataSize
, RequiredSize
);
6087 SetLastError(ERROR_INVALID_PARAMETER
);
6088 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6089 SetLastError(ERROR_INVALID_HANDLE
);
6090 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6091 SetLastError(ERROR_INVALID_HANDLE
);
6092 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6093 SetLastError(ERROR_INVALID_USER_BUFFER
);
6094 else if (!DriverInfoData
)
6095 SetLastError(ERROR_INVALID_PARAMETER
);
6096 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6097 SetLastError(ERROR_INVALID_PARAMETER
);
6098 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6099 SetLastError(ERROR_INVALID_PARAMETER
);
6100 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6101 SetLastError(ERROR_INVALID_USER_BUFFER
);
6102 else if (DriverInfoData
->Reserved
== 0)
6103 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6106 struct DriverInfoElement
*driverInfoElement
;
6107 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6110 DriverInfoDetailData
,
6111 &driverInfoElement
->Details
,
6112 driverInfoElement
->Details
.cbSize
);
6113 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6114 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6119 TRACE("Returning %d\n", ret
);
6123 /***********************************************************************
6124 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6127 SetupDiSelectBestCompatDrv(
6128 IN HDEVINFO DeviceInfoSet
,
6129 IN PSP_DEVINFO_DATA DeviceInfoData
)
6131 SP_DRVINFO_DATA_W drvInfoData
;
6134 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6136 /* Drivers are sorted by rank in the driver list, so
6137 * the first driver in the list is the best one.
6139 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6140 ret
= SetupDiEnumDriverInfoW(
6144 0, /* Member index */
6149 ret
= SetupDiSetSelectedDriverW(
6155 TRACE("Returning %d\n", ret
);
6159 /***********************************************************************
6160 * SetupDiInstallDriverFiles (SETUPAPI.@)
6163 SetupDiInstallDriverFiles(
6164 IN HDEVINFO DeviceInfoSet
,
6165 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6169 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6172 SetLastError(ERROR_INVALID_PARAMETER
);
6173 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6174 SetLastError(ERROR_INVALID_HANDLE
);
6175 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6176 SetLastError(ERROR_INVALID_HANDLE
);
6177 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6178 SetLastError(ERROR_INVALID_USER_BUFFER
);
6179 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
6180 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6181 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
6182 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6185 SP_DEVINSTALL_PARAMS_W InstallParams
;
6186 struct DriverInfoElement
*SelectedDriver
;
6187 WCHAR SectionName
[MAX_PATH
];
6188 DWORD SectionNameLength
= 0;
6190 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6191 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6195 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6196 if (!SelectedDriver
)
6198 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6202 ret
= SetupDiGetActualSectionToInstallW(
6203 SelectedDriver
->InfFileDetails
->hInf
,
6204 SelectedDriver
->Details
.SectionName
,
6205 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6209 if (!InstallParams
.InstallMsgHandler
)
6211 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6212 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6213 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6215 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6216 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6217 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
6218 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6219 DeviceInfoSet
, DeviceInfoData
);
6223 TRACE("Returning %d\n", ret
);
6227 /***********************************************************************
6228 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6231 SetupDiRegisterCoDeviceInstallers(
6232 IN HDEVINFO DeviceInfoSet
,
6233 IN PSP_DEVINFO_DATA DeviceInfoData
)
6235 BOOL ret
= FALSE
; /* Return value */
6237 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6240 SetLastError(ERROR_INVALID_PARAMETER
);
6241 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6242 SetLastError(ERROR_INVALID_HANDLE
);
6243 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6244 SetLastError(ERROR_INVALID_HANDLE
);
6245 else if (!DeviceInfoData
)
6246 SetLastError(ERROR_INVALID_PARAMETER
);
6247 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6248 SetLastError(ERROR_INVALID_USER_BUFFER
);
6251 SP_DEVINSTALL_PARAMS_W InstallParams
;
6252 struct DriverInfoElement
*SelectedDriver
;
6255 WCHAR SectionName
[MAX_PATH
];
6256 DWORD SectionNameLength
= 0;
6257 HKEY hKey
= INVALID_HANDLE_VALUE
;
6259 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6260 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6264 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6265 if (SelectedDriver
== NULL
)
6267 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6271 /* Get .CoInstallers section name */
6272 Result
= SetupDiGetActualSectionToInstallW(
6273 SelectedDriver
->InfFileDetails
->hInf
,
6274 SelectedDriver
->Details
.SectionName
,
6275 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6276 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
6278 wcscat(SectionName
, L
".CoInstallers");
6280 /* Open/Create driver key information */
6281 #if _WIN32_WINNT >= 0x502
6282 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6284 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6286 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6287 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6288 if (hKey
== INVALID_HANDLE_VALUE
)
6291 /* Install .CoInstallers section */
6292 DoAction
= SPINST_REGISTRY
;
6293 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6295 DoAction
|= SPINST_FILES
;
6296 if (!InstallParams
.InstallMsgHandler
)
6298 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6299 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6300 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6303 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6304 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6305 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6306 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6307 DeviceInfoSet
, DeviceInfoData
);
6314 if (hKey
!= INVALID_HANDLE_VALUE
)
6318 TRACE("Returning %d\n", ret
);
6322 /***********************************************************************
6323 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
6326 SetupDiInstallDeviceInterfaces(
6327 IN HDEVINFO DeviceInfoSet
,
6328 IN PSP_DEVINFO_DATA DeviceInfoData
)
6330 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6332 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
6333 //SetLastError(ERROR_GEN_FAILURE);
6339 InfIsFromOEMLocation(
6341 OUT LPBOOL IsOEMLocation
)
6345 last
= strrchrW(FullName
, '\\');
6348 /* No directory specified */
6349 *IsOEMLocation
= FALSE
;
6353 WCHAR Windir
[MAX_PATH
];
6356 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
6357 if (ret
== 0 || ret
>= MAX_PATH
)
6359 SetLastError(ERROR_GEN_FAILURE
);
6363 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
6365 /* The path is %SYSTEMROOT%\Inf */
6366 *IsOEMLocation
= FALSE
;
6370 /* The file is in another place */
6371 *IsOEMLocation
= TRUE
;
6377 /***********************************************************************
6378 * SetupDiInstallDevice (SETUPAPI.@)
6381 SetupDiInstallDevice(
6382 IN HDEVINFO DeviceInfoSet
,
6383 IN PSP_DEVINFO_DATA DeviceInfoData
)
6385 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6386 SP_DEVINSTALL_PARAMS_W InstallParams
;
6387 struct DriverInfoElement
*SelectedDriver
;
6388 SYSTEMTIME DriverDate
;
6389 WCHAR SectionName
[MAX_PATH
];
6391 DWORD SectionNameLength
= 0;
6392 BOOL Result
= FALSE
;
6393 INFCONTEXT ContextService
;
6397 LPCWSTR AssociatedService
= NULL
;
6398 LPWSTR pSectionName
= NULL
;
6399 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
6401 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
6402 BOOL RebootRequired
= FALSE
;
6403 HKEY hKey
= INVALID_HANDLE_VALUE
;
6404 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
6405 BOOL NeedtoCopyFile
;
6407 BOOL ret
= FALSE
; /* Return value */
6409 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6412 SetLastError(ERROR_INVALID_PARAMETER
);
6413 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6414 SetLastError(ERROR_INVALID_HANDLE
);
6415 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6416 SetLastError(ERROR_INVALID_HANDLE
);
6417 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6418 SetLastError(ERROR_INVALID_USER_BUFFER
);
6424 /* One parameter is bad */
6428 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6429 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6433 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
6435 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6439 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6440 if (SelectedDriver
== NULL
)
6442 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6446 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
6448 Result
= SetupDiGetActualSectionToInstallW(
6449 SelectedDriver
->InfFileDetails
->hInf
,
6450 SelectedDriver
->Details
.SectionName
,
6451 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6452 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
6454 pSectionName
= &SectionName
[wcslen(SectionName
)];
6456 /* Get information from [Version] section */
6457 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
6459 /* Format ClassGuid to a string */
6460 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
6462 RequiredSize
= lstrlenW(lpGuidString
);
6463 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
6464 if (!lpFullGuidString
)
6466 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6469 lpFullGuidString
[0] = '{';
6470 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
6471 lpFullGuidString
[RequiredSize
+ 1] = '}';
6472 lpFullGuidString
[RequiredSize
+ 2] = '\0';
6474 /* Open/Create driver key information */
6475 #if _WIN32_WINNT >= 0x502
6476 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6478 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6480 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6481 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6482 if (hKey
== INVALID_HANDLE_VALUE
)
6485 /* Install main section */
6486 DoAction
= SPINST_REGISTRY
;
6487 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6489 DoAction
|= SPINST_FILES
;
6490 if (!InstallParams
.InstallMsgHandler
)
6492 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6493 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6494 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6497 *pSectionName
= '\0';
6498 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6499 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6500 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6501 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6502 DeviceInfoSet
, DeviceInfoData
);
6505 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
6507 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
6509 /* Delete resources allocated by SetupInitDefaultQueueCallback */
6510 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
6513 InstallParams
.Flags
|= DI_NOFILECOPY
;
6514 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6516 /* Write information to driver key */
6517 *pSectionName
= UNICODE_NULL
;
6518 TRACE("Write information to driver key\n");
6519 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6520 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6521 TRACE("DriverVersion : '%u.%u.%u.%u'\n", SelectedDriver
->Info
.DriverVersion
& 0xff, (SelectedDriver
->Info
.DriverVersion
>> 8) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 16) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 24) & 0xff);
6522 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
6523 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
6524 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
6525 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
6526 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
6527 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6528 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
6529 if (rc
== ERROR_SUCCESS
)
6530 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
6531 if (rc
== ERROR_SUCCESS
)
6532 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6533 if (rc
== ERROR_SUCCESS
)
6535 swprintf(Buffer
, L
"%u.%u.%u.%u", SelectedDriver
->Info
.DriverVersion
& 0xff, (SelectedDriver
->Info
.DriverVersion
>> 8) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 16) & 0xff, (SelectedDriver
->Info
.DriverVersion
>> 24) & 0xff);
6536 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
6538 if (rc
== ERROR_SUCCESS
)
6539 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
6540 if (rc
== ERROR_SUCCESS
)
6541 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
6542 if (rc
== ERROR_SUCCESS
)
6543 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
6544 if (rc
== ERROR_SUCCESS
)
6545 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
6546 if (rc
== ERROR_SUCCESS
)
6547 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
6548 if (rc
!= ERROR_SUCCESS
)
6554 hKey
= INVALID_HANDLE_VALUE
;
6556 /* FIXME: Process .LogConfigOverride section */
6558 /* Install .Services section */
6559 wcscpy(pSectionName
, L
".Services");
6560 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
6563 LPWSTR ServiceName
= NULL
;
6564 LPWSTR ServiceSection
= NULL
;
6566 Result
= SetupGetStringFieldW(
6568 1, /* Field index */
6573 if (RequiredSize
> 0)
6575 /* We got the needed size for the buffer */
6576 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6579 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6582 Result
= SetupGetStringFieldW(
6584 1, /* Field index */
6585 ServiceName
, RequiredSize
,
6590 Result
= SetupGetIntField(
6592 2, /* Field index */
6596 /* The field may be empty. Ignore the error */
6599 Result
= SetupGetStringFieldW(
6601 3, /* Field index */
6606 if (GetLastError() == ERROR_INVALID_PARAMETER
)
6608 /* This first is probably missing. It is not
6609 * required, so ignore the error */
6616 if (RequiredSize
> 0)
6618 /* We got the needed size for the buffer */
6619 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6620 if (!ServiceSection
)
6622 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6625 Result
= SetupGetStringFieldW(
6627 3, /* Field index */
6628 ServiceSection
, RequiredSize
,
6633 SetLastError(ERROR_SUCCESS
);
6634 Result
= SetupInstallServicesFromInfSectionExW(
6635 SelectedDriver
->InfFileDetails
->hInf
,
6636 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
6638 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
6640 AssociatedService
= ServiceName
;
6642 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
6643 RebootRequired
= TRUE
;
6646 HeapFree(GetProcessHeap(), 0, ServiceName
);
6647 HeapFree(GetProcessHeap(), 0, ServiceSection
);
6650 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
6653 /* Copy .inf file to Inf\ directory (if needed) */
6654 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
6659 Result
= SetupCopyOEMInfW(
6660 SelectedDriver
->InfFileDetails
->FullInfFileName
,
6663 SP_COPY_NOOVERWRITE
,
6669 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6670 * to release use of current InfFile */
6673 /* Open device registry key */
6674 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
6675 if (hKey
== INVALID_HANDLE_VALUE
)
6678 /* Install .HW section */
6679 wcscpy(pSectionName
, L
".HW");
6680 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6681 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6682 SPINST_REGISTRY
, hKey
, NULL
, 0,
6683 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6684 DeviceInfoSet
, DeviceInfoData
);
6688 /* Write information to enum key */
6689 TRACE("Write information to enum key\n");
6690 TRACE("Class : '%S'\n", ClassName
);
6691 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
6692 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6693 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
6694 TRACE("Service : '%S'\n", AssociatedService
);
6695 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
6696 if (rc
== ERROR_SUCCESS
)
6697 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
6698 if (rc
== ERROR_SUCCESS
)
6699 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6700 if (rc
== ERROR_SUCCESS
)
6701 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
6702 if (rc
== ERROR_SUCCESS
&& *AssociatedService
)
6703 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
6704 if (rc
!= ERROR_SUCCESS
)
6710 /* Start the device */
6711 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
6713 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6715 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
6716 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6717 ret
= NT_SUCCESS(Status
);
6723 /* End of installation */
6724 if (hClassKey
!= INVALID_HANDLE_VALUE
)
6725 RegCloseKey(hClassKey
);
6726 if (hKey
!= INVALID_HANDLE_VALUE
)
6729 RpcStringFreeW(&lpGuidString
);
6730 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
6731 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6733 TRACE("Returning %d\n", ret
);