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
);
624 /***********************************************************************
625 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
628 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
633 struct DeviceInfoSet
*list
;
634 LPWSTR UNCServerName
= NULL
;
638 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
640 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
641 debugstr_w(MachineName
), Reserved
);
643 size
= sizeof(struct DeviceInfoSet
);
645 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
646 list
= HeapAlloc(GetProcessHeap(), 0, size
);
649 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
652 memset(list
, 0, sizeof(struct DeviceInfoSet
));
654 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
657 ClassGuid
? ClassGuid
: &GUID_NULL
,
658 sizeof(list
->ClassGuid
));
659 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
660 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
661 list
->InstallParams
.hwndParent
= hwndParent
;
664 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
665 if (rc
!= ERROR_SUCCESS
)
670 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
673 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
677 strcpyW(UNCServerName
+ 2, MachineName
);
678 list
->szData
[0] = list
->szData
[1] = '\\';
679 strcpyW(list
->szData
+ 2, MachineName
);
680 list
->MachineName
= list
->szData
;
684 DWORD Size
= MAX_PATH
;
685 list
->HKLM
= HKEY_LOCAL_MACHINE
;
686 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
689 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
692 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
694 list
->MachineName
= NULL
;
697 UNCServerName
[0] = UNCServerName
[1] = '\\';
698 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
699 if (cr
!= CR_SUCCESS
)
703 case CR_OUT_OF_MEMORY
: rc
= ERROR_NOT_ENOUGH_MEMORY
; break;
704 case CR_INVALID_MACHINENAME
: rc
= ERROR_INVALID_COMPUTERNAME
; break;
705 default: rc
= ERROR_GEN_FAILURE
; break;
711 InitializeListHead(&list
->DriverListHead
);
712 InitializeListHead(&list
->ListHead
);
714 ret
= (HDEVINFO
)list
;
717 if (ret
== INVALID_HANDLE_VALUE
)
719 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
720 RegCloseKey(list
->HKLM
);
721 HeapFree(GetProcessHeap(), 0, list
);
723 HeapFree(GetProcessHeap(), 0, UNCServerName
);
727 /***********************************************************************
728 * SetupDiEnumDeviceInfo (SETUPAPI.@)
730 BOOL WINAPI
SetupDiEnumDeviceInfo(
731 HDEVINFO DeviceInfoSet
,
733 PSP_DEVINFO_DATA DeviceInfoData
)
737 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
739 SetLastError(ERROR_INVALID_PARAMETER
);
740 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
742 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
744 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
745 SetLastError(ERROR_INVALID_HANDLE
);
746 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
747 SetLastError(ERROR_INVALID_USER_BUFFER
);
750 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
751 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
752 ItemList
= ItemList
->Flink
;
753 if (ItemList
== &list
->ListHead
)
754 SetLastError(ERROR_NO_MORE_ITEMS
);
757 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
758 memcpy(&DeviceInfoData
->ClassGuid
,
761 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
762 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
768 SetLastError(ERROR_INVALID_HANDLE
);
772 /***********************************************************************
773 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
775 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
777 PCSTR InfSectionName
,
778 PSTR InfSectionWithExt
,
779 DWORD InfSectionWithExtSize
,
783 LPWSTR InfSectionNameW
= NULL
;
784 PWSTR InfSectionWithExtW
= NULL
;
786 BOOL bResult
= FALSE
;
792 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
793 if (InfSectionNameW
== NULL
) goto end
;
795 if (InfSectionWithExt
)
797 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
798 if (InfSectionWithExtW
== NULL
) goto end
;
801 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
802 InfSectionWithExt
? InfSectionNameW
: NULL
,
803 InfSectionWithExtSize
, RequiredSize
,
804 Extension
? &ExtensionW
: NULL
);
806 if (bResult
&& InfSectionWithExt
)
808 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
809 InfSectionWithExtSize
, NULL
, NULL
) != 0;
811 if (bResult
&& Extension
)
813 if (ExtensionW
== NULL
)
816 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
820 if (InfSectionNameW
) MyFree(InfSectionNameW
);
821 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
826 /***********************************************************************
827 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
829 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
831 PCWSTR InfSectionName
,
832 PWSTR InfSectionWithExt
,
833 DWORD InfSectionWithExtSize
,
837 WCHAR szBuffer
[MAX_PATH
];
840 LONG lLineCount
= -1;
842 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
843 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
845 lstrcpyW(szBuffer
, InfSectionName
);
846 dwLength
= lstrlenW(szBuffer
);
848 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
850 /* Test section name with '.NTx86' extension */
851 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
852 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
854 if (lLineCount
== -1)
856 /* Test section name with '.NT' extension */
857 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
858 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
863 /* Test section name with '.Win' extension */
864 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
865 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
868 if (lLineCount
== -1)
870 /* Test section name without extension */
871 szBuffer
[dwLength
] = 0;
872 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
875 if (lLineCount
== -1)
877 SetLastError(ERROR_INVALID_PARAMETER
);
881 dwFullLength
= lstrlenW(szBuffer
);
883 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
885 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
887 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
891 lstrcpyW(InfSectionWithExt
, szBuffer
);
892 if (Extension
!= NULL
)
894 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
898 if (RequiredSize
!= NULL
)
900 *RequiredSize
= dwFullLength
+ 1;
906 /***********************************************************************
907 * SetupDiGetClassDescriptionA (SETUPAPI.@)
909 BOOL WINAPI
SetupDiGetClassDescriptionA(
910 const GUID
* ClassGuid
,
911 PSTR ClassDescription
,
912 DWORD ClassDescriptionSize
,
915 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
916 ClassDescriptionSize
,
917 RequiredSize
, NULL
, NULL
);
920 /***********************************************************************
921 * SetupDiGetClassDescriptionW (SETUPAPI.@)
923 BOOL WINAPI
SetupDiGetClassDescriptionW(
924 const GUID
* ClassGuid
,
925 PWSTR ClassDescription
,
926 DWORD ClassDescriptionSize
,
929 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
930 ClassDescriptionSize
,
931 RequiredSize
, NULL
, NULL
);
934 /***********************************************************************
935 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
937 BOOL WINAPI
SetupDiGetClassDescriptionExA(
938 const GUID
* ClassGuid
,
939 PSTR ClassDescription
,
940 DWORD ClassDescriptionSize
,
945 PWCHAR ClassDescriptionW
;
946 LPWSTR MachineNameW
= NULL
;
950 if (ClassDescriptionSize
> 0)
952 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
953 if (!ClassDescriptionW
)
955 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
961 ClassDescriptionW
= NULL
;
965 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
968 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
974 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
975 NULL
, MachineNameW
, Reserved
);
978 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
979 ClassDescriptionSize
, NULL
, NULL
);
981 if (!ClassDescriptionSize
&& RequiredSize
)
986 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
987 MyFree(MachineNameW
);
991 /***********************************************************************
992 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
994 BOOL WINAPI
SetupDiGetClassDescriptionExW(
995 const GUID
* ClassGuid
,
996 PWSTR ClassDescription
,
997 DWORD ClassDescriptionSize
,
1005 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1006 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1008 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1013 if (hKey
== INVALID_HANDLE_VALUE
)
1015 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1019 if (RequiredSize
!= NULL
)
1022 if (RegQueryValueExW(hKey
,
1033 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1036 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1037 if (RegQueryValueExW(hKey
,
1041 (LPBYTE
)ClassDescription
,
1053 /***********************************************************************
1054 * SetupDiGetClassDevsA (SETUPAPI.@)
1056 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1062 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1063 flags
, NULL
, NULL
, NULL
);
1066 /***********************************************************************
1067 * SetupDiGetClassDevsW (SETUPAPI.@)
1069 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1075 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1076 flags
, NULL
, NULL
, NULL
);
1079 /***********************************************************************
1080 * SetupDiGetClassDevsExA (SETUPAPI.@)
1082 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1092 LPWSTR enumstrW
= NULL
;
1093 LPWSTR machineW
= NULL
;
1097 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1098 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1101 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1104 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1108 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1109 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1112 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1115 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1117 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1120 HeapFree(GetProcessHeap(), 0, enumstrW
);
1121 HeapFree(GetProcessHeap(), 0, machineW
);
1126 CreateDeviceInfoElement(
1127 IN LPCWSTR InstancePath
,
1128 IN LPCGUID pClassGuid
,
1129 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1132 struct DeviceInfoElement
*deviceInfo
;
1134 *pDeviceInfo
= NULL
;
1136 size
= sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1137 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1140 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1143 memset(deviceInfo
, 0, size
);
1144 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1145 wcscpy(deviceInfo
->Data
, InstancePath
);
1146 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1147 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1148 deviceInfo
->DeviceDescription
= NULL
;
1149 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1150 deviceInfo
->CreationFlags
= 0;
1151 InitializeListHead(&deviceInfo
->DriverListHead
);
1152 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1154 *pDeviceInfo
= deviceInfo
;
1159 CreateDeviceInterface(
1160 IN
struct DeviceInfoElement
* deviceInfo
,
1161 IN LPCWSTR SymbolicLink
,
1162 IN LPCGUID pInterfaceGuid
,
1163 OUT
struct DeviceInterface
**pDeviceInterface
)
1165 struct DeviceInterface
*deviceInterface
;
1167 *pDeviceInterface
= NULL
;
1169 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1170 if (!deviceInterface
)
1172 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1175 deviceInterface
->DeviceInfo
= deviceInfo
;
1176 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1177 deviceInterface
->Flags
= 0; /* FIXME */
1178 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1180 *pDeviceInterface
= deviceInterface
;
1184 static LONG
SETUP_CreateDevListFromEnumerator(
1185 struct DeviceInfoSet
*list
,
1186 LPCGUID pClassGuid OPTIONAL
,
1188 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1190 HKEY hDeviceIdKey
, hInstanceIdKey
;
1191 WCHAR KeyBuffer
[MAX_PATH
];
1192 WCHAR InstancePath
[MAX_PATH
];
1193 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1194 struct DeviceInfoElement
*deviceInfo
;
1196 DWORD dwLength
, dwRegType
;
1199 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1202 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1203 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1204 if (rc
== ERROR_NO_MORE_ITEMS
)
1206 if (rc
!= ERROR_SUCCESS
)
1210 /* Open device id sub key */
1211 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1212 if (rc
!= ERROR_SUCCESS
)
1214 wcscpy(InstancePath
, Enumerator
);
1215 wcscat(InstancePath
, L
"\\");
1216 wcscat(InstancePath
, KeyBuffer
);
1217 wcscat(InstancePath
, L
"\\");
1218 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1220 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1226 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1227 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1228 if (rc
== ERROR_NO_MORE_ITEMS
)
1230 if (rc
!= ERROR_SUCCESS
)
1232 RegCloseKey(hDeviceIdKey
);
1237 /* Open instance id sub key */
1238 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1239 if (rc
!= ERROR_SUCCESS
)
1241 RegCloseKey(hDeviceIdKey
);
1244 *pEndOfInstancePath
= '\0';
1245 wcscat(InstancePath
, KeyBuffer
);
1247 /* Read ClassGUID value */
1248 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1249 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1250 RegCloseKey(hInstanceIdKey
);
1251 if (rc
== ERROR_FILE_NOT_FOUND
)
1254 /* Skip this bad entry as we can't verify it */
1256 /* Set a default GUID for this device */
1257 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1259 else if (rc
!= ERROR_SUCCESS
)
1261 RegCloseKey(hDeviceIdKey
);
1264 else if (dwRegType
!= REG_SZ
)
1266 RegCloseKey(hDeviceIdKey
);
1267 return ERROR_GEN_FAILURE
;
1271 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1272 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1273 /* Bad GUID, skip the entry */
1277 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1279 /* Skip this entry as it is not the right device class */
1283 /* Add the entry to the list */
1284 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1286 RegCloseKey(hDeviceIdKey
);
1287 return GetLastError();
1289 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1290 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1292 RegCloseKey(hDeviceIdKey
);
1295 return ERROR_SUCCESS
;
1298 static LONG
SETUP_CreateDevList(
1299 struct DeviceInfoSet
*list
,
1300 PCWSTR MachineName OPTIONAL
,
1301 LPGUID
class OPTIONAL
,
1302 PCWSTR Enumerator OPTIONAL
)
1304 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1305 WCHAR KeyBuffer
[MAX_PATH
];
1310 if (class && IsEqualIID(class, &GUID_NULL
))
1314 if (MachineName
!= NULL
)
1316 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1317 if (rc
!= ERROR_SUCCESS
)
1321 HKLM
= HKEY_LOCAL_MACHINE
;
1323 rc
= RegOpenKeyExW(HKLM
,
1326 KEY_ENUMERATE_SUB_KEYS
,
1328 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1329 if (rc
!= ERROR_SUCCESS
)
1332 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1333 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1342 KEY_ENUMERATE_SUB_KEYS
,
1344 RegCloseKey(hEnumKey
);
1345 if (rc
!= ERROR_SUCCESS
)
1347 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1348 RegCloseKey(hEnumeratorKey
);
1353 /* Enumerate enumerators */
1357 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1358 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1359 if (rc
== ERROR_NO_MORE_ITEMS
)
1361 if (rc
!= ERROR_SUCCESS
)
1363 RegCloseKey(hEnumKey
);
1369 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1370 if (rc
!= ERROR_SUCCESS
)
1372 RegCloseKey(hEnumKey
);
1376 /* Call SETUP_CreateDevListFromEnumerator */
1377 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1378 RegCloseKey(hEnumeratorKey
);
1379 if (rc
!= ERROR_SUCCESS
)
1381 RegCloseKey(hEnumKey
);
1385 RegCloseKey(hEnumKey
);
1386 return ERROR_SUCCESS
;
1391 static LONG
SETUP_CreateSerialDeviceList(
1392 struct DeviceInfoSet
*list
,
1394 LPGUID InterfaceGuid
,
1395 PCWSTR DeviceInstanceW
)
1397 static const size_t initialSize
= 100;
1399 WCHAR buf
[initialSize
];
1401 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1403 struct DeviceInfoElement
*deviceInfo
;
1406 WARN("'MachineName' is ignored on Wine!\n");
1407 if (DeviceInstanceW
)
1408 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1414 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1416 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1420 HeapFree(GetProcessHeap(), 0, devices
);
1421 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1423 return ERROR_NOT_ENOUGH_MEMORY
;
1429 HeapFree(GetProcessHeap(), 0, devices
);
1430 return GetLastError();
1434 /* 'devices' is a MULTI_SZ string */
1435 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1437 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1439 /* We have found a device */
1440 struct DeviceInterface
*interfaceInfo
;
1441 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1442 /* Step 1. Create a device info element */
1443 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1446 HeapFree(GetProcessHeap(), 0, devices
);
1447 return GetLastError();
1449 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1451 /* Step 2. Create an interface list for this element */
1452 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1455 HeapFree(GetProcessHeap(), 0, devices
);
1456 return GetLastError();
1458 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1462 HeapFree(GetProcessHeap(), 0, devices
);
1463 return ERROR_SUCCESS
;
1466 #else /* __REACTOS__ */
1468 static LONG
SETUP_CreateInterfaceList(
1469 struct DeviceInfoSet
*list
,
1471 LPGUID InterfaceGuid
,
1472 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1474 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1475 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1476 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1477 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1478 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1480 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1483 DWORD dwLength
, dwInstancePathLength
;
1486 struct DeviceInfoElement
*deviceInfo
;
1488 /* Open registry key related to this interface */
1489 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1490 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1491 return GetLastError();
1493 /* Enumerate sub keys of hInterfaceKey */
1497 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1498 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1499 if (rc
== ERROR_NO_MORE_ITEMS
)
1501 if (rc
!= ERROR_SUCCESS
)
1503 RegCloseKey(hInterfaceKey
);
1509 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1510 if (rc
!= ERROR_SUCCESS
)
1512 RegCloseKey(hInterfaceKey
);
1516 /* Read DeviceInstance */
1517 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1518 if (rc
!= ERROR_SUCCESS
)
1520 RegCloseKey(hDeviceInstanceKey
);
1521 RegCloseKey(hInterfaceKey
);
1524 if (dwRegType
!= REG_SZ
)
1526 RegCloseKey(hDeviceInstanceKey
);
1527 RegCloseKey(hInterfaceKey
);
1528 return ERROR_GEN_FAILURE
;
1530 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1533 RegCloseKey(hDeviceInstanceKey
);
1534 RegCloseKey(hInterfaceKey
);
1535 return ERROR_NOT_ENOUGH_MEMORY
;
1537 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1538 if (rc
!= ERROR_SUCCESS
)
1540 HeapFree(GetProcessHeap(), 0, InstancePath
);
1541 RegCloseKey(hDeviceInstanceKey
);
1542 RegCloseKey(hInterfaceKey
);
1545 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1546 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1548 if (DeviceInstanceW
)
1550 /* Check if device enumerator is not the right one */
1551 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1553 HeapFree(GetProcessHeap(), 0, InstancePath
);
1554 RegCloseKey(hDeviceInstanceKey
);
1559 /* Find class GUID associated to the device instance */
1564 KEY_ENUMERATE_SUB_KEYS
,
1566 if (rc
!= ERROR_SUCCESS
)
1568 HeapFree(GetProcessHeap(), 0, InstancePath
);
1569 RegCloseKey(hDeviceInstanceKey
);
1570 RegCloseKey(hInterfaceKey
);
1579 RegCloseKey(hEnumKey
);
1580 if (rc
!= ERROR_SUCCESS
)
1582 HeapFree(GetProcessHeap(), 0, InstancePath
);
1583 RegCloseKey(hDeviceInstanceKey
);
1584 RegCloseKey(hInterfaceKey
);
1587 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1588 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1590 if (rc
!= ERROR_SUCCESS
)
1592 HeapFree(GetProcessHeap(), 0, InstancePath
);
1593 RegCloseKey(hDeviceInstanceKey
);
1594 RegCloseKey(hInterfaceKey
);
1597 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1598 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1599 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1601 HeapFree(GetProcessHeap(), 0, InstancePath
);
1602 RegCloseKey(hDeviceInstanceKey
);
1603 RegCloseKey(hInterfaceKey
);
1604 return ERROR_GEN_FAILURE
;
1606 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1608 /* If current device doesn't match the list GUID (if any), skip this entry */
1609 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1611 HeapFree(GetProcessHeap(), 0, InstancePath
);
1612 RegCloseKey(hDeviceInstanceKey
);
1616 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1620 LPWSTR pSymbolicLink
;
1621 struct DeviceInterface
*interfaceInfo
;
1623 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1624 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1625 if (rc
== ERROR_NO_MORE_ITEMS
)
1627 if (rc
!= ERROR_SUCCESS
)
1629 HeapFree(GetProcessHeap(), 0, InstancePath
);
1630 RegCloseKey(hDeviceInstanceKey
);
1631 RegCloseKey(hInterfaceKey
);
1635 if (KeyBuffer
[0] != '#')
1636 /* This entry doesn't represent an interesting entry */
1640 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1641 if (rc
!= ERROR_SUCCESS
)
1643 RegCloseKey(hDeviceInstanceKey
);
1644 RegCloseKey(hInterfaceKey
);
1648 /* Read SymbolicLink value */
1649 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1650 if (rc
!= ERROR_SUCCESS
)
1652 RegCloseKey(hReferenceKey
);
1653 RegCloseKey(hDeviceInstanceKey
);
1654 RegCloseKey(hInterfaceKey
);
1657 if (dwRegType
!= REG_SZ
)
1659 RegCloseKey(hReferenceKey
);
1660 RegCloseKey(hDeviceInstanceKey
);
1661 RegCloseKey(hInterfaceKey
);
1662 return ERROR_GEN_FAILURE
;
1665 /* We have found a device */
1666 /* Step 1. Create a device info element */
1667 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1669 RegCloseKey(hReferenceKey
);
1670 RegCloseKey(hDeviceInstanceKey
);
1671 RegCloseKey(hInterfaceKey
);
1672 return GetLastError();
1674 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1675 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1677 /* Step 2. Create an interface list for this element */
1678 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1681 RegCloseKey(hReferenceKey
);
1682 RegCloseKey(hDeviceInstanceKey
);
1683 RegCloseKey(hInterfaceKey
);
1684 return ERROR_NOT_ENOUGH_MEMORY
;
1686 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1687 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1688 RegCloseKey(hReferenceKey
);
1689 if (rc
!= ERROR_SUCCESS
)
1691 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1692 RegCloseKey(hDeviceInstanceKey
);
1693 RegCloseKey(hInterfaceKey
);
1696 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1698 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1699 RegCloseKey(hDeviceInstanceKey
);
1700 RegCloseKey(hInterfaceKey
);
1701 return GetLastError();
1703 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1704 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1705 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1707 RegCloseKey(hDeviceInstanceKey
);
1709 RegCloseKey(hInterfaceKey
);
1710 return ERROR_SUCCESS
;
1712 #endif /* __REACTOS__ */
1714 /***********************************************************************
1715 * SetupDiGetClassDevsExW (SETUPAPI.@)
1717 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1726 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1727 struct DeviceInfoSet
*list
;
1731 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1732 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1734 /* Create the deviceset if not set */
1737 list
= (struct DeviceInfoSet
*)deviceset
;
1738 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1740 SetLastError(ERROR_INVALID_HANDLE
);
1741 return INVALID_HANDLE_VALUE
;
1743 hDeviceInfo
= deviceset
;
1747 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1748 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1749 NULL
, machine
, NULL
);
1750 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1751 return INVALID_HANDLE_VALUE
;
1752 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1755 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1758 pClassGuid
= &list
->ClassGuid
;
1760 if (flags
& DIGCF_PRESENT
)
1761 FIXME(": flag DIGCF_PRESENT ignored\n");
1762 if (flags
& DIGCF_PROFILE
)
1763 FIXME(": flag DIGCF_PROFILE ignored\n");
1765 if (flags
& DIGCF_ALLCLASSES
)
1767 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1768 if (rc
!= ERROR_SUCCESS
)
1772 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1773 return INVALID_HANDLE_VALUE
;
1777 else if (flags
& DIGCF_DEVICEINTERFACE
)
1781 SetLastError(ERROR_INVALID_PARAMETER
);
1783 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1784 return INVALID_HANDLE_VALUE
;
1788 /* Special case: find serial ports by calling QueryDosDevice */
1789 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1790 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1791 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1792 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1795 ERR("Wine can only enumerate serial devices at the moment!\n");
1796 rc
= ERROR_INVALID_PARAMETER
;
1798 #else /* __REACTOS__ */
1799 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1800 #endif /* __REACTOS__ */
1801 if (rc
!= ERROR_SUCCESS
)
1805 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1806 return INVALID_HANDLE_VALUE
;
1812 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1813 if (rc
!= ERROR_SUCCESS
)
1817 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1818 return INVALID_HANDLE_VALUE
;
1824 /***********************************************************************
1825 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1827 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1828 HDEVINFO DeviceInfoSet
,
1829 PSP_DEVINFO_DATA DeviceInfoData
,
1830 CONST GUID
* InterfaceClassGuid
,
1832 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1836 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1837 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1839 if (!DeviceInterfaceData
)
1840 SetLastError(ERROR_INVALID_PARAMETER
);
1841 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1842 SetLastError(ERROR_INVALID_USER_BUFFER
);
1843 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1845 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1847 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1849 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1851 while (ItemList
!= &list
->ListHead
&& !Found
)
1853 PLIST_ENTRY InterfaceListEntry
;
1854 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1855 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1857 /* We are not searching for this element */
1858 ItemList
= ItemList
->Flink
;
1861 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1862 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1864 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1865 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1867 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1870 if (MemberIndex
-- == 0)
1872 /* return this item */
1873 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1874 &DevItf
->InterfaceClassGuid
,
1876 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1877 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1880 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1882 ItemList
= ItemList
->Flink
;
1885 SetLastError(ERROR_NO_MORE_ITEMS
);
1890 SetLastError(ERROR_INVALID_HANDLE
);
1893 SetLastError(ERROR_INVALID_HANDLE
);
1897 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
1899 InterlockedIncrement(&infFile
->References
);
1902 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
1904 if (InterlockedDecrement(&infFile
->References
) == 0)
1906 SetupCloseInfFile(infFile
->hInf
);
1907 HeapFree(GetProcessHeap(), 0, infFile
);
1911 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
1913 DereferenceInfFile(driverInfo
->InfFileDetails
);
1914 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
1915 HeapFree(GetProcessHeap(), 0, driverInfo
);
1919 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
1921 PLIST_ENTRY ListEntry
;
1922 struct DriverInfoElement
*driverInfo
;
1924 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1926 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1927 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
1928 if (!DestroyDriverInfoElement(driverInfo
))
1931 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1933 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1934 HeapFree(GetProcessHeap(), 0, ListEntry
);
1936 HeapFree(GetProcessHeap(), 0, deviceInfo
);
1940 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
1942 PLIST_ENTRY ListEntry
;
1943 struct DeviceInfoElement
*deviceInfo
;
1945 while (!IsListEmpty(&list
->ListHead
))
1947 ListEntry
= RemoveHeadList(&list
->ListHead
);
1948 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1949 if (!DestroyDeviceInfoElement(deviceInfo
))
1952 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1953 RegCloseKey(list
->HKLM
);
1954 CM_Disconnect_Machine(list
->hMachine
);
1955 HeapFree(GetProcessHeap(), 0, list
);
1959 /***********************************************************************
1960 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1962 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1966 TRACE("%p\n", devinfo
);
1967 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1969 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1971 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1972 ret
= DestroyDeviceInfoSet(list
);
1974 SetLastError(ERROR_INVALID_HANDLE
);
1977 SetLastError(ERROR_INVALID_HANDLE
);
1979 TRACE("Returning %d\n", ret
);
1983 /***********************************************************************
1984 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1986 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1987 HDEVINFO DeviceInfoSet
,
1988 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1989 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1990 DWORD DeviceInterfaceDetailDataSize
,
1991 PDWORD RequiredSize
,
1992 PSP_DEVINFO_DATA DeviceInfoData
)
1994 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
1995 DWORD sizeW
= 0, sizeA
;
1998 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
1999 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2000 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2002 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2003 SetLastError(ERROR_INVALID_USER_BUFFER
);
2004 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2005 SetLastError(ERROR_INVALID_PARAMETER
);
2006 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2007 SetLastError(ERROR_INVALID_PARAMETER
);
2010 if (DeviceInterfaceDetailData
!= NULL
)
2012 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2013 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2014 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2015 if (!DeviceInterfaceDetailDataW
)
2017 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2020 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2022 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2023 ret
= SetupDiGetDeviceInterfaceDetailW(
2025 DeviceInterfaceData
,
2026 DeviceInterfaceDetailDataW
,
2030 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2031 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2033 *RequiredSize
= sizeA
;
2034 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2036 if (!WideCharToMultiByte(
2038 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2039 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2046 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2049 TRACE("Returning %d\n", ret
);
2053 /***********************************************************************
2054 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2056 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2057 HDEVINFO DeviceInfoSet
,
2058 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2059 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2060 DWORD DeviceInterfaceDetailDataSize
,
2061 PDWORD RequiredSize
,
2062 PSP_DEVINFO_DATA DeviceInfoData
)
2064 struct DeviceInfoSet
*list
;
2067 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2068 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2069 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2071 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2072 SetLastError(ERROR_INVALID_PARAMETER
);
2073 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2074 SetLastError(ERROR_INVALID_HANDLE
);
2075 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2076 SetLastError(ERROR_INVALID_HANDLE
);
2077 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2078 SetLastError(ERROR_INVALID_USER_BUFFER
);
2079 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2080 SetLastError(ERROR_INVALID_USER_BUFFER
);
2081 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2082 SetLastError(ERROR_INVALID_USER_BUFFER
);
2083 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2084 SetLastError(ERROR_INVALID_PARAMETER
);
2085 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2086 SetLastError(ERROR_INVALID_PARAMETER
);
2089 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2090 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2091 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2092 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2094 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2096 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2098 *RequiredSize
= sizeRequired
;
2102 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2103 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2106 memcpy(&DeviceInfoData
->ClassGuid
,
2107 &deviceInterface
->DeviceInfo
->ClassGuid
,
2109 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
2110 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2116 TRACE("Returning %d\n", ret
);
2120 /***********************************************************************
2121 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2123 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2125 PSP_DEVINFO_DATA DeviceInfoData
,
2127 PDWORD PropertyRegDataType
,
2128 PBYTE PropertyBuffer
,
2129 DWORD PropertyBufferSize
,
2130 PDWORD RequiredSize
)
2133 BOOL bIsStringProperty
;
2135 DWORD RequiredSizeA
, RequiredSizeW
;
2136 DWORD PropertyBufferSizeW
;
2137 PBYTE PropertyBufferW
;
2139 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2140 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2143 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2144 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2146 bResult
= SetupDiGetDeviceRegistryPropertyW(
2152 PropertyBufferSizeW
,
2155 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2157 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2159 if (bIsStringProperty
)
2160 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2162 RequiredSizeA
= RequiredSizeW
;
2164 *RequiredSize
= RequiredSizeA
;
2165 if (PropertyRegDataType
)
2166 *PropertyRegDataType
= RegType
;
2171 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2175 if (RequiredSizeA
<= PropertyBufferSize
)
2177 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2179 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2181 /* Last error is already set by WideCharToMultiByte */
2186 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2190 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2194 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2198 /***********************************************************************
2199 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2201 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2202 HDEVINFO DeviceInfoSet
,
2203 PSP_DEVINFO_DATA DeviceInfoData
,
2205 PDWORD PropertyRegDataType
,
2206 PBYTE PropertyBuffer
,
2207 DWORD PropertyBufferSize
,
2208 PDWORD RequiredSize
)
2210 HKEY hEnumKey
, hKey
;
2214 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2215 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2218 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2219 SetLastError(ERROR_INVALID_HANDLE
);
2220 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2221 SetLastError(ERROR_INVALID_HANDLE
);
2222 else if (!DeviceInfoData
)
2223 SetLastError(ERROR_INVALID_PARAMETER
);
2224 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2225 SetLastError(ERROR_INVALID_USER_BUFFER
);
2226 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2227 SetLastError(ERROR_INVALID_PARAMETER
);
2230 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2231 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2235 case SPDRP_CAPABILITIES
:
2237 case SPDRP_CLASSGUID
:
2238 case SPDRP_COMPATIBLEIDS
:
2239 case SPDRP_CONFIGFLAGS
:
2240 case SPDRP_DEVICEDESC
:
2242 case SPDRP_FRIENDLYNAME
:
2243 case SPDRP_HARDWAREID
:
2244 case SPDRP_LOCATION_INFORMATION
:
2245 case SPDRP_LOWERFILTERS
:
2247 case SPDRP_SECURITY
:
2249 case SPDRP_UI_NUMBER
:
2250 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2251 case SPDRP_UPPERFILTERS
:
2253 LPCWSTR RegistryPropertyName
;
2258 case SPDRP_CAPABILITIES
:
2259 RegistryPropertyName
= L
"Capabilities"; break;
2261 RegistryPropertyName
= L
"Class"; break;
2262 case SPDRP_CLASSGUID
:
2263 RegistryPropertyName
= L
"ClassGUID"; break;
2264 case SPDRP_COMPATIBLEIDS
:
2265 RegistryPropertyName
= L
"CompatibleIDs"; break;
2266 case SPDRP_CONFIGFLAGS
:
2267 RegistryPropertyName
= L
"ConfigFlags"; break;
2268 case SPDRP_DEVICEDESC
:
2269 RegistryPropertyName
= L
"DeviceDesc"; break;
2271 RegistryPropertyName
= L
"Driver"; break;
2272 case SPDRP_FRIENDLYNAME
:
2273 RegistryPropertyName
= L
"FriendlyName"; break;
2274 case SPDRP_HARDWAREID
:
2275 RegistryPropertyName
= L
"HardwareID"; break;
2276 case SPDRP_LOCATION_INFORMATION
:
2277 RegistryPropertyName
= L
"LocationInformation"; break;
2278 case SPDRP_LOWERFILTERS
:
2279 RegistryPropertyName
= L
"LowerFilters"; break;
2281 RegistryPropertyName
= L
"Mfg"; break;
2282 case SPDRP_SECURITY
:
2283 RegistryPropertyName
= L
"Security"; break;
2285 RegistryPropertyName
= L
"Service"; break;
2286 case SPDRP_UI_NUMBER
:
2287 RegistryPropertyName
= L
"UINumber"; break;
2288 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2289 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2290 case SPDRP_UPPERFILTERS
:
2291 RegistryPropertyName
= L
"UpperFilters"; break;
2293 /* Should not happen */
2294 RegistryPropertyName
= NULL
; break;
2297 /* Open registry key name */
2302 KEY_ENUMERATE_SUB_KEYS
,
2304 if (rc
!= ERROR_SUCCESS
)
2315 RegCloseKey(hEnumKey
);
2316 if (rc
!= ERROR_SUCCESS
)
2321 /* Read registry entry */
2322 BufferSize
= PropertyBufferSize
;
2323 rc
= RegQueryValueExW(
2325 RegistryPropertyName
,
2326 NULL
, /* Reserved */
2327 PropertyRegDataType
,
2331 *RequiredSize
= BufferSize
;
2334 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2337 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2339 case ERROR_MORE_DATA
:
2340 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2349 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2351 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2353 if (PropertyRegDataType
)
2354 *PropertyRegDataType
= REG_SZ
;
2356 *RequiredSize
= required
;
2357 if (PropertyBufferSize
>= required
)
2359 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2363 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2367 /*case SPDRP_BUSTYPEGUID:
2368 case SPDRP_LEGACYBUSTYPE:
2369 case SPDRP_BUSNUMBER:
2370 case SPDRP_ENUMERATOR_NAME:
2371 case SPDRP_SECURITY_SDS:
2373 case SPDRP_EXCLUSIVE:
2374 case SPDRP_CHARACTERISTICS:
2376 case SPDRP_DEVICE_POWER_DATA:*/
2377 #if (WINVER >= 0x501)
2378 /*case SPDRP_REMOVAL_POLICY:
2379 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2380 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2381 case SPDRP_INSTALL_STATE:*/
2386 ERR("Property 0x%lx not implemented\n", Property
);
2387 SetLastError(ERROR_NOT_SUPPORTED
);
2392 TRACE("Returning %d\n", ret
);
2396 /***********************************************************************
2397 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2399 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2400 IN HDEVINFO DeviceInfoSet
,
2401 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2403 IN CONST BYTE
*PropertyBuffer
,
2404 IN DWORD PropertyBufferSize
)
2406 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2407 Property
, PropertyBuffer
, PropertyBufferSize
);
2408 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2412 /***********************************************************************
2413 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2415 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2416 IN HDEVINFO DeviceInfoSet
,
2417 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2419 IN
const BYTE
*PropertyBuffer
,
2420 IN DWORD PropertyBufferSize
)
2422 struct DeviceInfoSet
*list
;
2425 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2426 Property
, PropertyBuffer
, PropertyBufferSize
);
2429 SetLastError(ERROR_INVALID_HANDLE
);
2430 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2431 SetLastError(ERROR_INVALID_HANDLE
);
2432 else if (DeviceInfoData
)
2433 SetLastError(ERROR_INVALID_HANDLE
);
2434 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2435 SetLastError(ERROR_INVALID_USER_BUFFER
);
2440 case SPDRP_COMPATIBLEIDS
:
2441 case SPDRP_CONFIGFLAGS
:
2442 case SPDRP_FRIENDLYNAME
:
2443 case SPDRP_HARDWAREID
:
2444 case SPDRP_LOCATION_INFORMATION
:
2445 case SPDRP_LOWERFILTERS
:
2446 case SPDRP_SECURITY
:
2448 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2449 case SPDRP_UPPERFILTERS
:
2451 LPCWSTR RegistryPropertyName
;
2452 DWORD RegistryDataType
;
2458 case SPDRP_COMPATIBLEIDS
:
2459 RegistryPropertyName
= L
"CompatibleIDs";
2460 RegistryDataType
= REG_MULTI_SZ
;
2462 case SPDRP_CONFIGFLAGS
:
2463 RegistryPropertyName
= L
"ConfigFlags";
2464 RegistryDataType
= REG_DWORD
;
2466 case SPDRP_FRIENDLYNAME
:
2467 RegistryPropertyName
= L
"FriendlyName";
2468 RegistryDataType
= REG_SZ
;
2470 case SPDRP_HARDWAREID
:
2471 RegistryPropertyName
= L
"HardwareID";
2472 RegistryDataType
= REG_MULTI_SZ
;
2474 case SPDRP_LOCATION_INFORMATION
:
2475 RegistryPropertyName
= L
"LocationInformation";
2476 RegistryDataType
= REG_SZ
;
2478 case SPDRP_LOWERFILTERS
:
2479 RegistryPropertyName
= L
"LowerFilters";
2480 RegistryDataType
= REG_MULTI_SZ
;
2482 case SPDRP_SECURITY
:
2483 RegistryPropertyName
= L
"Security";
2484 RegistryDataType
= REG_BINARY
;
2487 RegistryPropertyName
= L
"Service";
2488 RegistryDataType
= REG_SZ
;
2490 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2491 RegistryPropertyName
= L
"UINumberDescFormat";
2492 RegistryDataType
= REG_SZ
;
2494 case SPDRP_UPPERFILTERS
:
2495 RegistryPropertyName
= L
"UpperFilters";
2496 RegistryDataType
= REG_MULTI_SZ
;
2499 /* Should not happen */
2500 RegistryPropertyName
= NULL
;
2501 RegistryDataType
= REG_BINARY
;
2504 /* Open device registry key */
2505 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2506 if (hKey
!= INVALID_HANDLE_VALUE
)
2508 /* Write new data */
2509 rc
= RegSetValueExW(
2511 RegistryPropertyName
,
2515 PropertyBufferSize
);
2516 if (rc
== ERROR_SUCCESS
)
2525 /*case SPDRP_CHARACTERISTICS:
2527 case SPDRP_EXCLUSIVE:*/
2528 #if (WINVER >= 0x501)
2529 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2531 //case SPDRP_SECURITY_SDS:
2535 ERR("Property 0x%lx not implemented\n", Property
);
2536 SetLastError(ERROR_NOT_SUPPORTED
);
2541 TRACE("Returning %d\n", ret
);
2545 /***********************************************************************
2546 * SetupDiInstallClassA (SETUPAPI.@)
2548 BOOL WINAPI
SetupDiInstallClassA(
2554 UNICODE_STRING FileNameW
;
2557 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2559 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2563 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2565 RtlFreeUnicodeString(&FileNameW
);
2570 static HKEY
CreateClassKey(HINF hInf
)
2572 WCHAR FullBuffer
[MAX_PATH
];
2573 WCHAR Buffer
[MAX_PATH
];
2578 if (!SetupGetLineTextW(NULL
,
2586 return INVALID_HANDLE_VALUE
;
2589 lstrcpyW(FullBuffer
, ControlClass
);
2590 lstrcatW(FullBuffer
, Buffer
);
2593 if (!SetupGetLineTextW(NULL
,
2601 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2602 return INVALID_HANDLE_VALUE
;
2605 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2609 REG_OPTION_NON_VOLATILE
,
2615 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2616 return INVALID_HANDLE_VALUE
;
2619 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2624 RequiredSize
* sizeof(WCHAR
)))
2626 RegCloseKey(hClassKey
);
2627 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2628 return INVALID_HANDLE_VALUE
;
2634 /***********************************************************************
2635 * SetupDiInstallClassW (SETUPAPI.@)
2637 BOOL WINAPI
SetupDiInstallClassW(
2643 WCHAR SectionName
[MAX_PATH
];
2644 DWORD SectionNameLength
= 0;
2646 BOOL bFileQueueCreated
= FALSE
;
2649 TRACE("%p %s 0x%lx %p\n", hwndParent
, debugstr_w(InfFileName
),
2652 FIXME("not fully implemented\n");
2654 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2656 SetLastError(ERROR_INVALID_PARAMETER
);
2660 /* Open the .inf file */
2661 hInf
= SetupOpenInfFileW(InfFileName
,
2665 if (hInf
== INVALID_HANDLE_VALUE
)
2671 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2672 hClassKey
= CreateClassKey(hInf
);
2673 if (hClassKey
== INVALID_HANDLE_VALUE
)
2675 SetupCloseInfFile(hInf
);
2681 /* Try to append a layout file */
2683 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2686 /* Retrieve the actual section name */
2687 SetupDiGetActualSectionToInstallW(hInf
,
2695 if (!(Flags
& DI_NOVCP
))
2697 FileQueue
= SetupOpenFileQueue();
2698 if (FileQueue
== INVALID_HANDLE_VALUE
)
2700 SetupCloseInfFile(hInf
);
2701 RegCloseKey(hClassKey
);
2705 bFileQueueCreated
= TRUE
;
2710 SetupInstallFromInfSectionW(NULL
,
2719 INVALID_HANDLE_VALUE
,
2722 /* FIXME: More code! */
2724 if (bFileQueueCreated
)
2725 SetupCloseFileQueue(FileQueue
);
2727 SetupCloseInfFile(hInf
);
2729 RegCloseKey(hClassKey
);
2734 /***********************************************************************
2735 * SetupDiOpenClassRegKey (SETUPAPI.@)
2737 HKEY WINAPI
SetupDiOpenClassRegKey(
2738 const GUID
* ClassGuid
,
2741 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2742 DIOCR_INSTALLER
, NULL
, NULL
);
2746 /***********************************************************************
2747 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2749 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2750 const GUID
* ClassGuid
,
2756 PWSTR MachineNameW
= NULL
;
2763 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2764 if (MachineNameW
== NULL
)
2765 return INVALID_HANDLE_VALUE
;
2768 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2769 Flags
, MachineNameW
, Reserved
);
2772 MyFree(MachineNameW
);
2778 /***********************************************************************
2779 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2781 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2782 const GUID
* ClassGuid
,
2788 LPWSTR lpGuidString
;
2789 LPWSTR lpFullGuidString
;
2797 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
2798 Flags
, debugstr_w(MachineName
), Reserved
);
2800 if (Flags
== DIOCR_INSTALLER
)
2802 lpKeyName
= ControlClass
;
2804 else if (Flags
== DIOCR_INTERFACE
)
2806 lpKeyName
= DeviceClasses
;
2810 ERR("Invalid Flags parameter!\n");
2811 SetLastError(ERROR_INVALID_FLAGS
);
2812 return INVALID_HANDLE_VALUE
;
2815 if (MachineName
!= NULL
)
2817 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2818 if (rc
!= ERROR_SUCCESS
)
2821 return INVALID_HANDLE_VALUE
;
2825 HKLM
= HKEY_LOCAL_MACHINE
;
2827 rc
= RegOpenKeyExW(HKLM
,
2830 ClassGuid
? KEY_ENUMERATE_SUB_KEYS
: samDesired
,
2832 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2833 if (rc
!= ERROR_SUCCESS
)
2836 return INVALID_HANDLE_VALUE
;
2839 if (ClassGuid
== NULL
)
2842 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2844 SetLastError(ERROR_GEN_FAILURE
);
2845 RegCloseKey(hClassesKey
);
2846 return INVALID_HANDLE_VALUE
;
2849 dwLength
= lstrlenW(lpGuidString
);
2850 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2851 if (!lpFullGuidString
)
2853 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2854 RpcStringFreeW(&lpGuidString
);
2855 return INVALID_HANDLE_VALUE
;
2857 lpFullGuidString
[0] = '{';
2858 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2859 lpFullGuidString
[dwLength
+ 1] = '}';
2860 lpFullGuidString
[dwLength
+ 2] = '\0';
2861 RpcStringFreeW(&lpGuidString
);
2863 rc
= RegOpenKeyExW(hClassesKey
,
2868 if (rc
!= ERROR_SUCCESS
)
2871 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2872 RegCloseKey(hClassesKey
);
2873 return INVALID_HANDLE_VALUE
;
2876 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2877 RegCloseKey(hClassesKey
);
2882 /***********************************************************************
2883 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2885 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2886 HDEVINFO DeviceInfoSet
,
2889 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2891 FIXME("%p %s %08lx %p\n",
2892 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2896 /***********************************************************************
2897 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2899 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2900 HDEVINFO DeviceInfoSet
,
2903 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2905 LPWSTR DevicePathW
= NULL
;
2908 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2910 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2911 if (DevicePathW
== NULL
)
2914 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2915 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2917 MyFree(DevicePathW
);
2922 /***********************************************************************
2923 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2925 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2926 HDEVINFO DeviceInfoSet
,
2927 PSP_DEVINFO_DATA DeviceInfoData
,
2928 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2929 DWORD ClassInstallParamsSize
)
2931 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2932 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2938 IN PWSTR InstallerName
,
2939 OUT HMODULE
* ModulePointer
,
2940 OUT PVOID
* FunctionPointer
)
2942 HMODULE hModule
= NULL
;
2943 LPSTR FunctionNameA
= NULL
;
2947 *ModulePointer
= NULL
;
2948 *FunctionPointer
= NULL
;
2950 Comma
= strchrW(InstallerName
, ',');
2953 rc
= ERROR_INVALID_PARAMETER
;
2959 hModule
= LoadLibraryW(InstallerName
);
2963 rc
= GetLastError();
2967 /* Skip comma spaces */
2968 while (*Comma
== ',' || isspaceW(*Comma
))
2971 /* W->A conversion for function name */
2972 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
2975 rc
= GetLastError();
2979 /* Search function */
2980 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
2981 if (!*FunctionPointer
)
2983 rc
= GetLastError();
2987 *ModulePointer
= hModule
;
2991 if (rc
!= ERROR_SUCCESS
&& hModule
)
2992 FreeLibrary(hModule
);
2993 MyFree(FunctionNameA
);
2998 FreeFunctionPointer(
2999 IN HMODULE ModulePointer
,
3000 IN PVOID FunctionPointer
)
3002 if (ModulePointer
== NULL
)
3003 return ERROR_SUCCESS
;
3004 if (FreeLibrary(ModulePointer
))
3005 return ERROR_SUCCESS
;
3007 return GetLastError();
3010 /***********************************************************************
3011 * SetupDiCallClassInstaller (SETUPAPI.@)
3013 BOOL WINAPI
SetupDiCallClassInstaller(
3014 IN DI_FUNCTION InstallFunction
,
3015 IN HDEVINFO DeviceInfoSet
,
3016 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3020 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3023 SetLastError(ERROR_INVALID_PARAMETER
);
3024 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3025 SetLastError(ERROR_INVALID_HANDLE
);
3026 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3027 SetLastError(ERROR_INVALID_HANDLE
);
3028 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3029 SetLastError(ERROR_INVALID_HANDLE
);
3030 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3031 SetLastError(ERROR_INVALID_USER_BUFFER
);
3034 SP_DEVINSTALL_PARAMS_W InstallParams
;
3035 #define CLASS_COINSTALLER 0x1
3036 #define DEVICE_COINSTALLER 0x2
3037 #define CLASS_INSTALLER 0x4
3038 UCHAR CanHandle
= 0;
3039 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3041 switch (InstallFunction
)
3043 case DIF_ALLOW_INSTALL
:
3044 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3046 case DIF_DESTROYPRIVATEDATA
:
3047 CanHandle
= CLASS_INSTALLER
;
3049 case DIF_INSTALLDEVICE
:
3050 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3051 DefaultHandler
= SetupDiInstallDevice
;
3053 case DIF_INSTALLDEVICEFILES
:
3054 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3055 DefaultHandler
= SetupDiInstallDriverFiles
;
3057 case DIF_INSTALLINTERFACES
:
3058 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3059 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3061 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3062 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3064 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3065 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3067 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3068 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3070 case DIF_REGISTER_COINSTALLERS
:
3071 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3072 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3074 case DIF_SELECTBESTCOMPATDRV
:
3075 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3076 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3079 ERR("Install function %u not supported\n", InstallFunction
);
3080 SetLastError(ERROR_NOT_SUPPORTED
);
3083 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3084 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3085 /* Don't process this call, as a parameter is invalid */
3090 LIST_ENTRY ClassCoInstallersListHead
;
3091 LIST_ENTRY DeviceCoInstallersListHead
;
3092 HMODULE ClassInstallerLibrary
= NULL
;
3093 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3094 COINSTALLER_CONTEXT_DATA Context
;
3095 PLIST_ENTRY ListEntry
;
3097 DWORD dwRegType
, dwLength
;
3098 DWORD rc
= NO_ERROR
;
3100 InitializeListHead(&ClassCoInstallersListHead
);
3101 InitializeListHead(&DeviceCoInstallersListHead
);
3103 if (CanHandle
& DEVICE_COINSTALLER
)
3105 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3106 if (hKey
!= INVALID_HANDLE_VALUE
)
3108 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3109 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3111 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3112 if (KeyBuffer
!= NULL
)
3114 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3115 if (rc
== ERROR_SUCCESS
)
3118 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3120 /* Add coinstaller to DeviceCoInstallersListHead list */
3121 struct CoInstallerElement
*coinstaller
;
3122 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3123 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3126 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3127 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3128 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3130 HeapFree(GetProcessHeap(), 0, coinstaller
);
3133 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3139 if (CanHandle
& CLASS_COINSTALLER
)
3143 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3147 if (rc
== ERROR_SUCCESS
)
3149 LPWSTR lpGuidString
;
3150 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3152 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3153 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3155 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3156 if (KeyBuffer
!= NULL
)
3158 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3159 if (rc
== ERROR_SUCCESS
)
3162 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3164 /* Add coinstaller to ClassCoInstallersListHead list */
3165 struct CoInstallerElement
*coinstaller
;
3166 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3167 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3170 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3171 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3172 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3174 HeapFree(GetProcessHeap(), 0, coinstaller
);
3177 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3180 RpcStringFreeW(&lpGuidString
);
3185 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3187 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3188 if (hKey
!= INVALID_HANDLE_VALUE
)
3190 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3191 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3193 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3194 if (KeyBuffer
!= NULL
)
3196 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3197 if (rc
== ERROR_SUCCESS
)
3199 /* Get ClassInstaller function pointer */
3200 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3201 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3203 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3204 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3207 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3214 /* Call Class co-installers */
3215 Context
.PostProcessing
= FALSE
;
3217 ListEntry
= ClassCoInstallersListHead
.Flink
;
3218 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3220 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3221 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3222 coinstaller
->PrivateData
= Context
.PrivateData
;
3223 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3225 coinstaller
->DoPostProcessing
= TRUE
;
3228 ListEntry
= ListEntry
->Flink
;
3231 /* Call Device co-installers */
3232 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3233 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3235 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3236 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3237 coinstaller
->PrivateData
= Context
.PrivateData
;
3238 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3240 coinstaller
->DoPostProcessing
= TRUE
;
3243 ListEntry
= ListEntry
->Flink
;
3246 /* Call Class installer */
3249 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3250 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3253 rc
= ERROR_DI_DO_DEFAULT
;
3255 /* Call default handler */
3256 if (rc
== ERROR_DI_DO_DEFAULT
)
3258 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3260 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3263 rc
= GetLastError();
3269 /* Call Class co-installers that required postprocessing */
3270 Context
.PostProcessing
= TRUE
;
3271 ListEntry
= ClassCoInstallersListHead
.Flink
;
3272 while (ListEntry
!= &ClassCoInstallersListHead
)
3274 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3275 if (coinstaller
->DoPostProcessing
)
3277 Context
.InstallResult
= rc
;
3278 Context
.PrivateData
= coinstaller
->PrivateData
;
3279 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3281 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3282 ListEntry
= ListEntry
->Flink
;
3285 /* Call Device co-installers that required postprocessing */
3286 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3287 while (ListEntry
!= &DeviceCoInstallersListHead
)
3289 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3290 if (coinstaller
->DoPostProcessing
)
3292 Context
.InstallResult
= rc
;
3293 Context
.PrivateData
= coinstaller
->PrivateData
;
3294 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3296 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3297 ListEntry
= ListEntry
->Flink
;
3300 /* Free allocated memory */
3301 while (!IsListEmpty(&ClassCoInstallersListHead
))
3303 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3304 HeapFree(GetProcessHeap(), 0, ListEntry
);
3306 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3308 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3309 HeapFree(GetProcessHeap(), 0, ListEntry
);
3312 ret
= (rc
== NO_ERROR
);
3316 TRACE("Returning %d\n", ret
);
3320 /***********************************************************************
3321 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3323 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
3324 IN HDEVINFO DeviceInfoSet
,
3325 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
3327 struct DeviceInfoSet
*list
;
3330 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
3333 SetLastError(ERROR_INVALID_HANDLE
);
3334 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3335 SetLastError(ERROR_INVALID_HANDLE
);
3336 else if (!DeviceInfoListDetailData
)
3337 SetLastError(ERROR_INVALID_PARAMETER
);
3338 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
3339 SetLastError(ERROR_INVALID_USER_BUFFER
);
3343 &DeviceInfoListDetailData
->ClassGuid
,
3346 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
3347 if (list
->MachineName
)
3348 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
3350 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
3355 TRACE("Returning %d\n", ret
);
3359 /***********************************************************************
3360 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3362 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3363 IN HDEVINFO DeviceInfoSet
,
3364 IN PSP_DEVINFO_DATA DeviceInfoData
,
3365 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3367 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3370 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3372 if (DeviceInstallParams
== NULL
)
3373 SetLastError(ERROR_INVALID_PARAMETER
);
3374 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3375 SetLastError(ERROR_INVALID_USER_BUFFER
);
3378 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3379 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3383 /* Do W->A conversion */
3385 DeviceInstallParams
,
3386 &deviceInstallParamsW
,
3387 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3388 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3389 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3391 DeviceInstallParams
->DriverPath
[0] = '\0';
3397 TRACE("Returning %d\n", ret
);
3401 /***********************************************************************
3402 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3404 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3405 IN HDEVINFO DeviceInfoSet
,
3406 IN PSP_DEVINFO_DATA DeviceInfoData
,
3407 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3409 struct DeviceInfoSet
*list
;
3412 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3415 SetLastError(ERROR_INVALID_HANDLE
);
3416 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3417 SetLastError(ERROR_INVALID_HANDLE
);
3418 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3419 SetLastError(ERROR_INVALID_USER_BUFFER
);
3420 else if (!DeviceInstallParams
)
3421 SetLastError(ERROR_INVALID_PARAMETER
);
3422 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3423 SetLastError(ERROR_INVALID_USER_BUFFER
);
3426 PSP_DEVINSTALL_PARAMS_W Source
;
3429 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3431 Source
= &list
->InstallParams
;
3432 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3436 TRACE("Returning %d\n", ret
);
3440 /***********************************************************************
3441 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3443 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3444 IN HDEVINFO DeviceInfoSet
,
3445 IN PSP_DEVINFO_DATA DeviceInfoData
,
3446 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3448 struct DeviceInfoSet
*list
;
3451 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3454 SetLastError(ERROR_INVALID_HANDLE
);
3455 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3456 SetLastError(ERROR_INVALID_HANDLE
);
3457 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3458 SetLastError(ERROR_INVALID_USER_BUFFER
);
3459 else if (!DeviceInstallParams
)
3460 SetLastError(ERROR_INVALID_PARAMETER
);
3461 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3462 SetLastError(ERROR_INVALID_USER_BUFFER
);
3465 PSP_DEVINSTALL_PARAMS_W Destination
;
3467 /* FIXME: Validate parameters */
3470 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3472 Destination
= &list
->InstallParams
;
3473 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3477 TRACE("Returning %d\n", ret
);
3481 /***********************************************************************
3482 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
3484 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
3485 IN HDEVINFO DeviceInfoSet
,
3486 IN PSP_DEVINFO_DATA DeviceInfoData
,
3487 OUT PSTR DeviceInstanceId OPTIONAL
,
3488 IN DWORD DeviceInstanceIdSize
,
3489 OUT PDWORD RequiredSize OPTIONAL
)
3491 PWSTR DeviceInstanceIdW
= NULL
;
3494 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
3495 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
3497 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
3498 SetLastError(ERROR_INVALID_PARAMETER
);
3501 if (DeviceInstanceIdSize
!= 0)
3503 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
3504 if (DeviceInstanceIdW
== NULL
)
3508 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
3509 DeviceInstanceIdW
, DeviceInstanceIdSize
,
3512 if (ret
&& DeviceInstanceIdW
!= NULL
)
3514 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
3515 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
3517 DeviceInstanceId
[0] = '\0';
3523 TRACE("Returning %d\n", ret
);
3527 /***********************************************************************
3528 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
3530 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
3531 IN HDEVINFO DeviceInfoSet
,
3532 IN PSP_DEVINFO_DATA DeviceInfoData
,
3533 OUT PWSTR DeviceInstanceId OPTIONAL
,
3534 IN DWORD DeviceInstanceIdSize
,
3535 OUT PDWORD RequiredSize OPTIONAL
)
3539 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
3540 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
3543 SetLastError(ERROR_INVALID_HANDLE
);
3544 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3545 SetLastError(ERROR_INVALID_HANDLE
);
3546 else if (!DeviceInfoData
)
3547 SetLastError(ERROR_INVALID_PARAMETER
);
3548 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3549 SetLastError(ERROR_INVALID_USER_BUFFER
);
3550 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
3551 SetLastError(ERROR_INVALID_PARAMETER
);
3552 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
3553 SetLastError(ERROR_INVALID_PARAMETER
);
3556 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3559 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
3561 *RequiredSize
= required
;
3563 if (required
<= DeviceInstanceIdSize
)
3565 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
3569 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3572 TRACE("Returning %d\n", ret
);
3576 /***********************************************************************
3577 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
3579 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
3580 IN HDEVINFO DeviceInfoSet
,
3581 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3582 IN LPPROPSHEETHEADERA PropertySheetHeader
,
3583 IN DWORD PropertySheetHeaderPageListSize
,
3584 OUT PDWORD RequiredSize OPTIONAL
,
3585 IN DWORD PropertySheetType
)
3587 FIXME ("Stub %p %p %p %d %p %d\n",
3588 DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
, PropertySheetHeaderPageListSize
,
3589 RequiredSize
, PropertySheetType
);
3590 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3594 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
3595 IN HPROPSHEETPAGE hPropSheetPage
,
3598 FIXME("Need to add a property page!\n");
3602 /***********************************************************************
3603 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
3605 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
3606 IN HDEVINFO DeviceInfoSet
,
3607 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3608 IN LPPROPSHEETHEADERW PropertySheetHeader
,
3609 IN DWORD PropertySheetHeaderPageListSize
,
3610 OUT PDWORD RequiredSize OPTIONAL
,
3611 IN DWORD PropertySheetType
)
3613 struct DeviceInfoSet
*list
;
3616 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3617 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
3618 RequiredSize
, PropertySheetType
);
3621 SetLastError(ERROR_INVALID_HANDLE
);
3622 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3623 SetLastError(ERROR_INVALID_HANDLE
);
3624 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3625 SetLastError(ERROR_INVALID_HANDLE
);
3626 else if (!PropertySheetHeader
)
3627 SetLastError(ERROR_INVALID_PARAMETER
);
3628 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3629 SetLastError(ERROR_INVALID_USER_BUFFER
);
3630 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
3631 SetLastError(ERROR_INVALID_PARAMETER
);
3632 else if (!PropertySheetHeader
)
3633 SetLastError(ERROR_INVALID_PARAMETER
);
3634 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
3635 && PropertySheetType
!= DIGCDP_FLAG_BASIC
3636 /* FIXME: && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
3637 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC*/)
3638 SetLastError(ERROR_INVALID_PARAMETER
);
3641 HKEY hKey
= INVALID_HANDLE_VALUE
;
3642 SP_PROPSHEETPAGE_REQUEST Request
;
3643 LPWSTR PropPageProvider
= NULL
;
3644 HMODULE hModule
= NULL
;
3645 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
3646 DWORD dwLength
, dwRegType
;
3650 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3653 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
3654 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
3656 if (hKey
== INVALID_HANDLE_VALUE
)
3659 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
);
3660 if (rc
== ERROR_FILE_NOT_FOUND
)
3662 /* No registry key. As it is optional, don't say it's a bad error */
3668 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
3674 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
3675 if (!PropPageProvider
)
3677 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3680 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
3681 if (rc
!= ERROR_SUCCESS
)
3686 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
3688 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
3689 if (rc
!= ERROR_SUCCESS
)
3695 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
3696 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
3697 Request
.DeviceInfoSet
= DeviceInfoSet
;
3698 Request
.DeviceInfoData
= DeviceInfoData
;
3700 *RequiredSize
= 0; /* FIXME */
3701 pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)0);
3705 if (hKey
!= INVALID_HANDLE_VALUE
)
3707 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
3708 FreeFunctionPointer(hModule
, pPropPageProvider
);
3711 TRACE("Returning %d\n", ret
);
3715 /***********************************************************************
3716 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3718 HKEY WINAPI
SetupDiCreateDevRegKeyA(
3719 IN HDEVINFO DeviceInfoSet
,
3720 IN PSP_DEVINFO_DATA DeviceInfoData
,
3724 IN HINF InfHandle OPTIONAL
,
3725 IN PCSTR InfSectionName OPTIONAL
)
3727 PCWSTR InfSectionNameW
= NULL
;
3728 HKEY ret
= INVALID_HANDLE_VALUE
;
3732 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
3733 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
3736 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
3744 if (InfSectionNameW
!= NULL
)
3745 MyFree((PVOID
)InfSectionNameW
);
3750 /***********************************************************************
3751 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3753 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3754 IN HDEVINFO DeviceInfoSet
,
3755 IN PSP_DEVINFO_DATA DeviceInfoData
,
3759 IN HINF InfHandle OPTIONAL
,
3760 IN PCWSTR InfSectionName OPTIONAL
)
3762 struct DeviceInfoSet
*list
;
3763 HKEY ret
= INVALID_HANDLE_VALUE
;
3765 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3766 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3769 SetLastError(ERROR_INVALID_HANDLE
);
3770 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3771 SetLastError(ERROR_INVALID_HANDLE
);
3772 else if (!DeviceInfoData
)
3773 SetLastError(ERROR_INVALID_PARAMETER
);
3774 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3775 SetLastError(ERROR_INVALID_USER_BUFFER
);
3776 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3777 SetLastError(ERROR_INVALID_PARAMETER
);
3778 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3779 SetLastError(ERROR_INVALID_PARAMETER
);
3780 else if (InfHandle
&& !InfSectionName
)
3781 SetLastError(ERROR_INVALID_PARAMETER
);
3782 else if (!InfHandle
&& InfSectionName
)
3783 SetLastError(ERROR_INVALID_PARAMETER
);
3786 LPWSTR lpGuidString
= NULL
;
3787 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3788 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3789 DWORD Index
; /* Index used in the DriverKey name */
3791 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3792 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3793 HKEY hKey
= INVALID_HANDLE_VALUE
;
3795 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3797 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3801 if (KeyType
== DIREG_DEV
)
3803 FIXME("DIREG_DEV case unimplemented\n");
3805 else /* KeyType == DIREG_DRV */
3807 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3809 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3810 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3813 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3816 wcscpy(DriverKey
, L
"{");
3817 wcscat(DriverKey
, lpGuidString
);
3818 wcscat(DriverKey
, L
"}\\");
3819 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3820 rc
= RegOpenKeyExW(list
->HKLM
,
3825 if (rc
!= ERROR_SUCCESS
)
3831 /* Try all values for Index between 0 and 9999 */
3833 while (Index
<= 9999)
3836 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3837 rc
= RegCreateKeyEx(hClassKey
,
3841 REG_OPTION_NON_VOLATILE
,
3842 #if _WIN32_WINNT >= 0x502
3843 KEY_READ
| KEY_WRITE
,
3850 if (rc
!= ERROR_SUCCESS
)
3855 if (Disposition
== REG_CREATED_NEW_KEY
)
3858 hKey
= INVALID_HANDLE_VALUE
;
3863 /* Unable to create more than 9999 devices within the same class */
3864 SetLastError(ERROR_GEN_FAILURE
);
3868 /* Open device key, to write Driver value */
3869 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3870 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3872 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3873 if (rc
!= ERROR_SUCCESS
)
3880 /* Do installation of the specified section */
3883 FIXME("Need to install section %s in file %p\n",
3884 debugstr_w(InfSectionName
), InfHandle
);
3890 RpcStringFreeW(&lpGuidString
);
3891 HeapFree(GetProcessHeap(), 0, DriverKey
);
3892 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3893 RegCloseKey(hClassKey
);
3894 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3895 RegCloseKey(hDeviceKey
);
3896 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3900 TRACE("Returning 0x%p\n", ret
);
3904 /***********************************************************************
3905 * SetupDiOpenDevRegKey (SETUPAPI.@)
3907 HKEY WINAPI
SetupDiOpenDevRegKey(
3908 HDEVINFO DeviceInfoSet
,
3909 PSP_DEVINFO_DATA DeviceInfoData
,
3915 struct DeviceInfoSet
*list
;
3916 HKEY ret
= INVALID_HANDLE_VALUE
;
3918 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3919 Scope
, HwProfile
, KeyType
, samDesired
);
3922 SetLastError(ERROR_INVALID_HANDLE
);
3923 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3924 SetLastError(ERROR_INVALID_HANDLE
);
3925 else if (!DeviceInfoData
)
3926 SetLastError(ERROR_INVALID_PARAMETER
);
3927 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3928 SetLastError(ERROR_INVALID_USER_BUFFER
);
3929 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3930 SetLastError(ERROR_INVALID_PARAMETER
);
3931 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3932 SetLastError(ERROR_INVALID_PARAMETER
);
3935 HKEY hKey
= INVALID_HANDLE_VALUE
;
3936 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3937 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3938 LPWSTR DriverKey
= NULL
;
3943 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3945 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3947 else /* Scope == DICS_FLAG_GLOBAL */
3953 KEY_ENUMERATE_SUB_KEYS
,
3955 if (rc
!= ERROR_SUCCESS
)
3962 deviceInfo
->DeviceName
,
3964 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3966 RegCloseKey(hRootKey
);
3967 hRootKey
= INVALID_HANDLE_VALUE
;
3968 if (rc
!= ERROR_SUCCESS
)
3973 if (KeyType
== DIREG_DEV
)
3975 /* We're done. Just return the hKey handle */
3979 /* Read the 'Driver' key */
3980 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3981 if (rc
!= ERROR_SUCCESS
)
3986 if (dwRegType
!= REG_SZ
)
3988 SetLastError(ERROR_GEN_FAILURE
);
3991 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3994 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3997 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3998 if (rc
!= ERROR_SUCCESS
)
4004 hKey
= INVALID_HANDLE_VALUE
;
4005 /* Need to open the driver key */
4010 KEY_ENUMERATE_SUB_KEYS
,
4012 if (rc
!= ERROR_SUCCESS
)
4023 if (rc
!= ERROR_SUCCESS
)
4031 if (hRootKey
!= INVALID_HANDLE_VALUE
)
4032 RegCloseKey(hRootKey
);
4033 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4037 TRACE("Returning 0x%p\n", ret
);
4041 /***********************************************************************
4042 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4044 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4045 HDEVINFO DeviceInfoSet
,
4047 CONST GUID
*ClassGuid
,
4048 PCSTR DeviceDescription
,
4050 DWORD CreationFlags
,
4051 PSP_DEVINFO_DATA DeviceInfoData
)
4053 LPWSTR DeviceNameW
= NULL
;
4054 LPWSTR DeviceDescriptionW
= NULL
;
4061 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4062 if (DeviceNameW
== NULL
) return FALSE
;
4064 if (DeviceDescription
)
4066 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4067 if (DeviceDescriptionW
== NULL
)
4069 if (DeviceNameW
) MyFree(DeviceNameW
);
4074 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4075 ClassGuid
, DeviceDescriptionW
,
4076 hwndParent
, CreationFlags
,
4079 if (DeviceNameW
) MyFree(DeviceNameW
);
4080 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4085 /***********************************************************************
4086 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4088 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4089 HDEVINFO DeviceInfoSet
,
4091 CONST GUID
*ClassGuid
,
4092 PCWSTR DeviceDescription
,
4094 DWORD CreationFlags
,
4095 PSP_DEVINFO_DATA DeviceInfoData
)
4097 struct DeviceInfoSet
*list
;
4100 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4101 debugstr_guid(ClassGuid
), DeviceDescription
,
4102 hwndParent
, CreationFlags
, DeviceInfoData
);
4105 SetLastError(ERROR_INVALID_HANDLE
);
4106 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4107 SetLastError(ERROR_INVALID_HANDLE
);
4108 else if (!ClassGuid
)
4109 SetLastError(ERROR_INVALID_PARAMETER
);
4110 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4111 SetLastError(ERROR_CLASS_MISMATCH
);
4112 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4114 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4115 SetLastError(ERROR_INVALID_FLAGS
);
4119 SP_DEVINFO_DATA DevInfo
;
4121 if (CreationFlags
& DICD_GENERATE_ID
)
4123 /* Generate a new unique ID for this device */
4124 SetLastError(ERROR_GEN_FAILURE
);
4125 FIXME("not implemented\n");
4129 /* Device name is fully qualified. Try to open it */
4132 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4133 rc
= SetupDiOpenDeviceInfoW(
4136 NULL
, /* hwndParent */
4137 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
4142 /* SetupDiOpenDeviceInfoW has already added
4143 * the device info to the device info set
4145 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
4147 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
4149 struct DeviceInfoElement
*deviceInfo
;
4151 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
4153 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4155 if (!DeviceInfoData
)
4159 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
4161 SetLastError(ERROR_INVALID_USER_BUFFER
);
4165 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4166 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
4167 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4176 TRACE("Returning %d\n", ret
);
4180 /***********************************************************************
4181 * Helper functions for SetupDiBuildDriverInfoList
4185 IN PLIST_ENTRY DriverListHead
,
4186 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4187 IN LPGUID ClassGuid
,
4188 IN INFCONTEXT ContextDevice
,
4189 IN
struct InfFileDetails
*InfFileDetails
,
4191 IN LPCWSTR ProviderName
,
4192 IN LPCWSTR ManufacturerName
,
4193 IN LPCWSTR MatchingId
,
4194 FILETIME DriverDate
,
4195 DWORDLONG DriverVersion
,
4198 struct DriverInfoElement
*driverInfo
= NULL
;
4199 HANDLE hFile
= INVALID_HANDLE_VALUE
;
4200 DWORD RequiredSize
= 128; /* Initial buffer size */
4201 BOOL Result
= FALSE
;
4202 PLIST_ENTRY PreviousEntry
;
4203 LPWSTR InfInstallSection
= NULL
;
4206 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
4209 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4212 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
4214 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
4215 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
4217 /* Copy InfFileName field */
4218 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
4219 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
4221 /* Fill InfDate field */
4222 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4223 GENERIC_READ, FILE_SHARE_READ,
4224 NULL, OPEN_EXISTING, 0, NULL);
4225 if (hFile == INVALID_HANDLE_VALUE)
4227 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4231 /* Fill SectionName field */
4232 Result
= SetupGetStringFieldW(
4235 driverInfo
->Details
.SectionName
, LINE_LEN
,
4240 /* Fill DrvDescription field */
4241 Result
= SetupGetStringFieldW(
4243 0, /* Field index */
4244 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
4247 /* Copy MatchingId information */
4248 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4249 if (!driverInfo
->MatchingId
)
4251 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4254 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4256 /* Get inf install section */
4258 RequiredSize
= 128; /* Initial buffer size */
4259 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4260 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4262 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4263 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4264 if (!InfInstallSection
)
4266 Result
= SetupGetStringFieldW(
4268 1, /* Field index */
4269 InfInstallSection
, RequiredSize
,
4275 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4276 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4278 driverInfo
->DriverRank
= Rank
;
4279 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4280 driverInfo
->Info
.DriverType
= DriverType
;
4281 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4282 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4283 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4284 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4285 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4288 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4289 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4292 driverInfo
->Info
.ProviderName
[0] = '\0';
4293 driverInfo
->Info
.DriverDate
= DriverDate
;
4294 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4295 ReferenceInfFile(InfFileDetails
);
4296 driverInfo
->InfFileDetails
= InfFileDetails
;
4298 /* Insert current driver in driver list, according to its rank */
4299 PreviousEntry
= DriverListHead
->Flink
;
4300 while (PreviousEntry
!= DriverListHead
)
4302 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
4304 /* Insert before the current item */
4305 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4308 PreviousEntry
= PreviousEntry
->Flink
;
4310 if (PreviousEntry
== DriverListHead
)
4312 /* Insert at the end of the list */
4313 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4322 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4323 HeapFree(GetProcessHeap(), 0, driverInfo
);
4325 if (hFile
!= INVALID_HANDLE_VALUE
)
4327 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4333 GetVersionInformationFromInfFile(
4335 OUT LPGUID ClassGuid
,
4336 OUT LPWSTR
* pProviderName
,
4337 OUT FILETIME
* DriverDate
,
4338 OUT DWORDLONG
* DriverVersion
)
4341 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4342 LPWSTR DriverVer
= NULL
;
4343 LPWSTR ProviderName
= NULL
;
4344 LPWSTR pComma
; /* Points into DriverVer */
4345 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4346 SYSTEMTIME SystemTime
;
4348 BOOL ret
= FALSE
; /* Final result */
4350 /* Get class Guid */
4351 if (!SetupGetLineTextW(
4354 L
"Version", L
"ClassGUID",
4355 guidW
, sizeof(guidW
),
4356 NULL
/* Required size */))
4360 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4361 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4363 SetLastError(ERROR_GEN_FAILURE
);
4367 /* Get provider name */
4368 Result
= SetupGetLineTextW(
4370 hInf
, L
"Version", L
"Provider",
4375 /* We know know the needed buffer size */
4376 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4379 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4382 Result
= SetupGetLineTextW(
4384 hInf
, L
"Version", L
"Provider",
4385 ProviderName
, RequiredSize
,
4390 *pProviderName
= ProviderName
;
4392 /* Read the "DriverVer" value */
4393 Result
= SetupGetLineTextW(
4395 hInf
, L
"Version", L
"DriverVer",
4400 /* We know know the needed buffer size */
4401 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4404 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4407 Result
= SetupGetLineTextW(
4409 hInf
, L
"Version", L
"DriverVer",
4410 DriverVer
, RequiredSize
,
4416 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4417 pComma
= wcschr(DriverVer
, ',');
4420 *pComma
= UNICODE_NULL
;
4421 pVersion
= pComma
+ 1;
4423 /* Get driver date version. Invalid date = 00/00/00 */
4424 memset(DriverDate
, 0, sizeof(FILETIME
));
4425 if (wcslen(DriverVer
) == 10
4426 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4427 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4429 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4430 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4431 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4432 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4433 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4434 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4436 /* Get driver version. Invalid version = 0.0.0.0 */
4438 /* FIXME: use pVersion to fill DriverVersion variable */
4444 HeapFree(GetProcessHeap(), 0, ProviderName
);
4445 HeapFree(GetProcessHeap(), 0, DriverVer
);
4450 /***********************************************************************
4451 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4454 SetupDiBuildDriverInfoList(
4455 IN HDEVINFO DeviceInfoSet
,
4456 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4457 IN DWORD DriverType
)
4459 struct DeviceInfoSet
*list
;
4460 SP_DEVINSTALL_PARAMS_W InstallParams
;
4461 PVOID Buffer
= NULL
;
4462 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4463 LPWSTR ProviderName
= NULL
;
4464 LPWSTR ManufacturerName
= NULL
;
4465 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4466 LPWSTR HardwareIDs
= NULL
;
4467 LPWSTR CompatibleIDs
= NULL
;
4468 LPWSTR FullInfFileName
= NULL
;
4469 FILETIME DriverDate
;
4470 DWORDLONG DriverVersion
= 0;
4474 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4477 SetLastError(ERROR_INVALID_HANDLE
);
4478 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4479 SetLastError(ERROR_INVALID_HANDLE
);
4480 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4481 SetLastError(ERROR_INVALID_HANDLE
);
4482 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4483 SetLastError(ERROR_INVALID_PARAMETER
);
4484 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4485 SetLastError(ERROR_INVALID_PARAMETER
);
4486 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4487 SetLastError(ERROR_INVALID_PARAMETER
);
4488 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4489 SetLastError(ERROR_INVALID_USER_BUFFER
);
4494 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4495 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4499 if (DriverType
== SPDIT_COMPATDRIVER
)
4501 /* Get hardware IDs list */
4503 RequiredSize
= 512; /* Initial buffer size */
4504 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4505 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4507 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4508 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4511 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4514 Result
= SetupDiGetDeviceRegistryPropertyW(
4526 /* Get compatible IDs list */
4528 RequiredSize
= 512; /* Initial buffer size */
4529 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4530 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4532 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4533 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4536 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4539 Result
= SetupDiGetDeviceRegistryPropertyW(
4542 SPDRP_COMPATIBLEIDS
,
4544 (PBYTE
)CompatibleIDs
,
4547 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4549 /* No compatible ID for this device */
4550 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4551 CompatibleIDs
= NULL
;
4559 /* Enumerate .inf files */
4561 RequiredSize
= 32768; /* Initial buffer size */
4562 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4563 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4565 HeapFree(GetProcessHeap(), 0, Buffer
);
4566 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4570 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4573 Result
= SetupGetInfFileListW(
4574 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4576 Buffer
, RequiredSize
,
4579 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4581 /* No .inf file in specified directory. So, we should
4582 * success as we created an empty driver info list.
4590 LPWSTR pFullFilename
;
4592 if (*InstallParams
.DriverPath
)
4595 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
4598 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
4599 if (!FullInfFileName
)
4601 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
4604 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
4605 wcscat(FullInfFileName
, L
"\\");
4606 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
4610 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
4611 if (!FullInfFileName
)
4613 pFullFilename
= &FullInfFileName
[0];
4616 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4618 INFCONTEXT ContextManufacturer
, ContextDevice
;
4621 wcscpy(pFullFilename
, filename
);
4622 TRACE("Opening file %S\n", FullInfFileName
);
4624 currentInfFileDetails
= HeapAlloc(
4627 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
4628 if (!currentInfFileDetails
)
4630 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
4631 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
4633 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
4634 ReferenceInfFile(currentInfFileDetails
);
4635 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
4637 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
4638 currentInfFileDetails
= NULL
;
4642 if (!GetVersionInformationFromInfFile(
4643 currentInfFileDetails
->hInf
,
4649 SetupCloseInfFile(currentInfFileDetails
->hInf
);
4650 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
4651 currentInfFileDetails
= NULL
;
4655 if (DriverType
== SPDIT_CLASSDRIVER
)
4657 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4658 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4664 /* Get the manufacturers list */
4665 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4668 Result
= SetupGetStringFieldW(
4669 &ContextManufacturer
,
4670 0, /* Field index */
4675 /* We got the needed size for the buffer */
4676 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4677 if (!ManufacturerName
)
4679 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4682 Result
= SetupGetStringFieldW(
4683 &ContextManufacturer
,
4684 0, /* Field index */
4685 ManufacturerName
, RequiredSize
,
4688 /* Get manufacturer section name */
4689 Result
= SetupGetStringFieldW(
4690 &ContextManufacturer
,
4691 1, /* Field index */
4692 ManufacturerSection
, LINE_LEN
,
4696 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
4697 /* Add (possible) extension to manufacturer section name */
4698 Result
= SetupDiGetActualSectionToInstallW(
4699 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
4702 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4703 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4708 if (DriverType
== SPDIT_CLASSDRIVER
)
4710 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4711 if (!AddDriverToList(
4712 &list
->DriverListHead
,
4716 currentInfFileDetails
,
4721 DriverDate
, DriverVersion
,
4727 else /* DriverType = SPDIT_COMPATDRIVER */
4729 /* 1. Get all fields */
4730 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4734 BOOL DriverAlreadyAdded
;
4736 for (i
= 2; i
<= FieldCount
; i
++)
4738 LPWSTR DeviceId
= NULL
;
4740 RequiredSize
= 128; /* Initial buffer size */
4741 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4742 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4744 HeapFree(GetProcessHeap(), 0, DeviceId
);
4745 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4748 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4751 Result
= SetupGetStringFieldW(
4754 DeviceId
, RequiredSize
,
4759 HeapFree(GetProcessHeap(), 0, DeviceId
);
4762 DriverAlreadyAdded
= FALSE
;
4763 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4765 if (wcsicmp(DeviceId
, currentId
) == 0)
4768 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4772 currentInfFileDetails
,
4777 DriverDate
, DriverVersion
,
4778 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4779 DriverAlreadyAdded
= TRUE
;
4784 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4786 if (wcsicmp(DeviceId
, currentId
) == 0)
4789 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4793 currentInfFileDetails
,
4798 DriverDate
, DriverVersion
,
4799 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4800 DriverAlreadyAdded
= TRUE
;
4804 HeapFree(GetProcessHeap(), 0, DeviceId
);
4807 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4810 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4811 ManufacturerName
= NULL
;
4812 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4817 HeapFree(GetProcessHeap(), 0, ProviderName
);
4818 ProviderName
= NULL
;
4820 DereferenceInfFile(currentInfFileDetails
);
4821 currentInfFileDetails
= NULL
;
4832 InstallParams
.Flags
|= DI_DIDCOMPAT
;
4833 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
4837 InstallParams
.Flags
|= DI_DIDCLASS
;
4838 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
4840 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4843 HeapFree(GetProcessHeap(), 0, ProviderName
);
4844 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4845 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4846 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4847 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
4848 if (currentInfFileDetails
)
4849 DereferenceInfFile(currentInfFileDetails
);
4850 HeapFree(GetProcessHeap(), 0, Buffer
);
4852 TRACE("Returning %d\n", ret
);
4856 /***********************************************************************
4857 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4860 SetupDiDeleteDeviceInfo(
4861 IN HDEVINFO DeviceInfoSet
,
4862 IN PSP_DEVINFO_DATA DeviceInfoData
)
4864 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4866 FIXME("not implemented\n");
4867 SetLastError(ERROR_GEN_FAILURE
);
4872 /***********************************************************************
4873 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4876 SetupDiDestroyDriverInfoList(
4877 IN HDEVINFO DeviceInfoSet
,
4878 IN PSP_DEVINFO_DATA DeviceInfoData
,
4879 IN DWORD DriverType
)
4881 struct DeviceInfoSet
*list
;
4884 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4887 SetLastError(ERROR_INVALID_HANDLE
);
4888 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4889 SetLastError(ERROR_INVALID_HANDLE
);
4890 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4891 SetLastError(ERROR_INVALID_PARAMETER
);
4892 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4893 SetLastError(ERROR_INVALID_PARAMETER
);
4894 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4895 SetLastError(ERROR_INVALID_USER_BUFFER
);
4898 PLIST_ENTRY ListEntry
;
4899 struct DriverInfoElement
*driverInfo
;
4900 SP_DEVINSTALL_PARAMS_W InstallParams
;
4902 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4903 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4906 if (!DeviceInfoData
)
4907 /* Fall back to destroying class driver list */
4908 DriverType
= SPDIT_CLASSDRIVER
;
4910 if (DriverType
== SPDIT_CLASSDRIVER
)
4912 while (!IsListEmpty(&list
->DriverListHead
))
4914 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
4915 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4916 DestroyDriverInfoElement(driverInfo
);
4918 InstallParams
.Reserved
= 0;
4919 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
4920 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
4921 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
4925 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
4926 struct DeviceInfoElement
*deviceInfo
;
4928 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4929 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
4931 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4932 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
4934 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
4935 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4936 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
4938 InstallParamsSet
.Reserved
= 0;
4939 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
4941 DestroyDriverInfoElement(driverInfo
);
4943 InstallParams
.Reserved
= 0;
4944 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
4945 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
4946 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4951 TRACE("Returning %d\n", ret
);
4956 /***********************************************************************
4957 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4960 SetupDiOpenDeviceInfoA(
4961 IN HDEVINFO DeviceInfoSet
,
4962 IN PCSTR DeviceInstanceId
,
4963 IN HWND hwndParent OPTIONAL
,
4965 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4967 LPWSTR DeviceInstanceIdW
= NULL
;
4970 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4972 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4973 if (DeviceInstanceIdW
== NULL
)
4976 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4977 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4979 MyFree(DeviceInstanceIdW
);
4985 /***********************************************************************
4986 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4989 SetupDiOpenDeviceInfoW(
4990 IN HDEVINFO DeviceInfoSet
,
4991 IN PCWSTR DeviceInstanceId
,
4992 IN HWND hwndParent OPTIONAL
,
4994 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4996 struct DeviceInfoSet
*list
;
4997 HKEY hEnumKey
, hKey
;
5001 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5003 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5004 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5007 SetLastError(ERROR_INVALID_HANDLE
);
5008 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5009 SetLastError(ERROR_INVALID_HANDLE
);
5010 else if (!DeviceInstanceId
)
5011 SetLastError(ERROR_INVALID_PARAMETER
);
5012 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5014 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5015 SetLastError(ERROR_INVALID_FLAGS
);
5017 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5018 SetLastError(ERROR_INVALID_USER_BUFFER
);
5021 struct DeviceInfoElement
*deviceInfo
= NULL
;
5022 /* Search if device already exists in DeviceInfoSet.
5023 * If yes, return the existing element
5024 * If no, create a new element using informations in registry
5026 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5027 while (ItemList
!= &list
->ListHead
)
5032 FIXME("not implemented\n");
5033 ItemList
= ItemList
->Flink
;
5038 /* good one found */
5043 /* Open supposed registry key */
5048 KEY_ENUMERATE_SUB_KEYS
,
5050 if (rc
!= ERROR_SUCCESS
)
5061 RegCloseKey(hEnumKey
);
5062 if (rc
!= ERROR_SUCCESS
)
5064 if (rc
== ERROR_FILE_NOT_FOUND
)
5065 rc
= ERROR_NO_SUCH_DEVINST
;
5070 /* FIXME: try to get ClassGUID from registry, instead of
5071 * sending GUID_NULL to CreateDeviceInfoElement
5073 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
5078 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5084 if (ret
&& deviceInfo
&& DeviceInfoData
)
5086 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5087 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
5088 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5096 /***********************************************************************
5097 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5100 SetupDiEnumDriverInfoA(
5101 IN HDEVINFO DeviceInfoSet
,
5102 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5103 IN DWORD DriverType
,
5104 IN DWORD MemberIndex
,
5105 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5107 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5110 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5111 DriverType
, MemberIndex
, DriverInfoData
);
5113 if (DriverInfoData
== NULL
)
5114 SetLastError(ERROR_INVALID_PARAMETER
);
5115 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5116 SetLastError(ERROR_INVALID_USER_BUFFER
);
5119 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5120 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
5121 DriverType
, MemberIndex
, &driverInfoData2W
);
5125 /* Do W->A conversion */
5126 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5127 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5128 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5129 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5131 DriverInfoData
->Description
[0] = '\0';
5134 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5135 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5137 DriverInfoData
->MfgName
[0] = '\0';
5140 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5141 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5143 DriverInfoData
->ProviderName
[0] = '\0';
5146 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5148 /* Copy more fields */
5149 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5150 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5155 TRACE("Returning %d\n", ret
);
5160 /***********************************************************************
5161 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5164 SetupDiEnumDriverInfoW(
5165 IN HDEVINFO DeviceInfoSet
,
5166 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5167 IN DWORD DriverType
,
5168 IN DWORD MemberIndex
,
5169 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5171 PLIST_ENTRY ListHead
;
5174 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5175 DriverType
, MemberIndex
, DriverInfoData
);
5177 if (!DeviceInfoSet
|| !DriverInfoData
)
5178 SetLastError(ERROR_INVALID_PARAMETER
);
5179 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5180 SetLastError(ERROR_INVALID_HANDLE
);
5181 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5182 SetLastError(ERROR_INVALID_HANDLE
);
5183 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5184 SetLastError(ERROR_INVALID_PARAMETER
);
5185 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5186 SetLastError(ERROR_INVALID_PARAMETER
);
5187 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5188 SetLastError(ERROR_INVALID_PARAMETER
);
5189 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5190 SetLastError(ERROR_INVALID_USER_BUFFER
);
5193 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5194 PLIST_ENTRY ItemList
;
5195 if (DriverType
== SPDIT_CLASSDRIVER
||
5196 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
5198 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5202 ListHead
= &devInfo
->DriverListHead
;
5205 ItemList
= ListHead
->Flink
;
5206 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
5207 ItemList
= ItemList
->Flink
;
5208 if (ItemList
== ListHead
)
5209 SetLastError(ERROR_NO_MORE_ITEMS
);
5212 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
5215 &DriverInfoData
->DriverType
,
5216 &DrvInfo
->Info
.DriverType
,
5217 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5222 TRACE("Returning %d\n", ret
);
5227 /***********************************************************************
5228 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5231 SetupDiGetSelectedDriverA(
5232 IN HDEVINFO DeviceInfoSet
,
5233 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5234 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5236 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5239 if (DriverInfoData
== NULL
)
5240 SetLastError(ERROR_INVALID_PARAMETER
);
5241 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5242 SetLastError(ERROR_INVALID_USER_BUFFER
);
5245 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5247 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5253 /* Do W->A conversion */
5254 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5255 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5256 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5257 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5259 DriverInfoData
->Description
[0] = '\0';
5262 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5263 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5265 DriverInfoData
->MfgName
[0] = '\0';
5268 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5269 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5271 DriverInfoData
->ProviderName
[0] = '\0';
5274 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5276 /* Copy more fields */
5277 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5278 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5287 /***********************************************************************
5288 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5291 SetupDiGetSelectedDriverW(
5292 IN HDEVINFO DeviceInfoSet
,
5293 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5294 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5298 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5300 if (!DeviceInfoSet
|| !DriverInfoData
)
5301 SetLastError(ERROR_INVALID_PARAMETER
);
5302 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5303 SetLastError(ERROR_INVALID_HANDLE
);
5304 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5305 SetLastError(ERROR_INVALID_HANDLE
);
5306 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5307 SetLastError(ERROR_INVALID_USER_BUFFER
);
5308 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5309 SetLastError(ERROR_INVALID_USER_BUFFER
);
5312 SP_DEVINSTALL_PARAMS InstallParams
;
5314 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5315 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5317 struct DriverInfoElement
*driverInfo
;
5318 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5319 if (driverInfo
== NULL
)
5320 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5324 &DriverInfoData
->DriverType
,
5325 &driverInfo
->Info
.DriverType
,
5326 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5332 TRACE("Returning %d\n", ret
);
5337 /***********************************************************************
5338 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5341 SetupDiSetSelectedDriverA(
5342 IN HDEVINFO DeviceInfoSet
,
5343 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5344 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5346 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5347 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5350 if (DriverInfoData
!= NULL
)
5352 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5353 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5355 SetLastError(ERROR_INVALID_PARAMETER
);
5359 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5360 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5362 if (DriverInfoDataW
.Reserved
== 0)
5364 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5366 /* convert the strings to unicode */
5367 if (!MultiByteToWideChar(CP_ACP
,
5369 DriverInfoData
->Description
,
5371 DriverInfoDataW
.Description
,
5373 !MultiByteToWideChar(CP_ACP
,
5375 DriverInfoData
->ProviderName
,
5377 DriverInfoDataW
.ProviderName
,
5384 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5387 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5391 if (ret
&& pDriverInfoDataW
!= NULL
)
5393 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5400 /***********************************************************************
5401 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5404 SetupDiSetSelectedDriverW(
5405 IN HDEVINFO DeviceInfoSet
,
5406 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5407 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5411 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5414 SetLastError(ERROR_INVALID_PARAMETER
);
5415 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5416 SetLastError(ERROR_INVALID_HANDLE
);
5417 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5418 SetLastError(ERROR_INVALID_HANDLE
);
5419 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5420 SetLastError(ERROR_INVALID_USER_BUFFER
);
5421 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5422 SetLastError(ERROR_INVALID_USER_BUFFER
);
5425 struct DriverInfoElement
**pDriverInfo
;
5426 PLIST_ENTRY ListHead
, ItemList
;
5430 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5431 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5435 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5436 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5439 if (!DriverInfoData
)
5441 *pDriverInfo
= NULL
;
5446 /* Search selected driver in list */
5447 ItemList
= ListHead
->Flink
;
5448 while (ItemList
!= ListHead
)
5450 if (DriverInfoData
->Reserved
!= 0)
5452 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5457 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5458 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5459 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5460 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5461 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5467 if (ItemList
== ListHead
)
5468 SetLastError(ERROR_INVALID_PARAMETER
);
5471 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5472 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5474 TRACE("Choosing driver whose rank is 0x%lx\n",
5475 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5477 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5482 TRACE("Returning %d\n", ret
);
5486 /***********************************************************************
5487 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5490 SetupDiGetDriverInfoDetailA(
5491 IN HDEVINFO DeviceInfoSet
,
5492 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5493 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5494 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5495 IN DWORD DriverInfoDetailDataSize
,
5496 OUT PDWORD RequiredSize OPTIONAL
)
5498 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5499 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5501 DWORD HardwareIDLen
= 0;
5504 /* do some sanity checks, the unicode version might do more thorough checks */
5505 if (DriverInfoData
== NULL
||
5506 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5507 (DriverInfoDetailData
!= NULL
&&
5508 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5509 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5511 SetLastError(ERROR_INVALID_PARAMETER
);
5515 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5516 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5518 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5520 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5522 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5526 SetLastError(ERROR_INVALID_PARAMETER
);
5529 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5530 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5532 /* convert the strings to unicode */
5533 if (MultiByteToWideChar(CP_ACP
,
5535 DriverInfoData
->Description
,
5537 DriverInfoDataW
.Description
,
5539 MultiByteToWideChar(CP_ACP
,
5541 DriverInfoData
->MfgName
,
5543 DriverInfoDataW
.MfgName
,
5545 MultiByteToWideChar(CP_ACP
,
5547 DriverInfoData
->ProviderName
,
5549 DriverInfoDataW
.ProviderName
,
5552 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5554 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5555 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5558 if (DriverInfoDetailData
!= NULL
)
5560 /* calculate the unicode buffer size from the ansi buffer size */
5561 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5562 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5563 (HardwareIDLen
* sizeof(WCHAR
));
5565 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5566 if (DriverInfoDetailDataW
== NULL
)
5568 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5572 /* initialize the buffer */
5573 ZeroMemory(DriverInfoDetailDataW
,
5575 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5578 /* call the unicode version */
5579 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5582 DriverInfoDetailDataW
,
5588 if (DriverInfoDetailDataW
!= NULL
)
5590 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5591 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
5592 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
5593 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
5594 if (WideCharToMultiByte(CP_ACP
,
5596 DriverInfoDetailDataW
->SectionName
,
5598 DriverInfoDetailData
->SectionName
,
5602 WideCharToMultiByte(CP_ACP
,
5604 DriverInfoDetailDataW
->InfFileName
,
5606 DriverInfoDetailData
->InfFileName
,
5610 WideCharToMultiByte(CP_ACP
,
5612 DriverInfoDetailDataW
->DrvDescription
,
5614 DriverInfoDetailData
->DrvDescription
,
5618 WideCharToMultiByte(CP_ACP
,
5620 DriverInfoDetailDataW
->HardwareID
,
5622 DriverInfoDetailData
->HardwareID
,
5628 DWORD hwidlen
= HardwareIDLen
;
5629 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
5631 /* count the strings in the list */
5634 len
= lstrlenA(s
) + 1;
5643 /* looks like the string list wasn't terminated... */
5644 SetLastError(ERROR_INVALID_USER_BUFFER
);
5650 /* make sure CompatIDsOffset points to the second string in the
5654 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
5655 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
5656 DriverInfoDetailData
->CompatIDsOffset
+ 1;
5660 DriverInfoDetailData
->CompatIDsOffset
= 0;
5661 DriverInfoDetailData
->CompatIDsLength
= 0;
5670 if (RequiredSize
!= NULL
)
5672 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
5673 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
5679 if (DriverInfoDetailDataW
!= NULL
)
5681 MyFree(DriverInfoDetailDataW
);
5687 /***********************************************************************
5688 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5691 SetupDiGetDriverInfoDetailW(
5692 IN HDEVINFO DeviceInfoSet
,
5693 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5694 IN PSP_DRVINFO_DATA_W DriverInfoData
,
5695 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
5696 IN DWORD DriverInfoDetailDataSize
,
5697 OUT PDWORD RequiredSize OPTIONAL
)
5701 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
5702 DriverInfoData
, DriverInfoDetailData
,
5703 DriverInfoDetailDataSize
, RequiredSize
);
5706 SetLastError(ERROR_INVALID_PARAMETER
);
5707 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5708 SetLastError(ERROR_INVALID_HANDLE
);
5709 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5710 SetLastError(ERROR_INVALID_HANDLE
);
5711 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5712 SetLastError(ERROR_INVALID_USER_BUFFER
);
5713 else if (!DriverInfoData
)
5714 SetLastError(ERROR_INVALID_PARAMETER
);
5715 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
5716 SetLastError(ERROR_INVALID_PARAMETER
);
5717 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5718 SetLastError(ERROR_INVALID_PARAMETER
);
5719 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5720 SetLastError(ERROR_INVALID_USER_BUFFER
);
5721 else if (DriverInfoData
->Reserved
== 0)
5722 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5725 struct DriverInfoElement
*driverInfoElement
;
5726 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
5729 DriverInfoDetailData
,
5730 &driverInfoElement
->Details
,
5731 driverInfoElement
->Details
.cbSize
);
5732 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5733 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5738 TRACE("Returning %d\n", ret
);
5742 /***********************************************************************
5743 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5746 SetupDiSelectBestCompatDrv(
5747 IN HDEVINFO DeviceInfoSet
,
5748 IN PSP_DEVINFO_DATA DeviceInfoData
)
5750 SP_DRVINFO_DATA_W drvInfoData
;
5753 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5755 /* Drivers are sorted by rank in the driver list, so
5756 * the first driver in the list is the best one.
5758 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
5759 ret
= SetupDiEnumDriverInfoW(
5763 0, /* Member index */
5768 ret
= SetupDiSetSelectedDriverW(
5774 TRACE("Returning %d\n", ret
);
5778 /***********************************************************************
5779 * SetupDiInstallDriverFiles (SETUPAPI.@)
5782 SetupDiInstallDriverFiles(
5783 IN HDEVINFO DeviceInfoSet
,
5784 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5788 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5791 SetLastError(ERROR_INVALID_PARAMETER
);
5792 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5793 SetLastError(ERROR_INVALID_HANDLE
);
5794 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5795 SetLastError(ERROR_INVALID_HANDLE
);
5796 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5797 SetLastError(ERROR_INVALID_USER_BUFFER
);
5798 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
5799 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5800 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
5801 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5804 SP_DEVINSTALL_PARAMS_W InstallParams
;
5805 struct DriverInfoElement
*SelectedDriver
;
5806 WCHAR SectionName
[MAX_PATH
];
5807 DWORD SectionNameLength
= 0;
5809 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5810 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5814 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5815 if (!SelectedDriver
)
5817 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5821 ret
= SetupDiGetActualSectionToInstallW(
5822 SelectedDriver
->InfFileDetails
->hInf
,
5823 SelectedDriver
->Details
.SectionName
,
5824 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5828 if (!InstallParams
.InstallMsgHandler
)
5830 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5831 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5832 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5834 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5835 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5836 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
5837 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5838 DeviceInfoSet
, DeviceInfoData
);
5842 TRACE("Returning %d\n", ret
);
5846 /***********************************************************************
5847 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5850 SetupDiRegisterCoDeviceInstallers(
5851 IN HDEVINFO DeviceInfoSet
,
5852 IN PSP_DEVINFO_DATA DeviceInfoData
)
5854 BOOL ret
= FALSE
; /* Return value */
5856 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5859 SetLastError(ERROR_INVALID_PARAMETER
);
5860 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5861 SetLastError(ERROR_INVALID_HANDLE
);
5862 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5863 SetLastError(ERROR_INVALID_HANDLE
);
5864 else if (!DeviceInfoData
)
5865 SetLastError(ERROR_INVALID_PARAMETER
);
5866 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5867 SetLastError(ERROR_INVALID_USER_BUFFER
);
5870 SP_DEVINSTALL_PARAMS_W InstallParams
;
5871 struct DriverInfoElement
*SelectedDriver
;
5874 WCHAR SectionName
[MAX_PATH
];
5875 DWORD SectionNameLength
= 0;
5876 HKEY hKey
= INVALID_HANDLE_VALUE
;
5878 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5879 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5883 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5884 if (SelectedDriver
== NULL
)
5886 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5890 /* Get .CoInstallers section name */
5891 Result
= SetupDiGetActualSectionToInstallW(
5892 SelectedDriver
->InfFileDetails
->hInf
,
5893 SelectedDriver
->Details
.SectionName
,
5894 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5895 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
5897 wcscat(SectionName
, L
".CoInstallers");
5899 /* Open/Create driver key information */
5900 #if _WIN32_WINNT >= 0x502
5901 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5903 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5905 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5906 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5907 if (hKey
== INVALID_HANDLE_VALUE
)
5910 /* Install .CoInstallers section */
5911 DoAction
= SPINST_REGISTRY
;
5912 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5914 DoAction
|= SPINST_FILES
;
5915 if (!InstallParams
.InstallMsgHandler
)
5917 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5918 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5919 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5922 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5923 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5924 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5925 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5926 DeviceInfoSet
, DeviceInfoData
);
5933 if (hKey
!= INVALID_HANDLE_VALUE
)
5937 TRACE("Returning %d\n", ret
);
5941 /***********************************************************************
5942 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5945 SetupDiInstallDeviceInterfaces(
5946 IN HDEVINFO DeviceInfoSet
,
5947 IN PSP_DEVINFO_DATA DeviceInfoData
)
5949 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5951 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5952 //SetLastError(ERROR_GEN_FAILURE);
5958 InfIsFromOEMLocation(
5960 OUT LPBOOL IsOEMLocation
)
5964 last
= strrchrW(FullName
, '\\');
5967 /* No directory specified */
5968 *IsOEMLocation
= FALSE
;
5972 WCHAR Windir
[MAX_PATH
];
5975 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
5976 if (ret
== 0 || ret
>= MAX_PATH
)
5978 SetLastError(ERROR_GEN_FAILURE
);
5982 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
5984 /* The path is %SYSTEMROOT%\Inf */
5985 *IsOEMLocation
= FALSE
;
5989 /* The file is in another place */
5990 *IsOEMLocation
= TRUE
;
5996 /***********************************************************************
5997 * SetupDiInstallDevice (SETUPAPI.@)
6000 SetupDiInstallDevice(
6001 IN HDEVINFO DeviceInfoSet
,
6002 IN PSP_DEVINFO_DATA DeviceInfoData
)
6004 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6005 SP_DEVINSTALL_PARAMS_W InstallParams
;
6006 struct DriverInfoElement
*SelectedDriver
;
6007 SYSTEMTIME DriverDate
;
6008 WCHAR SectionName
[MAX_PATH
];
6010 DWORD SectionNameLength
= 0;
6011 BOOL Result
= FALSE
;
6012 INFCONTEXT ContextService
;
6016 LPCWSTR AssociatedService
= NULL
;
6017 LPWSTR pSectionName
= NULL
;
6018 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
6020 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
6021 BOOL RebootRequired
= FALSE
;
6022 HKEY hKey
= INVALID_HANDLE_VALUE
;
6023 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
6024 BOOL NeedtoCopyFile
;
6026 BOOL ret
= FALSE
; /* Return value */
6028 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6031 SetLastError(ERROR_INVALID_PARAMETER
);
6032 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6033 SetLastError(ERROR_INVALID_HANDLE
);
6034 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6035 SetLastError(ERROR_INVALID_HANDLE
);
6036 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6037 SetLastError(ERROR_INVALID_USER_BUFFER
);
6043 /* One parameter is bad */
6047 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6048 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6052 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
6054 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6058 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6059 if (SelectedDriver
== NULL
)
6061 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6065 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
6067 Result
= SetupDiGetActualSectionToInstallW(
6068 SelectedDriver
->InfFileDetails
->hInf
,
6069 SelectedDriver
->Details
.SectionName
,
6070 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6071 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
6073 pSectionName
= &SectionName
[wcslen(SectionName
)];
6075 /* Get information from [Version] section */
6076 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
6078 /* Format ClassGuid to a string */
6079 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
6081 RequiredSize
= lstrlenW(lpGuidString
);
6082 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
6083 if (!lpFullGuidString
)
6085 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6088 lpFullGuidString
[0] = '{';
6089 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
6090 lpFullGuidString
[RequiredSize
+ 1] = '}';
6091 lpFullGuidString
[RequiredSize
+ 2] = '\0';
6093 /* Open/Create driver key information */
6094 #if _WIN32_WINNT >= 0x502
6095 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6097 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6099 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6100 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6101 if (hKey
== INVALID_HANDLE_VALUE
)
6104 /* Install main section */
6105 DoAction
= SPINST_REGISTRY
;
6106 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6108 DoAction
|= SPINST_FILES
;
6109 if (!InstallParams
.InstallMsgHandler
)
6111 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6112 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6113 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6116 *pSectionName
= '\0';
6117 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6118 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6119 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6120 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6121 DeviceInfoSet
, DeviceInfoData
);
6124 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
6126 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
6128 /* Delete resources allocated by SetupInitDefaultQueueCallback */
6129 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
6132 InstallParams
.Flags
|= DI_NOFILECOPY
;
6133 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6135 /* Write information to driver key */
6136 *pSectionName
= UNICODE_NULL
;
6137 TRACE("Write information to driver key\n");
6138 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6139 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6140 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);
6141 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
6142 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
6143 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
6144 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
6145 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
6146 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6147 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
6148 if (rc
== ERROR_SUCCESS
)
6149 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
6150 if (rc
== ERROR_SUCCESS
)
6151 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6152 if (rc
== ERROR_SUCCESS
)
6154 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);
6155 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
6157 if (rc
== ERROR_SUCCESS
)
6158 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
6159 if (rc
== ERROR_SUCCESS
)
6160 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
6161 if (rc
== ERROR_SUCCESS
)
6162 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
6163 if (rc
== ERROR_SUCCESS
)
6164 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
6165 if (rc
== ERROR_SUCCESS
)
6166 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
6167 if (rc
!= ERROR_SUCCESS
)
6173 hKey
= INVALID_HANDLE_VALUE
;
6175 /* FIXME: Process .LogConfigOverride section */
6177 /* Install .Services section */
6178 wcscpy(pSectionName
, L
".Services");
6179 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
6182 LPWSTR ServiceName
= NULL
;
6183 LPWSTR ServiceSection
= NULL
;
6185 Result
= SetupGetStringFieldW(
6187 1, /* Field index */
6192 if (RequiredSize
> 0)
6194 /* We got the needed size for the buffer */
6195 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6198 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6201 Result
= SetupGetStringFieldW(
6203 1, /* Field index */
6204 ServiceName
, RequiredSize
,
6209 Result
= SetupGetIntField(
6211 2, /* Field index */
6215 /* The field may be empty. Ignore the error */
6218 Result
= SetupGetStringFieldW(
6220 3, /* Field index */
6225 if (GetLastError() == ERROR_INVALID_PARAMETER
)
6227 /* This first is probably missing. It is not
6228 * required, so ignore the error */
6235 if (RequiredSize
> 0)
6237 /* We got the needed size for the buffer */
6238 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6239 if (!ServiceSection
)
6241 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6244 Result
= SetupGetStringFieldW(
6246 3, /* Field index */
6247 ServiceSection
, RequiredSize
,
6252 SetLastError(ERROR_SUCCESS
);
6253 Result
= SetupInstallServicesFromInfSectionExW(
6254 SelectedDriver
->InfFileDetails
->hInf
,
6255 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
6257 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
6259 AssociatedService
= ServiceName
;
6261 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
6262 RebootRequired
= TRUE
;
6265 HeapFree(GetProcessHeap(), 0, ServiceName
);
6266 HeapFree(GetProcessHeap(), 0, ServiceSection
);
6269 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
6272 /* Copy .inf file to Inf\ directory (if needed) */
6273 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
6278 Result
= SetupCopyOEMInfW(
6279 SelectedDriver
->InfFileDetails
->FullInfFileName
,
6282 SP_COPY_NOOVERWRITE
,
6288 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6289 * to release use of current InfFile */
6292 /* Open device registry key */
6293 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
6294 if (hKey
== INVALID_HANDLE_VALUE
)
6297 /* Install .HW section */
6298 wcscpy(pSectionName
, L
".HW");
6299 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6300 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6301 SPINST_REGISTRY
, hKey
, NULL
, 0,
6302 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6303 DeviceInfoSet
, DeviceInfoData
);
6307 /* Write information to enum key */
6308 TRACE("Write information to enum key\n");
6309 TRACE("Class : '%S'\n", ClassName
);
6310 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
6311 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6312 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
6313 TRACE("Service : '%S'\n", AssociatedService
);
6314 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
6315 if (rc
== ERROR_SUCCESS
)
6316 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
6317 if (rc
== ERROR_SUCCESS
)
6318 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6319 if (rc
== ERROR_SUCCESS
)
6320 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
6321 if (rc
== ERROR_SUCCESS
&& *AssociatedService
)
6322 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
6323 if (rc
!= ERROR_SUCCESS
)
6329 /* Start the device */
6330 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
6332 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6334 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
6335 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6336 ret
= NT_SUCCESS(Status
);
6342 /* End of installation */
6343 if (hClassKey
!= INVALID_HANDLE_VALUE
)
6344 RegCloseKey(hClassKey
);
6345 if (hKey
!= INVALID_HANDLE_VALUE
)
6348 RpcStringFreeW(&lpGuidString
);
6349 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
6350 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6352 TRACE("Returning %d\n", ret
);