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 struct CoInstallerElement
81 COINSTALLER_PROC Function
;
82 BOOL DoPostProcessing
;
86 /***********************************************************************
87 * SetupDiBuildClassInfoList (SETUPAPI.@)
89 BOOL WINAPI
SetupDiBuildClassInfoList(
92 DWORD ClassGuidListSize
,
96 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
97 ClassGuidListSize
, RequiredSize
,
101 /***********************************************************************
102 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
104 BOOL WINAPI
SetupDiBuildClassInfoListExA(
106 LPGUID ClassGuidList
,
107 DWORD ClassGuidListSize
,
112 LPWSTR MachineNameW
= NULL
;
119 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
120 if (MachineNameW
== NULL
) return FALSE
;
123 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
124 ClassGuidListSize
, RequiredSize
,
125 MachineNameW
, Reserved
);
128 MyFree(MachineNameW
);
133 /***********************************************************************
134 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
136 BOOL WINAPI
SetupDiBuildClassInfoListExW(
138 LPGUID ClassGuidList
,
139 DWORD ClassGuidListSize
,
144 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
150 DWORD dwGuidListIndex
= 0;
154 if (RequiredSize
!= NULL
)
157 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
162 if (hClassesKey
== INVALID_HANDLE_VALUE
)
167 for (dwIndex
= 0; ; dwIndex
++)
169 dwLength
= MAX_GUID_STRING_LEN
+ 1;
170 lError
= RegEnumKeyExW(hClassesKey
,
178 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
179 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
181 TRACE("Key name: %p\n", szKeyName
);
183 if (RegOpenKeyExW(hClassesKey
,
189 RegCloseKey(hClassesKey
);
193 if (!RegQueryValueExW(hClassKey
,
200 TRACE("'NoUseClass' value found!\n");
201 RegCloseKey(hClassKey
);
205 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
206 (!RegQueryValueExW(hClassKey
,
213 TRACE("'NoInstallClass' value found!\n");
214 RegCloseKey(hClassKey
);
218 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
219 (!RegQueryValueExW(hClassKey
,
226 TRACE("'NoDisplayClass' value found!\n");
227 RegCloseKey(hClassKey
);
231 RegCloseKey(hClassKey
);
233 TRACE("Guid: %p\n", szKeyName
);
234 if (dwGuidListIndex
< ClassGuidListSize
)
236 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
240 TRACE("Guid: %p\n", &szKeyName
[1]);
242 UuidFromStringW(&szKeyName
[1],
243 &ClassGuidList
[dwGuidListIndex
]);
249 if (lError
!= ERROR_SUCCESS
)
253 RegCloseKey(hClassesKey
);
255 if (RequiredSize
!= NULL
)
256 *RequiredSize
= dwGuidListIndex
;
258 if (ClassGuidListSize
< dwGuidListIndex
)
260 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
267 /***********************************************************************
268 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
270 BOOL WINAPI
SetupDiClassGuidsFromNameA(
272 LPGUID ClassGuidList
,
273 DWORD ClassGuidListSize
,
276 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
277 ClassGuidListSize
, RequiredSize
,
281 /***********************************************************************
282 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
284 BOOL WINAPI
SetupDiClassGuidsFromNameW(
286 LPGUID ClassGuidList
,
287 DWORD ClassGuidListSize
,
290 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
291 ClassGuidListSize
, RequiredSize
,
295 /***********************************************************************
296 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
298 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
300 LPGUID ClassGuidList
,
301 DWORD ClassGuidListSize
,
306 LPWSTR ClassNameW
= NULL
;
307 LPWSTR MachineNameW
= NULL
;
312 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
313 if (ClassNameW
== NULL
)
318 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
319 if (MachineNameW
== NULL
)
326 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
327 ClassGuidListSize
, RequiredSize
,
328 MachineNameW
, Reserved
);
331 MyFree(MachineNameW
);
338 /***********************************************************************
339 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
341 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
343 LPGUID ClassGuidList
,
344 DWORD ClassGuidListSize
,
349 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
350 WCHAR szClassName
[256];
356 DWORD dwGuidListIndex
= 0;
358 if (RequiredSize
!= NULL
)
361 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
362 KEY_ENUMERATE_SUB_KEYS
,
366 if (hClassesKey
== INVALID_HANDLE_VALUE
)
371 for (dwIndex
= 0; ; dwIndex
++)
373 dwLength
= MAX_GUID_STRING_LEN
+ 1;
374 lError
= RegEnumKeyExW(hClassesKey
,
382 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
383 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
385 TRACE("Key name: %p\n", szKeyName
);
387 if (RegOpenKeyExW(hClassesKey
,
393 RegCloseKey(hClassesKey
);
397 dwLength
= 256 * sizeof(WCHAR
);
398 if (!RegQueryValueExW(hClassKey
,
405 TRACE("Class name: %p\n", szClassName
);
407 if (strcmpiW(szClassName
, ClassName
) == 0)
409 TRACE("Found matching class name\n");
411 TRACE("Guid: %p\n", szKeyName
);
412 if (dwGuidListIndex
< ClassGuidListSize
)
414 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
418 TRACE("Guid: %p\n", &szKeyName
[1]);
420 UuidFromStringW(&szKeyName
[1],
421 &ClassGuidList
[dwGuidListIndex
]);
428 RegCloseKey(hClassKey
);
431 if (lError
!= ERROR_SUCCESS
)
435 RegCloseKey(hClassesKey
);
437 if (RequiredSize
!= NULL
)
438 *RequiredSize
= dwGuidListIndex
;
440 if (ClassGuidListSize
< dwGuidListIndex
)
442 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
449 /***********************************************************************
450 * SetupDiClassNameFromGuidA (SETUPAPI.@)
452 BOOL WINAPI
SetupDiClassNameFromGuidA(
453 const GUID
* ClassGuid
,
458 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
459 ClassNameSize
, RequiredSize
,
463 /***********************************************************************
464 * SetupDiClassNameFromGuidW (SETUPAPI.@)
466 BOOL WINAPI
SetupDiClassNameFromGuidW(
467 const GUID
* ClassGuid
,
472 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
473 ClassNameSize
, RequiredSize
,
477 /***********************************************************************
478 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
480 BOOL WINAPI
SetupDiClassNameFromGuidExA(
481 const GUID
* ClassGuid
,
488 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
489 LPWSTR MachineNameW
= NULL
;
493 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
494 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
495 NULL
, MachineNameW
, Reserved
);
498 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
499 ClassNameSize
, NULL
, NULL
);
501 if (!ClassNameSize
&& RequiredSize
)
504 MyFree(MachineNameW
);
508 /***********************************************************************
509 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
511 BOOL WINAPI
SetupDiClassNameFromGuidExW(
512 const GUID
* ClassGuid
,
523 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
528 if (hKey
== INVALID_HANDLE_VALUE
)
533 if (RequiredSize
!= NULL
)
536 rc
= RegQueryValueExW(hKey
,
542 if (rc
!= ERROR_SUCCESS
)
549 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
552 dwLength
= ClassNameSize
* sizeof(WCHAR
);
553 rc
= RegQueryValueExW(hKey
,
559 if (rc
!= ERROR_SUCCESS
)
571 /***********************************************************************
572 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
575 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
578 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
581 /***********************************************************************
582 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
585 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
590 LPWSTR MachineNameW
= NULL
;
593 TRACE("%p %p %s %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
597 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
598 if (MachineNameW
== NULL
)
599 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
602 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
603 MachineNameW
, Reserved
);
606 MyFree(MachineNameW
);
611 /***********************************************************************
612 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
615 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
620 struct DeviceInfoSet
*list
;
621 LPWSTR UNCServerName
= NULL
;
624 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
626 TRACE("%p %p %S %p\n", ClassGuid
, hwndParent
, MachineName
, Reserved
);
628 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
631 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
634 memset(list
, 0, sizeof(struct DeviceInfoSet
));
636 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
639 ClassGuid
? ClassGuid
: &GUID_NULL
,
640 sizeof(list
->ClassGuid
));
641 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
642 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
643 list
->InstallParams
.hwndParent
= hwndParent
;
646 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
647 if (rc
!= ERROR_SUCCESS
)
652 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
655 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
659 strcpyW(UNCServerName
+ 2, MachineName
);
663 DWORD Size
= MAX_PATH
;
664 list
->HKLM
= HKEY_LOCAL_MACHINE
;
665 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
668 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
671 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
675 UNCServerName
[0] = UNCServerName
[1] = '\\';
676 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
677 if (cr
!= CR_SUCCESS
)
681 case CR_OUT_OF_MEMORY
: rc
= ERROR_NOT_ENOUGH_MEMORY
; break;
682 case CR_INVALID_MACHINENAME
: rc
= ERROR_INVALID_COMPUTERNAME
; break;
683 default: rc
= ERROR_GEN_FAILURE
; break;
689 InitializeListHead(&list
->DriverListHead
);
690 InitializeListHead(&list
->ListHead
);
692 ret
= (HDEVINFO
)list
;
695 if (ret
== INVALID_HANDLE_VALUE
)
697 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
698 RegCloseKey(list
->HKLM
);
699 HeapFree(GetProcessHeap(), 0, list
);
701 HeapFree(GetProcessHeap(), 0, UNCServerName
);
705 /***********************************************************************
706 * SetupDiEnumDeviceInfo (SETUPAPI.@)
708 BOOL WINAPI
SetupDiEnumDeviceInfo(
709 HDEVINFO DeviceInfoSet
,
711 PSP_DEVINFO_DATA DeviceInfoData
)
715 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
717 SetLastError(ERROR_INVALID_PARAMETER
);
718 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
720 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
722 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
723 SetLastError(ERROR_INVALID_HANDLE
);
724 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
725 SetLastError(ERROR_INVALID_USER_BUFFER
);
728 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
729 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
730 ItemList
= ItemList
->Flink
;
731 if (ItemList
== &list
->ListHead
)
732 SetLastError(ERROR_NO_MORE_ITEMS
);
735 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
736 memcpy(&DeviceInfoData
->ClassGuid
,
739 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
740 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
746 SetLastError(ERROR_INVALID_HANDLE
);
750 /***********************************************************************
751 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
753 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
755 PCSTR InfSectionName
,
756 PSTR InfSectionWithExt
,
757 DWORD InfSectionWithExtSize
,
761 LPWSTR InfSectionNameW
= NULL
;
762 PWSTR InfSectionWithExtW
= NULL
;
764 BOOL bResult
= FALSE
;
770 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
771 if (InfSectionNameW
== NULL
) goto end
;
773 if (InfSectionWithExt
)
775 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
776 if (InfSectionWithExtW
== NULL
) goto end
;
779 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
780 InfSectionWithExt
? InfSectionNameW
: NULL
,
781 InfSectionWithExtSize
, RequiredSize
,
782 Extension
? &ExtensionW
: NULL
);
784 if (bResult
&& InfSectionWithExt
)
786 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
787 InfSectionWithExtSize
, NULL
, NULL
) != 0;
789 if (bResult
&& Extension
)
791 if (ExtensionW
== NULL
)
794 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
798 if (InfSectionNameW
) MyFree(InfSectionNameW
);
799 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
804 /***********************************************************************
805 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
807 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
809 PCWSTR InfSectionName
,
810 PWSTR InfSectionWithExt
,
811 DWORD InfSectionWithExtSize
,
815 WCHAR szBuffer
[MAX_PATH
];
818 LONG lLineCount
= -1;
820 lstrcpyW(szBuffer
, InfSectionName
);
821 dwLength
= lstrlenW(szBuffer
);
823 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
825 /* Test section name with '.NTx86' extension */
826 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
827 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
829 if (lLineCount
== -1)
831 /* Test section name with '.NT' extension */
832 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
833 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
838 /* Test section name with '.Win' extension */
839 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
840 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
843 if (lLineCount
== -1)
845 /* Test section name without extension */
846 szBuffer
[dwLength
] = 0;
847 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
850 if (lLineCount
== -1)
852 SetLastError(ERROR_INVALID_PARAMETER
);
856 dwFullLength
= lstrlenW(szBuffer
);
858 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
860 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
862 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
866 lstrcpyW(InfSectionWithExt
, szBuffer
);
867 if (Extension
!= NULL
)
869 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
873 if (RequiredSize
!= NULL
)
875 *RequiredSize
= dwFullLength
+ 1;
881 /***********************************************************************
882 * SetupDiGetClassDescriptionA (SETUPAPI.@)
884 BOOL WINAPI
SetupDiGetClassDescriptionA(
885 const GUID
* ClassGuid
,
886 PSTR ClassDescription
,
887 DWORD ClassDescriptionSize
,
890 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
891 ClassDescriptionSize
,
892 RequiredSize
, NULL
, NULL
);
895 /***********************************************************************
896 * SetupDiGetClassDescriptionW (SETUPAPI.@)
898 BOOL WINAPI
SetupDiGetClassDescriptionW(
899 const GUID
* ClassGuid
,
900 PWSTR ClassDescription
,
901 DWORD ClassDescriptionSize
,
904 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
905 ClassDescriptionSize
,
906 RequiredSize
, NULL
, NULL
);
909 /***********************************************************************
910 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
912 BOOL WINAPI
SetupDiGetClassDescriptionExA(
913 const GUID
* ClassGuid
,
914 PSTR ClassDescription
,
915 DWORD ClassDescriptionSize
,
920 PWCHAR ClassDescriptionW
;
921 LPWSTR MachineNameW
= NULL
;
925 if (ClassDescriptionSize
> 0)
927 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
928 if (!ClassDescriptionW
)
930 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
936 ClassDescriptionW
= NULL
;
940 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
943 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
949 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
950 NULL
, MachineNameW
, Reserved
);
953 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
954 ClassDescriptionSize
, NULL
, NULL
);
956 if (!ClassDescriptionSize
&& RequiredSize
)
961 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
962 MyFree(MachineNameW
);
966 /***********************************************************************
967 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
969 BOOL WINAPI
SetupDiGetClassDescriptionExW(
970 const GUID
* ClassGuid
,
971 PWSTR ClassDescription
,
972 DWORD ClassDescriptionSize
,
980 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
985 if (hKey
== INVALID_HANDLE_VALUE
)
987 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
991 if (RequiredSize
!= NULL
)
994 if (RegQueryValueExW(hKey
,
1005 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1008 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1009 if (RegQueryValueExW(hKey
,
1013 (LPBYTE
)ClassDescription
,
1025 /***********************************************************************
1026 * SetupDiGetClassDevsA (SETUPAPI.@)
1028 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1034 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1035 flags
, NULL
, NULL
, NULL
);
1038 /***********************************************************************
1039 * SetupDiGetClassDevsW (SETUPAPI.@)
1041 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1047 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1048 flags
, NULL
, NULL
, NULL
);
1051 /***********************************************************************
1052 * SetupDiGetClassDevsExA (SETUPAPI.@)
1054 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1064 LPWSTR enumstrW
= NULL
;
1065 LPWSTR machineW
= NULL
;
1069 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1070 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1073 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1076 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1080 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1081 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1084 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1087 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1089 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1092 HeapFree(GetProcessHeap(), 0, enumstrW
);
1093 HeapFree(GetProcessHeap(), 0, machineW
);
1098 CreateDeviceInfoElement(
1099 IN LPCWSTR InstancePath
,
1100 IN LPCGUID pClassGuid
,
1101 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1104 struct DeviceInfoElement
*deviceInfo
;
1106 *pDeviceInfo
= NULL
;
1108 size
= sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1109 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1112 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1115 memset(deviceInfo
, 0, size
);
1116 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1117 wcscpy(deviceInfo
->Data
, InstancePath
);
1118 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1119 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1120 deviceInfo
->DeviceDescription
= NULL
;
1121 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1122 deviceInfo
->CreationFlags
= 0;
1123 InitializeListHead(&deviceInfo
->DriverListHead
);
1124 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1126 *pDeviceInfo
= deviceInfo
;
1131 CreateDeviceInterface(
1132 IN
struct DeviceInfoElement
* deviceInfo
,
1133 IN LPCWSTR SymbolicLink
,
1134 IN LPCGUID pInterfaceGuid
,
1135 OUT
struct DeviceInterface
**pDeviceInterface
)
1137 struct DeviceInterface
*deviceInterface
;
1139 *pDeviceInterface
= NULL
;
1141 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1142 if (!deviceInterface
)
1144 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1147 deviceInterface
->DeviceInfo
= deviceInfo
;
1148 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1149 deviceInterface
->Flags
= 0; /* FIXME */
1150 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1152 *pDeviceInterface
= deviceInterface
;
1156 static LONG
SETUP_CreateDevListFromEnumerator(
1157 struct DeviceInfoSet
*list
,
1158 LPCGUID pClassGuid OPTIONAL
,
1160 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1162 HKEY hDeviceIdKey
, hInstanceIdKey
;
1163 WCHAR KeyBuffer
[MAX_PATH
];
1164 WCHAR InstancePath
[MAX_PATH
];
1165 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1166 struct DeviceInfoElement
*deviceInfo
;
1168 DWORD dwLength
, dwRegType
;
1171 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1174 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1175 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1176 if (rc
== ERROR_NO_MORE_ITEMS
)
1178 if (rc
!= ERROR_SUCCESS
)
1182 /* Open device id sub key */
1183 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1184 if (rc
!= ERROR_SUCCESS
)
1186 wcscpy(InstancePath
, Enumerator
);
1187 wcscat(InstancePath
, L
"\\");
1188 wcscat(InstancePath
, KeyBuffer
);
1189 wcscat(InstancePath
, L
"\\");
1190 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1192 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1198 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1199 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1200 if (rc
== ERROR_NO_MORE_ITEMS
)
1202 if (rc
!= ERROR_SUCCESS
)
1204 RegCloseKey(hDeviceIdKey
);
1209 /* Open instance id sub key */
1210 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1211 if (rc
!= ERROR_SUCCESS
)
1213 RegCloseKey(hDeviceIdKey
);
1216 *pEndOfInstancePath
= '\0';
1217 wcscat(InstancePath
, KeyBuffer
);
1219 /* Read ClassGUID value */
1220 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1221 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1222 RegCloseKey(hInstanceIdKey
);
1223 if (rc
== ERROR_FILE_NOT_FOUND
)
1226 /* Skip this bad entry as we can't verify it */
1228 /* Set a default GUID for this device */
1229 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1231 else if (rc
!= ERROR_SUCCESS
)
1233 RegCloseKey(hDeviceIdKey
);
1236 else if (dwRegType
!= REG_SZ
)
1238 RegCloseKey(hDeviceIdKey
);
1239 return ERROR_GEN_FAILURE
;
1243 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1244 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1245 /* Bad GUID, skip the entry */
1249 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1251 /* Skip this entry as it is not the right device class */
1255 /* Add the entry to the list */
1256 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1258 RegCloseKey(hDeviceIdKey
);
1259 return GetLastError();
1261 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1262 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1264 RegCloseKey(hDeviceIdKey
);
1267 return ERROR_SUCCESS
;
1270 static LONG
SETUP_CreateDevList(
1271 struct DeviceInfoSet
*list
,
1272 PCWSTR MachineName OPTIONAL
,
1273 LPGUID
class OPTIONAL
,
1274 PCWSTR Enumerator OPTIONAL
)
1276 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1277 WCHAR KeyBuffer
[MAX_PATH
];
1282 if (class && IsEqualIID(class, &GUID_NULL
))
1286 if (MachineName
!= NULL
)
1288 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1289 if (rc
!= ERROR_SUCCESS
)
1293 HKLM
= HKEY_LOCAL_MACHINE
;
1295 rc
= RegOpenKeyExW(HKLM
,
1298 KEY_ENUMERATE_SUB_KEYS
,
1300 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1301 if (rc
!= ERROR_SUCCESS
)
1304 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1305 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1314 KEY_ENUMERATE_SUB_KEYS
,
1316 RegCloseKey(hEnumKey
);
1317 if (rc
!= ERROR_SUCCESS
)
1319 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1320 RegCloseKey(hEnumeratorKey
);
1325 /* Enumerate enumerators */
1329 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1330 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1331 if (rc
== ERROR_NO_MORE_ITEMS
)
1333 if (rc
!= ERROR_SUCCESS
)
1335 RegCloseKey(hEnumKey
);
1341 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1342 if (rc
!= ERROR_SUCCESS
)
1344 RegCloseKey(hEnumKey
);
1348 /* Call SETUP_CreateDevListFromEnumerator */
1349 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1350 RegCloseKey(hEnumeratorKey
);
1351 if (rc
!= ERROR_SUCCESS
)
1353 RegCloseKey(hEnumKey
);
1357 RegCloseKey(hEnumKey
);
1358 return ERROR_SUCCESS
;
1363 static LONG
SETUP_CreateSerialDeviceList(
1364 struct DeviceInfoSet
*list
,
1366 LPGUID InterfaceGuid
,
1367 PCWSTR DeviceInstanceW
)
1369 static const size_t initialSize
= 100;
1371 WCHAR buf
[initialSize
];
1373 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1375 struct DeviceInfoElement
*deviceInfo
;
1378 WARN("'MachineName' is ignored on Wine!\n");
1379 if (DeviceInstanceW
)
1380 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1386 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1388 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1392 HeapFree(GetProcessHeap(), 0, devices
);
1393 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1395 return ERROR_NOT_ENOUGH_MEMORY
;
1401 HeapFree(GetProcessHeap(), 0, devices
);
1402 return GetLastError();
1406 /* 'devices' is a MULTI_SZ string */
1407 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1409 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1411 /* We have found a device */
1412 struct DeviceInterface
*interfaceInfo
;
1413 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1414 /* Step 1. Create a device info element */
1415 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1418 HeapFree(GetProcessHeap(), 0, devices
);
1419 return GetLastError();
1421 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1423 /* Step 2. Create an interface list for this element */
1424 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1427 HeapFree(GetProcessHeap(), 0, devices
);
1428 return GetLastError();
1430 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1434 HeapFree(GetProcessHeap(), 0, devices
);
1435 return ERROR_SUCCESS
;
1438 #else /* __REACTOS__ */
1440 static LONG
SETUP_CreateInterfaceList(
1441 struct DeviceInfoSet
*list
,
1443 LPGUID InterfaceGuid
,
1444 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1446 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1447 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1448 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1449 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1450 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1452 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1455 DWORD dwLength
, dwInstancePathLength
;
1458 struct DeviceInfoElement
*deviceInfo
;
1460 /* Open registry key related to this interface */
1461 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1462 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1463 return GetLastError();
1465 /* Enumerate sub keys of hInterfaceKey */
1469 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1470 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1471 if (rc
== ERROR_NO_MORE_ITEMS
)
1473 if (rc
!= ERROR_SUCCESS
)
1475 RegCloseKey(hInterfaceKey
);
1481 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1482 if (rc
!= ERROR_SUCCESS
)
1484 RegCloseKey(hInterfaceKey
);
1488 /* Read DeviceInstance */
1489 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1490 if (rc
!= ERROR_SUCCESS
)
1492 RegCloseKey(hDeviceInstanceKey
);
1493 RegCloseKey(hInterfaceKey
);
1496 if (dwRegType
!= REG_SZ
)
1498 RegCloseKey(hDeviceInstanceKey
);
1499 RegCloseKey(hInterfaceKey
);
1500 return ERROR_GEN_FAILURE
;
1502 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1505 RegCloseKey(hDeviceInstanceKey
);
1506 RegCloseKey(hInterfaceKey
);
1507 return ERROR_NOT_ENOUGH_MEMORY
;
1509 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1510 if (rc
!= ERROR_SUCCESS
)
1512 HeapFree(GetProcessHeap(), 0, InstancePath
);
1513 RegCloseKey(hDeviceInstanceKey
);
1514 RegCloseKey(hInterfaceKey
);
1517 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1518 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1520 if (DeviceInstanceW
)
1522 /* Check if device enumerator is not the right one */
1523 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1525 HeapFree(GetProcessHeap(), 0, InstancePath
);
1526 RegCloseKey(hDeviceInstanceKey
);
1531 /* Find class GUID associated to the device instance */
1536 KEY_ENUMERATE_SUB_KEYS
,
1538 if (rc
!= ERROR_SUCCESS
)
1540 HeapFree(GetProcessHeap(), 0, InstancePath
);
1541 RegCloseKey(hDeviceInstanceKey
);
1542 RegCloseKey(hInterfaceKey
);
1551 RegCloseKey(hEnumKey
);
1552 if (rc
!= ERROR_SUCCESS
)
1554 HeapFree(GetProcessHeap(), 0, InstancePath
);
1555 RegCloseKey(hDeviceInstanceKey
);
1556 RegCloseKey(hInterfaceKey
);
1559 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1560 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1562 if (rc
!= ERROR_SUCCESS
)
1564 HeapFree(GetProcessHeap(), 0, InstancePath
);
1565 RegCloseKey(hDeviceInstanceKey
);
1566 RegCloseKey(hInterfaceKey
);
1569 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1570 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1571 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1573 HeapFree(GetProcessHeap(), 0, InstancePath
);
1574 RegCloseKey(hDeviceInstanceKey
);
1575 RegCloseKey(hInterfaceKey
);
1576 return ERROR_GEN_FAILURE
;
1578 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1580 /* If current device doesn't match the list GUID (if any), skip this entry */
1581 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1583 HeapFree(GetProcessHeap(), 0, InstancePath
);
1584 RegCloseKey(hDeviceInstanceKey
);
1588 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1592 LPWSTR pSymbolicLink
;
1593 struct DeviceInterface
*interfaceInfo
;
1595 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1596 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1597 if (rc
== ERROR_NO_MORE_ITEMS
)
1599 if (rc
!= ERROR_SUCCESS
)
1601 HeapFree(GetProcessHeap(), 0, InstancePath
);
1602 RegCloseKey(hDeviceInstanceKey
);
1603 RegCloseKey(hInterfaceKey
);
1607 if (KeyBuffer
[0] != '#')
1608 /* This entry doesn't represent an interesting entry */
1612 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1613 if (rc
!= ERROR_SUCCESS
)
1615 RegCloseKey(hDeviceInstanceKey
);
1616 RegCloseKey(hInterfaceKey
);
1620 /* Read SymbolicLink value */
1621 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1622 if (rc
!= ERROR_SUCCESS
)
1624 RegCloseKey(hReferenceKey
);
1625 RegCloseKey(hDeviceInstanceKey
);
1626 RegCloseKey(hInterfaceKey
);
1629 if (dwRegType
!= REG_SZ
)
1631 RegCloseKey(hReferenceKey
);
1632 RegCloseKey(hDeviceInstanceKey
);
1633 RegCloseKey(hInterfaceKey
);
1634 return ERROR_GEN_FAILURE
;
1637 /* We have found a device */
1638 /* Step 1. Create a device info element */
1639 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1641 RegCloseKey(hReferenceKey
);
1642 RegCloseKey(hDeviceInstanceKey
);
1643 RegCloseKey(hInterfaceKey
);
1644 return GetLastError();
1646 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1647 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1649 /* Step 2. Create an interface list for this element */
1650 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1653 RegCloseKey(hReferenceKey
);
1654 RegCloseKey(hDeviceInstanceKey
);
1655 RegCloseKey(hInterfaceKey
);
1656 return ERROR_NOT_ENOUGH_MEMORY
;
1658 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1659 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1660 RegCloseKey(hReferenceKey
);
1661 if (rc
!= ERROR_SUCCESS
)
1663 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1664 RegCloseKey(hDeviceInstanceKey
);
1665 RegCloseKey(hInterfaceKey
);
1668 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1670 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1671 RegCloseKey(hDeviceInstanceKey
);
1672 RegCloseKey(hInterfaceKey
);
1673 return GetLastError();
1675 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1676 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1677 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1679 RegCloseKey(hDeviceInstanceKey
);
1681 RegCloseKey(hInterfaceKey
);
1682 return ERROR_SUCCESS
;
1684 #endif /* __REACTOS__ */
1686 /***********************************************************************
1687 * SetupDiGetClassDevsExW (SETUPAPI.@)
1689 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1698 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1699 struct DeviceInfoSet
*list
;
1703 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1704 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1706 /* Create the deviceset if not set */
1709 list
= (struct DeviceInfoSet
*)deviceset
;
1710 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1712 SetLastError(ERROR_INVALID_HANDLE
);
1713 return INVALID_HANDLE_VALUE
;
1715 hDeviceInfo
= deviceset
;
1719 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1720 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1721 NULL
, machine
, NULL
);
1722 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1723 return INVALID_HANDLE_VALUE
;
1724 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1727 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1730 pClassGuid
= &list
->ClassGuid
;
1732 if (flags
& DIGCF_PRESENT
)
1733 FIXME(": flag DIGCF_PRESENT ignored\n");
1734 if (flags
& DIGCF_PROFILE
)
1735 FIXME(": flag DIGCF_PROFILE ignored\n");
1737 if (flags
& DIGCF_ALLCLASSES
)
1739 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1740 if (rc
!= ERROR_SUCCESS
)
1744 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1745 return INVALID_HANDLE_VALUE
;
1749 else if (flags
& DIGCF_DEVICEINTERFACE
)
1753 SetLastError(ERROR_INVALID_PARAMETER
);
1755 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1756 return INVALID_HANDLE_VALUE
;
1760 /* Special case: find serial ports by calling QueryDosDevice */
1761 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1762 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1763 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1764 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1767 ERR("Wine can only enumerate serial devices at the moment!\n");
1768 rc
= ERROR_INVALID_PARAMETER
;
1770 #else /* __REACTOS__ */
1771 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1772 #endif /* __REACTOS__ */
1773 if (rc
!= ERROR_SUCCESS
)
1777 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1778 return INVALID_HANDLE_VALUE
;
1784 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1785 if (rc
!= ERROR_SUCCESS
)
1789 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1790 return INVALID_HANDLE_VALUE
;
1796 /***********************************************************************
1797 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1799 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1800 HDEVINFO DeviceInfoSet
,
1801 PSP_DEVINFO_DATA DeviceInfoData
,
1802 CONST GUID
* InterfaceClassGuid
,
1804 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1808 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1809 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1811 if (!DeviceInterfaceData
)
1812 SetLastError(ERROR_INVALID_PARAMETER
);
1813 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1814 SetLastError(ERROR_INVALID_USER_BUFFER
);
1815 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1817 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1819 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1821 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1823 while (ItemList
!= &list
->ListHead
&& !Found
)
1825 PLIST_ENTRY InterfaceListEntry
;
1826 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1827 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1829 /* We are not searching for this element */
1830 ItemList
= ItemList
->Flink
;
1833 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1834 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1836 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1837 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1839 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1842 if (MemberIndex
-- == 0)
1844 /* return this item */
1845 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1846 &DevItf
->InterfaceClassGuid
,
1848 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1849 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1852 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1854 ItemList
= ItemList
->Flink
;
1857 SetLastError(ERROR_NO_MORE_ITEMS
);
1862 SetLastError(ERROR_INVALID_HANDLE
);
1865 SetLastError(ERROR_INVALID_HANDLE
);
1869 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
1871 InterlockedIncrement(&infFile
->References
);
1874 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
1876 if (InterlockedDecrement(&infFile
->References
) == 0)
1878 SetupCloseInfFile(infFile
->hInf
);
1879 HeapFree(GetProcessHeap(), 0, infFile
);
1883 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
1885 DereferenceInfFile(driverInfo
->InfFileDetails
);
1886 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
1887 HeapFree(GetProcessHeap(), 0, driverInfo
);
1891 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
1893 PLIST_ENTRY ListEntry
;
1894 struct DriverInfoElement
*driverInfo
;
1896 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1898 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1899 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
1900 if (!DestroyDriverInfoElement(driverInfo
))
1903 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1905 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1906 HeapFree(GetProcessHeap(), 0, ListEntry
);
1908 HeapFree(GetProcessHeap(), 0, deviceInfo
);
1912 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
1914 PLIST_ENTRY ListEntry
;
1915 struct DeviceInfoElement
*deviceInfo
;
1917 while (!IsListEmpty(&list
->ListHead
))
1919 ListEntry
= RemoveHeadList(&list
->ListHead
);
1920 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1921 if (!DestroyDeviceInfoElement(deviceInfo
))
1924 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1925 RegCloseKey(list
->HKLM
);
1926 CM_Disconnect_Machine(list
->hMachine
);
1927 HeapFree(GetProcessHeap(), 0, list
);
1931 /***********************************************************************
1932 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1934 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1938 TRACE("%p\n", devinfo
);
1939 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1941 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1943 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1944 ret
= DestroyDeviceInfoSet(list
);
1946 SetLastError(ERROR_INVALID_HANDLE
);
1949 SetLastError(ERROR_INVALID_HANDLE
);
1951 TRACE("Returning %d\n", ret
);
1955 /***********************************************************************
1956 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1958 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1959 HDEVINFO DeviceInfoSet
,
1960 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1961 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1962 DWORD DeviceInterfaceDetailDataSize
,
1963 PDWORD RequiredSize
,
1964 PSP_DEVINFO_DATA DeviceInfoData
)
1966 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
1967 DWORD sizeW
= 0, sizeA
;
1970 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
1971 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1972 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1974 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
1975 SetLastError(ERROR_INVALID_USER_BUFFER
);
1976 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
1977 SetLastError(ERROR_INVALID_PARAMETER
);
1978 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
1979 SetLastError(ERROR_INVALID_PARAMETER
);
1982 if (DeviceInterfaceDetailData
!= NULL
)
1984 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
1985 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
1986 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
1987 if (!DeviceInterfaceDetailDataW
)
1989 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1992 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
1994 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
1995 ret
= SetupDiGetDeviceInterfaceDetailW(
1997 DeviceInterfaceData
,
1998 DeviceInterfaceDetailDataW
,
2002 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2003 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2005 *RequiredSize
= sizeA
;
2006 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2008 if (!WideCharToMultiByte(
2010 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2011 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2018 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2021 TRACE("Returning %d\n", ret
);
2025 /***********************************************************************
2026 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2028 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2029 HDEVINFO DeviceInfoSet
,
2030 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2031 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2032 DWORD DeviceInterfaceDetailDataSize
,
2033 PDWORD RequiredSize
,
2034 PSP_DEVINFO_DATA DeviceInfoData
)
2036 struct DeviceInfoSet
*list
;
2039 TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
2040 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2041 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2043 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2044 SetLastError(ERROR_INVALID_PARAMETER
);
2045 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2046 SetLastError(ERROR_INVALID_HANDLE
);
2047 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2048 SetLastError(ERROR_INVALID_HANDLE
);
2049 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2050 SetLastError(ERROR_INVALID_USER_BUFFER
);
2051 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2052 SetLastError(ERROR_INVALID_USER_BUFFER
);
2053 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2054 SetLastError(ERROR_INVALID_USER_BUFFER
);
2055 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2056 SetLastError(ERROR_INVALID_PARAMETER
);
2057 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2058 SetLastError(ERROR_INVALID_PARAMETER
);
2061 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2062 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2063 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2064 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2066 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2068 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2070 *RequiredSize
= sizeRequired
;
2074 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2075 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2078 memcpy(&DeviceInfoData
->ClassGuid
,
2079 &deviceInterface
->DeviceInfo
->ClassGuid
,
2081 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
2082 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2088 TRACE("Returning %d\n", ret
);
2092 /***********************************************************************
2093 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2095 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2097 PSP_DEVINFO_DATA DeviceInfoData
,
2099 PDWORD PropertyRegDataType
,
2100 PBYTE PropertyBuffer
,
2101 DWORD PropertyBufferSize
,
2102 PDWORD RequiredSize
)
2105 BOOL bIsStringProperty
;
2107 DWORD RequiredSizeA
, RequiredSizeW
;
2108 DWORD PropertyBufferSizeW
;
2109 PBYTE PropertyBufferW
;
2111 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2112 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2115 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2116 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2118 bResult
= SetupDiGetDeviceRegistryPropertyW(
2124 PropertyBufferSizeW
,
2127 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2129 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2131 if (bIsStringProperty
)
2132 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2134 RequiredSizeA
= RequiredSizeW
;
2136 *RequiredSize
= RequiredSizeA
;
2137 if (PropertyRegDataType
)
2138 *PropertyRegDataType
= RegType
;
2143 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2147 if (RequiredSizeA
<= PropertyBufferSize
)
2149 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2151 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2153 /* Last error is already set by WideCharToMultiByte */
2158 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2162 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2166 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2170 /***********************************************************************
2171 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2173 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2174 HDEVINFO DeviceInfoSet
,
2175 PSP_DEVINFO_DATA DeviceInfoData
,
2177 PDWORD PropertyRegDataType
,
2178 PBYTE PropertyBuffer
,
2179 DWORD PropertyBufferSize
,
2180 PDWORD RequiredSize
)
2182 HKEY hEnumKey
, hKey
;
2186 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2187 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2190 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2191 SetLastError(ERROR_INVALID_HANDLE
);
2192 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2193 SetLastError(ERROR_INVALID_HANDLE
);
2194 else if (!DeviceInfoData
)
2195 SetLastError(ERROR_INVALID_PARAMETER
);
2196 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2197 SetLastError(ERROR_INVALID_USER_BUFFER
);
2198 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2199 SetLastError(ERROR_INVALID_PARAMETER
);
2202 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2203 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2207 case SPDRP_CAPABILITIES
:
2209 case SPDRP_CLASSGUID
:
2210 case SPDRP_COMPATIBLEIDS
:
2211 case SPDRP_CONFIGFLAGS
:
2212 case SPDRP_DEVICEDESC
:
2214 case SPDRP_FRIENDLYNAME
:
2215 case SPDRP_HARDWAREID
:
2216 case SPDRP_LOCATION_INFORMATION
:
2217 case SPDRP_LOWERFILTERS
:
2219 case SPDRP_SECURITY
:
2221 case SPDRP_UI_NUMBER
:
2222 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2223 case SPDRP_UPPERFILTERS
:
2225 LPCWSTR RegistryPropertyName
;
2230 case SPDRP_CAPABILITIES
:
2231 RegistryPropertyName
= L
"Capabilities"; break;
2233 RegistryPropertyName
= L
"Class"; break;
2234 case SPDRP_CLASSGUID
:
2235 RegistryPropertyName
= L
"ClassGUID"; break;
2236 case SPDRP_COMPATIBLEIDS
:
2237 RegistryPropertyName
= L
"CompatibleIDs"; break;
2238 case SPDRP_CONFIGFLAGS
:
2239 RegistryPropertyName
= L
"ConfigFlags"; break;
2240 case SPDRP_DEVICEDESC
:
2241 RegistryPropertyName
= L
"DeviceDesc"; break;
2243 RegistryPropertyName
= L
"Driver"; break;
2244 case SPDRP_FRIENDLYNAME
:
2245 RegistryPropertyName
= L
"FriendlyName"; break;
2246 case SPDRP_HARDWAREID
:
2247 RegistryPropertyName
= L
"HardwareID"; break;
2248 case SPDRP_LOCATION_INFORMATION
:
2249 RegistryPropertyName
= L
"LocationInformation"; break;
2250 case SPDRP_LOWERFILTERS
:
2251 RegistryPropertyName
= L
"LowerFilters"; break;
2253 RegistryPropertyName
= L
"Mfg"; break;
2254 case SPDRP_SECURITY
:
2255 RegistryPropertyName
= L
"Security"; break;
2257 RegistryPropertyName
= L
"Service"; break;
2258 case SPDRP_UI_NUMBER
:
2259 RegistryPropertyName
= L
"UINumber"; break;
2260 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2261 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2262 case SPDRP_UPPERFILTERS
:
2263 RegistryPropertyName
= L
"UpperFilters"; break;
2265 /* Should not happen */
2266 RegistryPropertyName
= NULL
; break;
2269 /* Open registry key name */
2274 KEY_ENUMERATE_SUB_KEYS
,
2276 if (rc
!= ERROR_SUCCESS
)
2287 RegCloseKey(hEnumKey
);
2288 if (rc
!= ERROR_SUCCESS
)
2293 /* Read registry entry */
2294 BufferSize
= PropertyBufferSize
;
2295 rc
= RegQueryValueExW(
2297 RegistryPropertyName
,
2298 NULL
, /* Reserved */
2299 PropertyRegDataType
,
2303 *RequiredSize
= BufferSize
;
2306 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2309 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2311 case ERROR_MORE_DATA
:
2312 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2321 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2323 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2325 if (PropertyRegDataType
)
2326 *PropertyRegDataType
= REG_SZ
;
2328 *RequiredSize
= required
;
2329 if (PropertyBufferSize
>= required
)
2331 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2335 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2339 /*case SPDRP_BUSTYPEGUID:
2340 case SPDRP_LEGACYBUSTYPE:
2341 case SPDRP_BUSNUMBER:
2342 case SPDRP_ENUMERATOR_NAME:
2343 case SPDRP_SECURITY_SDS:
2345 case SPDRP_EXCLUSIVE:
2346 case SPDRP_CHARACTERISTICS:
2348 case SPDRP_DEVICE_POWER_DATA:*/
2349 #if (WINVER >= 0x501)
2350 /*case SPDRP_REMOVAL_POLICY:
2351 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2352 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2353 case SPDRP_INSTALL_STATE:*/
2358 ERR("Property 0x%lx not implemented\n", Property
);
2359 SetLastError(ERROR_NOT_SUPPORTED
);
2364 TRACE("Returning %d\n", ret
);
2368 /***********************************************************************
2369 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2371 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2372 IN HDEVINFO DeviceInfoSet
,
2373 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2375 IN CONST BYTE
*PropertyBuffer
,
2376 IN DWORD PropertyBufferSize
)
2378 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2379 Property
, PropertyBuffer
, PropertyBufferSize
);
2380 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2384 /***********************************************************************
2385 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2387 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2388 IN HDEVINFO DeviceInfoSet
,
2389 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2391 IN
const BYTE
*PropertyBuffer
,
2392 IN DWORD PropertyBufferSize
)
2394 struct DeviceInfoSet
*list
;
2397 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2398 Property
, PropertyBuffer
, PropertyBufferSize
);
2401 SetLastError(ERROR_INVALID_HANDLE
);
2402 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2403 SetLastError(ERROR_INVALID_HANDLE
);
2404 else if (DeviceInfoData
)
2405 SetLastError(ERROR_INVALID_HANDLE
);
2406 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2407 SetLastError(ERROR_INVALID_USER_BUFFER
);
2412 case SPDRP_COMPATIBLEIDS
:
2413 case SPDRP_CONFIGFLAGS
:
2414 case SPDRP_FRIENDLYNAME
:
2415 case SPDRP_HARDWAREID
:
2416 case SPDRP_LOCATION_INFORMATION
:
2417 case SPDRP_LOWERFILTERS
:
2418 case SPDRP_SECURITY
:
2420 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2421 case SPDRP_UPPERFILTERS
:
2423 LPCWSTR RegistryPropertyName
;
2424 DWORD RegistryDataType
;
2430 case SPDRP_COMPATIBLEIDS
:
2431 RegistryPropertyName
= L
"CompatibleIDs";
2432 RegistryDataType
= REG_MULTI_SZ
;
2434 case SPDRP_CONFIGFLAGS
:
2435 RegistryPropertyName
= L
"ConfigFlags";
2436 RegistryDataType
= REG_DWORD
;
2438 case SPDRP_FRIENDLYNAME
:
2439 RegistryPropertyName
= L
"FriendlyName";
2440 RegistryDataType
= REG_SZ
;
2442 case SPDRP_HARDWAREID
:
2443 RegistryPropertyName
= L
"HardwareID";
2444 RegistryDataType
= REG_MULTI_SZ
;
2446 case SPDRP_LOCATION_INFORMATION
:
2447 RegistryPropertyName
= L
"LocationInformation";
2448 RegistryDataType
= REG_SZ
;
2450 case SPDRP_LOWERFILTERS
:
2451 RegistryPropertyName
= L
"LowerFilters";
2452 RegistryDataType
= REG_MULTI_SZ
;
2454 case SPDRP_SECURITY
:
2455 RegistryPropertyName
= L
"Security";
2456 RegistryDataType
= REG_BINARY
;
2459 RegistryPropertyName
= L
"Service";
2460 RegistryDataType
= REG_SZ
;
2462 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2463 RegistryPropertyName
= L
"UINumberDescFormat";
2464 RegistryDataType
= REG_SZ
;
2466 case SPDRP_UPPERFILTERS
:
2467 RegistryPropertyName
= L
"UpperFilters";
2468 RegistryDataType
= REG_MULTI_SZ
;
2471 /* Should not happen */
2472 RegistryPropertyName
= NULL
;
2473 RegistryDataType
= REG_BINARY
;
2476 /* Open device registry key */
2477 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2478 if (hKey
!= INVALID_HANDLE_VALUE
)
2480 /* Write new data */
2481 rc
= RegSetValueExW(
2483 RegistryPropertyName
,
2487 PropertyBufferSize
);
2488 if (rc
== ERROR_SUCCESS
)
2497 /*case SPDRP_CHARACTERISTICS:
2499 case SPDRP_EXCLUSIVE:*/
2500 #if (WINVER >= 0x501)
2501 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2503 //case SPDRP_SECURITY_SDS:
2507 ERR("Property 0x%lx not implemented\n", Property
);
2508 SetLastError(ERROR_NOT_SUPPORTED
);
2513 TRACE("Returning %d\n", ret
);
2517 /***********************************************************************
2518 * SetupDiInstallClassA (SETUPAPI.@)
2520 BOOL WINAPI
SetupDiInstallClassA(
2526 UNICODE_STRING FileNameW
;
2529 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2531 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2535 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2537 RtlFreeUnicodeString(&FileNameW
);
2542 static HKEY
CreateClassKey(HINF hInf
)
2544 WCHAR FullBuffer
[MAX_PATH
];
2545 WCHAR Buffer
[MAX_PATH
];
2550 if (!SetupGetLineTextW(NULL
,
2558 return INVALID_HANDLE_VALUE
;
2561 lstrcpyW(FullBuffer
, ControlClass
);
2562 lstrcatW(FullBuffer
, Buffer
);
2565 if (!SetupGetLineTextW(NULL
,
2573 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2574 return INVALID_HANDLE_VALUE
;
2577 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2581 REG_OPTION_NON_VOLATILE
,
2587 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2588 return INVALID_HANDLE_VALUE
;
2591 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2596 RequiredSize
* sizeof(WCHAR
)))
2598 RegCloseKey(hClassKey
);
2599 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2600 return INVALID_HANDLE_VALUE
;
2606 /***********************************************************************
2607 * SetupDiInstallClassW (SETUPAPI.@)
2609 BOOL WINAPI
SetupDiInstallClassW(
2615 WCHAR SectionName
[MAX_PATH
];
2616 DWORD SectionNameLength
= 0;
2618 BOOL bFileQueueCreated
= FALSE
;
2621 FIXME("not fully implemented\n");
2623 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2625 SetLastError(ERROR_INVALID_PARAMETER
);
2629 /* Open the .inf file */
2630 hInf
= SetupOpenInfFileW(InfFileName
,
2634 if (hInf
== INVALID_HANDLE_VALUE
)
2640 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2641 hClassKey
= CreateClassKey(hInf
);
2642 if (hClassKey
== INVALID_HANDLE_VALUE
)
2644 SetupCloseInfFile(hInf
);
2650 /* Try to append a layout file */
2652 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2655 /* Retrieve the actual section name */
2656 SetupDiGetActualSectionToInstallW(hInf
,
2664 if (!(Flags
& DI_NOVCP
))
2666 FileQueue
= SetupOpenFileQueue();
2667 if (FileQueue
== INVALID_HANDLE_VALUE
)
2669 SetupCloseInfFile(hInf
);
2670 RegCloseKey(hClassKey
);
2674 bFileQueueCreated
= TRUE
;
2679 SetupInstallFromInfSectionW(NULL
,
2688 INVALID_HANDLE_VALUE
,
2691 /* FIXME: More code! */
2693 if (bFileQueueCreated
)
2694 SetupCloseFileQueue(FileQueue
);
2696 SetupCloseInfFile(hInf
);
2698 RegCloseKey(hClassKey
);
2703 /***********************************************************************
2704 * SetupDiOpenClassRegKey (SETUPAPI.@)
2706 HKEY WINAPI
SetupDiOpenClassRegKey(
2707 const GUID
* ClassGuid
,
2710 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2711 DIOCR_INSTALLER
, NULL
, NULL
);
2715 /***********************************************************************
2716 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2718 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2719 const GUID
* ClassGuid
,
2725 PWSTR MachineNameW
= NULL
;
2732 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2733 if (MachineNameW
== NULL
)
2734 return INVALID_HANDLE_VALUE
;
2737 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2738 Flags
, MachineNameW
, Reserved
);
2741 MyFree(MachineNameW
);
2747 /***********************************************************************
2748 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2750 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2751 const GUID
* ClassGuid
,
2757 LPWSTR lpGuidString
;
2758 LPWSTR lpFullGuidString
;
2766 if (Flags
== DIOCR_INSTALLER
)
2768 lpKeyName
= ControlClass
;
2770 else if (Flags
== DIOCR_INTERFACE
)
2772 lpKeyName
= DeviceClasses
;
2776 ERR("Invalid Flags parameter!\n");
2777 SetLastError(ERROR_INVALID_PARAMETER
);
2778 return INVALID_HANDLE_VALUE
;
2781 if (MachineName
!= NULL
)
2783 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2784 if (rc
!= ERROR_SUCCESS
)
2787 return INVALID_HANDLE_VALUE
;
2791 HKLM
= HKEY_LOCAL_MACHINE
;
2793 rc
= RegOpenKeyExW(HKLM
,
2798 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2799 if (rc
!= ERROR_SUCCESS
)
2802 return INVALID_HANDLE_VALUE
;
2805 if (ClassGuid
== NULL
)
2808 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2810 SetLastError(ERROR_GEN_FAILURE
);
2811 RegCloseKey(hClassesKey
);
2812 return INVALID_HANDLE_VALUE
;
2815 dwLength
= lstrlenW(lpGuidString
);
2816 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2817 if (!lpFullGuidString
)
2819 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2820 RpcStringFreeW(&lpGuidString
);
2821 return INVALID_HANDLE_VALUE
;
2823 lpFullGuidString
[0] = '{';
2824 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2825 lpFullGuidString
[dwLength
+ 1] = '}';
2826 lpFullGuidString
[dwLength
+ 2] = '\0';
2827 RpcStringFreeW(&lpGuidString
);
2829 rc
= RegOpenKeyExW(hClassesKey
,
2834 if (rc
!= ERROR_SUCCESS
)
2837 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2838 RegCloseKey(hClassesKey
);
2839 return INVALID_HANDLE_VALUE
;
2842 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2843 RegCloseKey(hClassesKey
);
2848 /***********************************************************************
2849 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2851 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2852 HDEVINFO DeviceInfoSet
,
2855 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2857 FIXME("%p %s %08lx %p\n",
2858 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2862 /***********************************************************************
2863 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2865 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2866 HDEVINFO DeviceInfoSet
,
2869 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2871 LPWSTR DevicePathW
= NULL
;
2874 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2876 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2877 if (DevicePathW
== NULL
)
2880 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2881 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2883 MyFree(DevicePathW
);
2888 /***********************************************************************
2889 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2891 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2892 HDEVINFO DeviceInfoSet
,
2893 PSP_DEVINFO_DATA DeviceInfoData
,
2894 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2895 DWORD ClassInstallParamsSize
)
2897 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2898 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2904 IN PWSTR InstallerName
,
2905 OUT HMODULE
* ModulePointer
,
2906 OUT PVOID
* FunctionPointer
)
2908 HMODULE hModule
= NULL
;
2909 LPSTR FunctionNameA
= NULL
;
2913 *ModulePointer
= NULL
;
2914 *FunctionPointer
= NULL
;
2916 Comma
= strchrW(InstallerName
, ',');
2919 rc
= ERROR_INVALID_PARAMETER
;
2925 hModule
= LoadLibraryW(InstallerName
);
2929 rc
= GetLastError();
2933 /* Skip comma spaces */
2934 while (*Comma
== ',' || isspaceW(*Comma
))
2937 /* W->A conversion for function name */
2938 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
2941 rc
= GetLastError();
2945 /* Search function */
2946 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
2947 if (!*FunctionPointer
)
2949 rc
= GetLastError();
2953 *ModulePointer
= hModule
;
2957 if (rc
!= ERROR_SUCCESS
&& hModule
)
2958 FreeLibrary(hModule
);
2959 MyFree(FunctionNameA
);
2964 FreeFunctionPointer(
2965 IN HMODULE ModulePointer
,
2966 IN PVOID FunctionPointer
)
2968 if (ModulePointer
== NULL
)
2969 return ERROR_SUCCESS
;
2970 if (FreeLibrary(ModulePointer
))
2971 return ERROR_SUCCESS
;
2973 return GetLastError();
2976 /***********************************************************************
2977 * SetupDiCallClassInstaller (SETUPAPI.@)
2979 BOOL WINAPI
SetupDiCallClassInstaller(
2980 IN DI_FUNCTION InstallFunction
,
2981 IN HDEVINFO DeviceInfoSet
,
2982 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2986 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
2989 SetLastError(ERROR_INVALID_PARAMETER
);
2990 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2991 SetLastError(ERROR_INVALID_HANDLE
);
2992 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2993 SetLastError(ERROR_INVALID_HANDLE
);
2994 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2995 SetLastError(ERROR_INVALID_HANDLE
);
2996 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2997 SetLastError(ERROR_INVALID_USER_BUFFER
);
3000 SP_DEVINSTALL_PARAMS_W InstallParams
;
3001 #define CLASS_COINSTALLER 0x1
3002 #define DEVICE_COINSTALLER 0x2
3003 #define CLASS_INSTALLER 0x4
3004 UCHAR CanHandle
= 0;
3005 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3007 switch (InstallFunction
)
3009 case DIF_ALLOW_INSTALL
:
3010 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3012 case DIF_DESTROYPRIVATEDATA
:
3013 CanHandle
= CLASS_INSTALLER
;
3015 case DIF_INSTALLDEVICE
:
3016 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3017 DefaultHandler
= SetupDiInstallDevice
;
3019 case DIF_INSTALLDEVICEFILES
:
3020 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3021 DefaultHandler
= SetupDiInstallDriverFiles
;
3023 case DIF_INSTALLINTERFACES
:
3024 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3025 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3027 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3028 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3030 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3031 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3033 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3034 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3036 case DIF_REGISTER_COINSTALLERS
:
3037 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3038 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3040 case DIF_SELECTBESTCOMPATDRV
:
3041 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3042 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3045 ERR("Install function %lu not supported\n", InstallFunction
);
3046 SetLastError(ERROR_NOT_SUPPORTED
);
3049 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3050 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3051 /* Don't process this call, as a parameter is invalid */
3056 LIST_ENTRY ClassCoInstallersListHead
;
3057 LIST_ENTRY DeviceCoInstallersListHead
;
3058 HMODULE ClassInstallerLibrary
= NULL
;
3059 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3060 COINSTALLER_CONTEXT_DATA Context
;
3061 PLIST_ENTRY ListEntry
;
3063 DWORD dwRegType
, dwLength
;
3064 DWORD rc
= NO_ERROR
;
3066 InitializeListHead(&ClassCoInstallersListHead
);
3067 InitializeListHead(&DeviceCoInstallersListHead
);
3069 if (CanHandle
& DEVICE_COINSTALLER
)
3071 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3072 if (hKey
!= INVALID_HANDLE_VALUE
)
3074 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3075 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3077 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3078 if (KeyBuffer
!= NULL
)
3080 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3081 if (rc
== ERROR_SUCCESS
)
3084 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3086 /* Add coinstaller to DeviceCoInstallersListHead list */
3087 struct CoInstallerElement
*coinstaller
;
3088 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3089 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3092 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3093 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3094 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3096 HeapFree(GetProcessHeap(), 0, coinstaller
);
3099 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3105 if (CanHandle
& CLASS_COINSTALLER
)
3109 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3113 if (rc
== ERROR_SUCCESS
)
3115 LPWSTR lpGuidString
;
3116 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3118 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3119 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3121 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3122 if (KeyBuffer
!= NULL
)
3124 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3125 if (rc
== ERROR_SUCCESS
)
3128 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3130 /* Add coinstaller to ClassCoInstallersListHead list */
3131 struct CoInstallerElement
*coinstaller
;
3132 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3133 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3136 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3137 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3138 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3140 HeapFree(GetProcessHeap(), 0, coinstaller
);
3143 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3146 RpcStringFreeW(&lpGuidString
);
3151 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3153 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3154 if (hKey
!= INVALID_HANDLE_VALUE
)
3156 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3157 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3159 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3160 if (KeyBuffer
!= NULL
)
3162 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3163 if (rc
== ERROR_SUCCESS
)
3165 /* Get ClassInstaller function pointer */
3166 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3167 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3169 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3170 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3173 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3180 /* Call Class co-installers */
3181 Context
.PostProcessing
= FALSE
;
3183 ListEntry
= ClassCoInstallersListHead
.Flink
;
3184 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3186 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3187 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3188 coinstaller
->PrivateData
= Context
.PrivateData
;
3189 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3191 coinstaller
->DoPostProcessing
= TRUE
;
3194 ListEntry
= ListEntry
->Flink
;
3197 /* Call Device co-installers */
3198 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3199 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3201 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3202 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3203 coinstaller
->PrivateData
= Context
.PrivateData
;
3204 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3206 coinstaller
->DoPostProcessing
= TRUE
;
3209 ListEntry
= ListEntry
->Flink
;
3212 /* Call Class installer */
3215 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3216 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3219 rc
= ERROR_DI_DO_DEFAULT
;
3221 /* Call default handler */
3222 if (rc
== ERROR_DI_DO_DEFAULT
)
3224 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3226 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3229 rc
= GetLastError();
3235 /* Call Class co-installers that required postprocessing */
3236 Context
.PostProcessing
= TRUE
;
3237 ListEntry
= ClassCoInstallersListHead
.Flink
;
3238 while (ListEntry
!= &ClassCoInstallersListHead
)
3240 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3241 if (coinstaller
->DoPostProcessing
)
3243 Context
.InstallResult
= rc
;
3244 Context
.PrivateData
= coinstaller
->PrivateData
;
3245 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3247 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3248 ListEntry
= ListEntry
->Flink
;
3251 /* Call Device co-installers that required postprocessing */
3252 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3253 while (ListEntry
!= &DeviceCoInstallersListHead
)
3255 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3256 if (coinstaller
->DoPostProcessing
)
3258 Context
.InstallResult
= rc
;
3259 Context
.PrivateData
= coinstaller
->PrivateData
;
3260 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3262 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3263 ListEntry
= ListEntry
->Flink
;
3266 /* Free allocated memory */
3267 while (!IsListEmpty(&ClassCoInstallersListHead
))
3269 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3270 HeapFree(GetProcessHeap(), 0, ListEntry
);
3272 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3274 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3275 HeapFree(GetProcessHeap(), 0, ListEntry
);
3278 ret
= (rc
== NO_ERROR
);
3282 TRACE("Returning %d\n", ret
);
3286 /***********************************************************************
3287 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3289 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3290 IN HDEVINFO DeviceInfoSet
,
3291 IN PSP_DEVINFO_DATA DeviceInfoData
,
3292 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3294 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3297 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3299 if (DeviceInstallParams
== NULL
)
3300 SetLastError(ERROR_INVALID_PARAMETER
);
3301 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3302 SetLastError(ERROR_INVALID_USER_BUFFER
);
3305 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3306 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3310 /* Do W->A conversion */
3312 DeviceInstallParams
,
3313 &deviceInstallParamsW
,
3314 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3315 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3316 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3318 DeviceInstallParams
->DriverPath
[0] = '\0';
3324 TRACE("Returning %d\n", ret
);
3328 /***********************************************************************
3329 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3331 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3332 IN HDEVINFO DeviceInfoSet
,
3333 IN PSP_DEVINFO_DATA DeviceInfoData
,
3334 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3336 struct DeviceInfoSet
*list
;
3339 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3342 SetLastError(ERROR_INVALID_HANDLE
);
3343 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3344 SetLastError(ERROR_INVALID_HANDLE
);
3345 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3346 SetLastError(ERROR_INVALID_USER_BUFFER
);
3347 else if (!DeviceInstallParams
)
3348 SetLastError(ERROR_INVALID_PARAMETER
);
3349 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3350 SetLastError(ERROR_INVALID_USER_BUFFER
);
3353 PSP_DEVINSTALL_PARAMS_W Source
;
3356 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3358 Source
= &list
->InstallParams
;
3359 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3363 TRACE("Returning %d\n", ret
);
3367 /***********************************************************************
3368 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3370 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3371 IN HDEVINFO DeviceInfoSet
,
3372 IN PSP_DEVINFO_DATA DeviceInfoData
,
3373 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3375 struct DeviceInfoSet
*list
;
3378 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3381 SetLastError(ERROR_INVALID_HANDLE
);
3382 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3383 SetLastError(ERROR_INVALID_HANDLE
);
3384 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3385 SetLastError(ERROR_INVALID_USER_BUFFER
);
3386 else if (!DeviceInstallParams
)
3387 SetLastError(ERROR_INVALID_PARAMETER
);
3388 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3389 SetLastError(ERROR_INVALID_USER_BUFFER
);
3392 PSP_DEVINSTALL_PARAMS_W Destination
;
3394 /* FIXME: Validate parameters */
3397 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3399 Destination
= &list
->InstallParams
;
3400 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3404 TRACE("Returning %d\n", ret
);
3408 /***********************************************************************
3409 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3411 HKEY WINAPI
SetupDiCreateDevRegKeyA(
3412 IN HDEVINFO DeviceInfoSet
,
3413 IN PSP_DEVINFO_DATA DeviceInfoData
,
3417 IN HINF InfHandle OPTIONAL
,
3418 IN PCSTR InfSectionName OPTIONAL
)
3420 PCWSTR InfSectionNameW
= NULL
;
3421 HKEY ret
= INVALID_HANDLE_VALUE
;
3425 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
3426 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
3429 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
3437 if (InfSectionNameW
!= NULL
)
3438 MyFree((PVOID
)InfSectionNameW
);
3443 /***********************************************************************
3444 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3446 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3447 IN HDEVINFO DeviceInfoSet
,
3448 IN PSP_DEVINFO_DATA DeviceInfoData
,
3452 IN HINF InfHandle OPTIONAL
,
3453 IN PCWSTR InfSectionName OPTIONAL
)
3455 struct DeviceInfoSet
*list
;
3456 HKEY ret
= INVALID_HANDLE_VALUE
;
3458 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3459 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3462 SetLastError(ERROR_INVALID_HANDLE
);
3463 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3464 SetLastError(ERROR_INVALID_HANDLE
);
3465 else if (!DeviceInfoData
)
3466 SetLastError(ERROR_INVALID_PARAMETER
);
3467 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3468 SetLastError(ERROR_INVALID_USER_BUFFER
);
3469 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3470 SetLastError(ERROR_INVALID_PARAMETER
);
3471 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3472 SetLastError(ERROR_INVALID_PARAMETER
);
3473 else if (InfHandle
&& !InfSectionName
)
3474 SetLastError(ERROR_INVALID_PARAMETER
);
3475 else if (!InfHandle
&& InfSectionName
)
3476 SetLastError(ERROR_INVALID_PARAMETER
);
3479 LPWSTR lpGuidString
= NULL
;
3480 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3481 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3482 DWORD Index
; /* Index used in the DriverKey name */
3484 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3485 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3486 HKEY hKey
= INVALID_HANDLE_VALUE
;
3488 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3490 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3494 if (KeyType
== DIREG_DEV
)
3496 FIXME("DIREG_DEV case unimplemented\n");
3498 else /* KeyType == DIREG_DRV */
3500 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3502 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3503 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3506 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3509 wcscpy(DriverKey
, L
"{");
3510 wcscat(DriverKey
, lpGuidString
);
3511 wcscat(DriverKey
, L
"}\\");
3512 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3513 rc
= RegOpenKeyExW(list
->HKLM
,
3518 if (rc
!= ERROR_SUCCESS
)
3524 /* Try all values for Index between 0 and 9999 */
3526 while (Index
<= 9999)
3529 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3530 rc
= RegCreateKeyEx(hClassKey
,
3534 REG_OPTION_NON_VOLATILE
,
3535 #if _WIN32_WINNT >= 0x502
3536 KEY_READ
| KEY_WRITE
,
3543 if (rc
!= ERROR_SUCCESS
)
3548 if (Disposition
== REG_CREATED_NEW_KEY
)
3551 hKey
= INVALID_HANDLE_VALUE
;
3556 /* Unable to create more than 9999 devices within the same class */
3557 SetLastError(ERROR_GEN_FAILURE
);
3561 /* Open device key, to write Driver value */
3562 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3563 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3565 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3566 if (rc
!= ERROR_SUCCESS
)
3573 /* Do installation of the specified section */
3576 FIXME("Need to install section %s in file %p\n",
3577 debugstr_w(InfSectionName
), InfHandle
);
3583 RpcStringFreeW(&lpGuidString
);
3584 HeapFree(GetProcessHeap(), 0, DriverKey
);
3585 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3586 RegCloseKey(hClassKey
);
3587 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3588 RegCloseKey(hDeviceKey
);
3589 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3593 TRACE("Returning 0x%p\n", ret
);
3597 /***********************************************************************
3598 * SetupDiOpenDevRegKey (SETUPAPI.@)
3600 HKEY WINAPI
SetupDiOpenDevRegKey(
3601 HDEVINFO DeviceInfoSet
,
3602 PSP_DEVINFO_DATA DeviceInfoData
,
3608 struct DeviceInfoSet
*list
;
3609 HKEY ret
= INVALID_HANDLE_VALUE
;
3611 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3612 Scope
, HwProfile
, KeyType
, samDesired
);
3615 SetLastError(ERROR_INVALID_HANDLE
);
3616 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3617 SetLastError(ERROR_INVALID_HANDLE
);
3618 else if (!DeviceInfoData
)
3619 SetLastError(ERROR_INVALID_PARAMETER
);
3620 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3621 SetLastError(ERROR_INVALID_USER_BUFFER
);
3622 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3623 SetLastError(ERROR_INVALID_PARAMETER
);
3624 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3625 SetLastError(ERROR_INVALID_PARAMETER
);
3628 HKEY hKey
= INVALID_HANDLE_VALUE
;
3629 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3630 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3631 LPWSTR DriverKey
= NULL
;
3636 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3638 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3640 else /* Scope == DICS_FLAG_GLOBAL */
3646 KEY_ENUMERATE_SUB_KEYS
,
3648 if (rc
!= ERROR_SUCCESS
)
3655 deviceInfo
->DeviceName
,
3657 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3659 RegCloseKey(hRootKey
);
3660 hRootKey
= INVALID_HANDLE_VALUE
;
3661 if (rc
!= ERROR_SUCCESS
)
3666 if (KeyType
== DIREG_DEV
)
3668 /* We're done. Just return the hKey handle */
3672 /* Read the 'Driver' key */
3673 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3674 if (rc
!= ERROR_SUCCESS
)
3679 if (dwRegType
!= REG_SZ
)
3681 SetLastError(ERROR_GEN_FAILURE
);
3684 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3687 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3690 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3691 if (rc
!= ERROR_SUCCESS
)
3697 hKey
= INVALID_HANDLE_VALUE
;
3698 /* Need to open the driver key */
3703 KEY_ENUMERATE_SUB_KEYS
,
3705 if (rc
!= ERROR_SUCCESS
)
3716 if (rc
!= ERROR_SUCCESS
)
3724 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3725 RegCloseKey(hRootKey
);
3726 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3730 TRACE("Returning 0x%p\n", ret
);
3734 /***********************************************************************
3735 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3737 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3738 HDEVINFO DeviceInfoSet
,
3740 CONST GUID
*ClassGuid
,
3741 PCSTR DeviceDescription
,
3743 DWORD CreationFlags
,
3744 PSP_DEVINFO_DATA DeviceInfoData
)
3746 LPWSTR DeviceNameW
= NULL
;
3747 LPWSTR DeviceDescriptionW
= NULL
;
3754 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3755 if (DeviceNameW
== NULL
) return FALSE
;
3757 if (DeviceDescription
)
3759 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3760 if (DeviceDescriptionW
== NULL
)
3762 if (DeviceNameW
) MyFree(DeviceNameW
);
3767 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3768 ClassGuid
, DeviceDescriptionW
,
3769 hwndParent
, CreationFlags
,
3772 if (DeviceNameW
) MyFree(DeviceNameW
);
3773 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3778 /***********************************************************************
3779 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3781 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3782 HDEVINFO DeviceInfoSet
,
3784 CONST GUID
*ClassGuid
,
3785 PCWSTR DeviceDescription
,
3787 DWORD CreationFlags
,
3788 PSP_DEVINFO_DATA DeviceInfoData
)
3790 struct DeviceInfoSet
*list
;
3793 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3794 debugstr_guid(ClassGuid
), DeviceDescription
,
3795 hwndParent
, CreationFlags
, DeviceInfoData
);
3798 SetLastError(ERROR_INVALID_HANDLE
);
3799 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3800 SetLastError(ERROR_INVALID_HANDLE
);
3801 else if (!ClassGuid
)
3802 SetLastError(ERROR_INVALID_PARAMETER
);
3803 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3804 SetLastError(ERROR_CLASS_MISMATCH
);
3805 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3807 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3808 SetLastError(ERROR_INVALID_PARAMETER
);
3812 SP_DEVINFO_DATA DevInfo
;
3814 if (CreationFlags
& DICD_GENERATE_ID
)
3816 /* Generate a new unique ID for this device */
3817 SetLastError(ERROR_GEN_FAILURE
);
3818 FIXME("not implemented\n");
3822 /* Device name is fully qualified. Try to open it */
3825 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3826 rc
= SetupDiOpenDeviceInfoW(
3829 NULL
, /* hwndParent */
3830 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3835 /* SetupDiOpenDeviceInfoW has already added
3836 * the device info to the device info set
3838 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3840 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3842 struct DeviceInfoElement
*deviceInfo
;
3844 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3846 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3848 if (!DeviceInfoData
)
3852 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3854 SetLastError(ERROR_INVALID_USER_BUFFER
);
3858 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3859 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
3860 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3869 TRACE("Returning %d\n", ret
);
3873 /***********************************************************************
3874 * Helper functions for SetupDiBuildDriverInfoList
3878 IN PLIST_ENTRY DriverListHead
,
3879 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3880 IN LPGUID ClassGuid
,
3881 IN INFCONTEXT ContextDevice
,
3882 IN
struct InfFileDetails
*InfFileDetails
,
3884 IN LPCWSTR ProviderName
,
3885 IN LPCWSTR ManufacturerName
,
3886 IN LPCWSTR MatchingId
,
3887 FILETIME DriverDate
,
3888 DWORDLONG DriverVersion
,
3891 struct DriverInfoElement
*driverInfo
= NULL
;
3892 HANDLE hFile
= INVALID_HANDLE_VALUE
;
3893 DWORD RequiredSize
= 128; /* Initial buffer size */
3894 BOOL Result
= FALSE
;
3895 PLIST_ENTRY PreviousEntry
;
3896 LPWSTR InfInstallSection
= NULL
;
3899 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3902 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3905 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3907 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
3908 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
3910 /* Copy InfFileName field */
3911 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
3912 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
3914 /* Fill InfDate field */
3915 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3916 GENERIC_READ, FILE_SHARE_READ,
3917 NULL, OPEN_EXISTING, 0, NULL);
3918 if (hFile == INVALID_HANDLE_VALUE)
3920 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
3924 /* Fill SectionName field */
3925 Result
= SetupGetStringFieldW(
3928 driverInfo
->Details
.SectionName
, LINE_LEN
,
3933 /* Fill DrvDescription field */
3934 Result
= SetupGetStringFieldW(
3936 0, /* Field index */
3937 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
3940 /* Copy MatchingId information */
3941 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3942 if (!driverInfo
->MatchingId
)
3944 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3947 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3949 /* Get inf install section */
3951 RequiredSize
= 128; /* Initial buffer size */
3952 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3953 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3955 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
3956 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3957 if (!InfInstallSection
)
3959 Result
= SetupGetStringFieldW(
3961 1, /* Field index */
3962 InfInstallSection
, RequiredSize
,
3968 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
3969 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
3971 driverInfo
->DriverRank
= Rank
;
3972 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3973 driverInfo
->Info
.DriverType
= DriverType
;
3974 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
3975 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
3976 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
3977 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
3978 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
3981 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
3982 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
3985 driverInfo
->Info
.ProviderName
[0] = '\0';
3986 driverInfo
->Info
.DriverDate
= DriverDate
;
3987 driverInfo
->Info
.DriverVersion
= DriverVersion
;
3988 ReferenceInfFile(InfFileDetails
);
3989 driverInfo
->InfFileDetails
= InfFileDetails
;
3991 /* Insert current driver in driver list, according to its rank */
3992 PreviousEntry
= DriverListHead
->Flink
;
3993 while (PreviousEntry
!= DriverListHead
)
3995 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
3997 /* Insert before the current item */
3998 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4001 PreviousEntry
= PreviousEntry
->Flink
;
4003 if (PreviousEntry
== DriverListHead
)
4005 /* Insert at the end of the list */
4006 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4015 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4016 HeapFree(GetProcessHeap(), 0, driverInfo
);
4018 if (hFile
!= INVALID_HANDLE_VALUE
)
4020 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4026 GetVersionInformationFromInfFile(
4028 OUT LPGUID ClassGuid
,
4029 OUT LPWSTR
* pProviderName
,
4030 OUT FILETIME
* DriverDate
,
4031 OUT DWORDLONG
* DriverVersion
)
4034 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4035 LPWSTR DriverVer
= NULL
;
4036 LPWSTR ProviderName
= NULL
;
4037 LPWSTR pComma
; /* Points into DriverVer */
4038 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4039 SYSTEMTIME SystemTime
;
4041 BOOL ret
= FALSE
; /* Final result */
4043 /* Get class Guid */
4044 if (!SetupGetLineTextW(
4047 L
"Version", L
"ClassGUID",
4048 guidW
, sizeof(guidW
),
4049 NULL
/* Required size */))
4053 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4054 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4056 SetLastError(ERROR_GEN_FAILURE
);
4060 /* Get provider name */
4061 Result
= SetupGetLineTextW(
4063 hInf
, L
"Version", L
"Provider",
4068 /* We know know the needed buffer size */
4069 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4072 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4075 Result
= SetupGetLineTextW(
4077 hInf
, L
"Version", L
"Provider",
4078 ProviderName
, RequiredSize
,
4083 *pProviderName
= ProviderName
;
4085 /* Read the "DriverVer" value */
4086 Result
= SetupGetLineTextW(
4088 hInf
, L
"Version", L
"DriverVer",
4093 /* We know know the needed buffer size */
4094 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4097 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4100 Result
= SetupGetLineTextW(
4102 hInf
, L
"Version", L
"DriverVer",
4103 DriverVer
, RequiredSize
,
4109 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4110 pComma
= wcschr(DriverVer
, ',');
4113 *pComma
= UNICODE_NULL
;
4114 pVersion
= pComma
+ 1;
4116 /* Get driver date version. Invalid date = 00/00/00 */
4117 memset(DriverDate
, 0, sizeof(FILETIME
));
4118 if (wcslen(DriverVer
) == 10
4119 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4120 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4122 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4123 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4124 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4125 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4126 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4127 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4129 /* Get driver version. Invalid version = 0.0.0.0 */
4131 /* FIXME: use pVersion to fill DriverVersion variable */
4137 HeapFree(GetProcessHeap(), 0, ProviderName
);
4138 HeapFree(GetProcessHeap(), 0, DriverVer
);
4140 TRACE("Returning %d\n", ret
);
4144 /***********************************************************************
4145 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4148 SetupDiBuildDriverInfoList(
4149 IN HDEVINFO DeviceInfoSet
,
4150 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4151 IN DWORD DriverType
)
4153 struct DeviceInfoSet
*list
;
4154 SP_DEVINSTALL_PARAMS_W InstallParams
;
4155 PVOID Buffer
= NULL
;
4156 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4157 LPWSTR ProviderName
= NULL
;
4158 LPWSTR ManufacturerName
= NULL
;
4159 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4160 LPWSTR HardwareIDs
= NULL
;
4161 LPWSTR CompatibleIDs
= NULL
;
4162 LPWSTR FullInfFileName
= NULL
;
4163 FILETIME DriverDate
;
4164 DWORDLONG DriverVersion
= 0;
4168 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4171 SetLastError(ERROR_INVALID_HANDLE
);
4172 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4173 SetLastError(ERROR_INVALID_HANDLE
);
4174 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4175 SetLastError(ERROR_INVALID_HANDLE
);
4176 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4177 SetLastError(ERROR_INVALID_PARAMETER
);
4178 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4179 SetLastError(ERROR_INVALID_PARAMETER
);
4180 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4181 SetLastError(ERROR_INVALID_PARAMETER
);
4182 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4183 SetLastError(ERROR_INVALID_USER_BUFFER
);
4188 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4189 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4193 if (DriverType
== SPDIT_COMPATDRIVER
)
4195 /* Get hardware IDs list */
4197 RequiredSize
= 512; /* Initial buffer size */
4198 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4199 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4201 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4202 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4205 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4208 Result
= SetupDiGetDeviceRegistryPropertyW(
4220 /* Get compatible IDs list */
4222 RequiredSize
= 512; /* Initial buffer size */
4223 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4224 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4226 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4227 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4230 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4233 Result
= SetupDiGetDeviceRegistryPropertyW(
4236 SPDRP_COMPATIBLEIDS
,
4238 (PBYTE
)CompatibleIDs
,
4241 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4243 /* No compatible ID for this device */
4244 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4245 CompatibleIDs
= NULL
;
4253 /* Enumerate .inf files */
4255 RequiredSize
= 32768; /* Initial buffer size */
4256 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4257 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4259 HeapFree(GetProcessHeap(), 0, Buffer
);
4260 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4264 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4267 Result
= SetupGetInfFileListW(
4268 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4270 Buffer
, RequiredSize
,
4273 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4275 /* No .inf file in specified directory. So, we should
4276 * success as we created an empty driver info list.
4284 LPWSTR pFullFilename
;
4286 if (*InstallParams
.DriverPath
)
4289 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
4292 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
4293 if (!FullInfFileName
)
4295 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
4298 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
4299 wcscat(FullInfFileName
, L
"\\");
4300 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
4304 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
4305 if (!FullInfFileName
)
4307 pFullFilename
= &FullInfFileName
[0];
4310 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4312 INFCONTEXT ContextManufacturer
, ContextDevice
;
4315 wcscpy(pFullFilename
, filename
);
4316 TRACE("Opening file %S\n", FullInfFileName
);
4318 currentInfFileDetails
= HeapAlloc(
4321 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
4322 if (!currentInfFileDetails
)
4324 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
4325 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
4327 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
4328 ReferenceInfFile(currentInfFileDetails
);
4329 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
4331 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
4332 currentInfFileDetails
= NULL
;
4336 if (!GetVersionInformationFromInfFile(
4337 currentInfFileDetails
->hInf
,
4343 SetupCloseInfFile(currentInfFileDetails
->hInf
);
4344 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
4345 currentInfFileDetails
= NULL
;
4349 if (DriverType
== SPDIT_CLASSDRIVER
)
4351 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4352 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4358 /* Get the manufacturers list */
4359 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4362 Result
= SetupGetStringFieldW(
4363 &ContextManufacturer
,
4364 0, /* Field index */
4369 /* We got the needed size for the buffer */
4370 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4371 if (!ManufacturerName
)
4373 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4376 Result
= SetupGetStringFieldW(
4377 &ContextManufacturer
,
4378 0, /* Field index */
4379 ManufacturerName
, RequiredSize
,
4382 /* Get manufacturer section name */
4383 Result
= SetupGetStringFieldW(
4384 &ContextManufacturer
,
4385 1, /* Field index */
4386 ManufacturerSection
, LINE_LEN
,
4390 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
4391 /* Add (possible) extension to manufacturer section name */
4392 Result
= SetupDiGetActualSectionToInstallW(
4393 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
4396 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4397 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4402 if (DriverType
== SPDIT_CLASSDRIVER
)
4404 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4405 if (!AddDriverToList(
4406 &list
->DriverListHead
,
4410 currentInfFileDetails
,
4415 DriverDate
, DriverVersion
,
4421 else /* DriverType = SPDIT_COMPATDRIVER */
4423 /* 1. Get all fields */
4424 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4428 BOOL DriverAlreadyAdded
;
4430 for (i
= 2; i
<= FieldCount
; i
++)
4432 LPWSTR DeviceId
= NULL
;
4434 RequiredSize
= 128; /* Initial buffer size */
4435 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4436 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4438 HeapFree(GetProcessHeap(), 0, DeviceId
);
4439 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4442 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4445 Result
= SetupGetStringFieldW(
4448 DeviceId
, RequiredSize
,
4453 HeapFree(GetProcessHeap(), 0, DeviceId
);
4456 DriverAlreadyAdded
= FALSE
;
4457 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4459 if (wcsicmp(DeviceId
, currentId
) == 0)
4462 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4466 currentInfFileDetails
,
4471 DriverDate
, DriverVersion
,
4472 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4473 DriverAlreadyAdded
= TRUE
;
4478 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4480 if (wcsicmp(DeviceId
, currentId
) == 0)
4483 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4487 currentInfFileDetails
,
4492 DriverDate
, DriverVersion
,
4493 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4494 DriverAlreadyAdded
= TRUE
;
4498 HeapFree(GetProcessHeap(), 0, DeviceId
);
4501 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4504 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4505 ManufacturerName
= NULL
;
4506 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4511 HeapFree(GetProcessHeap(), 0, ProviderName
);
4512 ProviderName
= NULL
;
4514 DereferenceInfFile(currentInfFileDetails
);
4515 currentInfFileDetails
= NULL
;
4526 InstallParams
.Flags
|= DI_DIDCOMPAT
;
4527 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
4531 InstallParams
.Flags
|= DI_DIDCLASS
;
4532 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
4534 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4537 HeapFree(GetProcessHeap(), 0, ProviderName
);
4538 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4539 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4540 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4541 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
4542 if (currentInfFileDetails
)
4543 DereferenceInfFile(currentInfFileDetails
);
4544 HeapFree(GetProcessHeap(), 0, Buffer
);
4546 TRACE("Returning %d\n", ret
);
4550 /***********************************************************************
4551 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4554 SetupDiDeleteDeviceInfo(
4555 IN HDEVINFO DeviceInfoSet
,
4556 IN PSP_DEVINFO_DATA DeviceInfoData
)
4558 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4560 FIXME("not implemented\n");
4561 SetLastError(ERROR_GEN_FAILURE
);
4566 /***********************************************************************
4567 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4570 SetupDiDestroyDriverInfoList(
4571 IN HDEVINFO DeviceInfoSet
,
4572 IN PSP_DEVINFO_DATA DeviceInfoData
,
4573 IN DWORD DriverType
)
4575 struct DeviceInfoSet
*list
;
4578 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4581 SetLastError(ERROR_INVALID_HANDLE
);
4582 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4583 SetLastError(ERROR_INVALID_HANDLE
);
4584 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4585 SetLastError(ERROR_INVALID_PARAMETER
);
4586 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4587 SetLastError(ERROR_INVALID_PARAMETER
);
4588 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4589 SetLastError(ERROR_INVALID_USER_BUFFER
);
4592 PLIST_ENTRY ListEntry
;
4593 struct DriverInfoElement
*driverInfo
;
4594 SP_DEVINSTALL_PARAMS_W InstallParams
;
4596 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4597 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4600 if (!DeviceInfoData
)
4601 /* Fall back to destroying class driver list */
4602 DriverType
= SPDIT_CLASSDRIVER
;
4604 if (DriverType
== SPDIT_CLASSDRIVER
)
4606 while (!IsListEmpty(&list
->DriverListHead
))
4608 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
4609 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4610 DestroyDriverInfoElement(driverInfo
);
4612 InstallParams
.Reserved
= 0;
4613 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
4614 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
4615 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
4619 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
4620 struct DeviceInfoElement
*deviceInfo
;
4622 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4623 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
4625 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4626 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
4628 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
4629 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4630 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
4632 InstallParamsSet
.Reserved
= 0;
4633 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
4635 DestroyDriverInfoElement(driverInfo
);
4637 InstallParams
.Reserved
= 0;
4638 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
4639 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
4640 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4645 TRACE("Returning %d\n", ret
);
4650 /***********************************************************************
4651 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4654 SetupDiOpenDeviceInfoA(
4655 IN HDEVINFO DeviceInfoSet
,
4656 IN PCSTR DeviceInstanceId
,
4657 IN HWND hwndParent OPTIONAL
,
4659 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4661 LPWSTR DeviceInstanceIdW
= NULL
;
4664 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4666 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4667 if (DeviceInstanceIdW
== NULL
)
4670 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4671 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4673 MyFree(DeviceInstanceIdW
);
4679 /***********************************************************************
4680 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4683 SetupDiOpenDeviceInfoW(
4684 IN HDEVINFO DeviceInfoSet
,
4685 IN PCWSTR DeviceInstanceId
,
4686 IN HWND hwndParent OPTIONAL
,
4688 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4690 struct DeviceInfoSet
*list
;
4691 HKEY hEnumKey
, hKey
;
4695 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4697 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4698 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4701 SetLastError(ERROR_INVALID_HANDLE
);
4702 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4703 SetLastError(ERROR_INVALID_HANDLE
);
4704 else if (!DeviceInstanceId
)
4705 SetLastError(ERROR_INVALID_PARAMETER
);
4706 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4708 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4709 SetLastError(ERROR_INVALID_PARAMETER
);
4711 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4712 SetLastError(ERROR_INVALID_USER_BUFFER
);
4715 struct DeviceInfoElement
*deviceInfo
= NULL
;
4716 /* Search if device already exists in DeviceInfoSet.
4717 * If yes, return the existing element
4718 * If no, create a new element using informations in registry
4720 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4721 while (ItemList
!= &list
->ListHead
)
4726 FIXME("not implemented\n");
4727 ItemList
= ItemList
->Flink
;
4732 /* good one found */
4737 /* Open supposed registry key */
4742 KEY_ENUMERATE_SUB_KEYS
,
4744 if (rc
!= ERROR_SUCCESS
)
4755 RegCloseKey(hEnumKey
);
4756 if (rc
!= ERROR_SUCCESS
)
4762 /* FIXME: try to get ClassGUID from registry, instead of
4763 * sending GUID_NULL to CreateDeviceInfoElement
4765 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
4770 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4776 if (ret
&& deviceInfo
&& DeviceInfoData
)
4778 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4779 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
4780 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4788 /***********************************************************************
4789 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4792 SetupDiEnumDriverInfoA(
4793 IN HDEVINFO DeviceInfoSet
,
4794 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4795 IN DWORD DriverType
,
4796 IN DWORD MemberIndex
,
4797 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4799 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4802 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4803 DriverType
, MemberIndex
, DriverInfoData
);
4805 if (DriverInfoData
== NULL
)
4806 SetLastError(ERROR_INVALID_PARAMETER
);
4807 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4808 SetLastError(ERROR_INVALID_USER_BUFFER
);
4811 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4812 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4813 DriverType
, MemberIndex
, &driverInfoData2W
);
4817 /* Do W->A conversion */
4818 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4819 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4820 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4821 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4823 DriverInfoData
->Description
[0] = '\0';
4826 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4827 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4829 DriverInfoData
->MfgName
[0] = '\0';
4832 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4833 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4835 DriverInfoData
->ProviderName
[0] = '\0';
4838 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4840 /* Copy more fields */
4841 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4842 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4847 TRACE("Returning %d\n", ret
);
4852 /***********************************************************************
4853 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4856 SetupDiEnumDriverInfoW(
4857 IN HDEVINFO DeviceInfoSet
,
4858 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4859 IN DWORD DriverType
,
4860 IN DWORD MemberIndex
,
4861 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4863 PLIST_ENTRY ListHead
;
4866 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4867 DriverType
, MemberIndex
, DriverInfoData
);
4869 if (!DeviceInfoSet
|| !DriverInfoData
)
4870 SetLastError(ERROR_INVALID_PARAMETER
);
4871 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4872 SetLastError(ERROR_INVALID_HANDLE
);
4873 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4874 SetLastError(ERROR_INVALID_HANDLE
);
4875 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4876 SetLastError(ERROR_INVALID_PARAMETER
);
4877 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4878 SetLastError(ERROR_INVALID_PARAMETER
);
4879 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4880 SetLastError(ERROR_INVALID_PARAMETER
);
4881 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4882 SetLastError(ERROR_INVALID_USER_BUFFER
);
4885 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4886 PLIST_ENTRY ItemList
;
4887 if (DriverType
== SPDIT_CLASSDRIVER
||
4888 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4890 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4894 ListHead
= &devInfo
->DriverListHead
;
4897 ItemList
= ListHead
->Flink
;
4898 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4899 ItemList
= ItemList
->Flink
;
4900 if (ItemList
== ListHead
)
4901 SetLastError(ERROR_NO_MORE_ITEMS
);
4904 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4907 &DriverInfoData
->DriverType
,
4908 &DrvInfo
->Info
.DriverType
,
4909 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4914 TRACE("Returning %d\n", ret
);
4919 /***********************************************************************
4920 * SetupDiGetSelectedDriverA (SETUPAPI.@)
4923 SetupDiGetSelectedDriverA(
4924 IN HDEVINFO DeviceInfoSet
,
4925 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4926 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4928 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4931 if (DriverInfoData
== NULL
)
4932 SetLastError(ERROR_INVALID_PARAMETER
);
4933 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4934 SetLastError(ERROR_INVALID_USER_BUFFER
);
4937 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4939 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
4945 /* Do W->A conversion */
4946 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4947 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4948 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4949 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4951 DriverInfoData
->Description
[0] = '\0';
4954 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4955 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4957 DriverInfoData
->MfgName
[0] = '\0';
4960 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4961 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4963 DriverInfoData
->ProviderName
[0] = '\0';
4966 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4968 /* Copy more fields */
4969 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4970 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4979 /***********************************************************************
4980 * SetupDiGetSelectedDriverW (SETUPAPI.@)
4983 SetupDiGetSelectedDriverW(
4984 IN HDEVINFO DeviceInfoSet
,
4985 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4986 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4990 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
4992 if (!DeviceInfoSet
|| !DriverInfoData
)
4993 SetLastError(ERROR_INVALID_PARAMETER
);
4994 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4995 SetLastError(ERROR_INVALID_HANDLE
);
4996 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4997 SetLastError(ERROR_INVALID_HANDLE
);
4998 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4999 SetLastError(ERROR_INVALID_USER_BUFFER
);
5000 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5001 SetLastError(ERROR_INVALID_USER_BUFFER
);
5004 SP_DEVINSTALL_PARAMS InstallParams
;
5006 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5007 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5009 struct DriverInfoElement
*driverInfo
;
5010 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5011 if (driverInfo
== NULL
)
5012 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5016 &DriverInfoData
->DriverType
,
5017 &driverInfo
->Info
.DriverType
,
5018 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5024 TRACE("Returning %d\n", ret
);
5029 /***********************************************************************
5030 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5033 SetupDiSetSelectedDriverA(
5034 IN HDEVINFO DeviceInfoSet
,
5035 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5036 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5038 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5039 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5042 if (DriverInfoData
!= NULL
)
5044 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5045 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5047 SetLastError(ERROR_INVALID_PARAMETER
);
5051 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5052 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5054 if (DriverInfoDataW
.Reserved
== 0)
5056 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5058 /* convert the strings to unicode */
5059 if (!MultiByteToWideChar(CP_ACP
,
5061 DriverInfoData
->Description
,
5063 DriverInfoDataW
.Description
,
5065 !MultiByteToWideChar(CP_ACP
,
5067 DriverInfoData
->ProviderName
,
5069 DriverInfoDataW
.ProviderName
,
5076 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5079 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5083 if (ret
&& pDriverInfoDataW
!= NULL
)
5085 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5092 /***********************************************************************
5093 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5096 SetupDiSetSelectedDriverW(
5097 IN HDEVINFO DeviceInfoSet
,
5098 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5099 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5103 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5106 SetLastError(ERROR_INVALID_PARAMETER
);
5107 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5108 SetLastError(ERROR_INVALID_HANDLE
);
5109 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5110 SetLastError(ERROR_INVALID_HANDLE
);
5111 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5112 SetLastError(ERROR_INVALID_USER_BUFFER
);
5113 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5114 SetLastError(ERROR_INVALID_USER_BUFFER
);
5117 struct DriverInfoElement
**pDriverInfo
;
5118 PLIST_ENTRY ListHead
, ItemList
;
5122 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5123 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5127 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5128 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5131 if (!DriverInfoData
)
5133 *pDriverInfo
= NULL
;
5138 /* Search selected driver in list */
5139 ItemList
= ListHead
->Flink
;
5140 while (ItemList
!= ListHead
)
5142 if (DriverInfoData
->Reserved
!= 0)
5144 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5149 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5150 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5151 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5152 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5153 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5159 if (ItemList
== ListHead
)
5160 SetLastError(ERROR_INVALID_PARAMETER
);
5163 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5164 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5166 TRACE("Choosing driver whose rank is 0x%lx\n",
5167 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5169 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5174 TRACE("Returning %d\n", ret
);
5178 /***********************************************************************
5179 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5182 SetupDiGetDriverInfoDetailA(
5183 IN HDEVINFO DeviceInfoSet
,
5184 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5185 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5186 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5187 IN DWORD DriverInfoDetailDataSize
,
5188 OUT PDWORD RequiredSize OPTIONAL
)
5190 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5191 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5193 DWORD HardwareIDLen
= 0;
5196 /* do some sanity checks, the unicode version might do more thorough checks */
5197 if (DriverInfoData
== NULL
||
5198 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5199 (DriverInfoDetailData
!= NULL
&&
5200 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5201 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5203 SetLastError(ERROR_INVALID_PARAMETER
);
5207 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5208 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5210 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5212 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5214 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5218 SetLastError(ERROR_INVALID_PARAMETER
);
5221 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5222 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5224 /* convert the strings to unicode */
5225 if (MultiByteToWideChar(CP_ACP
,
5227 DriverInfoData
->Description
,
5229 DriverInfoDataW
.Description
,
5231 MultiByteToWideChar(CP_ACP
,
5233 DriverInfoData
->MfgName
,
5235 DriverInfoDataW
.MfgName
,
5237 MultiByteToWideChar(CP_ACP
,
5239 DriverInfoData
->ProviderName
,
5241 DriverInfoDataW
.ProviderName
,
5244 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5246 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5247 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5250 if (DriverInfoDetailData
!= NULL
)
5252 /* calculate the unicode buffer size from the ansi buffer size */
5253 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5254 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5255 (HardwareIDLen
* sizeof(WCHAR
));
5257 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5258 if (DriverInfoDetailDataW
== NULL
)
5260 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5264 /* initialize the buffer */
5265 ZeroMemory(DriverInfoDetailDataW
,
5267 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5270 /* call the unicode version */
5271 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5274 DriverInfoDetailDataW
,
5280 if (DriverInfoDetailDataW
!= NULL
)
5282 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5283 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
5284 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
5285 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
5286 if (WideCharToMultiByte(CP_ACP
,
5288 DriverInfoDetailDataW
->SectionName
,
5290 DriverInfoDetailData
->SectionName
,
5294 WideCharToMultiByte(CP_ACP
,
5296 DriverInfoDetailDataW
->InfFileName
,
5298 DriverInfoDetailData
->InfFileName
,
5302 WideCharToMultiByte(CP_ACP
,
5304 DriverInfoDetailDataW
->DrvDescription
,
5306 DriverInfoDetailData
->DrvDescription
,
5310 WideCharToMultiByte(CP_ACP
,
5312 DriverInfoDetailDataW
->HardwareID
,
5314 DriverInfoDetailData
->HardwareID
,
5320 DWORD hwidlen
= HardwareIDLen
;
5321 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
5323 /* count the strings in the list */
5326 len
= lstrlenA(s
) + 1;
5335 /* looks like the string list wasn't terminated... */
5336 SetLastError(ERROR_INVALID_USER_BUFFER
);
5342 /* make sure CompatIDsOffset points to the second string in the
5346 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
5347 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
5348 DriverInfoDetailData
->CompatIDsOffset
+ 1;
5352 DriverInfoDetailData
->CompatIDsOffset
= 0;
5353 DriverInfoDetailData
->CompatIDsLength
= 0;
5362 if (RequiredSize
!= NULL
)
5364 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
5365 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
5371 if (DriverInfoDetailDataW
!= NULL
)
5373 MyFree(DriverInfoDetailDataW
);
5379 /***********************************************************************
5380 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5383 SetupDiGetDriverInfoDetailW(
5384 IN HDEVINFO DeviceInfoSet
,
5385 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5386 IN PSP_DRVINFO_DATA_W DriverInfoData
,
5387 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
5388 IN DWORD DriverInfoDetailDataSize
,
5389 OUT PDWORD RequiredSize OPTIONAL
)
5393 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
5394 DriverInfoData
, DriverInfoDetailData
,
5395 DriverInfoDetailDataSize
, RequiredSize
);
5398 SetLastError(ERROR_INVALID_PARAMETER
);
5399 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5400 SetLastError(ERROR_INVALID_HANDLE
);
5401 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5402 SetLastError(ERROR_INVALID_HANDLE
);
5403 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5404 SetLastError(ERROR_INVALID_USER_BUFFER
);
5405 else if (!DriverInfoData
)
5406 SetLastError(ERROR_INVALID_PARAMETER
);
5407 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
5408 SetLastError(ERROR_INVALID_PARAMETER
);
5409 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5410 SetLastError(ERROR_INVALID_PARAMETER
);
5411 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5412 SetLastError(ERROR_INVALID_USER_BUFFER
);
5413 else if (DriverInfoData
->Reserved
== 0)
5414 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5417 struct DriverInfoElement
*driverInfoElement
;
5418 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
5421 DriverInfoDetailData
,
5422 &driverInfoElement
->Details
,
5423 driverInfoElement
->Details
.cbSize
);
5424 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5425 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5430 TRACE("Returning %d\n", ret
);
5434 /***********************************************************************
5435 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5438 SetupDiSelectBestCompatDrv(
5439 IN HDEVINFO DeviceInfoSet
,
5440 IN PSP_DEVINFO_DATA DeviceInfoData
)
5442 SP_DRVINFO_DATA_W drvInfoData
;
5445 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5447 /* Drivers are sorted by rank in the driver list, so
5448 * the first driver in the list is the best one.
5450 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
5451 ret
= SetupDiEnumDriverInfoW(
5455 0, /* Member index */
5460 ret
= SetupDiSetSelectedDriverW(
5466 TRACE("Returning %d\n", ret
);
5470 /***********************************************************************
5471 * SetupDiInstallDriverFiles (SETUPAPI.@)
5474 SetupDiInstallDriverFiles(
5475 IN HDEVINFO DeviceInfoSet
,
5476 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5480 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5483 SetLastError(ERROR_INVALID_PARAMETER
);
5484 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5485 SetLastError(ERROR_INVALID_HANDLE
);
5486 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5487 SetLastError(ERROR_INVALID_HANDLE
);
5488 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5489 SetLastError(ERROR_INVALID_USER_BUFFER
);
5490 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
5491 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5492 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
5493 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5496 SP_DEVINSTALL_PARAMS_W InstallParams
;
5497 struct DriverInfoElement
*SelectedDriver
;
5498 WCHAR SectionName
[MAX_PATH
];
5499 DWORD SectionNameLength
= 0;
5501 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5502 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5506 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5507 if (!SelectedDriver
)
5509 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5513 ret
= SetupDiGetActualSectionToInstallW(
5514 SelectedDriver
->InfFileDetails
->hInf
,
5515 SelectedDriver
->Details
.SectionName
,
5516 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5520 if (!InstallParams
.InstallMsgHandler
)
5522 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5523 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5524 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5526 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5527 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5528 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
5529 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5530 DeviceInfoSet
, DeviceInfoData
);
5534 TRACE("Returning %d\n", ret
);
5538 /***********************************************************************
5539 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5542 SetupDiRegisterCoDeviceInstallers(
5543 IN HDEVINFO DeviceInfoSet
,
5544 IN PSP_DEVINFO_DATA DeviceInfoData
)
5546 BOOL ret
= FALSE
; /* Return value */
5548 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5551 SetLastError(ERROR_INVALID_PARAMETER
);
5552 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5553 SetLastError(ERROR_INVALID_HANDLE
);
5554 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5555 SetLastError(ERROR_INVALID_HANDLE
);
5556 else if (!DeviceInfoData
)
5557 SetLastError(ERROR_INVALID_PARAMETER
);
5558 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5559 SetLastError(ERROR_INVALID_USER_BUFFER
);
5562 SP_DEVINSTALL_PARAMS_W InstallParams
;
5563 struct DriverInfoElement
*SelectedDriver
;
5566 WCHAR SectionName
[MAX_PATH
];
5567 DWORD SectionNameLength
= 0;
5568 HKEY hKey
= INVALID_HANDLE_VALUE
;;
5570 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5571 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5575 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5576 if (SelectedDriver
== NULL
)
5578 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5582 /* Get .CoInstallers section name */
5583 Result
= SetupDiGetActualSectionToInstallW(
5584 SelectedDriver
->InfFileDetails
->hInf
,
5585 SelectedDriver
->Details
.SectionName
,
5586 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5587 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
5589 wcscat(SectionName
, L
".CoInstallers");
5591 /* Open/Create driver key information */
5592 #if _WIN32_WINNT >= 0x502
5593 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5595 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5597 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5598 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5599 if (hKey
== INVALID_HANDLE_VALUE
)
5602 /* Install .CoInstallers section */
5603 DoAction
= SPINST_REGISTRY
;
5604 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5606 DoAction
|= SPINST_FILES
;
5607 if (!InstallParams
.InstallMsgHandler
)
5609 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5610 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5611 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5614 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5615 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5616 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5617 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5618 DeviceInfoSet
, DeviceInfoData
);
5625 if (hKey
!= INVALID_HANDLE_VALUE
)
5629 TRACE("Returning %d\n", ret
);
5633 /***********************************************************************
5634 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5637 SetupDiInstallDeviceInterfaces(
5638 IN HDEVINFO DeviceInfoSet
,
5639 IN PSP_DEVINFO_DATA DeviceInfoData
)
5641 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5643 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5644 //SetLastError(ERROR_GEN_FAILURE);
5650 InfIsFromOEMLocation(
5652 OUT LPBOOL IsOEMLocation
)
5656 last
= strrchrW(FullName
, '\\');
5659 /* No directory specified */
5660 *IsOEMLocation
= FALSE
;
5664 WCHAR Windir
[MAX_PATH
];
5667 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
5668 if (ret
== 0 || ret
>= MAX_PATH
)
5670 SetLastError(ERROR_GEN_FAILURE
);
5674 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
5676 /* The path is %SYSTEMROOT%\Inf */
5677 *IsOEMLocation
= FALSE
;
5681 /* The file is in another place */
5682 *IsOEMLocation
= TRUE
;
5688 /***********************************************************************
5689 * SetupDiInstallDevice (SETUPAPI.@)
5692 SetupDiInstallDevice(
5693 IN HDEVINFO DeviceInfoSet
,
5694 IN PSP_DEVINFO_DATA DeviceInfoData
)
5696 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5697 SP_DEVINSTALL_PARAMS_W InstallParams
;
5698 struct DriverInfoElement
*SelectedDriver
;
5699 SYSTEMTIME DriverDate
;
5700 WCHAR SectionName
[MAX_PATH
];
5702 DWORD SectionNameLength
= 0;
5703 BOOL Result
= FALSE
;
5704 INFCONTEXT ContextService
;
5708 LPCWSTR AssociatedService
= NULL
;
5709 LPWSTR pSectionName
= NULL
;
5710 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5712 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5713 BOOL RebootRequired
= FALSE
;
5714 HKEY hKey
= INVALID_HANDLE_VALUE
;
5715 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
5716 BOOL NeedtoCopyFile
;
5718 BOOL ret
= FALSE
; /* Return value */
5720 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5723 SetLastError(ERROR_INVALID_PARAMETER
);
5724 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5725 SetLastError(ERROR_INVALID_HANDLE
);
5726 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5727 SetLastError(ERROR_INVALID_HANDLE
);
5728 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5729 SetLastError(ERROR_INVALID_USER_BUFFER
);
5735 /* One parameter is bad */
5739 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5740 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5744 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5746 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5750 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5751 if (SelectedDriver
== NULL
)
5753 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5757 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5759 Result
= SetupDiGetActualSectionToInstallW(
5760 SelectedDriver
->InfFileDetails
->hInf
,
5761 SelectedDriver
->Details
.SectionName
,
5762 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5763 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
5765 pSectionName
= &SectionName
[wcslen(SectionName
)];
5767 /* Get information from [Version] section */
5768 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5770 /* Format ClassGuid to a string */
5771 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5773 RequiredSize
= lstrlenW(lpGuidString
);
5774 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5775 if (!lpFullGuidString
)
5777 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5780 lpFullGuidString
[0] = '{';
5781 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5782 lpFullGuidString
[RequiredSize
+ 1] = '}';
5783 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5785 /* Open/Create driver key information */
5786 #if _WIN32_WINNT >= 0x502
5787 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5789 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5791 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5792 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5793 if (hKey
== INVALID_HANDLE_VALUE
)
5796 /* Install main section */
5797 DoAction
= SPINST_REGISTRY
;
5798 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5800 DoAction
|= SPINST_FILES
;
5801 if (!InstallParams
.InstallMsgHandler
)
5803 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5804 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5805 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5808 *pSectionName
= '\0';
5809 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5810 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5811 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5812 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5813 DeviceInfoSet
, DeviceInfoData
);
5816 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
5818 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
5820 /* Delete resources allocated by SetupInitDefaultQueueCallback */
5821 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
5824 InstallParams
.Flags
|= DI_NOFILECOPY
;
5825 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5827 /* Write information to driver key */
5828 *pSectionName
= UNICODE_NULL
;
5829 TRACE("Write information to driver key\n");
5830 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5831 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5832 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);
5833 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
5834 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
5835 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
5836 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
5837 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
5838 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5839 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5840 if (rc
== ERROR_SUCCESS
)
5841 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5842 if (rc
== ERROR_SUCCESS
)
5843 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5844 if (rc
== ERROR_SUCCESS
)
5846 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);
5847 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5849 if (rc
== ERROR_SUCCESS
)
5850 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
5851 if (rc
== ERROR_SUCCESS
)
5852 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5853 if (rc
== ERROR_SUCCESS
)
5854 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5855 if (rc
== ERROR_SUCCESS
)
5856 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5857 if (rc
== ERROR_SUCCESS
)
5858 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5859 if (rc
!= ERROR_SUCCESS
)
5865 hKey
= INVALID_HANDLE_VALUE
;
5867 /* FIXME: Process .LogConfigOverride section */
5869 /* Install .Services section */
5870 wcscpy(pSectionName
, L
".Services");
5871 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
5874 LPWSTR ServiceName
= NULL
;
5875 LPWSTR ServiceSection
= NULL
;
5877 Result
= SetupGetStringFieldW(
5879 1, /* Field index */
5884 if (RequiredSize
> 0)
5886 /* We got the needed size for the buffer */
5887 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5890 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5893 Result
= SetupGetStringFieldW(
5895 1, /* Field index */
5896 ServiceName
, RequiredSize
,
5901 Result
= SetupGetIntField(
5903 2, /* Field index */
5907 /* The field may be empty. Ignore the error */
5910 Result
= SetupGetStringFieldW(
5912 3, /* Field index */
5917 if (RequiredSize
> 0)
5919 /* We got the needed size for the buffer */
5920 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5921 if (!ServiceSection
)
5923 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5926 Result
= SetupGetStringFieldW(
5928 3, /* Field index */
5929 ServiceSection
, RequiredSize
,
5934 SetLastError(ERROR_SUCCESS
);
5935 Result
= SetupInstallServicesFromInfSectionExW(
5936 SelectedDriver
->InfFileDetails
->hInf
,
5937 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
5938 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
5940 AssociatedService
= ServiceName
;
5942 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5943 RebootRequired
= TRUE
;
5946 HeapFree(GetProcessHeap(), 0, ServiceName
);
5947 HeapFree(GetProcessHeap(), 0, ServiceSection
);
5950 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
5953 /* Copy .inf file to Inf\ directory (if needed) */
5954 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
5959 Result
= SetupCopyOEMInfW(
5960 SelectedDriver
->InfFileDetails
->FullInfFileName
,
5963 SP_COPY_NOOVERWRITE
,
5969 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
5970 * to release use of current InfFile */
5973 /* Open device registry key */
5974 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5975 if (hKey
== INVALID_HANDLE_VALUE
)
5978 /* Install .HW section */
5979 wcscpy(pSectionName
, L
".HW");
5980 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5981 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5982 SPINST_REGISTRY
, hKey
, NULL
, 0,
5983 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5984 DeviceInfoSet
, DeviceInfoData
);
5988 /* Write information to enum key */
5989 TRACE("Write information to enum key\n");
5990 TRACE("Service : '%S'\n", AssociatedService
);
5991 TRACE("Class : '%S'\n", ClassName
);
5992 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
5993 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5994 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
5995 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
5996 if (rc
== ERROR_SUCCESS
)
5997 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
5998 if (rc
== ERROR_SUCCESS
)
5999 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
6000 if (rc
== ERROR_SUCCESS
)
6001 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6002 if (rc
== ERROR_SUCCESS
)
6003 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
6004 if (rc
!= ERROR_SUCCESS
)
6010 /* Start the device */
6011 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
6013 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6015 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
6016 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6017 ret
= NT_SUCCESS(Status
);
6023 /* End of installation */
6024 if (hClassKey
!= INVALID_HANDLE_VALUE
)
6025 RegCloseKey(hClassKey
);
6026 if (hKey
!= INVALID_HANDLE_VALUE
)
6029 RpcStringFreeW(&lpGuidString
);
6030 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
6031 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6033 TRACE("Returning %d\n", ret
);