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 InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
33 static const WCHAR NtExtension
[] = {'.','N','T',0};
34 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
35 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
36 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
37 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
39 /* FIXME: header mess */
40 DEFINE_GUID(GUID_NULL
,
41 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
43 (CALLBACK
* CLASS_INSTALL_PROC
) (
44 IN DI_FUNCTION InstallFunction
,
45 IN HDEVINFO DeviceInfoSet
,
46 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
48 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
49 IN HDEVINFO DeviceInfoSet
,
50 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
52 (CALLBACK
* COINSTALLER_PROC
) (
53 IN DI_FUNCTION InstallFunction
,
54 IN HDEVINFO DeviceInfoSet
,
55 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
56 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
58 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
59 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
60 IN LPFNADDPROPSHEETPAGE fAddFunc
,
63 (*UPDATE_CLASS_PARAM_HANDLER
) (
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
67 IN DWORD ClassInstallParamsSize
);
69 struct CoInstallerElement
74 COINSTALLER_PROC Function
;
75 BOOL DoPostProcessing
;
80 PropertyChangeHandler(
81 IN HDEVINFO DeviceInfoSet
,
82 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
83 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
84 IN DWORD ClassInstallParamsSize
);
86 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
87 NULL
, /* DIF_SELECTDEVICE */
88 NULL
, /* DIF_INSTALLDEVICE */
89 NULL
, /* DIF_ASSIGNRESOURCES */
90 NULL
, /* DIF_PROPERTIES */
91 NULL
, /* DIF_REMOVE */
92 NULL
, /* DIF_FIRSTTIMESETUP */
93 NULL
, /* DIF_FOUNDDEVICE */
94 NULL
, /* DIF_SELECTCLASSDRIVERS */
95 NULL
, /* DIF_VALIDATECLASSDRIVERS */
96 NULL
, /* DIF_INSTALLCLASSDRIVERS */
97 NULL
, /* DIF_CALCDISKSPACE */
98 NULL
, /* DIF_DESTROYPRIVATEDATA */
99 NULL
, /* DIF_VALIDATEDRIVER */
100 NULL
, /* DIF_MOVEDEVICE */
101 NULL
, /* DIF_DETECT */
102 NULL
, /* DIF_INSTALLWIZARD */
103 NULL
, /* DIF_DESTROYWIZARDDATA */
104 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
105 NULL
, /* DIF_ENABLECLASS */
106 NULL
, /* DIF_DETECTVERIFY */
107 NULL
, /* DIF_INSTALLDEVICEFILES */
108 NULL
, /* DIF_UNREMOVE */
109 NULL
, /* DIF_SELECTBESTCOMPATDRV */
110 NULL
, /* DIF_ALLOW_INSTALL */
111 NULL
, /* DIF_REGISTERDEVICE */
112 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
113 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
114 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
115 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
116 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
117 NULL
, /* DIF_UNUSED1 */
118 NULL
, /* DIF_INSTALLINTERFACES */
119 NULL
, /* DIF_DETECTCANCEL */
120 NULL
, /* DIF_REGISTER_COINSTALLERS */
121 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
122 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
123 NULL
, /* DIF_RESERVED1 */
124 NULL
, /* DIF_TROUBLESHOOTER */
125 NULL
, /* DIF_POWERMESSAGEWAKE */
126 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
127 NULL
, /* DIF_UPDATEDRIVER_UI */
128 NULL
/* DIF_RESERVED2 */
131 /***********************************************************************
132 * SetupDiBuildClassInfoList (SETUPAPI.@)
134 BOOL WINAPI
SetupDiBuildClassInfoList(
136 LPGUID ClassGuidList
,
137 DWORD ClassGuidListSize
,
141 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
142 ClassGuidListSize
, RequiredSize
,
146 /***********************************************************************
147 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
149 BOOL WINAPI
SetupDiBuildClassInfoListExA(
151 LPGUID ClassGuidList
,
152 DWORD ClassGuidListSize
,
157 LPWSTR MachineNameW
= NULL
;
164 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
165 if (MachineNameW
== NULL
) return FALSE
;
168 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
169 ClassGuidListSize
, RequiredSize
,
170 MachineNameW
, Reserved
);
173 MyFree(MachineNameW
);
178 /***********************************************************************
179 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
181 BOOL WINAPI
SetupDiBuildClassInfoListExW(
183 LPGUID ClassGuidList
,
184 DWORD ClassGuidListSize
,
189 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
195 DWORD dwGuidListIndex
= 0;
197 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
198 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
200 if (RequiredSize
!= NULL
)
203 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
204 KEY_ENUMERATE_SUB_KEYS
,
208 if (hClassesKey
== INVALID_HANDLE_VALUE
)
213 for (dwIndex
= 0; ; dwIndex
++)
215 dwLength
= MAX_GUID_STRING_LEN
+ 1;
216 lError
= RegEnumKeyExW(hClassesKey
,
224 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
225 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
227 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
229 if (RegOpenKeyExW(hClassesKey
,
235 RegCloseKey(hClassesKey
);
239 if (!RegQueryValueExW(hClassKey
,
240 REGSTR_VAL_NOUSECLASS
,
246 TRACE("'NoUseClass' value found!\n");
247 RegCloseKey(hClassKey
);
251 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
252 (!RegQueryValueExW(hClassKey
,
253 REGSTR_VAL_NOINSTALLCLASS
,
259 TRACE("'NoInstallClass' value found!\n");
260 RegCloseKey(hClassKey
);
264 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
265 (!RegQueryValueExW(hClassKey
,
266 REGSTR_VAL_NODISPLAYCLASS
,
272 TRACE("'NoDisplayClass' value found!\n");
273 RegCloseKey(hClassKey
);
277 RegCloseKey(hClassKey
);
279 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
280 if (dwGuidListIndex
< ClassGuidListSize
)
282 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
286 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
288 UuidFromStringW(&szKeyName
[1],
289 &ClassGuidList
[dwGuidListIndex
]);
295 if (lError
!= ERROR_SUCCESS
)
299 RegCloseKey(hClassesKey
);
301 if (RequiredSize
!= NULL
)
302 *RequiredSize
= dwGuidListIndex
;
304 if (ClassGuidListSize
< dwGuidListIndex
)
306 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
313 /***********************************************************************
314 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
316 BOOL WINAPI
SetupDiClassGuidsFromNameA(
318 LPGUID ClassGuidList
,
319 DWORD ClassGuidListSize
,
322 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
323 ClassGuidListSize
, RequiredSize
,
327 /***********************************************************************
328 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
330 BOOL WINAPI
SetupDiClassGuidsFromNameW(
332 LPGUID ClassGuidList
,
333 DWORD ClassGuidListSize
,
336 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
337 ClassGuidListSize
, RequiredSize
,
341 /***********************************************************************
342 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
344 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
346 LPGUID ClassGuidList
,
347 DWORD ClassGuidListSize
,
352 LPWSTR ClassNameW
= NULL
;
353 LPWSTR MachineNameW
= NULL
;
358 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
359 if (ClassNameW
== NULL
)
364 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
365 if (MachineNameW
== NULL
)
372 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
373 ClassGuidListSize
, RequiredSize
,
374 MachineNameW
, Reserved
);
377 MyFree(MachineNameW
);
384 /***********************************************************************
385 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
387 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
389 LPGUID ClassGuidList
,
390 DWORD ClassGuidListSize
,
395 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
396 WCHAR szClassName
[256];
402 DWORD dwGuidListIndex
= 0;
404 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
405 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
407 if (RequiredSize
!= NULL
)
410 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
411 KEY_ENUMERATE_SUB_KEYS
,
415 if (hClassesKey
== INVALID_HANDLE_VALUE
)
420 for (dwIndex
= 0; ; dwIndex
++)
422 dwLength
= MAX_GUID_STRING_LEN
+ 1;
423 lError
= RegEnumKeyExW(hClassesKey
,
431 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
432 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
434 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
436 if (RegOpenKeyExW(hClassesKey
,
442 RegCloseKey(hClassesKey
);
446 dwLength
= 256 * sizeof(WCHAR
);
447 if (!RegQueryValueExW(hClassKey
,
454 TRACE("Class name: %s\n", debugstr_w(szClassName
));
456 if (strcmpiW(szClassName
, ClassName
) == 0)
458 TRACE("Found matching class name\n");
460 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
461 if (dwGuidListIndex
< ClassGuidListSize
)
463 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
467 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
469 UuidFromStringW(&szKeyName
[1],
470 &ClassGuidList
[dwGuidListIndex
]);
477 RegCloseKey(hClassKey
);
480 if (lError
!= ERROR_SUCCESS
)
484 RegCloseKey(hClassesKey
);
486 if (RequiredSize
!= NULL
)
487 *RequiredSize
= dwGuidListIndex
;
489 if (ClassGuidListSize
< dwGuidListIndex
)
491 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
498 /***********************************************************************
499 * SetupDiClassNameFromGuidA (SETUPAPI.@)
501 BOOL WINAPI
SetupDiClassNameFromGuidA(
502 const GUID
* ClassGuid
,
507 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
508 ClassNameSize
, RequiredSize
,
512 /***********************************************************************
513 * SetupDiClassNameFromGuidW (SETUPAPI.@)
515 BOOL WINAPI
SetupDiClassNameFromGuidW(
516 const GUID
* ClassGuid
,
521 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
522 ClassNameSize
, RequiredSize
,
526 /***********************************************************************
527 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
529 BOOL WINAPI
SetupDiClassNameFromGuidExA(
530 const GUID
* ClassGuid
,
537 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
538 LPWSTR MachineNameW
= NULL
;
542 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
543 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
544 NULL
, MachineNameW
, Reserved
);
547 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
548 ClassNameSize
, NULL
, NULL
);
550 if (!ClassNameSize
&& RequiredSize
)
553 MyFree(MachineNameW
);
557 /***********************************************************************
558 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
560 BOOL WINAPI
SetupDiClassNameFromGuidExW(
561 const GUID
* ClassGuid
,
572 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
573 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
575 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
580 if (hKey
== INVALID_HANDLE_VALUE
)
585 if (RequiredSize
!= NULL
)
588 rc
= RegQueryValueExW(hKey
,
594 if (rc
!= ERROR_SUCCESS
)
601 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
604 dwLength
= ClassNameSize
* sizeof(WCHAR
);
605 rc
= RegQueryValueExW(hKey
,
611 if (rc
!= ERROR_SUCCESS
)
623 /***********************************************************************
624 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
627 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
630 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
633 /***********************************************************************
634 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
637 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
642 LPWSTR MachineNameW
= NULL
;
645 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
646 debugstr_a(MachineName
), Reserved
);
650 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
651 if (MachineNameW
== NULL
)
652 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
655 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
656 MachineNameW
, Reserved
);
659 MyFree(MachineNameW
);
665 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
669 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
670 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
671 case CR_SUCCESS
: return ERROR_SUCCESS
;
674 return ERROR_GEN_FAILURE
;
677 /* Does not happen */
680 /***********************************************************************
681 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
684 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
689 struct DeviceInfoSet
*list
;
690 LPWSTR UNCServerName
= NULL
;
694 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
696 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
697 debugstr_w(MachineName
), Reserved
);
699 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
701 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
702 list
= HeapAlloc(GetProcessHeap(), 0, size
);
705 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
708 memset(list
, 0, sizeof(struct DeviceInfoSet
));
710 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
713 ClassGuid
? ClassGuid
: &GUID_NULL
,
714 sizeof(list
->ClassGuid
));
715 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
716 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
717 list
->InstallParams
.hwndParent
= hwndParent
;
720 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
721 if (rc
!= ERROR_SUCCESS
)
726 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
729 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
733 strcpyW(UNCServerName
+ 2, MachineName
);
734 list
->szData
[0] = list
->szData
[1] = '\\';
735 strcpyW(list
->szData
+ 2, MachineName
);
736 list
->MachineName
= list
->szData
;
740 DWORD Size
= MAX_PATH
;
741 list
->HKLM
= HKEY_LOCAL_MACHINE
;
742 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
745 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
748 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
750 list
->MachineName
= NULL
;
753 UNCServerName
[0] = UNCServerName
[1] = '\\';
754 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
755 if (cr
!= CR_SUCCESS
)
757 SetLastError(GetErrorCodeFromCrCode(cr
));
761 InitializeListHead(&list
->DriverListHead
);
762 InitializeListHead(&list
->ListHead
);
764 ret
= (HDEVINFO
)list
;
767 if (ret
== INVALID_HANDLE_VALUE
)
769 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
770 RegCloseKey(list
->HKLM
);
771 HeapFree(GetProcessHeap(), 0, list
);
773 HeapFree(GetProcessHeap(), 0, UNCServerName
);
777 /***********************************************************************
778 * SetupDiEnumDeviceInfo (SETUPAPI.@)
780 BOOL WINAPI
SetupDiEnumDeviceInfo(
781 HDEVINFO DeviceInfoSet
,
783 PSP_DEVINFO_DATA DeviceInfoData
)
787 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
789 SetLastError(ERROR_INVALID_PARAMETER
);
790 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
792 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
794 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
795 SetLastError(ERROR_INVALID_HANDLE
);
796 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
797 SetLastError(ERROR_INVALID_USER_BUFFER
);
800 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
801 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
802 ItemList
= ItemList
->Flink
;
803 if (ItemList
== &list
->ListHead
)
804 SetLastError(ERROR_NO_MORE_ITEMS
);
807 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
808 memcpy(&DeviceInfoData
->ClassGuid
,
811 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
812 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
818 SetLastError(ERROR_INVALID_HANDLE
);
822 /***********************************************************************
823 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
825 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
827 PCSTR InfSectionName
,
828 PSTR InfSectionWithExt
,
829 DWORD InfSectionWithExtSize
,
833 LPWSTR InfSectionNameW
= NULL
;
834 PWSTR InfSectionWithExtW
= NULL
;
836 BOOL bResult
= FALSE
;
842 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
843 if (InfSectionNameW
== NULL
) goto end
;
845 if (InfSectionWithExt
)
847 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
848 if (InfSectionWithExtW
== NULL
) goto end
;
851 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
852 InfSectionWithExt
? InfSectionNameW
: NULL
,
853 InfSectionWithExtSize
, RequiredSize
,
854 Extension
? &ExtensionW
: NULL
);
856 if (bResult
&& InfSectionWithExt
)
858 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
859 InfSectionWithExtSize
, NULL
, NULL
) != 0;
861 if (bResult
&& Extension
)
863 if (ExtensionW
== NULL
)
866 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
870 if (InfSectionNameW
) MyFree(InfSectionNameW
);
871 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
876 /***********************************************************************
877 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
879 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
881 PCWSTR InfSectionName
,
882 PWSTR InfSectionWithExt
,
883 DWORD InfSectionWithExtSize
,
887 WCHAR szBuffer
[MAX_PATH
];
890 LONG lLineCount
= -1;
892 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
893 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
895 lstrcpyW(szBuffer
, InfSectionName
);
896 dwLength
= lstrlenW(szBuffer
);
898 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
900 /* Test section name with '.NTx86' extension */
901 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
902 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
904 if (lLineCount
== -1)
906 /* Test section name with '.NT' extension */
907 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
908 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
913 /* Test section name with '.Win' extension */
914 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
915 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
918 if (lLineCount
== -1)
920 /* Test section name without extension */
921 szBuffer
[dwLength
] = 0;
922 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
925 if (lLineCount
== -1)
927 SetLastError(ERROR_INVALID_PARAMETER
);
931 dwFullLength
= lstrlenW(szBuffer
);
933 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
935 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
937 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
941 lstrcpyW(InfSectionWithExt
, szBuffer
);
942 if (Extension
!= NULL
)
944 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
948 if (RequiredSize
!= NULL
)
950 *RequiredSize
= dwFullLength
+ 1;
956 /***********************************************************************
957 * SetupDiGetClassDescriptionA (SETUPAPI.@)
959 BOOL WINAPI
SetupDiGetClassDescriptionA(
960 const GUID
* ClassGuid
,
961 PSTR ClassDescription
,
962 DWORD ClassDescriptionSize
,
965 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
966 ClassDescriptionSize
,
967 RequiredSize
, NULL
, NULL
);
970 /***********************************************************************
971 * SetupDiGetClassDescriptionW (SETUPAPI.@)
973 BOOL WINAPI
SetupDiGetClassDescriptionW(
974 const GUID
* ClassGuid
,
975 PWSTR ClassDescription
,
976 DWORD ClassDescriptionSize
,
979 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
980 ClassDescriptionSize
,
981 RequiredSize
, NULL
, NULL
);
984 /***********************************************************************
985 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
987 BOOL WINAPI
SetupDiGetClassDescriptionExA(
988 const GUID
* ClassGuid
,
989 PSTR ClassDescription
,
990 DWORD ClassDescriptionSize
,
995 PWCHAR ClassDescriptionW
;
996 LPWSTR MachineNameW
= NULL
;
1000 if (ClassDescriptionSize
> 0)
1002 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1003 if (!ClassDescriptionW
)
1005 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1011 ClassDescriptionW
= NULL
;
1015 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1018 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1024 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1025 NULL
, MachineNameW
, Reserved
);
1028 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1029 ClassDescriptionSize
, NULL
, NULL
);
1031 if (!ClassDescriptionSize
&& RequiredSize
)
1032 *RequiredSize
= len
;
1036 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1037 MyFree(MachineNameW
);
1041 /***********************************************************************
1042 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1044 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1045 const GUID
* ClassGuid
,
1046 PWSTR ClassDescription
,
1047 DWORD ClassDescriptionSize
,
1048 PDWORD RequiredSize
,
1055 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1056 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1058 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1063 if (hKey
== INVALID_HANDLE_VALUE
)
1065 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1069 if (RequiredSize
!= NULL
)
1072 if (RegQueryValueExW(hKey
,
1083 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1086 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1087 if (RegQueryValueExW(hKey
,
1091 (LPBYTE
)ClassDescription
,
1103 /***********************************************************************
1104 * SetupDiGetClassDevsA (SETUPAPI.@)
1106 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1112 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1113 flags
, NULL
, NULL
, NULL
);
1116 /***********************************************************************
1117 * SetupDiGetClassDevsW (SETUPAPI.@)
1119 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1125 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1126 flags
, NULL
, NULL
, NULL
);
1129 /***********************************************************************
1130 * SetupDiGetClassDevsExA (SETUPAPI.@)
1132 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1142 LPWSTR enumstrW
= NULL
;
1143 LPWSTR machineW
= NULL
;
1147 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1148 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1151 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1154 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1158 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1159 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1162 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1165 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1167 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1170 HeapFree(GetProcessHeap(), 0, enumstrW
);
1171 HeapFree(GetProcessHeap(), 0, machineW
);
1176 CreateDeviceInfoElement(
1177 IN
struct DeviceInfoSet
*list
,
1178 IN LPCWSTR InstancePath
,
1179 IN LPCGUID pClassGuid
,
1180 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1184 struct DeviceInfoElement
*deviceInfo
;
1186 *pDeviceInfo
= NULL
;
1188 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1189 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1192 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1195 memset(deviceInfo
, 0, size
);
1197 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1198 if (cr
!= CR_SUCCESS
)
1200 SetLastError(GetErrorCodeFromCrCode(cr
));
1204 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1205 wcscpy(deviceInfo
->Data
, InstancePath
);
1206 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1207 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1208 deviceInfo
->DeviceDescription
= NULL
;
1209 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1210 deviceInfo
->CreationFlags
= 0;
1211 InitializeListHead(&deviceInfo
->DriverListHead
);
1212 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1214 *pDeviceInfo
= deviceInfo
;
1219 CreateDeviceInterface(
1220 IN
struct DeviceInfoElement
* deviceInfo
,
1221 IN LPCWSTR SymbolicLink
,
1222 IN LPCGUID pInterfaceGuid
,
1223 OUT
struct DeviceInterface
**pDeviceInterface
)
1225 struct DeviceInterface
*deviceInterface
;
1227 *pDeviceInterface
= NULL
;
1229 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1230 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1231 if (!deviceInterface
)
1233 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1236 deviceInterface
->DeviceInfo
= deviceInfo
;
1237 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1238 deviceInterface
->Flags
= 0; /* FIXME */
1239 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1241 *pDeviceInterface
= deviceInterface
;
1245 static LONG
SETUP_CreateDevListFromEnumerator(
1246 struct DeviceInfoSet
*list
,
1247 LPCGUID pClassGuid OPTIONAL
,
1249 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1251 HKEY hDeviceIdKey
, hInstanceIdKey
;
1252 WCHAR KeyBuffer
[MAX_PATH
];
1253 WCHAR InstancePath
[MAX_PATH
];
1254 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1255 struct DeviceInfoElement
*deviceInfo
;
1257 DWORD dwLength
, dwRegType
;
1260 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1263 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1264 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1265 if (rc
== ERROR_NO_MORE_ITEMS
)
1267 if (rc
!= ERROR_SUCCESS
)
1271 /* Open device id sub key */
1272 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1273 if (rc
!= ERROR_SUCCESS
)
1275 wcscpy(InstancePath
, Enumerator
);
1276 wcscat(InstancePath
, L
"\\");
1277 wcscat(InstancePath
, KeyBuffer
);
1278 wcscat(InstancePath
, L
"\\");
1279 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1281 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1287 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1288 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1289 if (rc
== ERROR_NO_MORE_ITEMS
)
1291 if (rc
!= ERROR_SUCCESS
)
1293 RegCloseKey(hDeviceIdKey
);
1298 /* Open instance id sub key */
1299 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1300 if (rc
!= ERROR_SUCCESS
)
1302 RegCloseKey(hDeviceIdKey
);
1305 *pEndOfInstancePath
= '\0';
1306 wcscat(InstancePath
, KeyBuffer
);
1308 /* Read ClassGUID value */
1309 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1310 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1311 RegCloseKey(hInstanceIdKey
);
1312 if (rc
== ERROR_FILE_NOT_FOUND
)
1315 /* Skip this bad entry as we can't verify it */
1317 /* Set a default GUID for this device */
1318 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1320 else if (rc
!= ERROR_SUCCESS
)
1322 RegCloseKey(hDeviceIdKey
);
1325 else if (dwRegType
!= REG_SZ
)
1327 RegCloseKey(hDeviceIdKey
);
1328 return ERROR_GEN_FAILURE
;
1332 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1333 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1334 /* Bad GUID, skip the entry */
1338 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1340 /* Skip this entry as it is not the right device class */
1344 /* Add the entry to the list */
1345 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1347 RegCloseKey(hDeviceIdKey
);
1348 return GetLastError();
1350 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1351 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1353 RegCloseKey(hDeviceIdKey
);
1356 return ERROR_SUCCESS
;
1359 static LONG
SETUP_CreateDevList(
1360 struct DeviceInfoSet
*list
,
1361 PCWSTR MachineName OPTIONAL
,
1362 LPGUID
class OPTIONAL
,
1363 PCWSTR Enumerator OPTIONAL
)
1365 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1366 WCHAR KeyBuffer
[MAX_PATH
];
1371 if (class && IsEqualIID(class, &GUID_NULL
))
1375 if (MachineName
!= NULL
)
1377 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1378 if (rc
!= ERROR_SUCCESS
)
1382 HKLM
= HKEY_LOCAL_MACHINE
;
1384 rc
= RegOpenKeyExW(HKLM
,
1385 REGSTR_PATH_SYSTEMENUM
,
1387 KEY_ENUMERATE_SUB_KEYS
,
1389 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1390 if (rc
!= ERROR_SUCCESS
)
1393 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1394 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1403 KEY_ENUMERATE_SUB_KEYS
,
1405 RegCloseKey(hEnumKey
);
1406 if (rc
!= ERROR_SUCCESS
)
1408 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1409 RegCloseKey(hEnumeratorKey
);
1414 /* Enumerate enumerators */
1418 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1419 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1420 if (rc
== ERROR_NO_MORE_ITEMS
)
1422 if (rc
!= ERROR_SUCCESS
)
1424 RegCloseKey(hEnumKey
);
1430 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1431 if (rc
!= ERROR_SUCCESS
)
1433 RegCloseKey(hEnumKey
);
1437 /* Call SETUP_CreateDevListFromEnumerator */
1438 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1439 RegCloseKey(hEnumeratorKey
);
1440 if (rc
!= ERROR_SUCCESS
)
1442 RegCloseKey(hEnumKey
);
1446 RegCloseKey(hEnumKey
);
1447 return ERROR_SUCCESS
;
1452 static LONG
SETUP_CreateSerialDeviceList(
1453 struct DeviceInfoSet
*list
,
1455 LPGUID InterfaceGuid
,
1456 PCWSTR DeviceInstanceW
)
1458 static const size_t initialSize
= 100;
1460 WCHAR buf
[initialSize
];
1462 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1464 struct DeviceInfoElement
*deviceInfo
;
1467 WARN("'MachineName' is ignored on Wine!\n");
1468 if (DeviceInstanceW
)
1469 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1475 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1477 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1481 HeapFree(GetProcessHeap(), 0, devices
);
1482 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1484 return ERROR_NOT_ENOUGH_MEMORY
;
1490 HeapFree(GetProcessHeap(), 0, devices
);
1491 return GetLastError();
1495 /* 'devices' is a MULTI_SZ string */
1496 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1498 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1500 /* We have found a device */
1501 struct DeviceInterface
*interfaceInfo
;
1502 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1503 /* Step 1. Create a device info element */
1504 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1507 HeapFree(GetProcessHeap(), 0, devices
);
1508 return GetLastError();
1510 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1512 /* Step 2. Create an interface list for this element */
1513 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1516 HeapFree(GetProcessHeap(), 0, devices
);
1517 return GetLastError();
1519 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1523 HeapFree(GetProcessHeap(), 0, devices
);
1524 return ERROR_SUCCESS
;
1527 #else /* __REACTOS__ */
1529 static LONG
SETUP_CreateInterfaceList(
1530 struct DeviceInfoSet
*list
,
1532 LPGUID InterfaceGuid
,
1533 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1535 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1536 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1537 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1538 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1539 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1541 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1544 DWORD dwLength
, dwInstancePathLength
;
1547 struct DeviceInfoElement
*deviceInfo
;
1549 /* Open registry key related to this interface */
1550 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1551 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1552 return GetLastError();
1554 /* Enumerate sub keys of hInterfaceKey */
1558 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1559 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1560 if (rc
== ERROR_NO_MORE_ITEMS
)
1562 if (rc
!= ERROR_SUCCESS
)
1564 RegCloseKey(hInterfaceKey
);
1570 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1571 if (rc
!= ERROR_SUCCESS
)
1573 RegCloseKey(hInterfaceKey
);
1577 /* Read DeviceInstance */
1578 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1579 if (rc
!= ERROR_SUCCESS
)
1581 RegCloseKey(hDeviceInstanceKey
);
1582 RegCloseKey(hInterfaceKey
);
1585 if (dwRegType
!= REG_SZ
)
1587 RegCloseKey(hDeviceInstanceKey
);
1588 RegCloseKey(hInterfaceKey
);
1589 return ERROR_GEN_FAILURE
;
1591 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1594 RegCloseKey(hDeviceInstanceKey
);
1595 RegCloseKey(hInterfaceKey
);
1596 return ERROR_NOT_ENOUGH_MEMORY
;
1598 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1599 if (rc
!= ERROR_SUCCESS
)
1601 HeapFree(GetProcessHeap(), 0, InstancePath
);
1602 RegCloseKey(hDeviceInstanceKey
);
1603 RegCloseKey(hInterfaceKey
);
1606 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1607 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1609 if (DeviceInstanceW
)
1611 /* Check if device enumerator is not the right one */
1612 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1614 HeapFree(GetProcessHeap(), 0, InstancePath
);
1615 RegCloseKey(hDeviceInstanceKey
);
1620 /* Find class GUID associated to the device instance */
1623 REGSTR_PATH_SYSTEMENUM
,
1627 if (rc
!= ERROR_SUCCESS
)
1629 HeapFree(GetProcessHeap(), 0, InstancePath
);
1630 RegCloseKey(hDeviceInstanceKey
);
1631 RegCloseKey(hInterfaceKey
);
1640 RegCloseKey(hEnumKey
);
1641 if (rc
!= ERROR_SUCCESS
)
1643 HeapFree(GetProcessHeap(), 0, InstancePath
);
1644 RegCloseKey(hDeviceInstanceKey
);
1645 RegCloseKey(hInterfaceKey
);
1648 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1649 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1651 if (rc
!= ERROR_SUCCESS
)
1653 HeapFree(GetProcessHeap(), 0, InstancePath
);
1654 RegCloseKey(hDeviceInstanceKey
);
1655 RegCloseKey(hInterfaceKey
);
1658 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1659 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1660 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1662 HeapFree(GetProcessHeap(), 0, InstancePath
);
1663 RegCloseKey(hDeviceInstanceKey
);
1664 RegCloseKey(hInterfaceKey
);
1665 return ERROR_GEN_FAILURE
;
1667 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1669 /* If current device doesn't match the list GUID (if any), skip this entry */
1670 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1672 HeapFree(GetProcessHeap(), 0, InstancePath
);
1673 RegCloseKey(hDeviceInstanceKey
);
1677 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1681 LPWSTR pSymbolicLink
;
1682 struct DeviceInterface
*interfaceInfo
;
1684 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1685 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1686 if (rc
== ERROR_NO_MORE_ITEMS
)
1688 if (rc
!= ERROR_SUCCESS
)
1690 HeapFree(GetProcessHeap(), 0, InstancePath
);
1691 RegCloseKey(hDeviceInstanceKey
);
1692 RegCloseKey(hInterfaceKey
);
1696 if (KeyBuffer
[0] != '#')
1697 /* This entry doesn't represent an interesting entry */
1701 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1702 if (rc
!= ERROR_SUCCESS
)
1704 RegCloseKey(hDeviceInstanceKey
);
1705 RegCloseKey(hInterfaceKey
);
1709 /* Read SymbolicLink value */
1710 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1711 if (rc
!= ERROR_SUCCESS
)
1713 RegCloseKey(hReferenceKey
);
1714 RegCloseKey(hDeviceInstanceKey
);
1715 RegCloseKey(hInterfaceKey
);
1718 if (dwRegType
!= REG_SZ
)
1720 RegCloseKey(hReferenceKey
);
1721 RegCloseKey(hDeviceInstanceKey
);
1722 RegCloseKey(hInterfaceKey
);
1723 return ERROR_GEN_FAILURE
;
1726 /* We have found a device */
1727 /* Step 1. Create a device info element */
1728 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1730 RegCloseKey(hReferenceKey
);
1731 RegCloseKey(hDeviceInstanceKey
);
1732 RegCloseKey(hInterfaceKey
);
1733 return GetLastError();
1735 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1736 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1738 /* Step 2. Create an interface list for this element */
1739 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1742 RegCloseKey(hReferenceKey
);
1743 RegCloseKey(hDeviceInstanceKey
);
1744 RegCloseKey(hInterfaceKey
);
1745 return ERROR_NOT_ENOUGH_MEMORY
;
1747 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1748 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1749 RegCloseKey(hReferenceKey
);
1750 if (rc
!= ERROR_SUCCESS
)
1752 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1753 RegCloseKey(hDeviceInstanceKey
);
1754 RegCloseKey(hInterfaceKey
);
1757 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1759 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1760 RegCloseKey(hDeviceInstanceKey
);
1761 RegCloseKey(hInterfaceKey
);
1762 return GetLastError();
1764 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1765 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1766 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1768 RegCloseKey(hDeviceInstanceKey
);
1770 RegCloseKey(hInterfaceKey
);
1771 return ERROR_SUCCESS
;
1773 #endif /* __REACTOS__ */
1775 /***********************************************************************
1776 * SetupDiGetClassDevsExW (SETUPAPI.@)
1778 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1787 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1788 struct DeviceInfoSet
*list
;
1792 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1793 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1795 /* Create the deviceset if not set */
1798 list
= (struct DeviceInfoSet
*)deviceset
;
1799 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1801 SetLastError(ERROR_INVALID_HANDLE
);
1802 return INVALID_HANDLE_VALUE
;
1804 hDeviceInfo
= deviceset
;
1808 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1809 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1810 NULL
, machine
, NULL
);
1811 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1812 return INVALID_HANDLE_VALUE
;
1813 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1816 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1819 pClassGuid
= &list
->ClassGuid
;
1821 if (flags
& DIGCF_PRESENT
)
1822 FIXME(": flag DIGCF_PRESENT ignored\n");
1823 if (flags
& DIGCF_PROFILE
)
1824 FIXME(": flag DIGCF_PROFILE ignored\n");
1826 if (flags
& DIGCF_ALLCLASSES
)
1828 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1829 if (rc
!= ERROR_SUCCESS
)
1833 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1834 return INVALID_HANDLE_VALUE
;
1838 else if (flags
& DIGCF_DEVICEINTERFACE
)
1842 SetLastError(ERROR_INVALID_PARAMETER
);
1844 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1845 return INVALID_HANDLE_VALUE
;
1849 /* Special case: find serial ports by calling QueryDosDevice */
1850 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1851 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1852 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1853 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1856 ERR("Wine can only enumerate serial devices at the moment!\n");
1857 rc
= ERROR_INVALID_PARAMETER
;
1859 #else /* __REACTOS__ */
1860 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1861 #endif /* __REACTOS__ */
1862 if (rc
!= ERROR_SUCCESS
)
1866 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1867 return INVALID_HANDLE_VALUE
;
1873 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1874 if (rc
!= ERROR_SUCCESS
)
1878 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1879 return INVALID_HANDLE_VALUE
;
1885 /***********************************************************************
1886 * SetupDiGetClassImageIndex (SETUPAPI.@)
1889 static BOOL
GetIconIndex(
1891 OUT PINT ImageIndex
)
1893 LPWSTR Buffer
= NULL
;
1894 DWORD dwRegType
, dwLength
;
1898 /* Read icon registry key */
1899 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1900 if (rc
!= ERROR_SUCCESS
)
1904 } else if (dwRegType
!= REG_SZ
)
1906 SetLastError(ERROR_INVALID_INDEX
);
1909 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1912 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1915 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1916 if (rc
!= ERROR_SUCCESS
)
1921 /* make sure the returned buffer is NULL-terminated */
1922 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1924 /* Transform icon value to a INT */
1925 *ImageIndex
= atoiW(Buffer
);
1933 BOOL WINAPI
SetupDiGetClassImageIndex(
1934 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1935 IN CONST GUID
*ClassGuid
,
1936 OUT PINT ImageIndex
)
1938 struct ClassImageList
*list
;
1941 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
1943 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
1944 SetLastError(ERROR_INVALID_PARAMETER
);
1945 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1946 SetLastError(ERROR_INVALID_USER_BUFFER
);
1947 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
1948 SetLastError(ERROR_INVALID_USER_BUFFER
);
1949 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
1950 SetLastError(ERROR_INVALID_USER_BUFFER
);
1951 else if (!ImageIndex
)
1952 SetLastError(ERROR_INVALID_PARAMETER
);
1955 HKEY hKey
= INVALID_HANDLE_VALUE
;
1958 /* Read Icon registry entry into Buffer */
1959 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
1960 if (hKey
== INVALID_HANDLE_VALUE
)
1962 if (!GetIconIndex(hKey
, &iconIndex
))
1967 SetLastError(ERROR_INVALID_INDEX
);
1971 *ImageIndex
= -iconIndex
;
1975 if (hKey
!= INVALID_HANDLE_VALUE
)
1979 TRACE("Returning %d\n", ret
);
1983 /***********************************************************************
1984 * SetupDiGetClassImageList(SETUPAPI.@)
1986 BOOL WINAPI
SetupDiGetClassImageList(
1987 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
1989 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
1992 /***********************************************************************
1993 * SetupDiGetClassImageListExA(SETUPAPI.@)
1995 BOOL WINAPI
SetupDiGetClassImageListExA(
1996 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1997 IN PCSTR MachineName OPTIONAL
,
2000 PWSTR MachineNameW
= NULL
;
2005 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2006 if (MachineNameW
== NULL
)
2010 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2013 MyFree(MachineNameW
);
2018 /***********************************************************************
2019 * SetupDiGetClassImageListExW(SETUPAPI.@)
2021 BOOL WINAPI
SetupDiGetClassImageListExW(
2022 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2023 IN PCWSTR MachineName OPTIONAL
,
2028 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2030 if (!ClassImageListData
)
2031 SetLastError(ERROR_INVALID_PARAMETER
);
2032 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2033 SetLastError(ERROR_INVALID_USER_BUFFER
);
2035 SetLastError(ERROR_INVALID_PARAMETER
);
2038 struct ClassImageList
*list
= NULL
;
2041 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2043 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2044 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2047 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2050 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2053 list
->szData
[0] = list
->szData
[1] = '\\';
2054 strcpyW(list
->szData
+ 2, MachineName
);
2055 list
->MachineName
= list
->szData
;
2059 list
->MachineName
= NULL
;
2062 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2070 TRACE("Returning %d\n", ret
);
2074 /***********************************************************************
2075 * SetupDiLoadClassIcon(SETUPAPI.@)
2077 BOOL WINAPI
SetupDiLoadClassIcon(
2078 IN CONST GUID
*ClassGuid
,
2079 OUT HICON
*LargeIcon OPTIONAL
,
2080 OUT PINT MiniIconIndex OPTIONAL
)
2085 SetLastError(ERROR_INVALID_PARAMETER
);
2088 LPWSTR Buffer
= NULL
;
2091 HKEY hKey
= INVALID_HANDLE_VALUE
;
2093 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2094 if (hKey
== INVALID_HANDLE_VALUE
)
2097 if (!GetIconIndex(hKey
, &iconIndex
))
2102 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2105 DWORD dwRegType
, dwLength
;
2106 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2107 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2109 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2112 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2115 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2116 if (rc
!= ERROR_SUCCESS
)
2121 /* make sure the returned buffer is NULL-terminated */
2122 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2125 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2126 && dwRegType
== REG_SZ
)
2128 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2131 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2134 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2135 if (rc
!= ERROR_SUCCESS
)
2140 /* make sure the returned buffer is NULL-terminated */
2141 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2145 /* Unable to find where to load the icon */
2146 SetLastError(ERROR_FILE_NOT_FOUND
);
2149 Comma
= strchrW(Buffer
, ',');
2152 SetLastError(ERROR_GEN_FAILURE
);
2160 /* Look up icon in setupapi.dll */
2161 DllName
= L
"setupapi.dll";
2162 iconIndex
= -iconIndex
;
2165 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2168 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2170 SetLastError(ERROR_INVALID_INDEX
);
2175 *MiniIconIndex
= iconIndex
;
2179 if (hKey
!= INVALID_HANDLE_VALUE
)
2184 TRACE("Returning %d\n", ret
);
2188 /***********************************************************************
2189 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2191 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2192 HDEVINFO DeviceInfoSet
,
2193 PSP_DEVINFO_DATA DeviceInfoData
,
2194 CONST GUID
* InterfaceClassGuid
,
2196 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2200 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2201 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2203 if (!DeviceInterfaceData
)
2204 SetLastError(ERROR_INVALID_PARAMETER
);
2205 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2206 SetLastError(ERROR_INVALID_USER_BUFFER
);
2207 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2209 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2211 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2213 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2215 while (ItemList
!= &list
->ListHead
&& !Found
)
2217 PLIST_ENTRY InterfaceListEntry
;
2218 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2219 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2221 /* We are not searching for this element */
2222 ItemList
= ItemList
->Flink
;
2225 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2226 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2228 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2229 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2231 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2234 if (MemberIndex
-- == 0)
2236 /* return this item */
2237 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2238 &DevItf
->InterfaceClassGuid
,
2240 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2241 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2244 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2246 ItemList
= ItemList
->Flink
;
2249 SetLastError(ERROR_NO_MORE_ITEMS
);
2254 SetLastError(ERROR_INVALID_HANDLE
);
2257 SetLastError(ERROR_INVALID_HANDLE
);
2261 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2263 InterlockedIncrement(&infFile
->References
);
2266 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2268 if (InterlockedDecrement(&infFile
->References
) == 0)
2270 SetupCloseInfFile(infFile
->hInf
);
2271 HeapFree(GetProcessHeap(), 0, infFile
);
2275 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2277 DereferenceInfFile(driverInfo
->InfFileDetails
);
2278 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2279 HeapFree(GetProcessHeap(), 0, driverInfo
);
2283 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2285 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2289 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2291 PLIST_ENTRY ListEntry
;
2292 struct DriverInfoElement
*driverInfo
;
2294 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2296 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2297 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2298 if (!DestroyDriverInfoElement(driverInfo
))
2301 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2303 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2304 HeapFree(GetProcessHeap(), 0, ListEntry
);
2306 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2307 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2311 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2313 PLIST_ENTRY ListEntry
;
2314 struct DeviceInfoElement
*deviceInfo
;
2316 while (!IsListEmpty(&list
->ListHead
))
2318 ListEntry
= RemoveHeadList(&list
->ListHead
);
2319 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2320 if (!DestroyDeviceInfoElement(deviceInfo
))
2323 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2324 RegCloseKey(list
->HKLM
);
2325 CM_Disconnect_Machine(list
->hMachine
);
2326 DestroyClassInstallParams(&list
->ClassInstallParams
);
2327 HeapFree(GetProcessHeap(), 0, list
);
2331 /***********************************************************************
2332 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2334 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2338 TRACE("%p\n", devinfo
);
2339 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2341 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2343 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2344 ret
= DestroyDeviceInfoSet(list
);
2346 SetLastError(ERROR_INVALID_HANDLE
);
2349 SetLastError(ERROR_INVALID_HANDLE
);
2351 TRACE("Returning %d\n", ret
);
2355 /***********************************************************************
2356 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2358 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2359 HDEVINFO DeviceInfoSet
,
2360 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2361 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2362 DWORD DeviceInterfaceDetailDataSize
,
2363 PDWORD RequiredSize
,
2364 PSP_DEVINFO_DATA DeviceInfoData
)
2366 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2367 DWORD sizeW
= 0, sizeA
;
2370 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2371 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2372 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2374 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2375 SetLastError(ERROR_INVALID_USER_BUFFER
);
2376 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2377 SetLastError(ERROR_INVALID_PARAMETER
);
2378 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2379 SetLastError(ERROR_INVALID_PARAMETER
);
2382 if (DeviceInterfaceDetailData
!= NULL
)
2384 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2385 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2386 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2387 if (!DeviceInterfaceDetailDataW
)
2389 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2392 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2394 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2395 ret
= SetupDiGetDeviceInterfaceDetailW(
2397 DeviceInterfaceData
,
2398 DeviceInterfaceDetailDataW
,
2402 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2403 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2405 *RequiredSize
= sizeA
;
2406 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2408 if (!WideCharToMultiByte(
2410 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2411 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2418 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2421 TRACE("Returning %d\n", ret
);
2425 /***********************************************************************
2426 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2428 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2429 HDEVINFO DeviceInfoSet
,
2430 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2431 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2432 DWORD DeviceInterfaceDetailDataSize
,
2433 PDWORD RequiredSize
,
2434 PSP_DEVINFO_DATA DeviceInfoData
)
2438 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2439 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2440 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2442 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2443 SetLastError(ERROR_INVALID_PARAMETER
);
2444 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2445 SetLastError(ERROR_INVALID_HANDLE
);
2446 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2447 SetLastError(ERROR_INVALID_HANDLE
);
2448 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2449 SetLastError(ERROR_INVALID_USER_BUFFER
);
2450 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2451 SetLastError(ERROR_INVALID_USER_BUFFER
);
2452 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2453 SetLastError(ERROR_INVALID_USER_BUFFER
);
2454 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2455 SetLastError(ERROR_INVALID_PARAMETER
);
2456 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2457 SetLastError(ERROR_INVALID_PARAMETER
);
2460 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2461 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2462 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2463 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2465 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2467 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2469 *RequiredSize
= sizeRequired
;
2473 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2474 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2477 memcpy(&DeviceInfoData
->ClassGuid
,
2478 &deviceInterface
->DeviceInfo
->ClassGuid
,
2480 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2481 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2487 TRACE("Returning %d\n", ret
);
2491 /***********************************************************************
2492 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2494 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2496 PSP_DEVINFO_DATA DeviceInfoData
,
2498 PDWORD PropertyRegDataType
,
2499 PBYTE PropertyBuffer
,
2500 DWORD PropertyBufferSize
,
2501 PDWORD RequiredSize
)
2504 BOOL bIsStringProperty
;
2506 DWORD RequiredSizeA
, RequiredSizeW
;
2507 DWORD PropertyBufferSizeW
;
2508 PBYTE PropertyBufferW
;
2510 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2511 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2514 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2515 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2517 bResult
= SetupDiGetDeviceRegistryPropertyW(
2523 PropertyBufferSizeW
,
2526 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2528 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2530 if (bIsStringProperty
)
2531 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2533 RequiredSizeA
= RequiredSizeW
;
2535 *RequiredSize
= RequiredSizeA
;
2536 if (PropertyRegDataType
)
2537 *PropertyRegDataType
= RegType
;
2542 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2546 if (RequiredSizeA
<= PropertyBufferSize
)
2548 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2550 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2552 /* Last error is already set by WideCharToMultiByte */
2557 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2561 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2565 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2569 /***********************************************************************
2570 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2572 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2573 HDEVINFO DeviceInfoSet
,
2574 PSP_DEVINFO_DATA DeviceInfoData
,
2576 PDWORD PropertyRegDataType
,
2577 PBYTE PropertyBuffer
,
2578 DWORD PropertyBufferSize
,
2579 PDWORD RequiredSize
)
2581 HKEY hEnumKey
, hKey
;
2585 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2586 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2589 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2590 SetLastError(ERROR_INVALID_HANDLE
);
2591 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2592 SetLastError(ERROR_INVALID_HANDLE
);
2593 else if (!DeviceInfoData
)
2594 SetLastError(ERROR_INVALID_PARAMETER
);
2595 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2596 SetLastError(ERROR_INVALID_USER_BUFFER
);
2597 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2598 SetLastError(ERROR_INVALID_PARAMETER
);
2601 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2602 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2606 case SPDRP_CAPABILITIES
:
2608 case SPDRP_CLASSGUID
:
2609 case SPDRP_COMPATIBLEIDS
:
2610 case SPDRP_CONFIGFLAGS
:
2611 case SPDRP_DEVICEDESC
:
2613 case SPDRP_FRIENDLYNAME
:
2614 case SPDRP_HARDWAREID
:
2615 case SPDRP_LOCATION_INFORMATION
:
2616 case SPDRP_LOWERFILTERS
:
2618 case SPDRP_SECURITY
:
2620 case SPDRP_UI_NUMBER
:
2621 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2622 case SPDRP_UPPERFILTERS
:
2624 LPCWSTR RegistryPropertyName
;
2629 case SPDRP_CAPABILITIES
:
2630 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2632 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2633 case SPDRP_CLASSGUID
:
2634 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2635 case SPDRP_COMPATIBLEIDS
:
2636 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2637 case SPDRP_CONFIGFLAGS
:
2638 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2639 case SPDRP_DEVICEDESC
:
2640 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2642 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2643 case SPDRP_FRIENDLYNAME
:
2644 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2645 case SPDRP_HARDWAREID
:
2646 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2647 case SPDRP_LOCATION_INFORMATION
:
2648 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2649 case SPDRP_LOWERFILTERS
:
2650 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2652 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2653 case SPDRP_SECURITY
:
2654 RegistryPropertyName
= L
"Security"; break;
2656 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2657 case SPDRP_UI_NUMBER
:
2658 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2659 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2660 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2661 case SPDRP_UPPERFILTERS
:
2662 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2664 /* Should not happen */
2665 RegistryPropertyName
= NULL
; break;
2668 /* Open registry key name */
2671 REGSTR_PATH_SYSTEMENUM
,
2675 if (rc
!= ERROR_SUCCESS
)
2686 RegCloseKey(hEnumKey
);
2687 if (rc
!= ERROR_SUCCESS
)
2692 /* Read registry entry */
2693 BufferSize
= PropertyBufferSize
;
2694 rc
= RegQueryValueExW(
2696 RegistryPropertyName
,
2697 NULL
, /* Reserved */
2698 PropertyRegDataType
,
2702 *RequiredSize
= BufferSize
;
2705 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2708 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2710 case ERROR_MORE_DATA
:
2711 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2720 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2722 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2724 if (PropertyRegDataType
)
2725 *PropertyRegDataType
= REG_SZ
;
2727 *RequiredSize
= required
;
2728 if (PropertyBufferSize
>= required
)
2730 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2734 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2738 /*case SPDRP_BUSTYPEGUID:
2739 case SPDRP_LEGACYBUSTYPE:
2740 case SPDRP_BUSNUMBER:
2741 case SPDRP_ENUMERATOR_NAME:
2742 case SPDRP_SECURITY_SDS:
2744 case SPDRP_EXCLUSIVE:
2745 case SPDRP_CHARACTERISTICS:
2747 case SPDRP_DEVICE_POWER_DATA:*/
2748 #if (WINVER >= 0x501)
2749 /*case SPDRP_REMOVAL_POLICY:
2750 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2751 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2752 case SPDRP_INSTALL_STATE:*/
2757 ERR("Property 0x%lx not implemented\n", Property
);
2758 SetLastError(ERROR_NOT_SUPPORTED
);
2763 TRACE("Returning %d\n", ret
);
2767 /***********************************************************************
2768 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2770 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2771 IN HDEVINFO DeviceInfoSet
,
2772 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2774 IN CONST BYTE
*PropertyBuffer
,
2775 IN DWORD PropertyBufferSize
)
2777 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2778 Property
, PropertyBuffer
, PropertyBufferSize
);
2779 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2783 /***********************************************************************
2784 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2786 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2787 IN HDEVINFO DeviceInfoSet
,
2788 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2790 IN
const BYTE
*PropertyBuffer
,
2791 IN DWORD PropertyBufferSize
)
2793 struct DeviceInfoSet
*list
;
2796 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2797 Property
, PropertyBuffer
, PropertyBufferSize
);
2800 SetLastError(ERROR_INVALID_HANDLE
);
2801 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2802 SetLastError(ERROR_INVALID_HANDLE
);
2803 else if (!DeviceInfoData
)
2804 SetLastError(ERROR_INVALID_HANDLE
);
2805 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2806 SetLastError(ERROR_INVALID_USER_BUFFER
);
2811 case SPDRP_COMPATIBLEIDS
:
2812 case SPDRP_CONFIGFLAGS
:
2813 case SPDRP_FRIENDLYNAME
:
2814 case SPDRP_HARDWAREID
:
2815 case SPDRP_LOCATION_INFORMATION
:
2816 case SPDRP_LOWERFILTERS
:
2817 case SPDRP_SECURITY
:
2819 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2820 case SPDRP_UPPERFILTERS
:
2822 LPCWSTR RegistryPropertyName
;
2823 DWORD RegistryDataType
;
2829 case SPDRP_COMPATIBLEIDS
:
2830 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2831 RegistryDataType
= REG_MULTI_SZ
;
2833 case SPDRP_CONFIGFLAGS
:
2834 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2835 RegistryDataType
= REG_DWORD
;
2837 case SPDRP_FRIENDLYNAME
:
2838 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2839 RegistryDataType
= REG_SZ
;
2841 case SPDRP_HARDWAREID
:
2842 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2843 RegistryDataType
= REG_MULTI_SZ
;
2845 case SPDRP_LOCATION_INFORMATION
:
2846 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2847 RegistryDataType
= REG_SZ
;
2849 case SPDRP_LOWERFILTERS
:
2850 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2851 RegistryDataType
= REG_MULTI_SZ
;
2853 case SPDRP_SECURITY
:
2854 RegistryPropertyName
= L
"Security";
2855 RegistryDataType
= REG_BINARY
;
2858 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2859 RegistryDataType
= REG_SZ
;
2861 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2862 RegistryPropertyName
= L
"UINumberDescFormat";
2863 RegistryDataType
= REG_SZ
;
2865 case SPDRP_UPPERFILTERS
:
2866 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2867 RegistryDataType
= REG_MULTI_SZ
;
2870 /* Should not happen */
2871 RegistryPropertyName
= NULL
;
2872 RegistryDataType
= REG_BINARY
;
2875 /* Open device registry key */
2876 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2877 if (hKey
!= INVALID_HANDLE_VALUE
)
2879 /* Write new data */
2880 rc
= RegSetValueExW(
2882 RegistryPropertyName
,
2886 PropertyBufferSize
);
2887 if (rc
== ERROR_SUCCESS
)
2896 /*case SPDRP_CHARACTERISTICS:
2898 case SPDRP_EXCLUSIVE:*/
2899 #if (WINVER >= 0x501)
2900 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2902 //case SPDRP_SECURITY_SDS:
2906 ERR("Property 0x%lx not implemented\n", Property
);
2907 SetLastError(ERROR_NOT_SUPPORTED
);
2912 TRACE("Returning %d\n", ret
);
2917 /***********************************************************************
2918 * SetupDiInstallClassA (SETUPAPI.@)
2920 BOOL WINAPI
SetupDiInstallClassA(
2921 IN HWND hwndParent OPTIONAL
,
2922 IN PCSTR InfFileName
,
2924 IN HSPFILEQ FileQueue OPTIONAL
)
2926 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
2930 /***********************************************************************
2931 * SetupDiInstallClassW (SETUPAPI.@)
2933 BOOL WINAPI
SetupDiInstallClassW(
2934 IN HWND hwndParent OPTIONAL
,
2935 IN PCWSTR InfFileName
,
2937 IN HSPFILEQ FileQueue OPTIONAL
)
2939 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
2943 /***********************************************************************
2944 * SetupDiInstallClassExA (SETUPAPI.@)
2946 BOOL WINAPI
SetupDiInstallClassExA(
2947 IN HWND hwndParent OPTIONAL
,
2948 IN PCSTR InfFileName OPTIONAL
,
2950 IN HSPFILEQ FileQueue OPTIONAL
,
2951 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
2955 PWSTR InfFileNameW
= NULL
;
2960 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
2961 if (InfFileNameW
== NULL
)
2963 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2968 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
2969 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
2971 MyFree(InfFileNameW
);
2977 static HKEY
CreateClassKey(HINF hInf
)
2979 WCHAR FullBuffer
[MAX_PATH
];
2980 WCHAR Buffer
[MAX_PATH
];
2985 if (!SetupGetLineTextW(NULL
,
2993 return INVALID_HANDLE_VALUE
;
2996 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
2997 lstrcatW(FullBuffer
, Buffer
);
3000 if (!SetupGetLineTextW(NULL
,
3008 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3009 return INVALID_HANDLE_VALUE
;
3012 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3016 REG_OPTION_NON_VOLATILE
,
3022 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3023 return INVALID_HANDLE_VALUE
;
3026 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3031 RequiredSize
* sizeof(WCHAR
)))
3033 RegCloseKey(hClassKey
);
3034 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3035 return INVALID_HANDLE_VALUE
;
3042 /***********************************************************************
3043 * SetupDiInstallClassExW (SETUPAPI.@)
3045 BOOL WINAPI
SetupDiInstallClassExW(
3046 IN HWND hwndParent OPTIONAL
,
3047 IN PCWSTR InfFileName OPTIONAL
,
3049 IN HSPFILEQ FileQueue OPTIONAL
,
3050 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3056 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3057 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3059 if (!InfFileName
&& !InterfaceClassGuid
)
3060 SetLastError(ERROR_INVALID_PARAMETER
);
3061 else if (InfFileName
&& InterfaceClassGuid
)
3062 SetLastError(ERROR_INVALID_PARAMETER
);
3063 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3065 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3066 SetLastError(ERROR_INVALID_FLAGS
);
3068 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3069 SetLastError(ERROR_INVALID_PARAMETER
);
3070 else if (Reserved1
!= NULL
)
3071 SetLastError(ERROR_INVALID_PARAMETER
);
3072 else if (Reserved2
!= NULL
)
3073 SetLastError(ERROR_INVALID_PARAMETER
);
3076 WCHAR SectionName
[MAX_PATH
];
3077 HINF hInf
= INVALID_HANDLE_VALUE
;
3078 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3079 PVOID callback_context
= NULL
;
3081 if (InterfaceClassGuid
)
3083 /* Retrieve the actual section name */
3084 ret
= SetupDiGetActualSectionToInstallW(hInf
,
3093 FIXME("Installing an interface is not implemented\n");
3097 if (Flags
& DI_NOVCP
)
3098 FIXME("FileQueue argument ignored\n");
3099 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3100 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3102 /* Open the .inf file */
3103 hInf
= SetupOpenInfFileW(
3108 if (hInf
== INVALID_HANDLE_VALUE
)
3111 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3112 hClassKey
= CreateClassKey(hInf
);
3113 if (hClassKey
== INVALID_HANDLE_VALUE
)
3116 /* Try to append a layout file */
3117 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3121 /* Retrieve the actual section name */
3122 ret
= SetupDiGetActualSectionToInstallW(
3132 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3133 if (!callback_context
)
3136 ret
= SetupInstallFromInfSectionW(
3140 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3142 NULL
, /* SourceRootPath */
3144 SetupDefaultQueueCallbackW
,
3151 /* FIXME: Install .Services section */
3157 if (hInf
!= INVALID_HANDLE_VALUE
)
3158 SetupCloseInfFile(hInf
);
3159 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3160 RegCloseKey(hClassKey
);
3161 SetupTermDefaultQueueCallback(callback_context
);
3164 TRACE("Returning %d\n", ret
);
3169 /***********************************************************************
3170 * SetupDiOpenClassRegKey (SETUPAPI.@)
3172 HKEY WINAPI
SetupDiOpenClassRegKey(
3173 const GUID
* ClassGuid
,
3176 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3177 DIOCR_INSTALLER
, NULL
, NULL
);
3181 /***********************************************************************
3182 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3184 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3185 const GUID
* ClassGuid OPTIONAL
,
3188 PCSTR MachineName OPTIONAL
,
3191 PWSTR MachineNameW
= NULL
;
3198 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3199 if (MachineNameW
== NULL
)
3200 return INVALID_HANDLE_VALUE
;
3203 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3204 Flags
, MachineNameW
, Reserved
);
3207 MyFree(MachineNameW
);
3213 /***********************************************************************
3214 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3216 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3217 const GUID
* ClassGuid OPTIONAL
,
3220 PCWSTR MachineName OPTIONAL
,
3223 LPWSTR lpGuidString
;
3224 LPWSTR lpFullGuidString
;
3232 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3233 Flags
, debugstr_w(MachineName
), Reserved
);
3235 if (Flags
== DIOCR_INSTALLER
)
3237 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3239 else if (Flags
== DIOCR_INTERFACE
)
3241 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3245 ERR("Invalid Flags parameter!\n");
3246 SetLastError(ERROR_INVALID_FLAGS
);
3247 return INVALID_HANDLE_VALUE
;
3250 if (MachineName
!= NULL
)
3252 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3253 if (rc
!= ERROR_SUCCESS
)
3256 return INVALID_HANDLE_VALUE
;
3260 HKLM
= HKEY_LOCAL_MACHINE
;
3262 rc
= RegOpenKeyExW(HKLM
,
3265 ClassGuid
? 0 : samDesired
,
3267 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3268 if (rc
!= ERROR_SUCCESS
)
3271 return INVALID_HANDLE_VALUE
;
3274 if (ClassGuid
== NULL
)
3277 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)