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;
152 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
153 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
155 if (RequiredSize
!= NULL
)
158 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
159 KEY_ENUMERATE_SUB_KEYS
,
163 if (hClassesKey
== INVALID_HANDLE_VALUE
)
168 for (dwIndex
= 0; ; dwIndex
++)
170 dwLength
= MAX_GUID_STRING_LEN
+ 1;
171 lError
= RegEnumKeyExW(hClassesKey
,
179 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
180 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
182 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
184 if (RegOpenKeyExW(hClassesKey
,
190 RegCloseKey(hClassesKey
);
194 if (!RegQueryValueExW(hClassKey
,
201 TRACE("'NoUseClass' value found!\n");
202 RegCloseKey(hClassKey
);
206 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
207 (!RegQueryValueExW(hClassKey
,
214 TRACE("'NoInstallClass' value found!\n");
215 RegCloseKey(hClassKey
);
219 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
220 (!RegQueryValueExW(hClassKey
,
227 TRACE("'NoDisplayClass' value found!\n");
228 RegCloseKey(hClassKey
);
232 RegCloseKey(hClassKey
);
234 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
235 if (dwGuidListIndex
< ClassGuidListSize
)
237 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
241 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
243 UuidFromStringW(&szKeyName
[1],
244 &ClassGuidList
[dwGuidListIndex
]);
250 if (lError
!= ERROR_SUCCESS
)
254 RegCloseKey(hClassesKey
);
256 if (RequiredSize
!= NULL
)
257 *RequiredSize
= dwGuidListIndex
;
259 if (ClassGuidListSize
< dwGuidListIndex
)
261 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
268 /***********************************************************************
269 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
271 BOOL WINAPI
SetupDiClassGuidsFromNameA(
273 LPGUID ClassGuidList
,
274 DWORD ClassGuidListSize
,
277 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
278 ClassGuidListSize
, RequiredSize
,
282 /***********************************************************************
283 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
285 BOOL WINAPI
SetupDiClassGuidsFromNameW(
287 LPGUID ClassGuidList
,
288 DWORD ClassGuidListSize
,
291 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
292 ClassGuidListSize
, RequiredSize
,
296 /***********************************************************************
297 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
299 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
301 LPGUID ClassGuidList
,
302 DWORD ClassGuidListSize
,
307 LPWSTR ClassNameW
= NULL
;
308 LPWSTR MachineNameW
= NULL
;
313 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
314 if (ClassNameW
== NULL
)
319 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
320 if (MachineNameW
== NULL
)
327 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
328 ClassGuidListSize
, RequiredSize
,
329 MachineNameW
, Reserved
);
332 MyFree(MachineNameW
);
339 /***********************************************************************
340 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
342 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
344 LPGUID ClassGuidList
,
345 DWORD ClassGuidListSize
,
350 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
351 WCHAR szClassName
[256];
357 DWORD dwGuidListIndex
= 0;
359 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
360 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
362 if (RequiredSize
!= NULL
)
365 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
366 KEY_ENUMERATE_SUB_KEYS
,
370 if (hClassesKey
== INVALID_HANDLE_VALUE
)
375 for (dwIndex
= 0; ; dwIndex
++)
377 dwLength
= MAX_GUID_STRING_LEN
+ 1;
378 lError
= RegEnumKeyExW(hClassesKey
,
386 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
387 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
389 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
391 if (RegOpenKeyExW(hClassesKey
,
397 RegCloseKey(hClassesKey
);
401 dwLength
= 256 * sizeof(WCHAR
);
402 if (!RegQueryValueExW(hClassKey
,
409 TRACE("Class name: %s\n", debugstr_w(szClassName
));
411 if (strcmpiW(szClassName
, ClassName
) == 0)
413 TRACE("Found matching class name\n");
415 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
416 if (dwGuidListIndex
< ClassGuidListSize
)
418 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
422 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
424 UuidFromStringW(&szKeyName
[1],
425 &ClassGuidList
[dwGuidListIndex
]);
432 RegCloseKey(hClassKey
);
435 if (lError
!= ERROR_SUCCESS
)
439 RegCloseKey(hClassesKey
);
441 if (RequiredSize
!= NULL
)
442 *RequiredSize
= dwGuidListIndex
;
444 if (ClassGuidListSize
< dwGuidListIndex
)
446 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
453 /***********************************************************************
454 * SetupDiClassNameFromGuidA (SETUPAPI.@)
456 BOOL WINAPI
SetupDiClassNameFromGuidA(
457 const GUID
* ClassGuid
,
462 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
463 ClassNameSize
, RequiredSize
,
467 /***********************************************************************
468 * SetupDiClassNameFromGuidW (SETUPAPI.@)
470 BOOL WINAPI
SetupDiClassNameFromGuidW(
471 const GUID
* ClassGuid
,
476 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
477 ClassNameSize
, RequiredSize
,
481 /***********************************************************************
482 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
484 BOOL WINAPI
SetupDiClassNameFromGuidExA(
485 const GUID
* ClassGuid
,
492 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
493 LPWSTR MachineNameW
= NULL
;
497 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
498 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
499 NULL
, MachineNameW
, Reserved
);
502 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
503 ClassNameSize
, NULL
, NULL
);
505 if (!ClassNameSize
&& RequiredSize
)
508 MyFree(MachineNameW
);
512 /***********************************************************************
513 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
515 BOOL WINAPI
SetupDiClassNameFromGuidExW(
516 const GUID
* ClassGuid
,
527 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
528 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
530 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
535 if (hKey
== INVALID_HANDLE_VALUE
)
540 if (RequiredSize
!= NULL
)
543 rc
= RegQueryValueExW(hKey
,
549 if (rc
!= ERROR_SUCCESS
)
556 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
559 dwLength
= ClassNameSize
* sizeof(WCHAR
);
560 rc
= RegQueryValueExW(hKey
,
566 if (rc
!= ERROR_SUCCESS
)
578 /***********************************************************************
579 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
582 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
585 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
588 /***********************************************************************
589 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
592 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
597 LPWSTR MachineNameW
= NULL
;
600 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
601 debugstr_a(MachineName
), Reserved
);
605 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
606 if (MachineNameW
== NULL
)
607 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
610 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
611 MachineNameW
, Reserved
);
614 MyFree(MachineNameW
);
619 /***********************************************************************
620 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
623 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
628 struct DeviceInfoSet
*list
;
629 LPWSTR UNCServerName
= NULL
;
632 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
634 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
635 debugstr_w(MachineName
), Reserved
);
637 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet
));
640 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
643 memset(list
, 0, sizeof(struct DeviceInfoSet
));
645 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
648 ClassGuid
? ClassGuid
: &GUID_NULL
,
649 sizeof(list
->ClassGuid
));
650 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
651 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
652 list
->InstallParams
.hwndParent
= hwndParent
;
655 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
656 if (rc
!= ERROR_SUCCESS
)
661 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
664 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
668 strcpyW(UNCServerName
+ 2, MachineName
);
672 DWORD Size
= MAX_PATH
;
673 list
->HKLM
= HKEY_LOCAL_MACHINE
;
674 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
677 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
680 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
684 UNCServerName
[0] = UNCServerName
[1] = '\\';
685 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
686 if (cr
!= CR_SUCCESS
)
690 case CR_OUT_OF_MEMORY
: rc
= ERROR_NOT_ENOUGH_MEMORY
; break;
691 case CR_INVALID_MACHINENAME
: rc
= ERROR_INVALID_COMPUTERNAME
; break;
692 default: rc
= ERROR_GEN_FAILURE
; break;
698 InitializeListHead(&list
->DriverListHead
);
699 InitializeListHead(&list
->ListHead
);
701 ret
= (HDEVINFO
)list
;
704 if (ret
== INVALID_HANDLE_VALUE
)
706 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
707 RegCloseKey(list
->HKLM
);
708 HeapFree(GetProcessHeap(), 0, list
);
710 HeapFree(GetProcessHeap(), 0, UNCServerName
);
714 /***********************************************************************
715 * SetupDiEnumDeviceInfo (SETUPAPI.@)
717 BOOL WINAPI
SetupDiEnumDeviceInfo(
718 HDEVINFO DeviceInfoSet
,
720 PSP_DEVINFO_DATA DeviceInfoData
)
724 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
726 SetLastError(ERROR_INVALID_PARAMETER
);
727 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
729 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
731 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
732 SetLastError(ERROR_INVALID_HANDLE
);
733 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
734 SetLastError(ERROR_INVALID_USER_BUFFER
);
737 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
738 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
739 ItemList
= ItemList
->Flink
;
740 if (ItemList
== &list
->ListHead
)
741 SetLastError(ERROR_NO_MORE_ITEMS
);
744 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
745 memcpy(&DeviceInfoData
->ClassGuid
,
748 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
749 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
755 SetLastError(ERROR_INVALID_HANDLE
);
759 /***********************************************************************
760 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
762 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
764 PCSTR InfSectionName
,
765 PSTR InfSectionWithExt
,
766 DWORD InfSectionWithExtSize
,
770 LPWSTR InfSectionNameW
= NULL
;
771 PWSTR InfSectionWithExtW
= NULL
;
773 BOOL bResult
= FALSE
;
779 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
780 if (InfSectionNameW
== NULL
) goto end
;
782 if (InfSectionWithExt
)
784 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
785 if (InfSectionWithExtW
== NULL
) goto end
;
788 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
789 InfSectionWithExt
? InfSectionNameW
: NULL
,
790 InfSectionWithExtSize
, RequiredSize
,
791 Extension
? &ExtensionW
: NULL
);
793 if (bResult
&& InfSectionWithExt
)
795 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
796 InfSectionWithExtSize
, NULL
, NULL
) != 0;
798 if (bResult
&& Extension
)
800 if (ExtensionW
== NULL
)
803 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
807 if (InfSectionNameW
) MyFree(InfSectionNameW
);
808 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
813 /***********************************************************************
814 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
816 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
818 PCWSTR InfSectionName
,
819 PWSTR InfSectionWithExt
,
820 DWORD InfSectionWithExtSize
,
824 WCHAR szBuffer
[MAX_PATH
];
827 LONG lLineCount
= -1;
829 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
830 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
832 lstrcpyW(szBuffer
, InfSectionName
);
833 dwLength
= lstrlenW(szBuffer
);
835 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
837 /* Test section name with '.NTx86' extension */
838 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
839 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
841 if (lLineCount
== -1)
843 /* Test section name with '.NT' extension */
844 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
845 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
850 /* Test section name with '.Win' extension */
851 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
852 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
855 if (lLineCount
== -1)
857 /* Test section name without extension */
858 szBuffer
[dwLength
] = 0;
859 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
862 if (lLineCount
== -1)
864 SetLastError(ERROR_INVALID_PARAMETER
);
868 dwFullLength
= lstrlenW(szBuffer
);
870 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
872 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
874 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
878 lstrcpyW(InfSectionWithExt
, szBuffer
);
879 if (Extension
!= NULL
)
881 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
885 if (RequiredSize
!= NULL
)
887 *RequiredSize
= dwFullLength
+ 1;
893 /***********************************************************************
894 * SetupDiGetClassDescriptionA (SETUPAPI.@)
896 BOOL WINAPI
SetupDiGetClassDescriptionA(
897 const GUID
* ClassGuid
,
898 PSTR ClassDescription
,
899 DWORD ClassDescriptionSize
,
902 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
903 ClassDescriptionSize
,
904 RequiredSize
, NULL
, NULL
);
907 /***********************************************************************
908 * SetupDiGetClassDescriptionW (SETUPAPI.@)
910 BOOL WINAPI
SetupDiGetClassDescriptionW(
911 const GUID
* ClassGuid
,
912 PWSTR ClassDescription
,
913 DWORD ClassDescriptionSize
,
916 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
917 ClassDescriptionSize
,
918 RequiredSize
, NULL
, NULL
);
921 /***********************************************************************
922 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
924 BOOL WINAPI
SetupDiGetClassDescriptionExA(
925 const GUID
* ClassGuid
,
926 PSTR ClassDescription
,
927 DWORD ClassDescriptionSize
,
932 PWCHAR ClassDescriptionW
;
933 LPWSTR MachineNameW
= NULL
;
937 if (ClassDescriptionSize
> 0)
939 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
940 if (!ClassDescriptionW
)
942 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
948 ClassDescriptionW
= NULL
;
952 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
955 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
961 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
962 NULL
, MachineNameW
, Reserved
);
965 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
966 ClassDescriptionSize
, NULL
, NULL
);
968 if (!ClassDescriptionSize
&& RequiredSize
)
973 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
974 MyFree(MachineNameW
);
978 /***********************************************************************
979 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
981 BOOL WINAPI
SetupDiGetClassDescriptionExW(
982 const GUID
* ClassGuid
,
983 PWSTR ClassDescription
,
984 DWORD ClassDescriptionSize
,
992 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
993 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
995 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1000 if (hKey
== INVALID_HANDLE_VALUE
)
1002 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1006 if (RequiredSize
!= NULL
)
1009 if (RegQueryValueExW(hKey
,
1020 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1023 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1024 if (RegQueryValueExW(hKey
,
1028 (LPBYTE
)ClassDescription
,
1040 /***********************************************************************
1041 * SetupDiGetClassDevsA (SETUPAPI.@)
1043 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1049 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1050 flags
, NULL
, NULL
, NULL
);
1053 /***********************************************************************
1054 * SetupDiGetClassDevsW (SETUPAPI.@)
1056 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1062 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1063 flags
, NULL
, NULL
, NULL
);
1066 /***********************************************************************
1067 * SetupDiGetClassDevsExA (SETUPAPI.@)
1069 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1079 LPWSTR enumstrW
= NULL
;
1080 LPWSTR machineW
= NULL
;
1084 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1085 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1088 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1091 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1095 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1096 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1099 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1102 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1104 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1107 HeapFree(GetProcessHeap(), 0, enumstrW
);
1108 HeapFree(GetProcessHeap(), 0, machineW
);
1113 CreateDeviceInfoElement(
1114 IN LPCWSTR InstancePath
,
1115 IN LPCGUID pClassGuid
,
1116 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1119 struct DeviceInfoElement
*deviceInfo
;
1121 *pDeviceInfo
= NULL
;
1123 size
= sizeof(struct DeviceInfoElement
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1124 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1127 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1130 memset(deviceInfo
, 0, size
);
1131 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1132 wcscpy(deviceInfo
->Data
, InstancePath
);
1133 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1134 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1135 deviceInfo
->DeviceDescription
= NULL
;
1136 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1137 deviceInfo
->CreationFlags
= 0;
1138 InitializeListHead(&deviceInfo
->DriverListHead
);
1139 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1141 *pDeviceInfo
= deviceInfo
;
1146 CreateDeviceInterface(
1147 IN
struct DeviceInfoElement
* deviceInfo
,
1148 IN LPCWSTR SymbolicLink
,
1149 IN LPCGUID pInterfaceGuid
,
1150 OUT
struct DeviceInterface
**pDeviceInterface
)
1152 struct DeviceInterface
*deviceInterface
;
1154 *pDeviceInterface
= NULL
;
1156 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1157 if (!deviceInterface
)
1159 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1162 deviceInterface
->DeviceInfo
= deviceInfo
;
1163 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1164 deviceInterface
->Flags
= 0; /* FIXME */
1165 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1167 *pDeviceInterface
= deviceInterface
;
1171 static LONG
SETUP_CreateDevListFromEnumerator(
1172 struct DeviceInfoSet
*list
,
1173 LPCGUID pClassGuid OPTIONAL
,
1175 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1177 HKEY hDeviceIdKey
, hInstanceIdKey
;
1178 WCHAR KeyBuffer
[MAX_PATH
];
1179 WCHAR InstancePath
[MAX_PATH
];
1180 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1181 struct DeviceInfoElement
*deviceInfo
;
1183 DWORD dwLength
, dwRegType
;
1186 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1189 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1190 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1191 if (rc
== ERROR_NO_MORE_ITEMS
)
1193 if (rc
!= ERROR_SUCCESS
)
1197 /* Open device id sub key */
1198 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1199 if (rc
!= ERROR_SUCCESS
)
1201 wcscpy(InstancePath
, Enumerator
);
1202 wcscat(InstancePath
, L
"\\");
1203 wcscat(InstancePath
, KeyBuffer
);
1204 wcscat(InstancePath
, L
"\\");
1205 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1207 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1213 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1214 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1215 if (rc
== ERROR_NO_MORE_ITEMS
)
1217 if (rc
!= ERROR_SUCCESS
)
1219 RegCloseKey(hDeviceIdKey
);
1224 /* Open instance id sub key */
1225 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1226 if (rc
!= ERROR_SUCCESS
)
1228 RegCloseKey(hDeviceIdKey
);
1231 *pEndOfInstancePath
= '\0';
1232 wcscat(InstancePath
, KeyBuffer
);
1234 /* Read ClassGUID value */
1235 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1236 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1237 RegCloseKey(hInstanceIdKey
);
1238 if (rc
== ERROR_FILE_NOT_FOUND
)
1241 /* Skip this bad entry as we can't verify it */
1243 /* Set a default GUID for this device */
1244 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1246 else if (rc
!= ERROR_SUCCESS
)
1248 RegCloseKey(hDeviceIdKey
);
1251 else if (dwRegType
!= REG_SZ
)
1253 RegCloseKey(hDeviceIdKey
);
1254 return ERROR_GEN_FAILURE
;
1258 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1259 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1260 /* Bad GUID, skip the entry */
1264 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1266 /* Skip this entry as it is not the right device class */
1270 /* Add the entry to the list */
1271 if (!CreateDeviceInfoElement(InstancePath
, &KeyGuid
, &deviceInfo
))
1273 RegCloseKey(hDeviceIdKey
);
1274 return GetLastError();
1276 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1277 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1279 RegCloseKey(hDeviceIdKey
);
1282 return ERROR_SUCCESS
;
1285 static LONG
SETUP_CreateDevList(
1286 struct DeviceInfoSet
*list
,
1287 PCWSTR MachineName OPTIONAL
,
1288 LPGUID
class OPTIONAL
,
1289 PCWSTR Enumerator OPTIONAL
)
1291 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1292 WCHAR KeyBuffer
[MAX_PATH
];
1297 if (class && IsEqualIID(class, &GUID_NULL
))
1301 if (MachineName
!= NULL
)
1303 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1304 if (rc
!= ERROR_SUCCESS
)
1308 HKLM
= HKEY_LOCAL_MACHINE
;
1310 rc
= RegOpenKeyExW(HKLM
,
1313 KEY_ENUMERATE_SUB_KEYS
,
1315 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1316 if (rc
!= ERROR_SUCCESS
)
1319 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1320 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1329 KEY_ENUMERATE_SUB_KEYS
,
1331 RegCloseKey(hEnumKey
);
1332 if (rc
!= ERROR_SUCCESS
)
1334 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1335 RegCloseKey(hEnumeratorKey
);
1340 /* Enumerate enumerators */
1344 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1345 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1346 if (rc
== ERROR_NO_MORE_ITEMS
)
1348 if (rc
!= ERROR_SUCCESS
)
1350 RegCloseKey(hEnumKey
);
1356 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1357 if (rc
!= ERROR_SUCCESS
)
1359 RegCloseKey(hEnumKey
);
1363 /* Call SETUP_CreateDevListFromEnumerator */
1364 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1365 RegCloseKey(hEnumeratorKey
);
1366 if (rc
!= ERROR_SUCCESS
)
1368 RegCloseKey(hEnumKey
);
1372 RegCloseKey(hEnumKey
);
1373 return ERROR_SUCCESS
;
1378 static LONG
SETUP_CreateSerialDeviceList(
1379 struct DeviceInfoSet
*list
,
1381 LPGUID InterfaceGuid
,
1382 PCWSTR DeviceInstanceW
)
1384 static const size_t initialSize
= 100;
1386 WCHAR buf
[initialSize
];
1388 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1390 struct DeviceInfoElement
*deviceInfo
;
1393 WARN("'MachineName' is ignored on Wine!\n");
1394 if (DeviceInstanceW
)
1395 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1401 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1403 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1407 HeapFree(GetProcessHeap(), 0, devices
);
1408 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1410 return ERROR_NOT_ENOUGH_MEMORY
;
1416 HeapFree(GetProcessHeap(), 0, devices
);
1417 return GetLastError();
1421 /* 'devices' is a MULTI_SZ string */
1422 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1424 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1426 /* We have found a device */
1427 struct DeviceInterface
*interfaceInfo
;
1428 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1429 /* Step 1. Create a device info element */
1430 if (!CreateDeviceInfoElement(ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1433 HeapFree(GetProcessHeap(), 0, devices
);
1434 return GetLastError();
1436 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1438 /* Step 2. Create an interface list for this element */
1439 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1442 HeapFree(GetProcessHeap(), 0, devices
);
1443 return GetLastError();
1445 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1449 HeapFree(GetProcessHeap(), 0, devices
);
1450 return ERROR_SUCCESS
;
1453 #else /* __REACTOS__ */
1455 static LONG
SETUP_CreateInterfaceList(
1456 struct DeviceInfoSet
*list
,
1458 LPGUID InterfaceGuid
,
1459 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1461 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1462 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1463 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1464 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1465 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1467 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1470 DWORD dwLength
, dwInstancePathLength
;
1473 struct DeviceInfoElement
*deviceInfo
;
1475 /* Open registry key related to this interface */
1476 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1477 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1478 return GetLastError();
1480 /* Enumerate sub keys of hInterfaceKey */
1484 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1485 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1486 if (rc
== ERROR_NO_MORE_ITEMS
)
1488 if (rc
!= ERROR_SUCCESS
)
1490 RegCloseKey(hInterfaceKey
);
1496 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1497 if (rc
!= ERROR_SUCCESS
)
1499 RegCloseKey(hInterfaceKey
);
1503 /* Read DeviceInstance */
1504 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1505 if (rc
!= ERROR_SUCCESS
)
1507 RegCloseKey(hDeviceInstanceKey
);
1508 RegCloseKey(hInterfaceKey
);
1511 if (dwRegType
!= REG_SZ
)
1513 RegCloseKey(hDeviceInstanceKey
);
1514 RegCloseKey(hInterfaceKey
);
1515 return ERROR_GEN_FAILURE
;
1517 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1520 RegCloseKey(hDeviceInstanceKey
);
1521 RegCloseKey(hInterfaceKey
);
1522 return ERROR_NOT_ENOUGH_MEMORY
;
1524 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1525 if (rc
!= ERROR_SUCCESS
)
1527 HeapFree(GetProcessHeap(), 0, InstancePath
);
1528 RegCloseKey(hDeviceInstanceKey
);
1529 RegCloseKey(hInterfaceKey
);
1532 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1533 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1535 if (DeviceInstanceW
)
1537 /* Check if device enumerator is not the right one */
1538 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1540 HeapFree(GetProcessHeap(), 0, InstancePath
);
1541 RegCloseKey(hDeviceInstanceKey
);
1546 /* Find class GUID associated to the device instance */
1551 KEY_ENUMERATE_SUB_KEYS
,
1553 if (rc
!= ERROR_SUCCESS
)
1555 HeapFree(GetProcessHeap(), 0, InstancePath
);
1556 RegCloseKey(hDeviceInstanceKey
);
1557 RegCloseKey(hInterfaceKey
);
1566 RegCloseKey(hEnumKey
);
1567 if (rc
!= ERROR_SUCCESS
)
1569 HeapFree(GetProcessHeap(), 0, InstancePath
);
1570 RegCloseKey(hDeviceInstanceKey
);
1571 RegCloseKey(hInterfaceKey
);
1574 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1575 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1577 if (rc
!= ERROR_SUCCESS
)
1579 HeapFree(GetProcessHeap(), 0, InstancePath
);
1580 RegCloseKey(hDeviceInstanceKey
);
1581 RegCloseKey(hInterfaceKey
);
1584 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1585 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1586 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1588 HeapFree(GetProcessHeap(), 0, InstancePath
);
1589 RegCloseKey(hDeviceInstanceKey
);
1590 RegCloseKey(hInterfaceKey
);
1591 return ERROR_GEN_FAILURE
;
1593 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1595 /* If current device doesn't match the list GUID (if any), skip this entry */
1596 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1598 HeapFree(GetProcessHeap(), 0, InstancePath
);
1599 RegCloseKey(hDeviceInstanceKey
);
1603 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1607 LPWSTR pSymbolicLink
;
1608 struct DeviceInterface
*interfaceInfo
;
1610 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1611 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1612 if (rc
== ERROR_NO_MORE_ITEMS
)
1614 if (rc
!= ERROR_SUCCESS
)
1616 HeapFree(GetProcessHeap(), 0, InstancePath
);
1617 RegCloseKey(hDeviceInstanceKey
);
1618 RegCloseKey(hInterfaceKey
);
1622 if (KeyBuffer
[0] != '#')
1623 /* This entry doesn't represent an interesting entry */
1627 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1628 if (rc
!= ERROR_SUCCESS
)
1630 RegCloseKey(hDeviceInstanceKey
);
1631 RegCloseKey(hInterfaceKey
);
1635 /* Read SymbolicLink value */
1636 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1637 if (rc
!= ERROR_SUCCESS
)
1639 RegCloseKey(hReferenceKey
);
1640 RegCloseKey(hDeviceInstanceKey
);
1641 RegCloseKey(hInterfaceKey
);
1644 if (dwRegType
!= REG_SZ
)
1646 RegCloseKey(hReferenceKey
);
1647 RegCloseKey(hDeviceInstanceKey
);
1648 RegCloseKey(hInterfaceKey
);
1649 return ERROR_GEN_FAILURE
;
1652 /* We have found a device */
1653 /* Step 1. Create a device info element */
1654 if (!CreateDeviceInfoElement(InstancePath
, &ClassGuid
, &deviceInfo
))
1656 RegCloseKey(hReferenceKey
);
1657 RegCloseKey(hDeviceInstanceKey
);
1658 RegCloseKey(hInterfaceKey
);
1659 return GetLastError();
1661 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1662 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1664 /* Step 2. Create an interface list for this element */
1665 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1668 RegCloseKey(hReferenceKey
);
1669 RegCloseKey(hDeviceInstanceKey
);
1670 RegCloseKey(hInterfaceKey
);
1671 return ERROR_NOT_ENOUGH_MEMORY
;
1673 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1674 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1675 RegCloseKey(hReferenceKey
);
1676 if (rc
!= ERROR_SUCCESS
)
1678 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1679 RegCloseKey(hDeviceInstanceKey
);
1680 RegCloseKey(hInterfaceKey
);
1683 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1685 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1686 RegCloseKey(hDeviceInstanceKey
);
1687 RegCloseKey(hInterfaceKey
);
1688 return GetLastError();
1690 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1691 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1692 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1694 RegCloseKey(hDeviceInstanceKey
);
1696 RegCloseKey(hInterfaceKey
);
1697 return ERROR_SUCCESS
;
1699 #endif /* __REACTOS__ */
1701 /***********************************************************************
1702 * SetupDiGetClassDevsExW (SETUPAPI.@)
1704 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1713 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1714 struct DeviceInfoSet
*list
;
1718 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1719 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1721 /* Create the deviceset if not set */
1724 list
= (struct DeviceInfoSet
*)deviceset
;
1725 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1727 SetLastError(ERROR_INVALID_HANDLE
);
1728 return INVALID_HANDLE_VALUE
;
1730 hDeviceInfo
= deviceset
;
1734 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1735 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1736 NULL
, machine
, NULL
);
1737 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1738 return INVALID_HANDLE_VALUE
;
1739 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1742 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1745 pClassGuid
= &list
->ClassGuid
;
1747 if (flags
& DIGCF_PRESENT
)
1748 FIXME(": flag DIGCF_PRESENT ignored\n");
1749 if (flags
& DIGCF_PROFILE
)
1750 FIXME(": flag DIGCF_PROFILE ignored\n");
1752 if (flags
& DIGCF_ALLCLASSES
)
1754 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1755 if (rc
!= ERROR_SUCCESS
)
1759 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1760 return INVALID_HANDLE_VALUE
;
1764 else if (flags
& DIGCF_DEVICEINTERFACE
)
1768 SetLastError(ERROR_INVALID_PARAMETER
);
1770 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1771 return INVALID_HANDLE_VALUE
;
1775 /* Special case: find serial ports by calling QueryDosDevice */
1776 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1777 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1778 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1779 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1782 ERR("Wine can only enumerate serial devices at the moment!\n");
1783 rc
= ERROR_INVALID_PARAMETER
;
1785 #else /* __REACTOS__ */
1786 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1787 #endif /* __REACTOS__ */
1788 if (rc
!= ERROR_SUCCESS
)
1792 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1793 return INVALID_HANDLE_VALUE
;
1799 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1800 if (rc
!= ERROR_SUCCESS
)
1804 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1805 return INVALID_HANDLE_VALUE
;
1811 /***********************************************************************
1812 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1814 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1815 HDEVINFO DeviceInfoSet
,
1816 PSP_DEVINFO_DATA DeviceInfoData
,
1817 CONST GUID
* InterfaceClassGuid
,
1819 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1823 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
1824 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1826 if (!DeviceInterfaceData
)
1827 SetLastError(ERROR_INVALID_PARAMETER
);
1828 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
1829 SetLastError(ERROR_INVALID_USER_BUFFER
);
1830 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1832 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1834 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1836 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1838 while (ItemList
!= &list
->ListHead
&& !Found
)
1840 PLIST_ENTRY InterfaceListEntry
;
1841 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
1842 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
1844 /* We are not searching for this element */
1845 ItemList
= ItemList
->Flink
;
1848 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
1849 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
1851 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
1852 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
1854 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1857 if (MemberIndex
-- == 0)
1859 /* return this item */
1860 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1861 &DevItf
->InterfaceClassGuid
,
1863 DeviceInterfaceData
->Flags
= 0; /* FIXME */
1864 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
1867 InterfaceListEntry
= InterfaceListEntry
->Flink
;
1869 ItemList
= ItemList
->Flink
;
1872 SetLastError(ERROR_NO_MORE_ITEMS
);
1877 SetLastError(ERROR_INVALID_HANDLE
);
1880 SetLastError(ERROR_INVALID_HANDLE
);
1884 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
1886 InterlockedIncrement(&infFile
->References
);
1889 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
1891 if (InterlockedDecrement(&infFile
->References
) == 0)
1893 SetupCloseInfFile(infFile
->hInf
);
1894 HeapFree(GetProcessHeap(), 0, infFile
);
1898 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
1900 DereferenceInfFile(driverInfo
->InfFileDetails
);
1901 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
1902 HeapFree(GetProcessHeap(), 0, driverInfo
);
1906 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
1908 PLIST_ENTRY ListEntry
;
1909 struct DriverInfoElement
*driverInfo
;
1911 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1913 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1914 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
1915 if (!DestroyDriverInfoElement(driverInfo
))
1918 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
1920 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
1921 HeapFree(GetProcessHeap(), 0, ListEntry
);
1923 HeapFree(GetProcessHeap(), 0, deviceInfo
);
1927 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
1929 PLIST_ENTRY ListEntry
;
1930 struct DeviceInfoElement
*deviceInfo
;
1932 while (!IsListEmpty(&list
->ListHead
))
1934 ListEntry
= RemoveHeadList(&list
->ListHead
);
1935 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
1936 if (!DestroyDeviceInfoElement(deviceInfo
))
1939 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1940 RegCloseKey(list
->HKLM
);
1941 CM_Disconnect_Machine(list
->hMachine
);
1942 HeapFree(GetProcessHeap(), 0, list
);
1946 /***********************************************************************
1947 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1949 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1953 TRACE("%p\n", devinfo
);
1954 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1956 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1958 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
1959 ret
= DestroyDeviceInfoSet(list
);
1961 SetLastError(ERROR_INVALID_HANDLE
);
1964 SetLastError(ERROR_INVALID_HANDLE
);
1966 TRACE("Returning %d\n", ret
);
1970 /***********************************************************************
1971 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1973 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1974 HDEVINFO DeviceInfoSet
,
1975 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1976 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1977 DWORD DeviceInterfaceDetailDataSize
,
1978 PDWORD RequiredSize
,
1979 PSP_DEVINFO_DATA DeviceInfoData
)
1981 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
1982 DWORD sizeW
= 0, sizeA
;
1985 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
1986 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1987 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1989 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
1990 SetLastError(ERROR_INVALID_USER_BUFFER
);
1991 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
1992 SetLastError(ERROR_INVALID_PARAMETER
);
1993 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
1994 SetLastError(ERROR_INVALID_PARAMETER
);
1997 if (DeviceInterfaceDetailData
!= NULL
)
1999 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2000 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2001 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2002 if (!DeviceInterfaceDetailDataW
)
2004 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2007 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2009 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2010 ret
= SetupDiGetDeviceInterfaceDetailW(
2012 DeviceInterfaceData
,
2013 DeviceInterfaceDetailDataW
,
2017 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2018 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2020 *RequiredSize
= sizeA
;
2021 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2023 if (!WideCharToMultiByte(
2025 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2026 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2033 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2036 TRACE("Returning %d\n", ret
);
2040 /***********************************************************************
2041 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2043 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2044 HDEVINFO DeviceInfoSet
,
2045 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2046 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2047 DWORD DeviceInterfaceDetailDataSize
,
2048 PDWORD RequiredSize
,
2049 PSP_DEVINFO_DATA DeviceInfoData
)
2051 struct DeviceInfoSet
*list
;
2054 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2055 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2056 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2058 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2059 SetLastError(ERROR_INVALID_PARAMETER
);
2060 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2061 SetLastError(ERROR_INVALID_HANDLE
);
2062 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2063 SetLastError(ERROR_INVALID_HANDLE
);
2064 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2065 SetLastError(ERROR_INVALID_USER_BUFFER
);
2066 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2067 SetLastError(ERROR_INVALID_USER_BUFFER
);
2068 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2069 SetLastError(ERROR_INVALID_USER_BUFFER
);
2070 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2071 SetLastError(ERROR_INVALID_PARAMETER
);
2072 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2073 SetLastError(ERROR_INVALID_PARAMETER
);
2076 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2077 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2078 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2079 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2081 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2083 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2085 *RequiredSize
= sizeRequired
;
2089 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2090 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2093 memcpy(&DeviceInfoData
->ClassGuid
,
2094 &deviceInterface
->DeviceInfo
->ClassGuid
,
2096 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
2097 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2103 TRACE("Returning %d\n", ret
);
2107 /***********************************************************************
2108 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2110 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2112 PSP_DEVINFO_DATA DeviceInfoData
,
2114 PDWORD PropertyRegDataType
,
2115 PBYTE PropertyBuffer
,
2116 DWORD PropertyBufferSize
,
2117 PDWORD RequiredSize
)
2120 BOOL bIsStringProperty
;
2122 DWORD RequiredSizeA
, RequiredSizeW
;
2123 DWORD PropertyBufferSizeW
;
2124 PBYTE PropertyBufferW
;
2126 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2127 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2130 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2131 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2133 bResult
= SetupDiGetDeviceRegistryPropertyW(
2139 PropertyBufferSizeW
,
2142 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2144 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2146 if (bIsStringProperty
)
2147 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2149 RequiredSizeA
= RequiredSizeW
;
2151 *RequiredSize
= RequiredSizeA
;
2152 if (PropertyRegDataType
)
2153 *PropertyRegDataType
= RegType
;
2158 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2162 if (RequiredSizeA
<= PropertyBufferSize
)
2164 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2166 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2168 /* Last error is already set by WideCharToMultiByte */
2173 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2177 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2181 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2185 /***********************************************************************
2186 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2188 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2189 HDEVINFO DeviceInfoSet
,
2190 PSP_DEVINFO_DATA DeviceInfoData
,
2192 PDWORD PropertyRegDataType
,
2193 PBYTE PropertyBuffer
,
2194 DWORD PropertyBufferSize
,
2195 PDWORD RequiredSize
)
2197 HKEY hEnumKey
, hKey
;
2201 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2202 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2205 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2206 SetLastError(ERROR_INVALID_HANDLE
);
2207 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2208 SetLastError(ERROR_INVALID_HANDLE
);
2209 else if (!DeviceInfoData
)
2210 SetLastError(ERROR_INVALID_PARAMETER
);
2211 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2212 SetLastError(ERROR_INVALID_USER_BUFFER
);
2213 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2214 SetLastError(ERROR_INVALID_PARAMETER
);
2217 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2218 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2222 case SPDRP_CAPABILITIES
:
2224 case SPDRP_CLASSGUID
:
2225 case SPDRP_COMPATIBLEIDS
:
2226 case SPDRP_CONFIGFLAGS
:
2227 case SPDRP_DEVICEDESC
:
2229 case SPDRP_FRIENDLYNAME
:
2230 case SPDRP_HARDWAREID
:
2231 case SPDRP_LOCATION_INFORMATION
:
2232 case SPDRP_LOWERFILTERS
:
2234 case SPDRP_SECURITY
:
2236 case SPDRP_UI_NUMBER
:
2237 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2238 case SPDRP_UPPERFILTERS
:
2240 LPCWSTR RegistryPropertyName
;
2245 case SPDRP_CAPABILITIES
:
2246 RegistryPropertyName
= L
"Capabilities"; break;
2248 RegistryPropertyName
= L
"Class"; break;
2249 case SPDRP_CLASSGUID
:
2250 RegistryPropertyName
= L
"ClassGUID"; break;
2251 case SPDRP_COMPATIBLEIDS
:
2252 RegistryPropertyName
= L
"CompatibleIDs"; break;
2253 case SPDRP_CONFIGFLAGS
:
2254 RegistryPropertyName
= L
"ConfigFlags"; break;
2255 case SPDRP_DEVICEDESC
:
2256 RegistryPropertyName
= L
"DeviceDesc"; break;
2258 RegistryPropertyName
= L
"Driver"; break;
2259 case SPDRP_FRIENDLYNAME
:
2260 RegistryPropertyName
= L
"FriendlyName"; break;
2261 case SPDRP_HARDWAREID
:
2262 RegistryPropertyName
= L
"HardwareID"; break;
2263 case SPDRP_LOCATION_INFORMATION
:
2264 RegistryPropertyName
= L
"LocationInformation"; break;
2265 case SPDRP_LOWERFILTERS
:
2266 RegistryPropertyName
= L
"LowerFilters"; break;
2268 RegistryPropertyName
= L
"Mfg"; break;
2269 case SPDRP_SECURITY
:
2270 RegistryPropertyName
= L
"Security"; break;
2272 RegistryPropertyName
= L
"Service"; break;
2273 case SPDRP_UI_NUMBER
:
2274 RegistryPropertyName
= L
"UINumber"; break;
2275 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2276 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2277 case SPDRP_UPPERFILTERS
:
2278 RegistryPropertyName
= L
"UpperFilters"; break;
2280 /* Should not happen */
2281 RegistryPropertyName
= NULL
; break;
2284 /* Open registry key name */
2289 KEY_ENUMERATE_SUB_KEYS
,
2291 if (rc
!= ERROR_SUCCESS
)
2302 RegCloseKey(hEnumKey
);
2303 if (rc
!= ERROR_SUCCESS
)
2308 /* Read registry entry */
2309 BufferSize
= PropertyBufferSize
;
2310 rc
= RegQueryValueExW(
2312 RegistryPropertyName
,
2313 NULL
, /* Reserved */
2314 PropertyRegDataType
,
2318 *RequiredSize
= BufferSize
;
2321 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2324 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2326 case ERROR_MORE_DATA
:
2327 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2336 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2338 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2340 if (PropertyRegDataType
)
2341 *PropertyRegDataType
= REG_SZ
;
2343 *RequiredSize
= required
;
2344 if (PropertyBufferSize
>= required
)
2346 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2350 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2354 /*case SPDRP_BUSTYPEGUID:
2355 case SPDRP_LEGACYBUSTYPE:
2356 case SPDRP_BUSNUMBER:
2357 case SPDRP_ENUMERATOR_NAME:
2358 case SPDRP_SECURITY_SDS:
2360 case SPDRP_EXCLUSIVE:
2361 case SPDRP_CHARACTERISTICS:
2363 case SPDRP_DEVICE_POWER_DATA:*/
2364 #if (WINVER >= 0x501)
2365 /*case SPDRP_REMOVAL_POLICY:
2366 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2367 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2368 case SPDRP_INSTALL_STATE:*/
2373 ERR("Property 0x%lx not implemented\n", Property
);
2374 SetLastError(ERROR_NOT_SUPPORTED
);
2379 TRACE("Returning %d\n", ret
);
2383 /***********************************************************************
2384 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2386 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2387 IN HDEVINFO DeviceInfoSet
,
2388 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2390 IN CONST BYTE
*PropertyBuffer
,
2391 IN DWORD PropertyBufferSize
)
2393 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2394 Property
, PropertyBuffer
, PropertyBufferSize
);
2395 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2399 /***********************************************************************
2400 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2402 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2403 IN HDEVINFO DeviceInfoSet
,
2404 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2406 IN
const BYTE
*PropertyBuffer
,
2407 IN DWORD PropertyBufferSize
)
2409 struct DeviceInfoSet
*list
;
2412 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2413 Property
, PropertyBuffer
, PropertyBufferSize
);
2416 SetLastError(ERROR_INVALID_HANDLE
);
2417 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2418 SetLastError(ERROR_INVALID_HANDLE
);
2419 else if (DeviceInfoData
)
2420 SetLastError(ERROR_INVALID_HANDLE
);
2421 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2422 SetLastError(ERROR_INVALID_USER_BUFFER
);
2427 case SPDRP_COMPATIBLEIDS
:
2428 case SPDRP_CONFIGFLAGS
:
2429 case SPDRP_FRIENDLYNAME
:
2430 case SPDRP_HARDWAREID
:
2431 case SPDRP_LOCATION_INFORMATION
:
2432 case SPDRP_LOWERFILTERS
:
2433 case SPDRP_SECURITY
:
2435 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2436 case SPDRP_UPPERFILTERS
:
2438 LPCWSTR RegistryPropertyName
;
2439 DWORD RegistryDataType
;
2445 case SPDRP_COMPATIBLEIDS
:
2446 RegistryPropertyName
= L
"CompatibleIDs";
2447 RegistryDataType
= REG_MULTI_SZ
;
2449 case SPDRP_CONFIGFLAGS
:
2450 RegistryPropertyName
= L
"ConfigFlags";
2451 RegistryDataType
= REG_DWORD
;
2453 case SPDRP_FRIENDLYNAME
:
2454 RegistryPropertyName
= L
"FriendlyName";
2455 RegistryDataType
= REG_SZ
;
2457 case SPDRP_HARDWAREID
:
2458 RegistryPropertyName
= L
"HardwareID";
2459 RegistryDataType
= REG_MULTI_SZ
;
2461 case SPDRP_LOCATION_INFORMATION
:
2462 RegistryPropertyName
= L
"LocationInformation";
2463 RegistryDataType
= REG_SZ
;
2465 case SPDRP_LOWERFILTERS
:
2466 RegistryPropertyName
= L
"LowerFilters";
2467 RegistryDataType
= REG_MULTI_SZ
;
2469 case SPDRP_SECURITY
:
2470 RegistryPropertyName
= L
"Security";
2471 RegistryDataType
= REG_BINARY
;
2474 RegistryPropertyName
= L
"Service";
2475 RegistryDataType
= REG_SZ
;
2477 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2478 RegistryPropertyName
= L
"UINumberDescFormat";
2479 RegistryDataType
= REG_SZ
;
2481 case SPDRP_UPPERFILTERS
:
2482 RegistryPropertyName
= L
"UpperFilters";
2483 RegistryDataType
= REG_MULTI_SZ
;
2486 /* Should not happen */
2487 RegistryPropertyName
= NULL
;
2488 RegistryDataType
= REG_BINARY
;
2491 /* Open device registry key */
2492 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2493 if (hKey
!= INVALID_HANDLE_VALUE
)
2495 /* Write new data */
2496 rc
= RegSetValueExW(
2498 RegistryPropertyName
,
2502 PropertyBufferSize
);
2503 if (rc
== ERROR_SUCCESS
)
2512 /*case SPDRP_CHARACTERISTICS:
2514 case SPDRP_EXCLUSIVE:*/
2515 #if (WINVER >= 0x501)
2516 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2518 //case SPDRP_SECURITY_SDS:
2522 ERR("Property 0x%lx not implemented\n", Property
);
2523 SetLastError(ERROR_NOT_SUPPORTED
);
2528 TRACE("Returning %d\n", ret
);
2532 /***********************************************************************
2533 * SetupDiInstallClassA (SETUPAPI.@)
2535 BOOL WINAPI
SetupDiInstallClassA(
2541 UNICODE_STRING FileNameW
;
2544 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2546 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2550 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2552 RtlFreeUnicodeString(&FileNameW
);
2557 static HKEY
CreateClassKey(HINF hInf
)
2559 WCHAR FullBuffer
[MAX_PATH
];
2560 WCHAR Buffer
[MAX_PATH
];
2565 if (!SetupGetLineTextW(NULL
,
2573 return INVALID_HANDLE_VALUE
;
2576 lstrcpyW(FullBuffer
, ControlClass
);
2577 lstrcatW(FullBuffer
, Buffer
);
2580 if (!SetupGetLineTextW(NULL
,
2588 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2589 return INVALID_HANDLE_VALUE
;
2592 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2596 REG_OPTION_NON_VOLATILE
,
2602 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2603 return INVALID_HANDLE_VALUE
;
2606 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2611 RequiredSize
* sizeof(WCHAR
)))
2613 RegCloseKey(hClassKey
);
2614 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2615 return INVALID_HANDLE_VALUE
;
2621 /***********************************************************************
2622 * SetupDiInstallClassW (SETUPAPI.@)
2624 BOOL WINAPI
SetupDiInstallClassW(
2630 WCHAR SectionName
[MAX_PATH
];
2631 DWORD SectionNameLength
= 0;
2633 BOOL bFileQueueCreated
= FALSE
;
2636 TRACE("%p %s 0x%lx %p\n", hwndParent
, debugstr_w(InfFileName
),
2639 FIXME("not fully implemented\n");
2641 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
2643 SetLastError(ERROR_INVALID_PARAMETER
);
2647 /* Open the .inf file */
2648 hInf
= SetupOpenInfFileW(InfFileName
,
2652 if (hInf
== INVALID_HANDLE_VALUE
)
2658 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2659 hClassKey
= CreateClassKey(hInf
);
2660 if (hClassKey
== INVALID_HANDLE_VALUE
)
2662 SetupCloseInfFile(hInf
);
2668 /* Try to append a layout file */
2670 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
2673 /* Retrieve the actual section name */
2674 SetupDiGetActualSectionToInstallW(hInf
,
2682 if (!(Flags
& DI_NOVCP
))
2684 FileQueue
= SetupOpenFileQueue();
2685 if (FileQueue
== INVALID_HANDLE_VALUE
)
2687 SetupCloseInfFile(hInf
);
2688 RegCloseKey(hClassKey
);
2692 bFileQueueCreated
= TRUE
;
2697 SetupInstallFromInfSectionW(NULL
,
2706 INVALID_HANDLE_VALUE
,
2709 /* FIXME: More code! */
2711 if (bFileQueueCreated
)
2712 SetupCloseFileQueue(FileQueue
);
2714 SetupCloseInfFile(hInf
);
2716 RegCloseKey(hClassKey
);
2721 /***********************************************************************
2722 * SetupDiOpenClassRegKey (SETUPAPI.@)
2724 HKEY WINAPI
SetupDiOpenClassRegKey(
2725 const GUID
* ClassGuid
,
2728 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2729 DIOCR_INSTALLER
, NULL
, NULL
);
2733 /***********************************************************************
2734 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
2736 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
2737 const GUID
* ClassGuid
,
2743 PWSTR MachineNameW
= NULL
;
2750 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2751 if (MachineNameW
== NULL
)
2752 return INVALID_HANDLE_VALUE
;
2755 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
2756 Flags
, MachineNameW
, Reserved
);
2759 MyFree(MachineNameW
);
2765 /***********************************************************************
2766 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2768 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
2769 const GUID
* ClassGuid
,
2775 LPWSTR lpGuidString
;
2776 LPWSTR lpFullGuidString
;
2784 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
2785 Flags
, debugstr_w(MachineName
), Reserved
);
2787 if (Flags
== DIOCR_INSTALLER
)
2789 lpKeyName
= ControlClass
;
2791 else if (Flags
== DIOCR_INTERFACE
)
2793 lpKeyName
= DeviceClasses
;
2797 ERR("Invalid Flags parameter!\n");
2798 SetLastError(ERROR_INVALID_FLAGS
);
2799 return INVALID_HANDLE_VALUE
;
2802 if (MachineName
!= NULL
)
2804 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
2805 if (rc
!= ERROR_SUCCESS
)
2808 return INVALID_HANDLE_VALUE
;
2812 HKLM
= HKEY_LOCAL_MACHINE
;
2814 rc
= RegOpenKeyExW(HKLM
,
2817 ClassGuid
? KEY_ENUMERATE_SUB_KEYS
: samDesired
,
2819 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
2820 if (rc
!= ERROR_SUCCESS
)
2823 return INVALID_HANDLE_VALUE
;
2826 if (ClassGuid
== NULL
)
2829 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2831 SetLastError(ERROR_GEN_FAILURE
);
2832 RegCloseKey(hClassesKey
);
2833 return INVALID_HANDLE_VALUE
;
2836 dwLength
= lstrlenW(lpGuidString
);
2837 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
2838 if (!lpFullGuidString
)
2840 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2841 RpcStringFreeW(&lpGuidString
);
2842 return INVALID_HANDLE_VALUE
;
2844 lpFullGuidString
[0] = '{';
2845 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
2846 lpFullGuidString
[dwLength
+ 1] = '}';
2847 lpFullGuidString
[dwLength
+ 2] = '\0';
2848 RpcStringFreeW(&lpGuidString
);
2850 rc
= RegOpenKeyExW(hClassesKey
,
2855 if (rc
!= ERROR_SUCCESS
)
2858 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2859 RegCloseKey(hClassesKey
);
2860 return INVALID_HANDLE_VALUE
;
2863 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
2864 RegCloseKey(hClassesKey
);
2869 /***********************************************************************
2870 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2872 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
2873 HDEVINFO DeviceInfoSet
,
2876 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2878 FIXME("%p %s %08lx %p\n",
2879 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2883 /***********************************************************************
2884 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2886 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
2887 HDEVINFO DeviceInfoSet
,
2890 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2892 LPWSTR DevicePathW
= NULL
;
2895 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
2897 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
2898 if (DevicePathW
== NULL
)
2901 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
2902 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
2904 MyFree(DevicePathW
);
2909 /***********************************************************************
2910 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2912 BOOL WINAPI
SetupDiSetClassInstallParamsA(
2913 HDEVINFO DeviceInfoSet
,
2914 PSP_DEVINFO_DATA DeviceInfoData
,
2915 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
2916 DWORD ClassInstallParamsSize
)
2918 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
2919 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
2925 IN PWSTR InstallerName
,
2926 OUT HMODULE
* ModulePointer
,
2927 OUT PVOID
* FunctionPointer
)
2929 HMODULE hModule
= NULL
;
2930 LPSTR FunctionNameA
= NULL
;
2934 *ModulePointer
= NULL
;
2935 *FunctionPointer
= NULL
;
2937 Comma
= strchrW(InstallerName
, ',');
2940 rc
= ERROR_INVALID_PARAMETER
;
2946 hModule
= LoadLibraryW(InstallerName
);
2950 rc
= GetLastError();
2954 /* Skip comma spaces */
2955 while (*Comma
== ',' || isspaceW(*Comma
))
2958 /* W->A conversion for function name */
2959 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
2962 rc
= GetLastError();
2966 /* Search function */
2967 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
2968 if (!*FunctionPointer
)
2970 rc
= GetLastError();
2974 *ModulePointer
= hModule
;
2978 if (rc
!= ERROR_SUCCESS
&& hModule
)
2979 FreeLibrary(hModule
);
2980 MyFree(FunctionNameA
);
2985 FreeFunctionPointer(
2986 IN HMODULE ModulePointer
,
2987 IN PVOID FunctionPointer
)
2989 if (ModulePointer
== NULL
)
2990 return ERROR_SUCCESS
;
2991 if (FreeLibrary(ModulePointer
))
2992 return ERROR_SUCCESS
;
2994 return GetLastError();
2997 /***********************************************************************
2998 * SetupDiCallClassInstaller (SETUPAPI.@)
3000 BOOL WINAPI
SetupDiCallClassInstaller(
3001 IN DI_FUNCTION InstallFunction
,
3002 IN HDEVINFO DeviceInfoSet
,
3003 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3007 TRACE("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3010 SetLastError(ERROR_INVALID_PARAMETER
);
3011 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3012 SetLastError(ERROR_INVALID_HANDLE
);
3013 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3014 SetLastError(ERROR_INVALID_HANDLE
);
3015 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3016 SetLastError(ERROR_INVALID_HANDLE
);
3017 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3018 SetLastError(ERROR_INVALID_USER_BUFFER
);
3021 SP_DEVINSTALL_PARAMS_W InstallParams
;
3022 #define CLASS_COINSTALLER 0x1
3023 #define DEVICE_COINSTALLER 0x2
3024 #define CLASS_INSTALLER 0x4
3025 UCHAR CanHandle
= 0;
3026 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3028 switch (InstallFunction
)
3030 case DIF_ALLOW_INSTALL
:
3031 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3033 case DIF_DESTROYPRIVATEDATA
:
3034 CanHandle
= CLASS_INSTALLER
;
3036 case DIF_INSTALLDEVICE
:
3037 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3038 DefaultHandler
= SetupDiInstallDevice
;
3040 case DIF_INSTALLDEVICEFILES
:
3041 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3042 DefaultHandler
= SetupDiInstallDriverFiles
;
3044 case DIF_INSTALLINTERFACES
:
3045 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3046 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3048 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3049 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3051 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3052 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3054 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3055 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3057 case DIF_REGISTER_COINSTALLERS
:
3058 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3059 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3061 case DIF_SELECTBESTCOMPATDRV
:
3062 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3063 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3066 ERR("Install function %lu not supported\n", InstallFunction
);
3067 SetLastError(ERROR_NOT_SUPPORTED
);
3070 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3071 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3072 /* Don't process this call, as a parameter is invalid */
3077 LIST_ENTRY ClassCoInstallersListHead
;
3078 LIST_ENTRY DeviceCoInstallersListHead
;
3079 HMODULE ClassInstallerLibrary
= NULL
;
3080 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3081 COINSTALLER_CONTEXT_DATA Context
;
3082 PLIST_ENTRY ListEntry
;
3084 DWORD dwRegType
, dwLength
;
3085 DWORD rc
= NO_ERROR
;
3087 InitializeListHead(&ClassCoInstallersListHead
);
3088 InitializeListHead(&DeviceCoInstallersListHead
);
3090 if (CanHandle
& DEVICE_COINSTALLER
)
3092 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3093 if (hKey
!= INVALID_HANDLE_VALUE
)
3095 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3096 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3098 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3099 if (KeyBuffer
!= NULL
)
3101 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3102 if (rc
== ERROR_SUCCESS
)
3105 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3107 /* Add coinstaller to DeviceCoInstallersListHead list */
3108 struct CoInstallerElement
*coinstaller
;
3109 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3110 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3113 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3114 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3115 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3117 HeapFree(GetProcessHeap(), 0, coinstaller
);
3120 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3126 if (CanHandle
& CLASS_COINSTALLER
)
3130 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3134 if (rc
== ERROR_SUCCESS
)
3136 LPWSTR lpGuidString
;
3137 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3139 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3140 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3142 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3143 if (KeyBuffer
!= NULL
)
3145 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3146 if (rc
== ERROR_SUCCESS
)
3149 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3151 /* Add coinstaller to ClassCoInstallersListHead list */
3152 struct CoInstallerElement
*coinstaller
;
3153 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3154 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3157 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3158 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3159 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3161 HeapFree(GetProcessHeap(), 0, coinstaller
);
3164 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3167 RpcStringFreeW(&lpGuidString
);
3172 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3174 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3175 if (hKey
!= INVALID_HANDLE_VALUE
)
3177 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3178 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3180 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3181 if (KeyBuffer
!= NULL
)
3183 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3184 if (rc
== ERROR_SUCCESS
)
3186 /* Get ClassInstaller function pointer */
3187 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3188 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3190 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3191 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3194 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3201 /* Call Class co-installers */
3202 Context
.PostProcessing
= FALSE
;
3204 ListEntry
= ClassCoInstallersListHead
.Flink
;
3205 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3207 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3208 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3209 coinstaller
->PrivateData
= Context
.PrivateData
;
3210 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3212 coinstaller
->DoPostProcessing
= TRUE
;
3215 ListEntry
= ListEntry
->Flink
;
3218 /* Call Device co-installers */
3219 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3220 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3222 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3223 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3224 coinstaller
->PrivateData
= Context
.PrivateData
;
3225 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3227 coinstaller
->DoPostProcessing
= TRUE
;
3230 ListEntry
= ListEntry
->Flink
;
3233 /* Call Class installer */
3236 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3237 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3240 rc
= ERROR_DI_DO_DEFAULT
;
3242 /* Call default handler */
3243 if (rc
== ERROR_DI_DO_DEFAULT
)
3245 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3247 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3250 rc
= GetLastError();
3256 /* Call Class co-installers that required postprocessing */
3257 Context
.PostProcessing
= TRUE
;
3258 ListEntry
= ClassCoInstallersListHead
.Flink
;
3259 while (ListEntry
!= &ClassCoInstallersListHead
)
3261 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3262 if (coinstaller
->DoPostProcessing
)
3264 Context
.InstallResult
= rc
;
3265 Context
.PrivateData
= coinstaller
->PrivateData
;
3266 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3268 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3269 ListEntry
= ListEntry
->Flink
;
3272 /* Call Device co-installers that required postprocessing */
3273 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3274 while (ListEntry
!= &DeviceCoInstallersListHead
)
3276 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3277 if (coinstaller
->DoPostProcessing
)
3279 Context
.InstallResult
= rc
;
3280 Context
.PrivateData
= coinstaller
->PrivateData
;
3281 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3283 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3284 ListEntry
= ListEntry
->Flink
;
3287 /* Free allocated memory */
3288 while (!IsListEmpty(&ClassCoInstallersListHead
))
3290 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3291 HeapFree(GetProcessHeap(), 0, ListEntry
);
3293 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3295 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3296 HeapFree(GetProcessHeap(), 0, ListEntry
);
3299 ret
= (rc
== NO_ERROR
);
3303 TRACE("Returning %d\n", ret
);
3307 /***********************************************************************
3308 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3310 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
3311 IN HDEVINFO DeviceInfoSet
,
3312 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
3314 struct DeviceInfoSet
*list
;
3317 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
3320 SetLastError(ERROR_INVALID_HANDLE
);
3321 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3322 SetLastError(ERROR_INVALID_HANDLE
);
3323 else if (!DeviceInfoListDetailData
)
3324 SetLastError(ERROR_INVALID_PARAMETER
);
3325 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
3326 SetLastError(ERROR_INVALID_USER_BUFFER
);
3330 &DeviceInfoListDetailData
->ClassGuid
,
3333 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
3334 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0; /* FIXME */
3339 TRACE("Returning %d\n", ret
);
3343 /***********************************************************************
3344 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3346 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3347 IN HDEVINFO DeviceInfoSet
,
3348 IN PSP_DEVINFO_DATA DeviceInfoData
,
3349 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3351 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3354 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3356 if (DeviceInstallParams
== NULL
)
3357 SetLastError(ERROR_INVALID_PARAMETER
);
3358 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3359 SetLastError(ERROR_INVALID_USER_BUFFER
);
3362 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3363 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3367 /* Do W->A conversion */
3369 DeviceInstallParams
,
3370 &deviceInstallParamsW
,
3371 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3372 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3373 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3375 DeviceInstallParams
->DriverPath
[0] = '\0';
3381 TRACE("Returning %d\n", ret
);
3385 /***********************************************************************
3386 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3388 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3389 IN HDEVINFO DeviceInfoSet
,
3390 IN PSP_DEVINFO_DATA DeviceInfoData
,
3391 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3393 struct DeviceInfoSet
*list
;
3396 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3399 SetLastError(ERROR_INVALID_HANDLE
);
3400 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3401 SetLastError(ERROR_INVALID_HANDLE
);
3402 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3403 SetLastError(ERROR_INVALID_USER_BUFFER
);
3404 else if (!DeviceInstallParams
)
3405 SetLastError(ERROR_INVALID_PARAMETER
);
3406 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3407 SetLastError(ERROR_INVALID_USER_BUFFER
);
3410 PSP_DEVINSTALL_PARAMS_W Source
;
3413 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3415 Source
= &list
->InstallParams
;
3416 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3420 TRACE("Returning %d\n", ret
);
3424 /***********************************************************************
3425 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3427 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3428 IN HDEVINFO DeviceInfoSet
,
3429 IN PSP_DEVINFO_DATA DeviceInfoData
,
3430 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3432 struct DeviceInfoSet
*list
;
3435 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3438 SetLastError(ERROR_INVALID_HANDLE
);
3439 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3440 SetLastError(ERROR_INVALID_HANDLE
);
3441 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3442 SetLastError(ERROR_INVALID_USER_BUFFER
);
3443 else if (!DeviceInstallParams
)
3444 SetLastError(ERROR_INVALID_PARAMETER
);
3445 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3446 SetLastError(ERROR_INVALID_USER_BUFFER
);
3449 PSP_DEVINSTALL_PARAMS_W Destination
;
3451 /* FIXME: Validate parameters */
3454 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3456 Destination
= &list
->InstallParams
;
3457 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3461 TRACE("Returning %d\n", ret
);
3465 /***********************************************************************
3466 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
3468 HKEY WINAPI
SetupDiCreateDevRegKeyA(
3469 IN HDEVINFO DeviceInfoSet
,
3470 IN PSP_DEVINFO_DATA DeviceInfoData
,
3474 IN HINF InfHandle OPTIONAL
,
3475 IN PCSTR InfSectionName OPTIONAL
)
3477 PCWSTR InfSectionNameW
= NULL
;
3478 HKEY ret
= INVALID_HANDLE_VALUE
;
3482 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
3483 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
3486 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
3494 if (InfSectionNameW
!= NULL
)
3495 MyFree((PVOID
)InfSectionNameW
);
3500 /***********************************************************************
3501 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
3503 HKEY WINAPI
SetupDiCreateDevRegKeyW(
3504 IN HDEVINFO DeviceInfoSet
,
3505 IN PSP_DEVINFO_DATA DeviceInfoData
,
3509 IN HINF InfHandle OPTIONAL
,
3510 IN PCWSTR InfSectionName OPTIONAL
)
3512 struct DeviceInfoSet
*list
;
3513 HKEY ret
= INVALID_HANDLE_VALUE
;
3515 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
3516 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
3519 SetLastError(ERROR_INVALID_HANDLE
);
3520 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3521 SetLastError(ERROR_INVALID_HANDLE
);
3522 else if (!DeviceInfoData
)
3523 SetLastError(ERROR_INVALID_PARAMETER
);
3524 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3525 SetLastError(ERROR_INVALID_USER_BUFFER
);
3526 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3527 SetLastError(ERROR_INVALID_PARAMETER
);
3528 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3529 SetLastError(ERROR_INVALID_PARAMETER
);
3530 else if (InfHandle
&& !InfSectionName
)
3531 SetLastError(ERROR_INVALID_PARAMETER
);
3532 else if (!InfHandle
&& InfSectionName
)
3533 SetLastError(ERROR_INVALID_PARAMETER
);
3536 LPWSTR lpGuidString
= NULL
;
3537 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
3538 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
3539 DWORD Index
; /* Index used in the DriverKey name */
3541 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3542 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
3543 HKEY hKey
= INVALID_HANDLE_VALUE
;
3545 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3547 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3551 if (KeyType
== DIREG_DEV
)
3553 FIXME("DIREG_DEV case unimplemented\n");
3555 else /* KeyType == DIREG_DRV */
3557 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3559 /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
3560 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
3563 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3566 wcscpy(DriverKey
, L
"{");
3567 wcscat(DriverKey
, lpGuidString
);
3568 wcscat(DriverKey
, L
"}\\");
3569 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
3570 rc
= RegOpenKeyExW(list
->HKLM
,
3575 if (rc
!= ERROR_SUCCESS
)
3581 /* Try all values for Index between 0 and 9999 */
3583 while (Index
<= 9999)
3586 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
3587 rc
= RegCreateKeyEx(hClassKey
,
3591 REG_OPTION_NON_VOLATILE
,
3592 #if _WIN32_WINNT >= 0x502
3593 KEY_READ
| KEY_WRITE
,
3600 if (rc
!= ERROR_SUCCESS
)
3605 if (Disposition
== REG_CREATED_NEW_KEY
)
3608 hKey
= INVALID_HANDLE_VALUE
;
3613 /* Unable to create more than 9999 devices within the same class */
3614 SetLastError(ERROR_GEN_FAILURE
);
3618 /* Open device key, to write Driver value */
3619 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
3620 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
3622 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
3623 if (rc
!= ERROR_SUCCESS
)
3630 /* Do installation of the specified section */
3633 FIXME("Need to install section %s in file %p\n",
3634 debugstr_w(InfSectionName
), InfHandle
);
3640 RpcStringFreeW(&lpGuidString
);
3641 HeapFree(GetProcessHeap(), 0, DriverKey
);
3642 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3643 RegCloseKey(hClassKey
);
3644 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
3645 RegCloseKey(hDeviceKey
);
3646 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3650 TRACE("Returning 0x%p\n", ret
);
3654 /***********************************************************************
3655 * SetupDiOpenDevRegKey (SETUPAPI.@)
3657 HKEY WINAPI
SetupDiOpenDevRegKey(
3658 HDEVINFO DeviceInfoSet
,
3659 PSP_DEVINFO_DATA DeviceInfoData
,
3665 struct DeviceInfoSet
*list
;
3666 HKEY ret
= INVALID_HANDLE_VALUE
;
3668 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3669 Scope
, HwProfile
, KeyType
, samDesired
);
3672 SetLastError(ERROR_INVALID_HANDLE
);
3673 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3674 SetLastError(ERROR_INVALID_HANDLE
);
3675 else if (!DeviceInfoData
)
3676 SetLastError(ERROR_INVALID_PARAMETER
);
3677 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3678 SetLastError(ERROR_INVALID_USER_BUFFER
);
3679 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3680 SetLastError(ERROR_INVALID_PARAMETER
);
3681 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
3682 SetLastError(ERROR_INVALID_PARAMETER
);
3685 HKEY hKey
= INVALID_HANDLE_VALUE
;
3686 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3687 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3688 LPWSTR DriverKey
= NULL
;
3693 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
3695 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
3697 else /* Scope == DICS_FLAG_GLOBAL */
3703 KEY_ENUMERATE_SUB_KEYS
,
3705 if (rc
!= ERROR_SUCCESS
)
3712 deviceInfo
->DeviceName
,
3714 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
3716 RegCloseKey(hRootKey
);
3717 hRootKey
= INVALID_HANDLE_VALUE
;
3718 if (rc
!= ERROR_SUCCESS
)
3723 if (KeyType
== DIREG_DEV
)
3725 /* We're done. Just return the hKey handle */
3729 /* Read the 'Driver' key */
3730 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
3731 if (rc
!= ERROR_SUCCESS
)
3736 if (dwRegType
!= REG_SZ
)
3738 SetLastError(ERROR_GEN_FAILURE
);
3741 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3744 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3747 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
3748 if (rc
!= ERROR_SUCCESS
)
3754 hKey
= INVALID_HANDLE_VALUE
;
3755 /* Need to open the driver key */
3760 KEY_ENUMERATE_SUB_KEYS
,
3762 if (rc
!= ERROR_SUCCESS
)
3773 if (rc
!= ERROR_SUCCESS
)
3781 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3782 RegCloseKey(hRootKey
);
3783 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
3787 TRACE("Returning 0x%p\n", ret
);
3791 /***********************************************************************
3792 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
3794 BOOL WINAPI
SetupDiCreateDeviceInfoA(
3795 HDEVINFO DeviceInfoSet
,
3797 CONST GUID
*ClassGuid
,
3798 PCSTR DeviceDescription
,
3800 DWORD CreationFlags
,
3801 PSP_DEVINFO_DATA DeviceInfoData
)
3803 LPWSTR DeviceNameW
= NULL
;
3804 LPWSTR DeviceDescriptionW
= NULL
;
3811 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
3812 if (DeviceNameW
== NULL
) return FALSE
;
3814 if (DeviceDescription
)
3816 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
3817 if (DeviceDescriptionW
== NULL
)
3819 if (DeviceNameW
) MyFree(DeviceNameW
);
3824 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
3825 ClassGuid
, DeviceDescriptionW
,
3826 hwndParent
, CreationFlags
,
3829 if (DeviceNameW
) MyFree(DeviceNameW
);
3830 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
3835 /***********************************************************************
3836 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
3838 BOOL WINAPI
SetupDiCreateDeviceInfoW(
3839 HDEVINFO DeviceInfoSet
,
3841 CONST GUID
*ClassGuid
,
3842 PCWSTR DeviceDescription
,
3844 DWORD CreationFlags
,
3845 PSP_DEVINFO_DATA DeviceInfoData
)
3847 struct DeviceInfoSet
*list
;
3850 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
3851 debugstr_guid(ClassGuid
), DeviceDescription
,
3852 hwndParent
, CreationFlags
, DeviceInfoData
);
3855 SetLastError(ERROR_INVALID_HANDLE
);
3856 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3857 SetLastError(ERROR_INVALID_HANDLE
);
3858 else if (!ClassGuid
)
3859 SetLastError(ERROR_INVALID_PARAMETER
);
3860 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
3861 SetLastError(ERROR_CLASS_MISMATCH
);
3862 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
3864 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
3865 SetLastError(ERROR_INVALID_FLAGS
);
3869 SP_DEVINFO_DATA DevInfo
;
3871 if (CreationFlags
& DICD_GENERATE_ID
)
3873 /* Generate a new unique ID for this device */
3874 SetLastError(ERROR_GEN_FAILURE
);
3875 FIXME("not implemented\n");
3879 /* Device name is fully qualified. Try to open it */
3882 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
3883 rc
= SetupDiOpenDeviceInfoW(
3886 NULL
, /* hwndParent */
3887 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
3892 /* SetupDiOpenDeviceInfoW has already added
3893 * the device info to the device info set
3895 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
3897 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
3899 struct DeviceInfoElement
*deviceInfo
;
3901 if (CreateDeviceInfoElement(DeviceName
, ClassGuid
, &deviceInfo
))
3903 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3905 if (!DeviceInfoData
)
3909 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
3911 SetLastError(ERROR_INVALID_USER_BUFFER
);
3915 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
3916 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
3917 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
3926 TRACE("Returning %d\n", ret
);
3930 /***********************************************************************
3931 * Helper functions for SetupDiBuildDriverInfoList
3935 IN PLIST_ENTRY DriverListHead
,
3936 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
3937 IN LPGUID ClassGuid
,
3938 IN INFCONTEXT ContextDevice
,
3939 IN
struct InfFileDetails
*InfFileDetails
,
3941 IN LPCWSTR ProviderName
,
3942 IN LPCWSTR ManufacturerName
,
3943 IN LPCWSTR MatchingId
,
3944 FILETIME DriverDate
,
3945 DWORDLONG DriverVersion
,
3948 struct DriverInfoElement
*driverInfo
= NULL
;
3949 HANDLE hFile
= INVALID_HANDLE_VALUE
;
3950 DWORD RequiredSize
= 128; /* Initial buffer size */
3951 BOOL Result
= FALSE
;
3952 PLIST_ENTRY PreviousEntry
;
3953 LPWSTR InfInstallSection
= NULL
;
3956 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
3959 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3962 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
3964 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
3965 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
3967 /* Copy InfFileName field */
3968 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
3969 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
3971 /* Fill InfDate field */
3972 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
3973 GENERIC_READ, FILE_SHARE_READ,
3974 NULL, OPEN_EXISTING, 0, NULL);
3975 if (hFile == INVALID_HANDLE_VALUE)
3977 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
3981 /* Fill SectionName field */
3982 Result
= SetupGetStringFieldW(
3985 driverInfo
->Details
.SectionName
, LINE_LEN
,
3990 /* Fill DrvDescription field */
3991 Result
= SetupGetStringFieldW(
3993 0, /* Field index */
3994 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
3997 /* Copy MatchingId information */
3998 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
3999 if (!driverInfo
->MatchingId
)
4001 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4004 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4006 /* Get inf install section */
4008 RequiredSize
= 128; /* Initial buffer size */
4009 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4010 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4012 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4013 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4014 if (!InfInstallSection
)
4016 Result
= SetupGetStringFieldW(
4018 1, /* Field index */
4019 InfInstallSection
, RequiredSize
,
4025 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4026 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4028 driverInfo
->DriverRank
= Rank
;
4029 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4030 driverInfo
->Info
.DriverType
= DriverType
;
4031 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4032 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4033 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4034 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4035 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4038 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4039 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4042 driverInfo
->Info
.ProviderName
[0] = '\0';
4043 driverInfo
->Info
.DriverDate
= DriverDate
;
4044 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4045 ReferenceInfFile(InfFileDetails
);
4046 driverInfo
->InfFileDetails
= InfFileDetails
;
4048 /* Insert current driver in driver list, according to its rank */
4049 PreviousEntry
= DriverListHead
->Flink
;
4050 while (PreviousEntry
!= DriverListHead
)
4052 if (((struct DriverInfoElement
*)PreviousEntry
)->DriverRank
>= Rank
)
4054 /* Insert before the current item */
4055 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4058 PreviousEntry
= PreviousEntry
->Flink
;
4060 if (PreviousEntry
== DriverListHead
)
4062 /* Insert at the end of the list */
4063 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4072 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4073 HeapFree(GetProcessHeap(), 0, driverInfo
);
4075 if (hFile
!= INVALID_HANDLE_VALUE
)
4077 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4083 GetVersionInformationFromInfFile(
4085 OUT LPGUID ClassGuid
,
4086 OUT LPWSTR
* pProviderName
,
4087 OUT FILETIME
* DriverDate
,
4088 OUT DWORDLONG
* DriverVersion
)
4091 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
4092 LPWSTR DriverVer
= NULL
;
4093 LPWSTR ProviderName
= NULL
;
4094 LPWSTR pComma
; /* Points into DriverVer */
4095 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
4096 SYSTEMTIME SystemTime
;
4098 BOOL ret
= FALSE
; /* Final result */
4100 /* Get class Guid */
4101 if (!SetupGetLineTextW(
4104 L
"Version", L
"ClassGUID",
4105 guidW
, sizeof(guidW
),
4106 NULL
/* Required size */))
4110 guidW
[37] = '\0'; /* Replace the } by a NULL character */
4111 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
4113 SetLastError(ERROR_GEN_FAILURE
);
4117 /* Get provider name */
4118 Result
= SetupGetLineTextW(
4120 hInf
, L
"Version", L
"Provider",
4125 /* We know know the needed buffer size */
4126 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4129 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4132 Result
= SetupGetLineTextW(
4134 hInf
, L
"Version", L
"Provider",
4135 ProviderName
, RequiredSize
,
4140 *pProviderName
= ProviderName
;
4142 /* Read the "DriverVer" value */
4143 Result
= SetupGetLineTextW(
4145 hInf
, L
"Version", L
"DriverVer",
4150 /* We know know the needed buffer size */
4151 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4154 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4157 Result
= SetupGetLineTextW(
4159 hInf
, L
"Version", L
"DriverVer",
4160 DriverVer
, RequiredSize
,
4166 /* Get driver date and driver version, by analyzing the "DriverVer" value */
4167 pComma
= wcschr(DriverVer
, ',');
4170 *pComma
= UNICODE_NULL
;
4171 pVersion
= pComma
+ 1;
4173 /* Get driver date version. Invalid date = 00/00/00 */
4174 memset(DriverDate
, 0, sizeof(FILETIME
));
4175 if (wcslen(DriverVer
) == 10
4176 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
4177 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
4179 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
4180 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
4181 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
4182 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
4183 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
4184 SystemTimeToFileTime(&SystemTime
, DriverDate
);
4186 /* Get driver version. Invalid version = 0.0.0.0 */
4188 /* FIXME: use pVersion to fill DriverVersion variable */
4194 HeapFree(GetProcessHeap(), 0, ProviderName
);
4195 HeapFree(GetProcessHeap(), 0, DriverVer
);
4197 TRACE("Returning %d\n", ret
);
4201 /***********************************************************************
4202 * SetupDiBuildDriverInfoList (SETUPAPI.@)
4205 SetupDiBuildDriverInfoList(
4206 IN HDEVINFO DeviceInfoSet
,
4207 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4208 IN DWORD DriverType
)
4210 struct DeviceInfoSet
*list
;
4211 SP_DEVINSTALL_PARAMS_W InstallParams
;
4212 PVOID Buffer
= NULL
;
4213 struct InfFileDetails
*currentInfFileDetails
= NULL
;
4214 LPWSTR ProviderName
= NULL
;
4215 LPWSTR ManufacturerName
= NULL
;
4216 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
4217 LPWSTR HardwareIDs
= NULL
;
4218 LPWSTR CompatibleIDs
= NULL
;
4219 LPWSTR FullInfFileName
= NULL
;
4220 FILETIME DriverDate
;
4221 DWORDLONG DriverVersion
= 0;
4225 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4228 SetLastError(ERROR_INVALID_HANDLE
);
4229 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4230 SetLastError(ERROR_INVALID_HANDLE
);
4231 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
4232 SetLastError(ERROR_INVALID_HANDLE
);
4233 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4234 SetLastError(ERROR_INVALID_PARAMETER
);
4235 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4236 SetLastError(ERROR_INVALID_PARAMETER
);
4237 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4238 SetLastError(ERROR_INVALID_PARAMETER
);
4239 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4240 SetLastError(ERROR_INVALID_USER_BUFFER
);
4245 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
4246 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4250 if (DriverType
== SPDIT_COMPATDRIVER
)
4252 /* Get hardware IDs list */
4254 RequiredSize
= 512; /* Initial buffer size */
4255 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4256 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4258 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4259 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4262 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4265 Result
= SetupDiGetDeviceRegistryPropertyW(
4277 /* Get compatible IDs list */
4279 RequiredSize
= 512; /* Initial buffer size */
4280 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4281 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4283 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4284 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
4287 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4290 Result
= SetupDiGetDeviceRegistryPropertyW(
4293 SPDRP_COMPATIBLEIDS
,
4295 (PBYTE
)CompatibleIDs
,
4298 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4300 /* No compatible ID for this device */
4301 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4302 CompatibleIDs
= NULL
;
4310 /* Enumerate .inf files */
4312 RequiredSize
= 32768; /* Initial buffer size */
4313 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4314 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4316 HeapFree(GetProcessHeap(), 0, Buffer
);
4317 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4321 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4324 Result
= SetupGetInfFileListW(
4325 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
4327 Buffer
, RequiredSize
,
4330 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4332 /* No .inf file in specified directory. So, we should
4333 * success as we created an empty driver info list.
4341 LPWSTR pFullFilename
;
4343 if (*InstallParams
.DriverPath
)
4346 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
4349 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
4350 if (!FullInfFileName
)
4352 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
4355 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
4356 wcscat(FullInfFileName
, L
"\\");
4357 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
4361 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
4362 if (!FullInfFileName
)
4364 pFullFilename
= &FullInfFileName
[0];
4367 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
4369 INFCONTEXT ContextManufacturer
, ContextDevice
;
4372 wcscpy(pFullFilename
, filename
);
4373 TRACE("Opening file %S\n", FullInfFileName
);
4375 currentInfFileDetails
= HeapAlloc(
4378 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
4379 if (!currentInfFileDetails
)
4381 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
4382 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
4384 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
4385 ReferenceInfFile(currentInfFileDetails
);
4386 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
4388 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
4389 currentInfFileDetails
= NULL
;
4393 if (!GetVersionInformationFromInfFile(
4394 currentInfFileDetails
->hInf
,
4400 SetupCloseInfFile(currentInfFileDetails
->hInf
);
4401 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
4402 currentInfFileDetails
= NULL
;
4406 if (DriverType
== SPDIT_CLASSDRIVER
)
4408 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
4409 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
4415 /* Get the manufacturers list */
4416 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
4419 Result
= SetupGetStringFieldW(
4420 &ContextManufacturer
,
4421 0, /* Field index */
4426 /* We got the needed size for the buffer */
4427 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4428 if (!ManufacturerName
)
4430 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4433 Result
= SetupGetStringFieldW(
4434 &ContextManufacturer
,
4435 0, /* Field index */
4436 ManufacturerName
, RequiredSize
,
4439 /* Get manufacturer section name */
4440 Result
= SetupGetStringFieldW(
4441 &ContextManufacturer
,
4442 1, /* Field index */
4443 ManufacturerSection
, LINE_LEN
,
4447 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
4448 /* Add (possible) extension to manufacturer section name */
4449 Result
= SetupDiGetActualSectionToInstallW(
4450 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
4453 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
4454 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
4459 if (DriverType
== SPDIT_CLASSDRIVER
)
4461 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
4462 if (!AddDriverToList(
4463 &list
->DriverListHead
,
4467 currentInfFileDetails
,
4472 DriverDate
, DriverVersion
,
4478 else /* DriverType = SPDIT_COMPATDRIVER */
4480 /* 1. Get all fields */
4481 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
4485 BOOL DriverAlreadyAdded
;
4487 for (i
= 2; i
<= FieldCount
; i
++)
4489 LPWSTR DeviceId
= NULL
;
4491 RequiredSize
= 128; /* Initial buffer size */
4492 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4493 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4495 HeapFree(GetProcessHeap(), 0, DeviceId
);
4496 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4499 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4502 Result
= SetupGetStringFieldW(
4505 DeviceId
, RequiredSize
,
4510 HeapFree(GetProcessHeap(), 0, DeviceId
);
4513 DriverAlreadyAdded
= FALSE
;
4514 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4516 if (wcsicmp(DeviceId
, currentId
) == 0)
4519 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4523 currentInfFileDetails
,
4528 DriverDate
, DriverVersion
,
4529 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
4530 DriverAlreadyAdded
= TRUE
;
4535 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
4537 if (wcsicmp(DeviceId
, currentId
) == 0)
4540 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
4544 currentInfFileDetails
,
4549 DriverDate
, DriverVersion
,
4550 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
4551 DriverAlreadyAdded
= TRUE
;
4555 HeapFree(GetProcessHeap(), 0, DeviceId
);
4558 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
4561 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4562 ManufacturerName
= NULL
;
4563 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
4568 HeapFree(GetProcessHeap(), 0, ProviderName
);
4569 ProviderName
= NULL
;
4571 DereferenceInfFile(currentInfFileDetails
);
4572 currentInfFileDetails
= NULL
;
4583 InstallParams
.Flags
|= DI_DIDCOMPAT
;
4584 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
4588 InstallParams
.Flags
|= DI_DIDCLASS
;
4589 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
4591 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4594 HeapFree(GetProcessHeap(), 0, ProviderName
);
4595 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
4596 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
4597 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
4598 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
4599 if (currentInfFileDetails
)
4600 DereferenceInfFile(currentInfFileDetails
);
4601 HeapFree(GetProcessHeap(), 0, Buffer
);
4603 TRACE("Returning %d\n", ret
);
4607 /***********************************************************************
4608 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4611 SetupDiDeleteDeviceInfo(
4612 IN HDEVINFO DeviceInfoSet
,
4613 IN PSP_DEVINFO_DATA DeviceInfoData
)
4615 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4617 FIXME("not implemented\n");
4618 SetLastError(ERROR_GEN_FAILURE
);
4623 /***********************************************************************
4624 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
4627 SetupDiDestroyDriverInfoList(
4628 IN HDEVINFO DeviceInfoSet
,
4629 IN PSP_DEVINFO_DATA DeviceInfoData
,
4630 IN DWORD DriverType
)
4632 struct DeviceInfoSet
*list
;
4635 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
4638 SetLastError(ERROR_INVALID_HANDLE
);
4639 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4640 SetLastError(ERROR_INVALID_HANDLE
);
4641 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4642 SetLastError(ERROR_INVALID_PARAMETER
);
4643 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4644 SetLastError(ERROR_INVALID_PARAMETER
);
4645 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4646 SetLastError(ERROR_INVALID_USER_BUFFER
);
4649 PLIST_ENTRY ListEntry
;
4650 struct DriverInfoElement
*driverInfo
;
4651 SP_DEVINSTALL_PARAMS_W InstallParams
;
4653 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4654 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4657 if (!DeviceInfoData
)
4658 /* Fall back to destroying class driver list */
4659 DriverType
= SPDIT_CLASSDRIVER
;
4661 if (DriverType
== SPDIT_CLASSDRIVER
)
4663 while (!IsListEmpty(&list
->DriverListHead
))
4665 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
4666 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4667 DestroyDriverInfoElement(driverInfo
);
4669 InstallParams
.Reserved
= 0;
4670 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
4671 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
4672 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
4676 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
4677 struct DeviceInfoElement
*deviceInfo
;
4679 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4680 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
4682 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4683 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
4685 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
4686 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
4687 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
4689 InstallParamsSet
.Reserved
= 0;
4690 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
4692 DestroyDriverInfoElement(driverInfo
);
4694 InstallParams
.Reserved
= 0;
4695 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
4696 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
4697 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4702 TRACE("Returning %d\n", ret
);
4707 /***********************************************************************
4708 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4711 SetupDiOpenDeviceInfoA(
4712 IN HDEVINFO DeviceInfoSet
,
4713 IN PCSTR DeviceInstanceId
,
4714 IN HWND hwndParent OPTIONAL
,
4716 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4718 LPWSTR DeviceInstanceIdW
= NULL
;
4721 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4723 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4724 if (DeviceInstanceIdW
== NULL
)
4727 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4728 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4730 MyFree(DeviceInstanceIdW
);
4736 /***********************************************************************
4737 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4740 SetupDiOpenDeviceInfoW(
4741 IN HDEVINFO DeviceInfoSet
,
4742 IN PCWSTR DeviceInstanceId
,
4743 IN HWND hwndParent OPTIONAL
,
4745 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4747 struct DeviceInfoSet
*list
;
4748 HKEY hEnumKey
, hKey
;
4752 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4754 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4755 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4758 SetLastError(ERROR_INVALID_HANDLE
);
4759 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4760 SetLastError(ERROR_INVALID_HANDLE
);
4761 else if (!DeviceInstanceId
)
4762 SetLastError(ERROR_INVALID_PARAMETER
);
4763 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4765 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4766 SetLastError(ERROR_INVALID_FLAGS
);
4768 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4769 SetLastError(ERROR_INVALID_USER_BUFFER
);
4772 struct DeviceInfoElement
*deviceInfo
= NULL
;
4773 /* Search if device already exists in DeviceInfoSet.
4774 * If yes, return the existing element
4775 * If no, create a new element using informations in registry
4777 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4778 while (ItemList
!= &list
->ListHead
)
4783 FIXME("not implemented\n");
4784 ItemList
= ItemList
->Flink
;
4789 /* good one found */
4794 /* Open supposed registry key */
4799 KEY_ENUMERATE_SUB_KEYS
,
4801 if (rc
!= ERROR_SUCCESS
)
4812 RegCloseKey(hEnumKey
);
4813 if (rc
!= ERROR_SUCCESS
)
4815 if (rc
== ERROR_FILE_NOT_FOUND
)
4816 rc
= ERROR_NO_SUCH_DEVINST
;
4821 /* FIXME: try to get ClassGUID from registry, instead of
4822 * sending GUID_NULL to CreateDeviceInfoElement
4824 if (!CreateDeviceInfoElement(DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
4829 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4835 if (ret
&& deviceInfo
&& DeviceInfoData
)
4837 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4838 DeviceInfoData
->DevInst
= (DWORD
)list
->hMachine
;
4839 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4847 /***********************************************************************
4848 * SetupDiEnumDriverInfoA (SETUPAPI.@)
4851 SetupDiEnumDriverInfoA(
4852 IN HDEVINFO DeviceInfoSet
,
4853 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4854 IN DWORD DriverType
,
4855 IN DWORD MemberIndex
,
4856 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4858 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4861 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4862 DriverType
, MemberIndex
, DriverInfoData
);
4864 if (DriverInfoData
== NULL
)
4865 SetLastError(ERROR_INVALID_PARAMETER
);
4866 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4867 SetLastError(ERROR_INVALID_USER_BUFFER
);
4870 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4871 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
4872 DriverType
, MemberIndex
, &driverInfoData2W
);
4876 /* Do W->A conversion */
4877 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
4878 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
4879 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
4880 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
4882 DriverInfoData
->Description
[0] = '\0';
4885 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
4886 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
4888 DriverInfoData
->MfgName
[0] = '\0';
4891 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
4892 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
4894 DriverInfoData
->ProviderName
[0] = '\0';
4897 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
4899 /* Copy more fields */
4900 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
4901 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
4906 TRACE("Returning %d\n", ret
);
4911 /***********************************************************************
4912 * SetupDiEnumDriverInfoW (SETUPAPI.@)
4915 SetupDiEnumDriverInfoW(
4916 IN HDEVINFO DeviceInfoSet
,
4917 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4918 IN DWORD DriverType
,
4919 IN DWORD MemberIndex
,
4920 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
4922 PLIST_ENTRY ListHead
;
4925 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
4926 DriverType
, MemberIndex
, DriverInfoData
);
4928 if (!DeviceInfoSet
|| !DriverInfoData
)
4929 SetLastError(ERROR_INVALID_PARAMETER
);
4930 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4931 SetLastError(ERROR_INVALID_HANDLE
);
4932 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4933 SetLastError(ERROR_INVALID_HANDLE
);
4934 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
4935 SetLastError(ERROR_INVALID_PARAMETER
);
4936 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
4937 SetLastError(ERROR_INVALID_PARAMETER
);
4938 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
4939 SetLastError(ERROR_INVALID_PARAMETER
);
4940 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
4941 SetLastError(ERROR_INVALID_USER_BUFFER
);
4944 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4945 PLIST_ENTRY ItemList
;
4946 if (DriverType
== SPDIT_CLASSDRIVER
||
4947 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
4949 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
4953 ListHead
= &devInfo
->DriverListHead
;
4956 ItemList
= ListHead
->Flink
;
4957 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
4958 ItemList
= ItemList
->Flink
;
4959 if (ItemList
== ListHead
)
4960 SetLastError(ERROR_NO_MORE_ITEMS
);
4963 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
4966 &DriverInfoData
->DriverType
,
4967 &DrvInfo
->Info
.DriverType
,
4968 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
4973 TRACE("Returning %d\n", ret
);
4978 /***********************************************************************
4979 * SetupDiGetSelectedDriverA (SETUPAPI.@)
4982 SetupDiGetSelectedDriverA(
4983 IN HDEVINFO DeviceInfoSet
,
4984 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4985 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
4987 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
4990 if (DriverInfoData
== NULL
)
4991 SetLastError(ERROR_INVALID_PARAMETER
);
4992 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
4993 SetLastError(ERROR_INVALID_USER_BUFFER
);
4996 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
4998 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5004 /* Do W->A conversion */
5005 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5006 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5007 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5008 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5010 DriverInfoData
->Description
[0] = '\0';
5013 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5014 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5016 DriverInfoData
->MfgName
[0] = '\0';
5019 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5020 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5022 DriverInfoData
->ProviderName
[0] = '\0';
5025 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5027 /* Copy more fields */
5028 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5029 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5038 /***********************************************************************
5039 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5042 SetupDiGetSelectedDriverW(
5043 IN HDEVINFO DeviceInfoSet
,
5044 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5045 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5049 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5051 if (!DeviceInfoSet
|| !DriverInfoData
)
5052 SetLastError(ERROR_INVALID_PARAMETER
);
5053 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5054 SetLastError(ERROR_INVALID_HANDLE
);
5055 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5056 SetLastError(ERROR_INVALID_HANDLE
);
5057 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5058 SetLastError(ERROR_INVALID_USER_BUFFER
);
5059 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5060 SetLastError(ERROR_INVALID_USER_BUFFER
);
5063 SP_DEVINSTALL_PARAMS InstallParams
;
5065 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5066 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5068 struct DriverInfoElement
*driverInfo
;
5069 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5070 if (driverInfo
== NULL
)
5071 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5075 &DriverInfoData
->DriverType
,
5076 &driverInfo
->Info
.DriverType
,
5077 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5083 TRACE("Returning %d\n", ret
);
5088 /***********************************************************************
5089 * SetupDiSetSelectedDriverA (SETUPAPI.@)
5092 SetupDiSetSelectedDriverA(
5093 IN HDEVINFO DeviceInfoSet
,
5094 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5095 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
5097 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
5098 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
5101 if (DriverInfoData
!= NULL
)
5103 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
5104 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
5106 SetLastError(ERROR_INVALID_PARAMETER
);
5110 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5111 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5113 if (DriverInfoDataW
.Reserved
== 0)
5115 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5117 /* convert the strings to unicode */
5118 if (!MultiByteToWideChar(CP_ACP
,
5120 DriverInfoData
->Description
,
5122 DriverInfoDataW
.Description
,
5124 !MultiByteToWideChar(CP_ACP
,
5126 DriverInfoData
->ProviderName
,
5128 DriverInfoDataW
.ProviderName
,
5135 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
5138 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
5142 if (ret
&& pDriverInfoDataW
!= NULL
)
5144 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
5151 /***********************************************************************
5152 * SetupDiSetSelectedDriverW (SETUPAPI.@)
5155 SetupDiSetSelectedDriverW(
5156 IN HDEVINFO DeviceInfoSet
,
5157 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5158 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
5162 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5165 SetLastError(ERROR_INVALID_PARAMETER
);
5166 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5167 SetLastError(ERROR_INVALID_HANDLE
);
5168 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5169 SetLastError(ERROR_INVALID_HANDLE
);
5170 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5171 SetLastError(ERROR_INVALID_USER_BUFFER
);
5172 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5173 SetLastError(ERROR_INVALID_USER_BUFFER
);
5176 struct DriverInfoElement
**pDriverInfo
;
5177 PLIST_ENTRY ListHead
, ItemList
;
5181 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
5182 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
5186 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
5187 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5190 if (!DriverInfoData
)
5192 *pDriverInfo
= NULL
;
5197 /* Search selected driver in list */
5198 ItemList
= ListHead
->Flink
;
5199 while (ItemList
!= ListHead
)
5201 if (DriverInfoData
->Reserved
!= 0)
5203 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
5208 /* The caller wants to compare only DriverType, Description and ProviderName fields */
5209 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
5210 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
5211 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
5212 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
5218 if (ItemList
== ListHead
)
5219 SetLastError(ERROR_INVALID_PARAMETER
);
5222 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
5223 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
5225 TRACE("Choosing driver whose rank is 0x%lx\n",
5226 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
5228 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
5233 TRACE("Returning %d\n", ret
);
5237 /***********************************************************************
5238 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
5241 SetupDiGetDriverInfoDetailA(
5242 IN HDEVINFO DeviceInfoSet
,
5243 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5244 IN PSP_DRVINFO_DATA_A DriverInfoData
,
5245 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
5246 IN DWORD DriverInfoDetailDataSize
,
5247 OUT PDWORD RequiredSize OPTIONAL
)
5249 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
5250 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
5252 DWORD HardwareIDLen
= 0;
5255 /* do some sanity checks, the unicode version might do more thorough checks */
5256 if (DriverInfoData
== NULL
||
5257 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
5258 (DriverInfoDetailData
!= NULL
&&
5259 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
5260 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
5262 SetLastError(ERROR_INVALID_PARAMETER
);
5266 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
5267 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
5269 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
5271 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5273 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5277 SetLastError(ERROR_INVALID_PARAMETER
);
5280 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
5281 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
5283 /* convert the strings to unicode */
5284 if (MultiByteToWideChar(CP_ACP
,
5286 DriverInfoData
->Description
,
5288 DriverInfoDataW
.Description
,
5290 MultiByteToWideChar(CP_ACP
,
5292 DriverInfoData
->MfgName
,
5294 DriverInfoDataW
.MfgName
,
5296 MultiByteToWideChar(CP_ACP
,
5298 DriverInfoData
->ProviderName
,
5300 DriverInfoDataW
.ProviderName
,
5303 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
5305 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
5306 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
5309 if (DriverInfoDetailData
!= NULL
)
5311 /* calculate the unicode buffer size from the ansi buffer size */
5312 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
5313 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
5314 (HardwareIDLen
* sizeof(WCHAR
));
5316 DriverInfoDetailDataW
= MyMalloc(BufSize
);
5317 if (DriverInfoDetailDataW
== NULL
)
5319 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5323 /* initialize the buffer */
5324 ZeroMemory(DriverInfoDetailDataW
,
5326 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
5329 /* call the unicode version */
5330 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
5333 DriverInfoDetailDataW
,
5339 if (DriverInfoDetailDataW
!= NULL
)
5341 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
5342 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
5343 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
5344 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
5345 if (WideCharToMultiByte(CP_ACP
,
5347 DriverInfoDetailDataW
->SectionName
,
5349 DriverInfoDetailData
->SectionName
,
5353 WideCharToMultiByte(CP_ACP
,
5355 DriverInfoDetailDataW
->InfFileName
,
5357 DriverInfoDetailData
->InfFileName
,
5361 WideCharToMultiByte(CP_ACP
,
5363 DriverInfoDetailDataW
->DrvDescription
,
5365 DriverInfoDetailData
->DrvDescription
,
5369 WideCharToMultiByte(CP_ACP
,
5371 DriverInfoDetailDataW
->HardwareID
,
5373 DriverInfoDetailData
->HardwareID
,
5379 DWORD hwidlen
= HardwareIDLen
;
5380 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
5382 /* count the strings in the list */
5385 len
= lstrlenA(s
) + 1;
5394 /* looks like the string list wasn't terminated... */
5395 SetLastError(ERROR_INVALID_USER_BUFFER
);
5401 /* make sure CompatIDsOffset points to the second string in the
5405 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
5406 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
5407 DriverInfoDetailData
->CompatIDsOffset
+ 1;
5411 DriverInfoDetailData
->CompatIDsOffset
= 0;
5412 DriverInfoDetailData
->CompatIDsLength
= 0;
5421 if (RequiredSize
!= NULL
)
5423 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
5424 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
5430 if (DriverInfoDetailDataW
!= NULL
)
5432 MyFree(DriverInfoDetailDataW
);
5438 /***********************************************************************
5439 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
5442 SetupDiGetDriverInfoDetailW(
5443 IN HDEVINFO DeviceInfoSet
,
5444 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5445 IN PSP_DRVINFO_DATA_W DriverInfoData
,
5446 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
5447 IN DWORD DriverInfoDetailDataSize
,
5448 OUT PDWORD RequiredSize OPTIONAL
)
5452 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
5453 DriverInfoData
, DriverInfoDetailData
,
5454 DriverInfoDetailDataSize
, RequiredSize
);
5457 SetLastError(ERROR_INVALID_PARAMETER
);
5458 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5459 SetLastError(ERROR_INVALID_HANDLE
);
5460 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5461 SetLastError(ERROR_INVALID_HANDLE
);
5462 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5463 SetLastError(ERROR_INVALID_USER_BUFFER
);
5464 else if (!DriverInfoData
)
5465 SetLastError(ERROR_INVALID_PARAMETER
);
5466 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
5467 SetLastError(ERROR_INVALID_PARAMETER
);
5468 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5469 SetLastError(ERROR_INVALID_PARAMETER
);
5470 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
5471 SetLastError(ERROR_INVALID_USER_BUFFER
);
5472 else if (DriverInfoData
->Reserved
== 0)
5473 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5476 struct DriverInfoElement
*driverInfoElement
;
5477 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
5480 DriverInfoDetailData
,
5481 &driverInfoElement
->Details
,
5482 driverInfoElement
->Details
.cbSize
);
5483 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
5484 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
5489 TRACE("Returning %d\n", ret
);
5493 /***********************************************************************
5494 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
5497 SetupDiSelectBestCompatDrv(
5498 IN HDEVINFO DeviceInfoSet
,
5499 IN PSP_DEVINFO_DATA DeviceInfoData
)
5501 SP_DRVINFO_DATA_W drvInfoData
;
5504 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5506 /* Drivers are sorted by rank in the driver list, so
5507 * the first driver in the list is the best one.
5509 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
5510 ret
= SetupDiEnumDriverInfoW(
5514 0, /* Member index */
5519 ret
= SetupDiSetSelectedDriverW(
5525 TRACE("Returning %d\n", ret
);
5529 /***********************************************************************
5530 * SetupDiInstallDriverFiles (SETUPAPI.@)
5533 SetupDiInstallDriverFiles(
5534 IN HDEVINFO DeviceInfoSet
,
5535 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5539 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5542 SetLastError(ERROR_INVALID_PARAMETER
);
5543 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5544 SetLastError(ERROR_INVALID_HANDLE
);
5545 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5546 SetLastError(ERROR_INVALID_HANDLE
);
5547 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5548 SetLastError(ERROR_INVALID_USER_BUFFER
);
5549 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
5550 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5551 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
5552 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5555 SP_DEVINSTALL_PARAMS_W InstallParams
;
5556 struct DriverInfoElement
*SelectedDriver
;
5557 WCHAR SectionName
[MAX_PATH
];
5558 DWORD SectionNameLength
= 0;
5560 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5561 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5565 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5566 if (!SelectedDriver
)
5568 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5572 ret
= SetupDiGetActualSectionToInstallW(
5573 SelectedDriver
->InfFileDetails
->hInf
,
5574 SelectedDriver
->Details
.SectionName
,
5575 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5579 if (!InstallParams
.InstallMsgHandler
)
5581 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5582 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5583 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5585 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5586 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5587 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
5588 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5589 DeviceInfoSet
, DeviceInfoData
);
5593 TRACE("Returning %d\n", ret
);
5597 /***********************************************************************
5598 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5601 SetupDiRegisterCoDeviceInstallers(
5602 IN HDEVINFO DeviceInfoSet
,
5603 IN PSP_DEVINFO_DATA DeviceInfoData
)
5605 BOOL ret
= FALSE
; /* Return value */
5607 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5610 SetLastError(ERROR_INVALID_PARAMETER
);
5611 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5612 SetLastError(ERROR_INVALID_HANDLE
);
5613 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5614 SetLastError(ERROR_INVALID_HANDLE
);
5615 else if (!DeviceInfoData
)
5616 SetLastError(ERROR_INVALID_PARAMETER
);
5617 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5618 SetLastError(ERROR_INVALID_USER_BUFFER
);
5621 SP_DEVINSTALL_PARAMS_W InstallParams
;
5622 struct DriverInfoElement
*SelectedDriver
;
5625 WCHAR SectionName
[MAX_PATH
];
5626 DWORD SectionNameLength
= 0;
5627 HKEY hKey
= INVALID_HANDLE_VALUE
;;
5629 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5630 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5634 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5635 if (SelectedDriver
== NULL
)
5637 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5641 /* Get .CoInstallers section name */
5642 Result
= SetupDiGetActualSectionToInstallW(
5643 SelectedDriver
->InfFileDetails
->hInf
,
5644 SelectedDriver
->Details
.SectionName
,
5645 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5646 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
5648 wcscat(SectionName
, L
".CoInstallers");
5650 /* Open/Create driver key information */
5651 #if _WIN32_WINNT >= 0x502
5652 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5654 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5656 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5657 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5658 if (hKey
== INVALID_HANDLE_VALUE
)
5661 /* Install .CoInstallers section */
5662 DoAction
= SPINST_REGISTRY
;
5663 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5665 DoAction
|= SPINST_FILES
;
5666 if (!InstallParams
.InstallMsgHandler
)
5668 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5669 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5670 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5673 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5674 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5675 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5676 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5677 DeviceInfoSet
, DeviceInfoData
);
5684 if (hKey
!= INVALID_HANDLE_VALUE
)
5688 TRACE("Returning %d\n", ret
);
5692 /***********************************************************************
5693 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
5696 SetupDiInstallDeviceInterfaces(
5697 IN HDEVINFO DeviceInfoSet
,
5698 IN PSP_DEVINFO_DATA DeviceInfoData
)
5700 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5702 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
5703 //SetLastError(ERROR_GEN_FAILURE);
5709 InfIsFromOEMLocation(
5711 OUT LPBOOL IsOEMLocation
)
5715 last
= strrchrW(FullName
, '\\');
5718 /* No directory specified */
5719 *IsOEMLocation
= FALSE
;
5723 WCHAR Windir
[MAX_PATH
];
5726 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
5727 if (ret
== 0 || ret
>= MAX_PATH
)
5729 SetLastError(ERROR_GEN_FAILURE
);
5733 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
5735 /* The path is %SYSTEMROOT%\Inf */
5736 *IsOEMLocation
= FALSE
;
5740 /* The file is in another place */
5741 *IsOEMLocation
= TRUE
;
5747 /***********************************************************************
5748 * SetupDiInstallDevice (SETUPAPI.@)
5751 SetupDiInstallDevice(
5752 IN HDEVINFO DeviceInfoSet
,
5753 IN PSP_DEVINFO_DATA DeviceInfoData
)
5755 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5756 SP_DEVINSTALL_PARAMS_W InstallParams
;
5757 struct DriverInfoElement
*SelectedDriver
;
5758 SYSTEMTIME DriverDate
;
5759 WCHAR SectionName
[MAX_PATH
];
5761 DWORD SectionNameLength
= 0;
5762 BOOL Result
= FALSE
;
5763 INFCONTEXT ContextService
;
5767 LPCWSTR AssociatedService
= NULL
;
5768 LPWSTR pSectionName
= NULL
;
5769 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5771 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5772 BOOL RebootRequired
= FALSE
;
5773 HKEY hKey
= INVALID_HANDLE_VALUE
;
5774 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
5775 BOOL NeedtoCopyFile
;
5777 BOOL ret
= FALSE
; /* Return value */
5779 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5782 SetLastError(ERROR_INVALID_PARAMETER
);
5783 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5784 SetLastError(ERROR_INVALID_HANDLE
);
5785 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5786 SetLastError(ERROR_INVALID_HANDLE
);
5787 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5788 SetLastError(ERROR_INVALID_USER_BUFFER
);
5794 /* One parameter is bad */
5798 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5799 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5803 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5805 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
5809 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5810 if (SelectedDriver
== NULL
)
5812 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5816 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5818 Result
= SetupDiGetActualSectionToInstallW(
5819 SelectedDriver
->InfFileDetails
->hInf
,
5820 SelectedDriver
->Details
.SectionName
,
5821 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5822 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
5824 pSectionName
= &SectionName
[wcslen(SectionName
)];
5826 /* Get information from [Version] section */
5827 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5829 /* Format ClassGuid to a string */
5830 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5832 RequiredSize
= lstrlenW(lpGuidString
);
5833 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5834 if (!lpFullGuidString
)
5836 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5839 lpFullGuidString
[0] = '{';
5840 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5841 lpFullGuidString
[RequiredSize
+ 1] = '}';
5842 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5844 /* Open/Create driver key information */
5845 #if _WIN32_WINNT >= 0x502
5846 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5848 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5850 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5851 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5852 if (hKey
== INVALID_HANDLE_VALUE
)
5855 /* Install main section */
5856 DoAction
= SPINST_REGISTRY
;
5857 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5859 DoAction
|= SPINST_FILES
;
5860 if (!InstallParams
.InstallMsgHandler
)
5862 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
5863 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5864 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5867 *pSectionName
= '\0';
5868 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5869 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5870 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
5871 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
5872 DeviceInfoSet
, DeviceInfoData
);
5875 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
5877 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
5879 /* Delete resources allocated by SetupInitDefaultQueueCallback */
5880 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
5883 InstallParams
.Flags
|= DI_NOFILECOPY
;
5884 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5886 /* Write information to driver key */
5887 *pSectionName
= UNICODE_NULL
;
5888 TRACE("Write information to driver key\n");
5889 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5890 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
5891 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);
5892 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
5893 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
5894 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
5895 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
5896 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
5897 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5898 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5899 if (rc
== ERROR_SUCCESS
)
5900 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5901 if (rc
== ERROR_SUCCESS
)
5902 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5903 if (rc
== ERROR_SUCCESS
)
5905 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);
5906 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
5908 if (rc
== ERROR_SUCCESS
)
5909 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
5910 if (rc
== ERROR_SUCCESS
)
5911 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5912 if (rc
== ERROR_SUCCESS
)
5913 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5914 if (rc
== ERROR_SUCCESS
)
5915 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5916 if (rc
== ERROR_SUCCESS
)
5917 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5918 if (rc
!= ERROR_SUCCESS
)
5924 hKey
= INVALID_HANDLE_VALUE
;
5926 /* FIXME: Process .LogConfigOverride section */
5928 /* Install .Services section */
5929 wcscpy(pSectionName
, L
".Services");
5930 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
5933 LPWSTR ServiceName
= NULL
;
5934 LPWSTR ServiceSection
= NULL
;
5936 Result
= SetupGetStringFieldW(
5938 1, /* Field index */
5943 if (RequiredSize
> 0)
5945 /* We got the needed size for the buffer */
5946 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5949 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5952 Result
= SetupGetStringFieldW(
5954 1, /* Field index */
5955 ServiceName
, RequiredSize
,
5960 Result
= SetupGetIntField(
5962 2, /* Field index */
5966 /* The field may be empty. Ignore the error */
5969 Result
= SetupGetStringFieldW(
5971 3, /* Field index */
5976 if (GetLastError() == ERROR_INVALID_PARAMETER
)
5978 /* This first is probably missing. It is not
5979 * required, so ignore the error */
5986 if (RequiredSize
> 0)
5988 /* We got the needed size for the buffer */
5989 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5990 if (!ServiceSection
)
5992 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5995 Result
= SetupGetStringFieldW(
5997 3, /* Field index */
5998 ServiceSection
, RequiredSize
,
6003 SetLastError(ERROR_SUCCESS
);
6004 Result
= SetupInstallServicesFromInfSectionExW(
6005 SelectedDriver
->InfFileDetails
->hInf
,
6006 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
6008 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
6010 AssociatedService
= ServiceName
;
6012 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
6013 RebootRequired
= TRUE
;
6016 HeapFree(GetProcessHeap(), 0, ServiceName
);
6017 HeapFree(GetProcessHeap(), 0, ServiceSection
);
6020 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
6023 /* Copy .inf file to Inf\ directory (if needed) */
6024 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
6029 Result
= SetupCopyOEMInfW(
6030 SelectedDriver
->InfFileDetails
->FullInfFileName
,
6033 SP_COPY_NOOVERWRITE
,
6039 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
6040 * to release use of current InfFile */
6043 /* Open device registry key */
6044 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
6045 if (hKey
== INVALID_HANDLE_VALUE
)
6048 /* Install .HW section */
6049 wcscpy(pSectionName
, L
".HW");
6050 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6051 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6052 SPINST_REGISTRY
, hKey
, NULL
, 0,
6053 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6054 DeviceInfoSet
, DeviceInfoData
);
6058 /* Write information to enum key */
6059 TRACE("Write information to enum key\n");
6060 TRACE("Class : '%S'\n", ClassName
);
6061 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
6062 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6063 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
6064 TRACE("Service : '%S'\n", AssociatedService
);
6065 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
6066 if (rc
== ERROR_SUCCESS
)
6067 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
6068 if (rc
== ERROR_SUCCESS
)
6069 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
6070 if (rc
== ERROR_SUCCESS
)
6071 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
6072 if (rc
== ERROR_SUCCESS
&& *AssociatedService
)
6073 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
6074 if (rc
!= ERROR_SUCCESS
)
6080 /* Start the device */
6081 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
6083 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6085 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
6086 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6087 ret
= NT_SUCCESS(Status
);
6093 /* End of installation */
6094 if (hClassKey
!= INVALID_HANDLE_VALUE
)
6095 RegCloseKey(hClassKey
);
6096 if (hKey
!= INVALID_HANDLE_VALUE
)
6099 RpcStringFreeW(&lpGuidString
);
6100 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
6101 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
6103 TRACE("Returning %d\n", ret
);