2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 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
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR AddInterface
[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0};
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 Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotHW
[] = {'.','H','W',0};
35 static const WCHAR DotInterfaces
[] = {'.','I','n','t','e','r','f','a','c','e','s',0};
36 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
37 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
38 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
39 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
40 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
43 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
44 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
45 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
46 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
48 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
49 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
50 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
53 (CALLBACK
* CLASS_INSTALL_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
58 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
59 IN HDEVINFO DeviceInfoSet
,
60 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
62 (CALLBACK
* COINSTALLER_PROC
) (
63 IN DI_FUNCTION InstallFunction
,
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
68 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
69 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
70 IN LPFNADDPROPSHEETPAGE fAddFunc
,
73 (*UPDATE_CLASS_PARAM_HANDLER
) (
74 IN HDEVINFO DeviceInfoSet
,
75 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
76 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
77 IN DWORD ClassInstallParamsSize
);
79 struct CoInstallerElement
84 COINSTALLER_PROC Function
;
85 BOOL DoPostProcessing
;
90 PropertyChangeHandler(
91 IN HDEVINFO DeviceInfoSet
,
92 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
93 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
94 IN DWORD ClassInstallParamsSize
);
96 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
97 NULL
, /* DIF_SELECTDEVICE */
98 NULL
, /* DIF_INSTALLDEVICE */
99 NULL
, /* DIF_ASSIGNRESOURCES */
100 NULL
, /* DIF_PROPERTIES */
101 NULL
, /* DIF_REMOVE */
102 NULL
, /* DIF_FIRSTTIMESETUP */
103 NULL
, /* DIF_FOUNDDEVICE */
104 NULL
, /* DIF_SELECTCLASSDRIVERS */
105 NULL
, /* DIF_VALIDATECLASSDRIVERS */
106 NULL
, /* DIF_INSTALLCLASSDRIVERS */
107 NULL
, /* DIF_CALCDISKSPACE */
108 NULL
, /* DIF_DESTROYPRIVATEDATA */
109 NULL
, /* DIF_VALIDATEDRIVER */
110 NULL
, /* DIF_MOVEDEVICE */
111 NULL
, /* DIF_DETECT */
112 NULL
, /* DIF_INSTALLWIZARD */
113 NULL
, /* DIF_DESTROYWIZARDDATA */
114 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
115 NULL
, /* DIF_ENABLECLASS */
116 NULL
, /* DIF_DETECTVERIFY */
117 NULL
, /* DIF_INSTALLDEVICEFILES */
118 NULL
, /* DIF_UNREMOVE */
119 NULL
, /* DIF_SELECTBESTCOMPATDRV */
120 NULL
, /* DIF_ALLOW_INSTALL */
121 NULL
, /* DIF_REGISTERDEVICE */
122 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
123 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
124 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
125 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
126 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
127 NULL
, /* DIF_UNUSED1 */
128 NULL
, /* DIF_INSTALLINTERFACES */
129 NULL
, /* DIF_DETECTCANCEL */
130 NULL
, /* DIF_REGISTER_COINSTALLERS */
131 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
132 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
133 NULL
, /* DIF_RESERVED1 */
134 NULL
, /* DIF_TROUBLESHOOTER */
135 NULL
, /* DIF_POWERMESSAGEWAKE */
136 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
137 NULL
, /* DIF_UPDATEDRIVER_UI */
138 NULL
/* DIF_RESERVED2 */
141 /***********************************************************************
142 * SetupDiBuildClassInfoList (SETUPAPI.@)
144 BOOL WINAPI
SetupDiBuildClassInfoList(
146 LPGUID ClassGuidList
,
147 DWORD ClassGuidListSize
,
151 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
152 ClassGuidListSize
, RequiredSize
,
156 /***********************************************************************
157 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
159 BOOL WINAPI
SetupDiBuildClassInfoListExA(
161 LPGUID ClassGuidList
,
162 DWORD ClassGuidListSize
,
167 LPWSTR MachineNameW
= NULL
;
174 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
175 if (MachineNameW
== NULL
) return FALSE
;
178 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
179 ClassGuidListSize
, RequiredSize
,
180 MachineNameW
, Reserved
);
183 MyFree(MachineNameW
);
188 /***********************************************************************
189 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
191 BOOL WINAPI
SetupDiBuildClassInfoListExW(
193 LPGUID ClassGuidList
,
194 DWORD ClassGuidListSize
,
199 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
205 DWORD dwGuidListIndex
= 0;
207 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
208 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
210 if (RequiredSize
!= NULL
)
213 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
214 KEY_ENUMERATE_SUB_KEYS
,
218 if (hClassesKey
== INVALID_HANDLE_VALUE
)
223 for (dwIndex
= 0; ; dwIndex
++)
225 dwLength
= MAX_GUID_STRING_LEN
+ 1;
226 lError
= RegEnumKeyExW(hClassesKey
,
234 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
235 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
237 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
239 if (RegOpenKeyExW(hClassesKey
,
245 RegCloseKey(hClassesKey
);
249 if (!RegQueryValueExW(hClassKey
,
250 REGSTR_VAL_NOUSECLASS
,
256 TRACE("'NoUseClass' value found!\n");
257 RegCloseKey(hClassKey
);
261 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
262 (!RegQueryValueExW(hClassKey
,
263 REGSTR_VAL_NOINSTALLCLASS
,
269 TRACE("'NoInstallClass' value found!\n");
270 RegCloseKey(hClassKey
);
274 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
275 (!RegQueryValueExW(hClassKey
,
276 REGSTR_VAL_NODISPLAYCLASS
,
282 TRACE("'NoDisplayClass' value found!\n");
283 RegCloseKey(hClassKey
);
287 RegCloseKey(hClassKey
);
289 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
290 if (dwGuidListIndex
< ClassGuidListSize
)
292 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
296 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
298 UuidFromStringW(&szKeyName
[1],
299 &ClassGuidList
[dwGuidListIndex
]);
305 if (lError
!= ERROR_SUCCESS
)
309 RegCloseKey(hClassesKey
);
311 if (RequiredSize
!= NULL
)
312 *RequiredSize
= dwGuidListIndex
;
314 if (ClassGuidListSize
< dwGuidListIndex
)
316 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
323 /***********************************************************************
324 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
326 BOOL WINAPI
SetupDiClassGuidsFromNameA(
328 LPGUID ClassGuidList
,
329 DWORD ClassGuidListSize
,
332 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
333 ClassGuidListSize
, RequiredSize
,
337 /***********************************************************************
338 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
340 BOOL WINAPI
SetupDiClassGuidsFromNameW(
342 LPGUID ClassGuidList
,
343 DWORD ClassGuidListSize
,
346 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
347 ClassGuidListSize
, RequiredSize
,
351 /***********************************************************************
352 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
354 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
356 LPGUID ClassGuidList
,
357 DWORD ClassGuidListSize
,
362 LPWSTR ClassNameW
= NULL
;
363 LPWSTR MachineNameW
= NULL
;
368 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
369 if (ClassNameW
== NULL
)
374 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
375 if (MachineNameW
== NULL
)
382 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
383 ClassGuidListSize
, RequiredSize
,
384 MachineNameW
, Reserved
);
387 MyFree(MachineNameW
);
394 /***********************************************************************
395 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
397 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
399 LPGUID ClassGuidList
,
400 DWORD ClassGuidListSize
,
405 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
406 WCHAR szClassName
[256];
412 DWORD dwGuidListIndex
= 0;
414 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
415 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
417 if (RequiredSize
!= NULL
)
420 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
421 KEY_ENUMERATE_SUB_KEYS
,
425 if (hClassesKey
== INVALID_HANDLE_VALUE
)
430 for (dwIndex
= 0; ; dwIndex
++)
432 dwLength
= MAX_GUID_STRING_LEN
+ 1;
433 lError
= RegEnumKeyExW(hClassesKey
,
441 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
442 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
444 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
446 if (RegOpenKeyExW(hClassesKey
,
452 RegCloseKey(hClassesKey
);
456 dwLength
= 256 * sizeof(WCHAR
);
457 if (!RegQueryValueExW(hClassKey
,
464 TRACE("Class name: %s\n", debugstr_w(szClassName
));
466 if (strcmpiW(szClassName
, ClassName
) == 0)
468 TRACE("Found matching class name\n");
470 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
471 if (dwGuidListIndex
< ClassGuidListSize
)
473 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
477 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
479 UuidFromStringW(&szKeyName
[1],
480 &ClassGuidList
[dwGuidListIndex
]);
487 RegCloseKey(hClassKey
);
490 if (lError
!= ERROR_SUCCESS
)
494 RegCloseKey(hClassesKey
);
496 if (RequiredSize
!= NULL
)
497 *RequiredSize
= dwGuidListIndex
;
499 if (ClassGuidListSize
< dwGuidListIndex
)
501 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
508 /***********************************************************************
509 * SetupDiClassNameFromGuidA (SETUPAPI.@)
511 BOOL WINAPI
SetupDiClassNameFromGuidA(
512 const GUID
* ClassGuid
,
517 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
518 ClassNameSize
, RequiredSize
,
522 /***********************************************************************
523 * SetupDiClassNameFromGuidW (SETUPAPI.@)
525 BOOL WINAPI
SetupDiClassNameFromGuidW(
526 const GUID
* ClassGuid
,
531 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
532 ClassNameSize
, RequiredSize
,
536 /***********************************************************************
537 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
539 BOOL WINAPI
SetupDiClassNameFromGuidExA(
540 const GUID
* ClassGuid
,
547 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
548 LPWSTR MachineNameW
= NULL
;
552 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
553 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
554 NULL
, MachineNameW
, Reserved
);
557 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
558 ClassNameSize
, NULL
, NULL
);
560 if (!ClassNameSize
&& RequiredSize
)
563 MyFree(MachineNameW
);
567 /***********************************************************************
568 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
570 BOOL WINAPI
SetupDiClassNameFromGuidExW(
571 const GUID
* ClassGuid
,
582 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
583 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
585 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
590 if (hKey
== INVALID_HANDLE_VALUE
)
595 if (RequiredSize
!= NULL
)
598 rc
= RegQueryValueExW(hKey
,
604 if (rc
!= ERROR_SUCCESS
)
611 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
614 dwLength
= ClassNameSize
* sizeof(WCHAR
);
615 rc
= RegQueryValueExW(hKey
,
621 if (rc
!= ERROR_SUCCESS
)
633 /***********************************************************************
634 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
637 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
640 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
643 /***********************************************************************
644 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
647 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
652 LPWSTR MachineNameW
= NULL
;
655 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
656 debugstr_a(MachineName
), Reserved
);
660 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
661 if (MachineNameW
== NULL
)
662 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
665 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
666 MachineNameW
, Reserved
);
669 MyFree(MachineNameW
);
675 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
679 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
680 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
681 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
682 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
683 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
684 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
685 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
686 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
687 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
688 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
689 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
690 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
691 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
692 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
693 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
694 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
695 case CR_SUCCESS
: return ERROR_SUCCESS
;
696 default: return ERROR_GEN_FAILURE
;
699 /* Does not happen */
702 /***********************************************************************
703 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
706 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
711 struct DeviceInfoSet
*list
;
712 LPWSTR UNCServerName
= NULL
;
716 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
718 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
719 debugstr_w(MachineName
), Reserved
);
721 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
723 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
724 list
= HeapAlloc(GetProcessHeap(), 0, size
);
727 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
730 memset(list
, 0, sizeof(struct DeviceInfoSet
));
732 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
735 ClassGuid
? ClassGuid
: &GUID_NULL
,
736 sizeof(list
->ClassGuid
));
737 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
738 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
739 list
->InstallParams
.hwndParent
= hwndParent
;
742 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
743 if (rc
!= ERROR_SUCCESS
)
748 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
751 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
755 strcpyW(UNCServerName
+ 2, MachineName
);
756 list
->szData
[0] = list
->szData
[1] = '\\';
757 strcpyW(list
->szData
+ 2, MachineName
);
758 list
->MachineName
= list
->szData
;
762 DWORD Size
= MAX_PATH
;
763 list
->HKLM
= HKEY_LOCAL_MACHINE
;
764 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
767 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
770 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
772 list
->MachineName
= NULL
;
775 UNCServerName
[0] = UNCServerName
[1] = '\\';
776 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
777 if (cr
!= CR_SUCCESS
)
779 SetLastError(GetErrorCodeFromCrCode(cr
));
783 InitializeListHead(&list
->DriverListHead
);
784 InitializeListHead(&list
->ListHead
);
786 ret
= (HDEVINFO
)list
;
789 if (ret
== INVALID_HANDLE_VALUE
)
793 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
794 RegCloseKey(list
->HKLM
);
796 HeapFree(GetProcessHeap(), 0, list
);
799 HeapFree(GetProcessHeap(), 0, UNCServerName
);
803 /***********************************************************************
804 * SetupDiEnumDeviceInfo (SETUPAPI.@)
806 BOOL WINAPI
SetupDiEnumDeviceInfo(
807 HDEVINFO DeviceInfoSet
,
809 PSP_DEVINFO_DATA DeviceInfoData
)
813 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
815 SetLastError(ERROR_INVALID_PARAMETER
);
816 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
818 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
820 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
821 SetLastError(ERROR_INVALID_HANDLE
);
822 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
823 SetLastError(ERROR_INVALID_USER_BUFFER
);
826 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
827 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
828 ItemList
= ItemList
->Flink
;
829 if (ItemList
== &list
->ListHead
)
830 SetLastError(ERROR_NO_MORE_ITEMS
);
833 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
834 memcpy(&DeviceInfoData
->ClassGuid
,
837 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
838 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
844 SetLastError(ERROR_INVALID_HANDLE
);
848 /***********************************************************************
849 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
852 SetupDiGetActualSectionToInstallA(
854 IN PCSTR InfSectionName
,
855 OUT PSTR InfSectionWithExt OPTIONAL
,
856 IN DWORD InfSectionWithExtSize
,
857 OUT PDWORD RequiredSize OPTIONAL
,
858 OUT PSTR
*Extension OPTIONAL
)
860 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
861 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
865 /***********************************************************************
866 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
869 SetupDiGetActualSectionToInstallW(
871 IN PCWSTR InfSectionName
,
872 OUT PWSTR InfSectionWithExt OPTIONAL
,
873 IN DWORD InfSectionWithExtSize
,
874 OUT PDWORD RequiredSize OPTIONAL
,
875 OUT PWSTR
*Extension OPTIONAL
)
877 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
878 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
882 /***********************************************************************
883 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
886 SetupDiGetActualSectionToInstallExA(
888 IN PCSTR InfSectionName
,
889 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
890 OUT PSTR InfSectionWithExt OPTIONAL
,
891 IN DWORD InfSectionWithExtSize
,
892 OUT PDWORD RequiredSize OPTIONAL
,
893 OUT PSTR
* Extension OPTIONAL
,
896 LPWSTR InfSectionNameW
= NULL
;
897 LPWSTR InfSectionWithExtW
= NULL
;
899 BOOL bResult
= FALSE
;
905 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
906 if (InfSectionNameW
== NULL
)
909 if (InfSectionWithExt
)
911 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
912 if (InfSectionWithExtW
== NULL
)
916 bResult
= SetupDiGetActualSectionToInstallExW(
917 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
918 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
919 InfSectionWithExtSize
,
921 Extension
? &ExtensionW
: NULL
,
924 if (bResult
&& InfSectionWithExt
)
926 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
927 InfSectionWithExtSize
, NULL
, NULL
) != 0;
929 if (bResult
&& Extension
)
931 if (ExtensionW
== NULL
)
934 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
938 MyFree(InfSectionNameW
);
939 MyFree(InfSectionWithExtW
);
944 /***********************************************************************
945 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
948 SetupDiGetActualSectionToInstallExW(
950 IN PCWSTR InfSectionName
,
951 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
952 OUT PWSTR InfSectionWithExt OPTIONAL
,
953 IN DWORD InfSectionWithExtSize
,
954 OUT PDWORD RequiredSize OPTIONAL
,
955 OUT PWSTR
* Extension OPTIONAL
,
960 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
961 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
962 RequiredSize
, Extension
, Reserved
);
964 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
965 SetLastError(ERROR_INVALID_HANDLE
);
966 else if (!InfSectionName
)
967 SetLastError(ERROR_INVALID_PARAMETER
);
968 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
969 SetLastError(ERROR_INVALID_USER_BUFFER
);
970 else if (Reserved
!= NULL
)
971 SetLastError(ERROR_INVALID_PARAMETER
);
974 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
975 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
976 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
977 WCHAR SectionName
[LINE_LEN
+ 1];
978 LONG lLineCount
= -1;
981 /* Fill platform info if needed */
982 if (AlternatePlatformInfo
)
983 pPlatformInfo
= AlternatePlatformInfo
;
984 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
986 /* That's the first time we go here. We need to fill in the structure */
987 OSVERSIONINFO VersionInfo
;
988 SYSTEM_INFO SystemInfo
;
989 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
990 ret
= GetVersionEx(&VersionInfo
);
993 GetSystemInfo(&SystemInfo
);
994 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
995 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
996 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
997 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
998 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
999 CurrentPlatform
.Reserved
= 0;
1002 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
1003 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
1004 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
1006 static const WCHAR ExtensionArchitectureNone
[] = {0};
1007 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
1008 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
1009 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
1010 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
1011 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
1012 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
1014 /* Set various extensions values */
1015 switch (pPlatformInfo
->Platform
)
1017 case VER_PLATFORM_WIN32_WINDOWS
:
1018 pExtensionPlatform
= ExtensionPlatformWindows
;
1020 case VER_PLATFORM_WIN32_NT
:
1021 pExtensionPlatform
= ExtensionPlatformNT
;
1024 ERR("Unkown platform 0x%lx\n", pPlatformInfo
->Platform
);
1025 pExtensionPlatform
= ExtensionPlatformNone
;
1028 switch (pPlatformInfo
->ProcessorArchitecture
)
1030 case PROCESSOR_ARCHITECTURE_ALPHA
:
1031 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1033 case PROCESSOR_ARCHITECTURE_AMD64
:
1034 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1036 case PROCESSOR_ARCHITECTURE_IA64
:
1037 pExtensionArchitecture
= ExtensionArchitectureia64
;
1039 case PROCESSOR_ARCHITECTURE_INTEL
:
1040 pExtensionArchitecture
= ExtensionArchitecturex86
;
1042 case PROCESSOR_ARCHITECTURE_MIPS
:
1043 pExtensionArchitecture
= ExtensionArchitecturemips
;
1045 case PROCESSOR_ARCHITECTURE_PPC
:
1046 pExtensionArchitecture
= ExtensionArchitectureppc
;
1049 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1050 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1051 pExtensionArchitecture
= ExtensionArchitectureNone
;
1055 static const WCHAR FormatPlatformArchitectureMajorMinor
[] = {'%','s','%','s','%','s','.','%','l','u','.','%','l','u',0};
1056 static const WCHAR FormatPlatformMajorMinor
[] = {'%','s','%','s','.','%','l','u','.','%','l','u',0};
1057 static const WCHAR FormatPlatformArchitectureMajor
[] = {'%','s','%','s','%','s','.','%','l','u',0};
1058 static const WCHAR FormatPlatformMajor
[] = {'%','s','%','s','.','%','l','u',0};
1059 static const WCHAR FormatPlatformArchitecture
[] = {'%','s','%','s','%','s',0};
1060 static const WCHAR FormatPlatform
[] = {'%','s','%','s',0};
1061 static const WCHAR FormatNone
[] = {'%','s',0};
1063 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1065 /* Test with platform.architecture.major.minor extension */
1066 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajorMinor
, InfSectionName
,
1067 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1068 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1069 if (lLineCount
!= -1) goto sectionfound
;
1071 /* Test with platform.major.minor extension */
1072 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajorMinor
, InfSectionName
,
1073 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1074 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1075 if (lLineCount
!= -1) goto sectionfound
;
1077 /* Test with platform.architecture.major extension */
1078 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajor
, InfSectionName
,
1079 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1080 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1081 if (lLineCount
!= -1) goto sectionfound
;
1083 /* Test with platform.major extension */
1084 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajor
, InfSectionName
,
1085 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1086 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1087 if (lLineCount
!= -1) goto sectionfound
;
1089 /* Test with platform.architecture extension */
1090 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitecture
, InfSectionName
,
1091 pExtensionPlatform
, pExtensionArchitecture
);
1092 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1093 if (lLineCount
!= -1) goto sectionfound
;
1095 /* Test with platform extension */
1096 snprintfW(SectionName
, LINE_LEN
, FormatPlatform
, InfSectionName
,
1097 pExtensionPlatform
);
1098 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1099 if (lLineCount
!= -1) goto sectionfound
;
1101 /* Test without extension */
1102 snprintfW(SectionName
, LINE_LEN
, FormatNone
, InfSectionName
);
1103 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1104 if (lLineCount
!= -1) goto sectionfound
;
1106 /* No appropriate section found */
1107 SetLastError(ERROR_INVALID_PARAMETER
);
1111 dwFullLength
= lstrlenW(SectionName
);
1112 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1114 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1116 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1120 lstrcpyW(InfSectionWithExt
, SectionName
);
1121 if (Extension
!= NULL
)
1123 DWORD dwLength
= lstrlenW(SectionName
);
1124 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1128 if (RequiredSize
!= NULL
)
1129 *RequiredSize
= dwFullLength
+ 1;
1135 TRACE("Returning %d\n", ret
);
1140 /***********************************************************************
1141 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1143 BOOL WINAPI
SetupDiGetClassDescriptionA(
1144 const GUID
* ClassGuid
,
1145 PSTR ClassDescription
,
1146 DWORD ClassDescriptionSize
,
1147 PDWORD RequiredSize
)
1149 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1150 ClassDescriptionSize
,
1151 RequiredSize
, NULL
, NULL
);
1154 /***********************************************************************
1155 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1157 BOOL WINAPI
SetupDiGetClassDescriptionW(
1158 const GUID
* ClassGuid
,
1159 PWSTR ClassDescription
,
1160 DWORD ClassDescriptionSize
,
1161 PDWORD RequiredSize
)
1163 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1164 ClassDescriptionSize
,
1165 RequiredSize
, NULL
, NULL
);
1168 /***********************************************************************
1169 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1171 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1172 const GUID
* ClassGuid
,
1173 PSTR ClassDescription
,
1174 DWORD ClassDescriptionSize
,
1175 PDWORD RequiredSize
,
1179 PWCHAR ClassDescriptionW
;
1180 LPWSTR MachineNameW
= NULL
;
1184 if (ClassDescriptionSize
> 0)
1186 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1187 if (!ClassDescriptionW
)
1189 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1195 ClassDescriptionW
= NULL
;
1199 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1202 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1208 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1209 NULL
, MachineNameW
, Reserved
);
1212 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1213 ClassDescriptionSize
, NULL
, NULL
);
1215 if (!ClassDescriptionSize
&& RequiredSize
)
1216 *RequiredSize
= len
;
1220 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1221 MyFree(MachineNameW
);
1225 /***********************************************************************
1226 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1228 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1229 const GUID
* ClassGuid
,
1230 PWSTR ClassDescription
,
1231 DWORD ClassDescriptionSize
,
1232 PDWORD RequiredSize
,
1239 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1240 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1242 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1247 if (hKey
== INVALID_HANDLE_VALUE
)
1249 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1253 if (RequiredSize
!= NULL
)
1256 if (RegQueryValueExW(hKey
,
1267 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1270 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1271 if (RegQueryValueExW(hKey
,
1275 (LPBYTE
)ClassDescription
,
1287 /***********************************************************************
1288 * SetupDiGetClassDevsA (SETUPAPI.@)
1290 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1296 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1297 flags
, NULL
, NULL
, NULL
);
1300 /***********************************************************************
1301 * SetupDiGetClassDevsW (SETUPAPI.@)
1303 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1309 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1310 flags
, NULL
, NULL
, NULL
);
1313 /***********************************************************************
1314 * SetupDiGetClassDevsExA (SETUPAPI.@)
1316 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1326 LPWSTR enumstrW
= NULL
;
1327 LPWSTR machineW
= NULL
;
1331 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1332 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1335 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1338 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1342 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1343 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1346 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1349 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1351 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1354 HeapFree(GetProcessHeap(), 0, enumstrW
);
1355 HeapFree(GetProcessHeap(), 0, machineW
);
1360 CreateDeviceInfoElement(
1361 IN
struct DeviceInfoSet
*list
,
1362 IN LPCWSTR InstancePath
,
1363 IN LPCGUID pClassGuid
,
1364 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1368 struct DeviceInfoElement
*deviceInfo
;
1370 *pDeviceInfo
= NULL
;
1372 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
1373 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1376 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1379 memset(deviceInfo
, 0, size
);
1381 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1382 if (cr
!= CR_SUCCESS
)
1384 SetLastError(GetErrorCodeFromCrCode(cr
));
1388 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1389 strcpyW(deviceInfo
->Data
, InstancePath
);
1390 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1391 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
1392 deviceInfo
->DeviceDescription
= NULL
;
1393 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1394 deviceInfo
->CreationFlags
= 0;
1395 InitializeListHead(&deviceInfo
->DriverListHead
);
1396 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1398 *pDeviceInfo
= deviceInfo
;
1403 CreateDeviceInterface(
1404 IN
struct DeviceInfoElement
* deviceInfo
,
1405 IN LPCWSTR SymbolicLink
,
1406 IN LPCGUID pInterfaceGuid
,
1407 OUT
struct DeviceInterface
**pDeviceInterface
)
1409 struct DeviceInterface
*deviceInterface
;
1411 *pDeviceInterface
= NULL
;
1413 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1414 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (strlenW(SymbolicLink
) + 1) * sizeof(WCHAR
));
1415 if (!deviceInterface
)
1417 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1420 deviceInterface
->DeviceInfo
= deviceInfo
;
1421 strcpyW(deviceInterface
->SymbolicLink
, SymbolicLink
);
1422 deviceInterface
->Flags
= 0; /* Flags will be updated later */
1423 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1425 *pDeviceInterface
= deviceInterface
;
1429 static LONG
SETUP_CreateDevListFromEnumerator(
1430 struct DeviceInfoSet
*list
,
1431 LPCGUID pClassGuid OPTIONAL
,
1433 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1435 HKEY hDeviceIdKey
, hInstanceIdKey
;
1436 WCHAR KeyBuffer
[MAX_PATH
];
1437 WCHAR InstancePath
[MAX_PATH
];
1438 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1439 struct DeviceInfoElement
*deviceInfo
;
1441 DWORD dwLength
, dwRegType
;
1444 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1447 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1448 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1449 if (rc
== ERROR_NO_MORE_ITEMS
)
1451 if (rc
!= ERROR_SUCCESS
)
1455 /* Open device id sub key */
1456 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1457 if (rc
!= ERROR_SUCCESS
)
1459 strcpyW(InstancePath
, Enumerator
);
1460 strcatW(InstancePath
, L
"\\");
1461 strcatW(InstancePath
, KeyBuffer
);
1462 strcatW(InstancePath
, L
"\\");
1463 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
1465 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1471 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1472 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1473 if (rc
== ERROR_NO_MORE_ITEMS
)
1475 if (rc
!= ERROR_SUCCESS
)
1477 RegCloseKey(hDeviceIdKey
);
1482 /* Open instance id sub key */
1483 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1484 if (rc
!= ERROR_SUCCESS
)
1486 RegCloseKey(hDeviceIdKey
);
1489 *pEndOfInstancePath
= '\0';
1490 strcatW(InstancePath
, KeyBuffer
);
1492 /* Read ClassGUID value */
1493 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1494 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1495 RegCloseKey(hInstanceIdKey
);
1496 if (rc
== ERROR_FILE_NOT_FOUND
)
1499 /* Skip this bad entry as we can't verify it */
1501 /* Set a default GUID for this device */
1502 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1504 else if (rc
!= ERROR_SUCCESS
)
1506 RegCloseKey(hDeviceIdKey
);
1509 else if (dwRegType
!= REG_SZ
)
1511 RegCloseKey(hDeviceIdKey
);
1512 return ERROR_GEN_FAILURE
;
1516 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1517 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1518 /* Bad GUID, skip the entry */
1522 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1524 /* Skip this entry as it is not the right device class */
1528 /* Add the entry to the list */
1529 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1531 RegCloseKey(hDeviceIdKey
);
1532 return GetLastError();
1534 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
1535 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1537 RegCloseKey(hDeviceIdKey
);
1540 return ERROR_SUCCESS
;
1543 static LONG
SETUP_CreateDevList(
1544 struct DeviceInfoSet
*list
,
1545 PCWSTR MachineName OPTIONAL
,
1546 LPGUID
class OPTIONAL
,
1547 PCWSTR Enumerator OPTIONAL
)
1549 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1550 WCHAR KeyBuffer
[MAX_PATH
];
1555 if (class && IsEqualIID(class, &GUID_NULL
))
1559 if (MachineName
!= NULL
)
1561 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1562 if (rc
!= ERROR_SUCCESS
)
1566 HKLM
= HKEY_LOCAL_MACHINE
;
1568 rc
= RegOpenKeyExW(HKLM
,
1569 REGSTR_PATH_SYSTEMENUM
,
1571 KEY_ENUMERATE_SUB_KEYS
,
1573 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1574 if (rc
!= ERROR_SUCCESS
)
1577 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1578 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1587 KEY_ENUMERATE_SUB_KEYS
,
1589 RegCloseKey(hEnumKey
);
1590 if (rc
!= ERROR_SUCCESS
)
1592 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1593 RegCloseKey(hEnumeratorKey
);
1598 /* Enumerate enumerators */
1602 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1603 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1604 if (rc
== ERROR_NO_MORE_ITEMS
)
1606 if (rc
!= ERROR_SUCCESS
)
1608 RegCloseKey(hEnumKey
);
1614 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1615 if (rc
!= ERROR_SUCCESS
)
1617 RegCloseKey(hEnumKey
);
1621 /* Call SETUP_CreateDevListFromEnumerator */
1622 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1623 RegCloseKey(hEnumeratorKey
);
1624 if (rc
!= ERROR_SUCCESS
)
1626 RegCloseKey(hEnumKey
);
1630 RegCloseKey(hEnumKey
);
1631 return ERROR_SUCCESS
;
1635 static BOOL
DestroyDeviceInterface(struct DeviceInterface
* deviceInterface
)
1637 HeapFree(GetProcessHeap(), 0, deviceInterface
);
1641 static LONG
SETUP_CreateInterfaceList(
1642 struct DeviceInfoSet
*list
,
1644 LPGUID InterfaceGuid
,
1645 PCWSTR DeviceInstanceW
/* OPTIONAL */,
1646 BOOL OnlyPresentInterfaces
1649 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1650 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1651 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1652 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1653 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1654 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1656 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1657 PWSTR pSymbolicLink
= NULL
;
1658 PWSTR InstancePath
= NULL
;
1660 DWORD dwLength
, dwInstancePathLength
;
1664 struct DeviceInfoElement
*deviceInfo
;
1666 hInterfaceKey
= INVALID_HANDLE_VALUE
;
1667 hDeviceInstanceKey
= NULL
;
1668 hReferenceKey
= NULL
;
1670 /* Open registry key related to this interface */
1671 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1672 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1674 rc
= GetLastError();
1678 /* Enumerate sub keys of hInterfaceKey */
1682 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1683 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1684 if (rc
== ERROR_NO_MORE_ITEMS
)
1686 if (rc
!= ERROR_SUCCESS
)
1691 if (hDeviceInstanceKey
!= NULL
)
1692 RegCloseKey(hDeviceInstanceKey
);
1693 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1694 if (rc
!= ERROR_SUCCESS
)
1697 /* Read DeviceInstance */
1698 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1699 if (rc
!= ERROR_SUCCESS
)
1701 if (dwRegType
!= REG_SZ
)
1703 rc
= ERROR_GEN_FAILURE
;
1706 if (InstancePath
!= NULL
)
1707 HeapFree(GetProcessHeap(), 0, InstancePath
);
1708 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1711 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1714 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1715 if (rc
!= ERROR_SUCCESS
)
1717 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1718 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1720 if (DeviceInstanceW
)
1722 /* Check if device enumerator is not the right one */
1723 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1727 /* Find class GUID associated to the device instance */
1730 REGSTR_PATH_SYSTEMENUM
,
1734 if (rc
!= ERROR_SUCCESS
)
1742 RegCloseKey(hEnumKey
);
1743 if (rc
!= ERROR_SUCCESS
)
1745 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1746 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1748 if (rc
!= ERROR_SUCCESS
)
1750 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1751 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1752 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1754 rc
= ERROR_GEN_FAILURE
;
1757 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1759 /* If current device doesn't match the list GUID (if any), skip this entry */
1760 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1763 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1767 struct DeviceInterface
*interfaceInfo
;
1769 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1770 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1771 if (rc
== ERROR_NO_MORE_ITEMS
)
1773 if (rc
!= ERROR_SUCCESS
)
1776 if (KeyBuffer
[0] != '#')
1777 /* This entry doesn't represent an interesting entry */
1781 if (hReferenceKey
!= NULL
)
1782 RegCloseKey(hReferenceKey
);
1783 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1784 if (rc
!= ERROR_SUCCESS
)
1787 /* Read SymbolicLink value */
1788 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1789 if (rc
!= ERROR_SUCCESS
)
1791 if (dwRegType
!= REG_SZ
)
1793 rc
= ERROR_GEN_FAILURE
;
1797 /* We have found a device */
1798 /* Step 1. Create a device info element */
1799 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1801 rc
= GetLastError();
1804 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1805 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1807 /* Step 2. Create an interface list for this element */
1808 if (pSymbolicLink
!= NULL
)
1809 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1810 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1813 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1816 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1817 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1818 if (rc
!= ERROR_SUCCESS
)
1820 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1822 rc
= GetLastError();
1826 /* Step 3. Update flags */
1827 if (KeyBuffer
[1] == '\0')
1828 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1829 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1830 if (rc
!= ERROR_SUCCESS
)
1832 if (OnlyPresentInterfaces
)
1834 DestroyDeviceInterface(interfaceInfo
);
1838 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1842 dwLength
= sizeof(DWORD
);
1843 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1844 && dwRegType
== REG_DWORD
&& LinkedValue
)
1845 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1846 RegCloseKey(hControlKey
);
1849 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1850 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1856 if (hReferenceKey
!= NULL
)
1857 RegCloseKey(hReferenceKey
);
1858 if (hDeviceInstanceKey
!= NULL
)
1859 RegCloseKey(hDeviceInstanceKey
);
1860 if (hInterfaceKey
!= INVALID_HANDLE_VALUE
)
1861 RegCloseKey(hInterfaceKey
);
1862 if (InstancePath
!= NULL
)
1863 HeapFree(GetProcessHeap(), 0, InstancePath
);
1864 if (pSymbolicLink
!= NULL
)
1865 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1869 /***********************************************************************
1870 * SetupDiGetClassDevsExW (SETUPAPI.@)
1872 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1881 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1882 struct DeviceInfoSet
*list
;
1886 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1887 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1889 /* Create the deviceset if not set */
1892 list
= (struct DeviceInfoSet
*)deviceset
;
1893 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1895 SetLastError(ERROR_INVALID_HANDLE
);
1896 return INVALID_HANDLE_VALUE
;
1898 hDeviceInfo
= deviceset
;
1902 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1903 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1904 NULL
, machine
, NULL
);
1905 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1906 return INVALID_HANDLE_VALUE
;
1907 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1910 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1913 pClassGuid
= &list
->ClassGuid
;
1915 if (flags
& DIGCF_PROFILE
)
1916 FIXME(": flag DIGCF_PROFILE ignored\n");
1918 if (flags
& DIGCF_ALLCLASSES
)
1920 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1921 if (rc
!= ERROR_SUCCESS
)
1925 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1926 return INVALID_HANDLE_VALUE
;
1930 else if (flags
& DIGCF_DEVICEINTERFACE
)
1934 SetLastError(ERROR_INVALID_PARAMETER
);
1936 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1937 return INVALID_HANDLE_VALUE
;
1940 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
, flags
& DIGCF_PRESENT
);
1941 if (rc
!= ERROR_SUCCESS
)
1945 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1946 return INVALID_HANDLE_VALUE
;
1952 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1953 if (rc
!= ERROR_SUCCESS
)
1957 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1958 return INVALID_HANDLE_VALUE
;
1964 /***********************************************************************
1965 * SetupDiGetClassImageIndex (SETUPAPI.@)
1968 static BOOL
GetIconIndex(
1970 OUT PINT ImageIndex
)
1972 LPWSTR Buffer
= NULL
;
1973 DWORD dwRegType
, dwLength
;
1977 /* Read icon registry key */
1978 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1979 if (rc
!= ERROR_SUCCESS
)
1983 } else if (dwRegType
!= REG_SZ
)
1985 SetLastError(ERROR_INVALID_INDEX
);
1988 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1991 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1994 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1995 if (rc
!= ERROR_SUCCESS
)
2000 /* make sure the returned buffer is NULL-terminated */
2001 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2003 /* Transform icon value to a INT */
2004 *ImageIndex
= atoiW(Buffer
);
2012 BOOL WINAPI
SetupDiGetClassImageIndex(
2013 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2014 IN CONST GUID
*ClassGuid
,
2015 OUT PINT ImageIndex
)
2017 struct ClassImageList
*list
;
2020 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2022 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2023 SetLastError(ERROR_INVALID_PARAMETER
);
2024 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2025 SetLastError(ERROR_INVALID_USER_BUFFER
);
2026 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2027 SetLastError(ERROR_INVALID_USER_BUFFER
);
2028 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2029 SetLastError(ERROR_INVALID_USER_BUFFER
);
2030 else if (!ImageIndex
)
2031 SetLastError(ERROR_INVALID_PARAMETER
);
2034 HKEY hKey
= INVALID_HANDLE_VALUE
;
2037 /* Read Icon registry entry into Buffer */
2038 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2039 if (hKey
== INVALID_HANDLE_VALUE
)
2041 if (!GetIconIndex(hKey
, &iconIndex
))
2046 SetLastError(ERROR_INVALID_INDEX
);
2050 *ImageIndex
= -iconIndex
;
2054 if (hKey
!= INVALID_HANDLE_VALUE
)
2058 TRACE("Returning %d\n", ret
);
2062 /***********************************************************************
2063 * SetupDiGetClassImageList(SETUPAPI.@)
2065 BOOL WINAPI
SetupDiGetClassImageList(
2066 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2068 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2071 /***********************************************************************
2072 * SetupDiGetClassImageListExA(SETUPAPI.@)
2074 BOOL WINAPI
SetupDiGetClassImageListExA(
2075 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2076 IN PCSTR MachineName OPTIONAL
,
2079 PWSTR MachineNameW
= NULL
;
2084 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2085 if (MachineNameW
== NULL
)
2089 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2092 MyFree(MachineNameW
);
2097 /***********************************************************************
2098 * SetupDiGetClassImageListExW(SETUPAPI.@)
2100 BOOL WINAPI
SetupDiGetClassImageListExW(
2101 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2102 IN PCWSTR MachineName OPTIONAL
,
2107 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2109 if (!ClassImageListData
)
2110 SetLastError(ERROR_INVALID_PARAMETER
);
2111 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2112 SetLastError(ERROR_INVALID_USER_BUFFER
);
2114 SetLastError(ERROR_INVALID_PARAMETER
);
2117 struct ClassImageList
*list
= NULL
;
2120 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2122 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2123 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2126 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2129 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2132 list
->szData
[0] = list
->szData
[1] = '\\';
2133 strcpyW(list
->szData
+ 2, MachineName
);
2134 list
->MachineName
= list
->szData
;
2138 list
->MachineName
= NULL
;
2141 ClassImageListData
->Reserved
= (ULONG_PTR
)list
;
2149 TRACE("Returning %d\n", ret
);
2153 /***********************************************************************
2154 * SetupDiLoadClassIcon(SETUPAPI.@)
2156 BOOL WINAPI
SetupDiLoadClassIcon(
2157 IN CONST GUID
*ClassGuid
,
2158 OUT HICON
*LargeIcon OPTIONAL
,
2159 OUT PINT MiniIconIndex OPTIONAL
)
2164 SetLastError(ERROR_INVALID_PARAMETER
);
2167 LPWSTR Buffer
= NULL
;
2170 HKEY hKey
= INVALID_HANDLE_VALUE
;
2172 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2173 if (hKey
== INVALID_HANDLE_VALUE
)
2176 if (!GetIconIndex(hKey
, &iconIndex
))
2181 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2184 DWORD dwRegType
, dwLength
;
2185 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2186 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2188 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2191 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2194 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2195 if (rc
!= ERROR_SUCCESS
)
2200 /* make sure the returned buffer is NULL-terminated */
2201 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2204 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2205 && dwRegType
== REG_SZ
)
2207 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2210 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2213 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2214 if (rc
!= ERROR_SUCCESS
)
2219 /* make sure the returned buffer is NULL-terminated */
2220 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2224 /* Unable to find where to load the icon */
2225 SetLastError(ERROR_FILE_NOT_FOUND
);
2228 Comma
= strchrW(Buffer
, ',');
2231 SetLastError(ERROR_GEN_FAILURE
);
2239 /* Look up icon in setupapi.dll */
2240 DllName
= L
"setupapi.dll";
2241 iconIndex
= -iconIndex
;
2244 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2247 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2249 SetLastError(ERROR_INVALID_INDEX
);
2254 *MiniIconIndex
= iconIndex
;
2258 if (hKey
!= INVALID_HANDLE_VALUE
)
2263 TRACE("Returning %d\n", ret
);
2267 /***********************************************************************
2268 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2270 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2271 HDEVINFO DeviceInfoSet
,
2272 PSP_DEVINFO_DATA DeviceInfoData
,
2273 CONST GUID
* InterfaceClassGuid
,
2275 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2279 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2280 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2282 if (!DeviceInterfaceData
)
2283 SetLastError(ERROR_INVALID_PARAMETER
);
2284 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2285 SetLastError(ERROR_INVALID_USER_BUFFER
);
2286 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2288 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2290 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2292 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2294 while (ItemList
!= &list
->ListHead
&& !Found
)
2296 PLIST_ENTRY InterfaceListEntry
;
2297 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
2298 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2300 /* We are not searching for this element */
2301 ItemList
= ItemList
->Flink
;
2304 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2305 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2307 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2308 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2310 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2313 if (MemberIndex
-- == 0)
2315 /* return this item */
2316 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2317 &DevItf
->InterfaceClassGuid
,
2319 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2320 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2323 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2325 ItemList
= ItemList
->Flink
;
2328 SetLastError(ERROR_NO_MORE_ITEMS
);
2333 SetLastError(ERROR_INVALID_HANDLE
);
2336 SetLastError(ERROR_INVALID_HANDLE
);
2340 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2342 InterlockedIncrement(&infFile
->References
);
2345 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2347 if (InterlockedDecrement(&infFile
->References
) == 0)
2349 SetupCloseInfFile(infFile
->hInf
);
2350 HeapFree(GetProcessHeap(), 0, infFile
);
2354 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2356 DereferenceInfFile(driverInfo
->InfFileDetails
);
2357 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2358 HeapFree(GetProcessHeap(), 0, driverInfo
);
2362 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2364 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2368 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2370 PLIST_ENTRY ListEntry
;
2371 struct DriverInfoElement
*driverInfo
;
2372 struct DeviceInterface
*deviceInterface
;
2374 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2376 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2377 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
2378 if (!DestroyDriverInfoElement(driverInfo
))
2381 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2383 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2384 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
2385 if (!DestroyDeviceInterface(deviceInterface
))
2388 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2389 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2393 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2395 PLIST_ENTRY ListEntry
;
2396 struct DeviceInfoElement
*deviceInfo
;
2398 while (!IsListEmpty(&list
->ListHead
))
2400 ListEntry
= RemoveHeadList(&list
->ListHead
);
2401 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
2402 if (!DestroyDeviceInfoElement(deviceInfo
))
2405 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2406 RegCloseKey(list
->HKLM
);
2407 CM_Disconnect_Machine(list
->hMachine
);
2408 DestroyClassInstallParams(&list
->ClassInstallParams
);
2409 HeapFree(GetProcessHeap(), 0, list
);
2413 /***********************************************************************
2414 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2416 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2420 TRACE("%p\n", devinfo
);
2421 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2423 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2425 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2426 ret
= DestroyDeviceInfoSet(list
);
2428 SetLastError(ERROR_INVALID_HANDLE
);
2431 SetLastError(ERROR_INVALID_HANDLE
);
2433 TRACE("Returning %d\n", ret
);
2437 /***********************************************************************
2438 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2440 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2441 HDEVINFO DeviceInfoSet
,
2442 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2443 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2444 DWORD DeviceInterfaceDetailDataSize
,
2445 PDWORD RequiredSize
,
2446 PSP_DEVINFO_DATA DeviceInfoData
)
2448 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2449 DWORD sizeW
= 0, sizeA
;
2452 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2453 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2454 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2456 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2457 SetLastError(ERROR_INVALID_USER_BUFFER
);
2458 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2459 SetLastError(ERROR_INVALID_PARAMETER
);
2460 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2461 SetLastError(ERROR_INVALID_PARAMETER
);
2464 if (DeviceInterfaceDetailData
!= NULL
)
2466 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2467 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2468 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2469 if (!DeviceInterfaceDetailDataW
)
2471 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2474 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2476 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2477 ret
= SetupDiGetDeviceInterfaceDetailW(
2479 DeviceInterfaceData
,
2480 DeviceInterfaceDetailDataW
,
2484 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2485 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2487 *RequiredSize
= sizeA
;
2488 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2490 if (!WideCharToMultiByte(
2492 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2493 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2500 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2503 TRACE("Returning %d\n", ret
);
2507 /***********************************************************************
2508 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2510 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2511 HDEVINFO DeviceInfoSet
,
2512 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2513 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2514 DWORD DeviceInterfaceDetailDataSize
,
2515 PDWORD RequiredSize
,
2516 PSP_DEVINFO_DATA DeviceInfoData
)
2520 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2521 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2522 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2524 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2525 SetLastError(ERROR_INVALID_PARAMETER
);
2526 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2527 SetLastError(ERROR_INVALID_HANDLE
);
2528 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2529 SetLastError(ERROR_INVALID_HANDLE
);
2530 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2531 SetLastError(ERROR_INVALID_USER_BUFFER
);
2532 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2533 SetLastError(ERROR_INVALID_USER_BUFFER
);
2534 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2535 SetLastError(ERROR_INVALID_USER_BUFFER
);
2536 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2537 SetLastError(ERROR_INVALID_PARAMETER
);
2538 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2539 SetLastError(ERROR_INVALID_PARAMETER
);
2542 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2543 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2544 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2545 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2547 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2549 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2551 *RequiredSize
= sizeRequired
;
2555 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2556 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2559 memcpy(&DeviceInfoData
->ClassGuid
,
2560 &deviceInterface
->DeviceInfo
->ClassGuid
,
2562 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2563 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2569 TRACE("Returning %d\n", ret
);
2573 /***********************************************************************
2574 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2576 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2578 PSP_DEVINFO_DATA DeviceInfoData
,
2580 PDWORD PropertyRegDataType
,
2581 PBYTE PropertyBuffer
,
2582 DWORD PropertyBufferSize
,
2583 PDWORD RequiredSize
)
2586 BOOL bIsStringProperty
;
2588 DWORD RequiredSizeA
, RequiredSizeW
;
2589 DWORD PropertyBufferSizeW
;
2590 PBYTE PropertyBufferW
;
2592 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2593 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2596 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2597 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2599 bResult
= SetupDiGetDeviceRegistryPropertyW(
2605 PropertyBufferSizeW
,
2608 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2610 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2612 if (bIsStringProperty
)
2613 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2615 RequiredSizeA
= RequiredSizeW
;
2617 *RequiredSize
= RequiredSizeA
;
2618 if (PropertyRegDataType
)
2619 *PropertyRegDataType
= RegType
;
2624 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2628 if (RequiredSizeA
<= PropertyBufferSize
)
2630 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2632 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2634 /* Last error is already set by WideCharToMultiByte */
2639 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2643 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2647 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2651 /***********************************************************************
2652 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2654 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2655 HDEVINFO DeviceInfoSet
,
2656 PSP_DEVINFO_DATA DeviceInfoData
,
2658 PDWORD PropertyRegDataType
,
2659 PBYTE PropertyBuffer
,
2660 DWORD PropertyBufferSize
,
2661 PDWORD RequiredSize
)
2663 HKEY hEnumKey
, hKey
;
2667 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2668 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2671 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2672 SetLastError(ERROR_INVALID_HANDLE
);
2673 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2674 SetLastError(ERROR_INVALID_HANDLE
);
2675 else if (!DeviceInfoData
)
2676 SetLastError(ERROR_INVALID_PARAMETER
);
2677 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2678 SetLastError(ERROR_INVALID_USER_BUFFER
);
2679 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2680 SetLastError(ERROR_INVALID_PARAMETER
);
2683 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2684 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2688 case SPDRP_CAPABILITIES
:
2690 case SPDRP_CLASSGUID
:
2691 case SPDRP_COMPATIBLEIDS
:
2692 case SPDRP_CONFIGFLAGS
:
2693 case SPDRP_DEVICEDESC
:
2695 case SPDRP_FRIENDLYNAME
:
2696 case SPDRP_HARDWAREID
:
2697 case SPDRP_LOCATION_INFORMATION
:
2698 case SPDRP_LOWERFILTERS
:
2700 case SPDRP_SECURITY
:
2702 case SPDRP_UI_NUMBER
:
2703 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2704 case SPDRP_UPPERFILTERS
:
2706 LPCWSTR RegistryPropertyName
;
2711 case SPDRP_CAPABILITIES
:
2712 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2714 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2715 case SPDRP_CLASSGUID
:
2716 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2717 case SPDRP_COMPATIBLEIDS
:
2718 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2719 case SPDRP_CONFIGFLAGS
:
2720 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2721 case SPDRP_DEVICEDESC
:
2722 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2724 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2725 case SPDRP_FRIENDLYNAME
:
2726 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2727 case SPDRP_HARDWAREID
:
2728 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2729 case SPDRP_LOCATION_INFORMATION
:
2730 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2731 case SPDRP_LOWERFILTERS
:
2732 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2734 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2735 case SPDRP_SECURITY
:
2736 RegistryPropertyName
= REGSTR_SECURITY
; break;
2738 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2739 case SPDRP_UI_NUMBER
:
2740 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2741 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2742 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2743 case SPDRP_UPPERFILTERS
:
2744 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2746 /* Should not happen */
2747 RegistryPropertyName
= NULL
; break;
2750 /* Open registry key name */
2753 REGSTR_PATH_SYSTEMENUM
,
2757 if (rc
!= ERROR_SUCCESS
)
2768 RegCloseKey(hEnumKey
);
2769 if (rc
!= ERROR_SUCCESS
)
2774 /* Read registry entry */
2775 BufferSize
= PropertyBufferSize
;
2776 rc
= RegQueryValueExW(
2778 RegistryPropertyName
,
2779 NULL
, /* Reserved */
2780 PropertyRegDataType
,
2784 *RequiredSize
= BufferSize
;
2787 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2790 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2792 case ERROR_MORE_DATA
:
2793 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2802 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2804 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2806 if (PropertyRegDataType
)
2807 *PropertyRegDataType
= REG_SZ
;
2809 *RequiredSize
= required
;
2810 if (PropertyBufferSize
>= required
)
2812 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2816 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2820 /*case SPDRP_BUSTYPEGUID:
2821 case SPDRP_LEGACYBUSTYPE:
2822 case SPDRP_BUSNUMBER:
2823 case SPDRP_ENUMERATOR_NAME:
2824 case SPDRP_SECURITY_SDS:
2826 case SPDRP_EXCLUSIVE:
2827 case SPDRP_CHARACTERISTICS:
2829 case SPDRP_DEVICE_POWER_DATA:*/
2830 #if (WINVER >= 0x501)
2831 /*case SPDRP_REMOVAL_POLICY:
2832 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2833 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2834 case SPDRP_INSTALL_STATE:*/
2839 ERR("Property 0x%lx not implemented\n", Property
);
2840 SetLastError(ERROR_NOT_SUPPORTED
);
2845 TRACE("Returning %d\n", ret
);
2849 /***********************************************************************
2850 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2852 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2853 IN HDEVINFO DeviceInfoSet
,
2854 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2856 IN CONST BYTE
*PropertyBuffer
,
2857 IN DWORD PropertyBufferSize
)
2859 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2860 Property
, PropertyBuffer
, PropertyBufferSize
);
2861 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2865 /***********************************************************************
2866 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2868 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2869 IN HDEVINFO DeviceInfoSet
,
2870 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2872 IN
const BYTE
*PropertyBuffer
,
2873 IN DWORD PropertyBufferSize
)
2875 struct DeviceInfoSet
*list
;
2878 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2879 Property
, PropertyBuffer
, PropertyBufferSize
);
2882 SetLastError(ERROR_INVALID_HANDLE
);
2883 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2884 SetLastError(ERROR_INVALID_HANDLE
);
2885 else if (!DeviceInfoData
)
2886 SetLastError(ERROR_INVALID_HANDLE
);
2887 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2888 SetLastError(ERROR_INVALID_USER_BUFFER
);
2893 case SPDRP_COMPATIBLEIDS
:
2894 case SPDRP_CONFIGFLAGS
:
2895 case SPDRP_FRIENDLYNAME
:
2896 case SPDRP_HARDWAREID
:
2897 case SPDRP_LOCATION_INFORMATION
:
2898 case SPDRP_LOWERFILTERS
:
2899 case SPDRP_SECURITY
:
2901 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2902 case SPDRP_UPPERFILTERS
:
2904 LPCWSTR RegistryPropertyName
;
2905 DWORD RegistryDataType
;
2911 case SPDRP_COMPATIBLEIDS
:
2912 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2913 RegistryDataType
= REG_MULTI_SZ
;
2915 case SPDRP_CONFIGFLAGS
:
2916 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2917 RegistryDataType
= REG_DWORD
;
2919 case SPDRP_FRIENDLYNAME
:
2920 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2921 RegistryDataType
= REG_SZ
;
2923 case SPDRP_HARDWAREID
:
2924 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2925 RegistryDataType
= REG_MULTI_SZ
;
2927 case SPDRP_LOCATION_INFORMATION
:
2928 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2929 RegistryDataType
= REG_SZ
;
2931 case SPDRP_LOWERFILTERS
:
2932 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2933 RegistryDataType
= REG_MULTI_SZ
;
2935 case SPDRP_SECURITY
:
2936 RegistryPropertyName
= REGSTR_SECURITY
;
2937 RegistryDataType
= REG_BINARY
;
2940 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2941 RegistryDataType
= REG_SZ
;
2943 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2944 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
2945 RegistryDataType
= REG_SZ
;
2947 case SPDRP_UPPERFILTERS
:
2948 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2949 RegistryDataType
= REG_MULTI_SZ
;
2952 /* Should not happen */
2953 RegistryPropertyName
= NULL
;
2954 RegistryDataType
= REG_BINARY
;
2957 /* Open device registry key */
2958 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2959 if (hKey
!= INVALID_HANDLE_VALUE
)
2961 /* Write new data */
2962 rc
= RegSetValueExW(
2964 RegistryPropertyName
,
2968 PropertyBufferSize
);
2969 if (rc
== ERROR_SUCCESS
)
2978 /*case SPDRP_CHARACTERISTICS:
2980 case SPDRP_EXCLUSIVE:*/
2981 #if (WINVER >= 0x501)
2982 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2984 //case SPDRP_SECURITY_SDS:
2988 ERR("Property 0x%lx not implemented\n", Property
);
2989 SetLastError(ERROR_NOT_SUPPORTED
);
2994 TRACE("Returning %d\n", ret
);
2999 /***********************************************************************
3000 * SetupDiInstallClassA (SETUPAPI.@)
3002 BOOL WINAPI
SetupDiInstallClassA(
3003 IN HWND hwndParent OPTIONAL
,
3004 IN PCSTR InfFileName
,
3006 IN HSPFILEQ FileQueue OPTIONAL
)
3008 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3012 /***********************************************************************
3013 * SetupDiInstallClassW (SETUPAPI.@)
3015 BOOL WINAPI
SetupDiInstallClassW(
3016 IN HWND hwndParent OPTIONAL
,
3017 IN PCWSTR InfFileName
,
3019 IN HSPFILEQ FileQueue OPTIONAL
)
3021 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3025 /***********************************************************************
3026 * SetupDiInstallClassExA (SETUPAPI.@)
3028 BOOL WINAPI
SetupDiInstallClassExA(
3029 IN HWND hwndParent OPTIONAL
,
3030 IN PCSTR InfFileName OPTIONAL
,
3032 IN HSPFILEQ FileQueue OPTIONAL
,
3033 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3037 PWSTR InfFileNameW
= NULL
;
3042 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3043 if (InfFileNameW
== NULL
)
3045 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3050 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3051 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3053 MyFree(InfFileNameW
);
3059 static HKEY
CreateClassKey(HINF hInf
)
3061 WCHAR FullBuffer
[MAX_PATH
];
3062 WCHAR Buffer
[MAX_PATH
];
3067 if (!SetupGetLineTextW(NULL
,
3075 return INVALID_HANDLE_VALUE
;
3078 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3079 lstrcatW(FullBuffer
, Buffer
);
3082 if (!SetupGetLineTextW(NULL
,
3090 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3091 return INVALID_HANDLE_VALUE
;
3094 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3098 REG_OPTION_NON_VOLATILE
,
3104 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3105 return INVALID_HANDLE_VALUE
;
3108 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3113 RequiredSize
* sizeof(WCHAR
)))
3115 RegCloseKey(hClassKey
);
3116 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3117 return INVALID_HANDLE_VALUE
;
3124 /***********************************************************************
3125 * SetupDiInstallClassExW (SETUPAPI.@)
3127 BOOL WINAPI
SetupDiInstallClassExW(
3128 IN HWND hwndParent OPTIONAL
,
3129 IN PCWSTR InfFileName OPTIONAL
,
3131 IN HSPFILEQ FileQueue OPTIONAL
,
3132 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3138 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3139 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3143 FIXME("Case not implemented: InfFileName NULL\n");
3144 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3146 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3148 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3149 SetLastError(ERROR_INVALID_FLAGS
);
3151 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3152 SetLastError(ERROR_INVALID_PARAMETER
);
3153 else if (Reserved1
!= NULL
)
3154 SetLastError(ERROR_INVALID_PARAMETER
);
3155 else if (Reserved2
!= NULL
)
3156 SetLastError(ERROR_INVALID_PARAMETER
);
3159 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3160 SP_DEVINSTALL_PARAMS_W InstallParams
;
3161 WCHAR SectionName
[MAX_PATH
];
3162 HINF hInf
= INVALID_HANDLE_VALUE
;
3163 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3164 PVOID callback_context
= NULL
;
3166 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3168 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3169 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3171 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3172 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3173 if (Flags
& DI_NOVCP
)
3174 InstallParams
.FileQueue
= FileQueue
;
3175 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3178 /* Open the .inf file */
3179 hInf
= SetupOpenInfFileW(
3184 if (hInf
== INVALID_HANDLE_VALUE
)
3187 /* Try to append a layout file */
3188 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3192 if (InterfaceClassGuid
)
3194 /* Retrieve the actual section name */
3195 ret
= SetupDiGetActualSectionToInstallW(
3205 /* Open registry key related to this interface */
3206 /* FIXME: What happens if the key doesn't exist? */
3207 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3208 if (hRootKey
== INVALID_HANDLE_VALUE
)
3211 /* SetupDiCreateDeviceInterface??? */
3212 FIXME("Installing an interface is not implemented\n");
3213 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3217 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3218 hRootKey
= CreateClassKey(hInf
);
3219 if (hRootKey
== INVALID_HANDLE_VALUE
)
3222 /* Retrieve the actual section name */
3223 ret
= SetupDiGetActualSectionToInstallW(
3227 MAX_PATH
- strlenW(DotServices
),
3233 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3234 if (!callback_context
)
3237 ret
= SetupInstallFromInfSectionW(
3241 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3243 NULL
, /* SourceRootPath */
3244 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3245 SetupDefaultQueueCallbackW
,
3252 /* Install .Services section */
3253 lstrcatW(SectionName
, DotServices
);
3254 ret
= SetupInstallServicesFromInfSectionExW(
3269 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3270 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3271 if (hInf
!= INVALID_HANDLE_VALUE
)
3272 SetupCloseInfFile(hInf
);
3273 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3274 RegCloseKey(hRootKey
);
3275 SetupTermDefaultQueueCallback(callback_context
);
3278 TRACE("Returning %d\n", ret
);
3283 /***********************************************************************
3284 * SetupDiOpenClassRegKey (SETUPAPI.@)
3286 HKEY WINAPI
SetupDiOpenClassRegKey(
3287 const GUID
* ClassGuid
,
3290 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3291 DIOCR_INSTALLER
, NULL
, NULL
);
3295 /***********************************************************************
3296 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3298 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3299 const GUID
* ClassGuid OPTIONAL
,
3302 PCSTR MachineName OPTIONAL
,
3305 PWSTR MachineNameW
= NULL
;
3312 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3313 if (MachineNameW
== NULL
)
3314 return INVALID_HANDLE_VALUE
;
3317 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3318 Flags
, MachineNameW
, Reserved
);
3321 MyFree(MachineNameW
);
3327 /***********************************************************************
3328 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3330 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3331 const GUID
* ClassGuid OPTIONAL
,
3334 PCWSTR MachineName OPTIONAL
,
3337 LPWSTR lpGuidString
= NULL
;
3338 LPWSTR lpFullGuidString
= NULL
;
3341 HKEY hClassesKey
= NULL
;
3342 HKEY hClassKey
= NULL
;
3343 HKEY ret
= INVALID_HANDLE_VALUE
;
3347 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3348 Flags
, debugstr_w(MachineName
), Reserved
);
3350 if (Flags
== DIOCR_INSTALLER
)
3351 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3352 else if (Flags
== DIOCR_INTERFACE
)
3353 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3356 ERR("Invalid Flags parameter!\n");
3357 SetLastError(ERROR_INVALID_FLAGS
);
3361 if (MachineName
!= NULL
)
3363 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3364 if (rc
!= ERROR_SUCCESS
)
3371 HKLM
= HKEY_LOCAL_MACHINE
;
3373 rc
= RegOpenKeyExW(HKLM
,
3376 ClassGuid
? 0 : samDesired
,
3378 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3379 if (rc
!= ERROR_SUCCESS
)
3385 if (ClassGuid
== NULL
)
3387 /* Stop here. We don't need to open a subkey */
3392 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3394 SetLastError(ERROR_GEN_FAILURE
);
3398 dwLength
= lstrlenW(lpGuidString
);
3399 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3400 if (!lpFullGuidString
)
3402 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3405 lpFullGuidString
[0] = '{';
3406 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3407 lpFullGuidString
[dwLength
+ 1] = '}';
3408 lpFullGuidString
[dwLength
+ 2] = '\0';
3410 rc
= RegOpenKeyExW(hClassesKey
,
3415 if (rc
!= ERROR_SUCCESS
)
3423 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3424 RegCloseKey(hClassesKey
);
3425 if (hClassesKey
!= NULL
&& hClassesKey
!= ret
)
3426 RegCloseKey(hClassesKey
);
3428 RpcStringFreeW(&lpGuidString
);
3429 if (lpFullGuidString
)
3430 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3435 /***********************************************************************
3436 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3438 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3439 HDEVINFO DeviceInfoSet
,
3442 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3444 FIXME("%p %s %08lx %p\n",
3445 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3449 /***********************************************************************
3450 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3452 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3453 HDEVINFO DeviceInfoSet
,
3456 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3458 LPWSTR DevicePathW
= NULL
;
3461 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3463 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3464 if (DevicePathW
== NULL
)
3467 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3468 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3470 MyFree(DevicePathW
);
3475 /***********************************************************************
3476 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3478 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3479 HDEVINFO DeviceInfoSet
,
3480 PSP_DEVINFO_DATA DeviceInfoData
,
3481 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3482 DWORD ClassInstallParamsSize
)
3484 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3485 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3489 /***********************************************************************
3490 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3492 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3493 IN HDEVINFO DeviceInfoSet
,
3494 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3495 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3496 IN DWORD ClassInstallParamsSize
)
3498 struct DeviceInfoSet
*list
;
3501 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3502 ClassInstallParams
, ClassInstallParamsSize
);
3505 SetLastError(ERROR_INVALID_PARAMETER
);
3506 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3507 SetLastError(ERROR_INVALID_HANDLE
);
3508 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3509 SetLastError(ERROR_INVALID_HANDLE
);
3510 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3511 SetLastError(ERROR_INVALID_USER_BUFFER
);
3512 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3513 SetLastError(ERROR_INVALID_USER_BUFFER
);
3514 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3515 SetLastError(ERROR_INVALID_PARAMETER
);
3516 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3517 SetLastError(ERROR_INVALID_PARAMETER
);
3520 SP_DEVINSTALL_PARAMS_W InstallParams
;
3523 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3524 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3528 if (ClassInstallParams
)
3530 /* Check parameters in ClassInstallParams */
3531 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3532 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3534 SetLastError(ERROR_INVALID_USER_BUFFER
);
3537 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3539 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3540 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3543 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3546 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3550 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3553 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3557 TRACE("Returning %d\n", ret
);
3561 static BOOL
PropertyChangeHandler(
3562 IN HDEVINFO DeviceInfoSet
,
3563 IN PSP_DEVINFO_DATA DeviceInfoData
,
3564 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3565 IN DWORD ClassInstallParamsSize
)
3567 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3570 if (!DeviceInfoData
)
3571 SetLastError(ERROR_INVALID_PARAMETER
);
3572 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3573 SetLastError(ERROR_INVALID_PARAMETER
);
3574 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3575 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3576 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3577 SetLastError(ERROR_INVALID_FLAGS
);
3578 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3579 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3580 SetLastError(ERROR_INVALID_FLAGS
);
3581 else if (PropChangeParams
3582 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3583 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3584 SetLastError(ERROR_INVALID_USER_BUFFER
);
3587 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3588 if (!DeviceInfoData
)
3590 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3591 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3595 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3596 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3598 if (*CurrentPropChangeParams
)
3600 MyFree(*CurrentPropChangeParams
);
3601 *CurrentPropChangeParams
= NULL
;
3603 if (PropChangeParams
)
3605 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3606 if (!*CurrentPropChangeParams
)
3608 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3611 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3622 IN PWSTR InstallerName
,
3623 OUT HMODULE
* ModulePointer
,
3624 OUT PVOID
* FunctionPointer
)
3626 HMODULE hModule
= NULL
;
3627 LPSTR FunctionNameA
= NULL
;
3631 *ModulePointer
= NULL
;
3632 *FunctionPointer
= NULL
;
3634 Comma
= strchrW(InstallerName
, ',');
3637 rc
= ERROR_INVALID_PARAMETER
;
3643 hModule
= LoadLibraryW(InstallerName
);
3647 rc
= GetLastError();
3651 /* Skip comma spaces */
3652 while (*Comma
== ',' || isspaceW(*Comma
))
3655 /* W->A conversion for function name */
3656 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3659 rc
= GetLastError();
3663 /* Search function */
3664 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3665 if (!*FunctionPointer
)
3667 rc
= GetLastError();
3671 *ModulePointer
= hModule
;
3675 if (rc
!= ERROR_SUCCESS
&& hModule
)
3676 FreeLibrary(hModule
);
3677 MyFree(FunctionNameA
);
3682 FreeFunctionPointer(
3683 IN HMODULE ModulePointer
,
3684 IN PVOID FunctionPointer
)
3686 if (ModulePointer
== NULL
)
3687 return ERROR_SUCCESS
;
3688 if (FreeLibrary(ModulePointer
))
3689 return ERROR_SUCCESS
;
3691 return GetLastError();
3695 IntSetupDiRegisterDeviceInfo(
3696 IN HDEVINFO DeviceInfoSet
,
3697 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3699 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3702 /***********************************************************************
3703 * SetupDiCallClassInstaller (SETUPAPI.@)
3705 BOOL WINAPI
SetupDiCallClassInstaller(
3706 IN DI_FUNCTION InstallFunction
,
3707 IN HDEVINFO DeviceInfoSet
,
3708 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3712 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3715 SetLastError(ERROR_INVALID_PARAMETER
);
3716 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3717 SetLastError(ERROR_INVALID_HANDLE
);
3718 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3719 SetLastError(ERROR_INVALID_HANDLE
);
3720 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3721 SetLastError(ERROR_INVALID_HANDLE
);
3722 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3723 SetLastError(ERROR_INVALID_USER_BUFFER
);
3726 SP_DEVINSTALL_PARAMS_W InstallParams
;
3727 #define CLASS_COINSTALLER 0x1
3728 #define DEVICE_COINSTALLER 0x2
3729 #define CLASS_INSTALLER 0x4
3730 UCHAR CanHandle
= 0;
3731 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3733 switch (InstallFunction
)
3735 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3736 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3738 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3739 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3741 case DIF_ALLOW_INSTALL
:
3742 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3745 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3747 case DIF_DESTROYPRIVATEDATA
:
3748 CanHandle
= CLASS_INSTALLER
;
3750 case DIF_INSTALLDEVICE
:
3751 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3752 DefaultHandler
= SetupDiInstallDevice
;
3754 case DIF_INSTALLDEVICEFILES
:
3755 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3756 DefaultHandler
= SetupDiInstallDriverFiles
;
3758 case DIF_INSTALLINTERFACES
:
3759 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3760 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3762 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3763 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3765 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3766 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3768 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3769 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3771 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3772 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3774 case DIF_NEWDEVICEWIZARD_SELECT
:
3775 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3777 case DIF_POWERMESSAGEWAKE
:
3778 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3780 case DIF_PROPERTYCHANGE
:
3781 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3782 DefaultHandler
= SetupDiChangeState
;
3784 case DIF_REGISTER_COINSTALLERS
:
3785 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3786 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3788 case DIF_REGISTERDEVICE
:
3789 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3790 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3793 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3794 DefaultHandler
= SetupDiRemoveDevice
;
3796 case DIF_SELECTBESTCOMPATDRV
:
3797 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3798 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3800 case DIF_SELECTDEVICE
:
3801 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3802 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3804 case DIF_TROUBLESHOOTER
:
3805 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3808 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3809 DefaultHandler
= SetupDiUnremoveDevice
;
3812 ERR("Install function %u not supported\n", InstallFunction
);
3813 SetLastError(ERROR_NOT_SUPPORTED
);
3816 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3817 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3818 /* Don't process this call, as a parameter is invalid */
3823 LIST_ENTRY ClassCoInstallersListHead
;
3824 LIST_ENTRY DeviceCoInstallersListHead
;
3825 HMODULE ClassInstallerLibrary
= NULL
;
3826 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3827 COINSTALLER_CONTEXT_DATA Context
;
3828 PLIST_ENTRY ListEntry
;
3830 DWORD dwRegType
, dwLength
;
3831 DWORD rc
= NO_ERROR
;
3833 InitializeListHead(&ClassCoInstallersListHead
);
3834 InitializeListHead(&DeviceCoInstallersListHead
);
3836 if (CanHandle
& DEVICE_COINSTALLER
)
3838 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3839 if (hKey
!= INVALID_HANDLE_VALUE
)
3841 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3842 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3844 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3845 if (KeyBuffer
!= NULL
)
3847 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3848 if (rc
== ERROR_SUCCESS
)
3851 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3853 /* Add coinstaller to DeviceCoInstallersListHead list */
3854 struct CoInstallerElement
*coinstaller
;
3855 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3856 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3859 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3860 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3861 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3863 HeapFree(GetProcessHeap(), 0, coinstaller
);
3866 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3872 if (CanHandle
& CLASS_COINSTALLER
)
3876 REGSTR_PATH_CODEVICEINSTALLERS
,
3880 if (rc
== ERROR_SUCCESS
)
3882 LPWSTR lpGuidString
;
3883 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3885 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3886 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3888 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3889 if (KeyBuffer
!= NULL
)
3891 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3892 if (rc
== ERROR_SUCCESS
)
3895 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3897 /* Add coinstaller to ClassCoInstallersListHead list */
3898 struct CoInstallerElement
*coinstaller
;
3899 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3900 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3903 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3904 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3905 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3907 HeapFree(GetProcessHeap(), 0, coinstaller
);
3910 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3913 RpcStringFreeW(&lpGuidString
);
3918 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3920 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3921 if (hKey
!= INVALID_HANDLE_VALUE
)
3923 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3924 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3926 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3927 if (KeyBuffer
!= NULL
)
3929 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3930 if (rc
== ERROR_SUCCESS
)
3932 /* Get ClassInstaller function pointer */
3933 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3934 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3936 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3937 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3940 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3947 /* Call Class co-installers */
3948 Context
.PostProcessing
= FALSE
;
3950 ListEntry
= ClassCoInstallersListHead
.Flink
;
3951 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3953 struct CoInstallerElement
*coinstaller
;
3954 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3955 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3956 coinstaller
->PrivateData
= Context
.PrivateData
;
3957 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3959 coinstaller
->DoPostProcessing
= TRUE
;
3962 ListEntry
= ListEntry
->Flink
;
3965 /* Call Device co-installers */
3966 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3967 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3969 struct CoInstallerElement
*coinstaller
;
3970 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3971 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3972 coinstaller
->PrivateData
= Context
.PrivateData
;
3973 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3975 coinstaller
->DoPostProcessing
= TRUE
;
3978 ListEntry
= ListEntry
->Flink
;
3981 /* Call Class installer */
3984 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3985 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3988 rc
= ERROR_DI_DO_DEFAULT
;
3990 /* Call default handler */
3991 if (rc
== ERROR_DI_DO_DEFAULT
)
3993 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3995 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3998 rc
= GetLastError();
4004 /* Call Class co-installers that required postprocessing */
4005 Context
.PostProcessing
= TRUE
;
4006 ListEntry
= ClassCoInstallersListHead
.Flink
;
4007 while (ListEntry
!= &ClassCoInstallersListHead
)
4009 struct CoInstallerElement
*coinstaller
;
4010 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4011 if (coinstaller
->DoPostProcessing
)
4013 Context
.InstallResult
= rc
;
4014 Context
.PrivateData
= coinstaller
->PrivateData
;
4015 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4017 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4018 ListEntry
= ListEntry
->Flink
;
4021 /* Call Device co-installers that required postprocessing */
4022 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4023 while (ListEntry
!= &DeviceCoInstallersListHead
)
4025 struct CoInstallerElement
*coinstaller
;
4026 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4027 if (coinstaller
->DoPostProcessing
)
4029 Context
.InstallResult
= rc
;
4030 Context
.PrivateData
= coinstaller
->PrivateData
;
4031 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4033 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4034 ListEntry
= ListEntry
->Flink
;
4037 /* Free allocated memory */
4038 while (!IsListEmpty(&ClassCoInstallersListHead
))
4040 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4041 HeapFree(GetProcessHeap(), 0, ListEntry
);
4043 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4045 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4046 HeapFree(GetProcessHeap(), 0, ListEntry
);
4049 ret
= (rc
== NO_ERROR
);
4053 TRACE("Returning %d\n", ret
);
4057 /***********************************************************************
4058 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4060 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4061 IN HDEVINFO DeviceInfoSet
,
4062 OUT LPGUID ClassGuid
)
4064 struct DeviceInfoSet
*list
;
4067 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4070 SetLastError(ERROR_INVALID_HANDLE
);
4071 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4072 SetLastError(ERROR_INVALID_HANDLE
);
4073 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4074 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4077 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4082 TRACE("Returning %d\n", ret
);
4086 /***********************************************************************
4087 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4089 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4090 IN HDEVINFO DeviceInfoSet
,
4091 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4093 struct DeviceInfoSet
*list
;
4096 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4099 SetLastError(ERROR_INVALID_HANDLE
);
4100 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4101 SetLastError(ERROR_INVALID_HANDLE
);
4102 else if (!DeviceInfoListDetailData
)
4103 SetLastError(ERROR_INVALID_PARAMETER
);
4104 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4105 SetLastError(ERROR_INVALID_USER_BUFFER
);
4109 &DeviceInfoListDetailData
->ClassGuid
,
4112 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4113 if (list
->MachineName
)
4114 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4116 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4121 TRACE("Returning %d\n", ret
);
4125 /***********************************************************************
4126 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4128 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4129 IN HDEVINFO DeviceInfoSet
,
4130 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4131 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4133 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4136 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4138 if (DeviceInstallParams
== NULL
)
4139 SetLastError(ERROR_INVALID_PARAMETER
);
4140 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4141 SetLastError(ERROR_INVALID_USER_BUFFER
);
4144 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4145 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4149 /* Do W->A conversion */
4151 DeviceInstallParams
,
4152 &deviceInstallParamsW
,
4153 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4154 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4155 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4157 DeviceInstallParams
->DriverPath
[0] = '\0';
4163 TRACE("Returning %d\n", ret
);
4167 /***********************************************************************
4168 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4170 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4171 IN HDEVINFO DeviceInfoSet
,
4172 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4173 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4175 struct DeviceInfoSet
*list
;
4178 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4181 SetLastError(ERROR_INVALID_HANDLE
);
4182 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4183 SetLastError(ERROR_INVALID_HANDLE
);
4184 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4185 SetLastError(ERROR_INVALID_USER_BUFFER
);
4186 else if (!DeviceInstallParams
)
4187 SetLastError(ERROR_INVALID_PARAMETER
);
4188 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4189 SetLastError(ERROR_INVALID_USER_BUFFER
);
4192 PSP_DEVINSTALL_PARAMS_W Source
;
4195 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4197 Source
= &list
->InstallParams
;
4198 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4202 TRACE("Returning %d\n", ret
);
4207 CheckDeviceInstallParameters(
4208 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4210 DWORD SupportedFlags
=
4211 DI_NOVCP
| /* 0x00000008 */
4212 DI_DIDCOMPAT
| /* 0x00000010 */
4213 DI_DIDCLASS
| /* 0x00000020 */
4214 DI_NEEDRESTART
| /* 0x00000080 */
4215 DI_NEEDREBOOT
| /* 0x00000100 */
4216 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4217 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4218 DI_ENUMSINGLEINF
| /* 0x00010000 */
4219 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4220 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4221 DI_QUIETINSTALL
| /* 0x00800000 */
4222 DI_NOFILECOPY
| /* 0x01000000 */
4223 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4224 DWORD SupportedFlagsEx
=
4225 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4226 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4227 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4228 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4229 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
4232 /* FIXME: add support for more flags */
4234 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4235 * It should be checked before accessing to other values
4236 * of the SP_DEVINSTALL_PARAMS structure */
4238 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4240 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4241 SetLastError(ERROR_INVALID_FLAGS
);
4243 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4245 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4246 SetLastError(ERROR_INVALID_FLAGS
);
4248 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4249 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4250 SetLastError(ERROR_INVALID_USER_BUFFER
);
4253 /* FIXME: check Reserved field */
4260 /***********************************************************************
4261 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4263 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4264 IN HDEVINFO DeviceInfoSet
,
4265 IN PSP_DEVINFO_DATA DeviceInfoData
,
4266 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4268 struct DeviceInfoSet
*list
;
4271 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4274 SetLastError(ERROR_INVALID_HANDLE
);
4275 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4276 SetLastError(ERROR_INVALID_HANDLE
);
4277 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4278 SetLastError(ERROR_INVALID_USER_BUFFER
);
4279 else if (!DeviceInstallParams
)
4280 SetLastError(ERROR_INVALID_PARAMETER
);
4281 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4282 SetLastError(ERROR_INVALID_USER_BUFFER
);
4283 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4285 PSP_DEVINSTALL_PARAMS_W Destination
;
4288 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4290 Destination
= &list
->InstallParams
;
4291 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4295 TRACE("Returning %d\n", ret
);
4299 /***********************************************************************
4300 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4302 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4303 IN HDEVINFO DeviceInfoSet
,
4304 IN PSP_DEVINFO_DATA DeviceInfoData
,
4305 OUT PSTR DeviceInstanceId OPTIONAL
,
4306 IN DWORD DeviceInstanceIdSize
,
4307 OUT PDWORD RequiredSize OPTIONAL
)
4309 PWSTR DeviceInstanceIdW
= NULL
;
4312 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4313 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4315 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4316 SetLastError(ERROR_INVALID_PARAMETER
);
4319 if (DeviceInstanceIdSize
!= 0)
4321 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4322 if (DeviceInstanceIdW
== NULL
)
4326 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4327 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4330 if (ret
&& DeviceInstanceIdW
!= NULL
)
4332 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4333 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4335 DeviceInstanceId
[0] = '\0';
4341 TRACE("Returning %d\n", ret
);
4345 /***********************************************************************
4346 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4348 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4349 IN HDEVINFO DeviceInfoSet
,
4350 IN PSP_DEVINFO_DATA DeviceInfoData
,
4351 OUT PWSTR DeviceInstanceId OPTIONAL
,
4352 IN DWORD DeviceInstanceIdSize
,
4353 OUT PDWORD RequiredSize OPTIONAL
)
4357 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4358 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4361 SetLastError(ERROR_INVALID_HANDLE
);
4362 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4363 SetLastError(ERROR_INVALID_HANDLE
);
4364 else if (!DeviceInfoData
)
4365 SetLastError(ERROR_INVALID_PARAMETER
);
4366 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4367 SetLastError(ERROR_INVALID_USER_BUFFER
);
4368 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4369 SetLastError(ERROR_INVALID_PARAMETER
);
4370 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4371 SetLastError(ERROR_INVALID_PARAMETER
);
4374 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4377 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4379 *RequiredSize
= required
;
4381 if (required
<= DeviceInstanceIdSize
)
4383 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
4387 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4390 TRACE("Returning %d\n", ret
);
4394 /***********************************************************************
4395 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4397 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4398 IN HDEVINFO DeviceInfoSet
,
4399 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4400 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4401 IN DWORD PropertySheetHeaderPageListSize
,
4402 OUT PDWORD RequiredSize OPTIONAL
,
4403 IN DWORD PropertySheetType
)
4405 PROPSHEETHEADERW psh
;
4408 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4409 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4410 RequiredSize
, PropertySheetType
);
4412 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4413 psh
.phpage
= PropertySheetHeader
->phpage
;
4414 psh
.nPages
= PropertySheetHeader
->nPages
;
4416 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4417 PropertySheetHeaderPageListSize
, RequiredSize
,
4421 PropertySheetHeader
->nPages
= psh
.nPages
;
4424 TRACE("Returning %d\n", ret
);
4428 struct ClassDevPropertySheetsData
4430 HPROPSHEETPAGE
*PropertySheetPages
;
4431 DWORD MaximumNumberOfPages
;
4432 DWORD NumberOfPages
;
4435 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4436 IN HPROPSHEETPAGE hPropSheetPage
,
4437 IN OUT LPARAM lParam
)
4439 struct ClassDevPropertySheetsData
*PropPageData
;
4441 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4443 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4445 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4446 PropPageData
->PropertySheetPages
++;
4449 PropPageData
->NumberOfPages
++;
4453 /***********************************************************************
4454 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4456 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4457 IN HDEVINFO DeviceInfoSet
,
4458 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4459 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4460 IN DWORD PropertySheetHeaderPageListSize
,
4461 OUT PDWORD RequiredSize OPTIONAL
,
4462 IN DWORD PropertySheetType
)
4464 struct DeviceInfoSet
*list
;
4467 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4468 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4469 RequiredSize
, PropertySheetType
);
4472 SetLastError(ERROR_INVALID_HANDLE
);
4473 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4474 SetLastError(ERROR_INVALID_HANDLE
);
4475 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4476 SetLastError(ERROR_INVALID_HANDLE
);
4477 else if (!PropertySheetHeader
)
4478 SetLastError(ERROR_INVALID_PARAMETER
);
4479 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4480 SetLastError(ERROR_INVALID_FLAGS
);
4481 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4482 SetLastError(ERROR_INVALID_USER_BUFFER
);
4483 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4484 SetLastError(ERROR_INVALID_PARAMETER
);
4485 else if (!PropertySheetHeader
)
4486 SetLastError(ERROR_INVALID_PARAMETER
);
4487 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4488 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4489 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4490 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4491 SetLastError(ERROR_INVALID_PARAMETER
);
4494 HKEY hKey
= INVALID_HANDLE_VALUE
;
4495 SP_PROPSHEETPAGE_REQUEST Request
;
4496 LPWSTR PropPageProvider
= NULL
;
4497 HMODULE hModule
= NULL
;
4498 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4499 struct ClassDevPropertySheetsData PropPageData
;
4500 DWORD dwLength
, dwRegType
;
4504 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4507 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4508 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4510 if (hKey
== INVALID_HANDLE_VALUE
)
4513 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4514 if (rc
== ERROR_FILE_NOT_FOUND
)
4516 /* No registry key. As it is optional, don't say it's a bad error */
4522 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4528 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4529 if (!PropPageProvider
)
4531 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4534 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4535 if (rc
!= ERROR_SUCCESS
)
4540 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4542 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4543 if (rc
!= ERROR_SUCCESS
)
4545 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4549 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4550 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4551 Request
.DeviceInfoSet
= DeviceInfoSet
;
4552 Request
.DeviceInfoData
= DeviceInfoData
;
4553 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4554 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4555 PropPageData
.NumberOfPages
= 0;
4556 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4561 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4562 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4564 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4569 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4570 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4574 if (hKey
!= INVALID_HANDLE_VALUE
)
4576 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4577 FreeFunctionPointer(hModule
, pPropPageProvider
);
4580 TRACE("Returning %d\n", ret
);
4584 /***********************************************************************
4585 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4587 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4588 IN HDEVINFO DeviceInfoSet
,
4589 IN PSP_DEVINFO_DATA DeviceInfoData
,
4593 IN HINF InfHandle OPTIONAL
,
4594 IN PCSTR InfSectionName OPTIONAL
)
4596 PCWSTR InfSectionNameW
= NULL
;
4597 HKEY ret
= INVALID_HANDLE_VALUE
;
4601 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4602 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4605 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4613 if (InfSectionNameW
!= NULL
)
4614 MyFree((PVOID
)InfSectionNameW
);
4620 OpenHardwareProfileKey(
4623 IN DWORD samDesired
)
4625 HKEY hHWProfilesKey
= NULL
;
4626 HKEY hHWProfileKey
= NULL
;
4627 HKEY ret
= INVALID_HANDLE_VALUE
;
4630 rc
= RegOpenKeyExW(HKLM
,
4631 REGSTR_PATH_HWPROFILES
,
4635 if (rc
!= ERROR_SUCCESS
)
4652 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4661 if (rc
!= ERROR_SUCCESS
)
4666 ret
= hHWProfileKey
;
4669 if (hHWProfilesKey
!= NULL
)
4670 RegCloseKey(hHWProfilesKey
);
4671 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4672 RegCloseKey(hHWProfileKey
);
4676 /***********************************************************************
4677 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4679 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4680 IN HDEVINFO DeviceInfoSet
,
4681 IN PSP_DEVINFO_DATA DeviceInfoData
,
4685 IN HINF InfHandle OPTIONAL
,
4686 IN PCWSTR InfSectionName OPTIONAL
)
4688 struct DeviceInfoSet
*list
;
4689 HKEY ret
= INVALID_HANDLE_VALUE
;
4691 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4692 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4695 SetLastError(ERROR_INVALID_HANDLE
);
4696 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4697 SetLastError(ERROR_INVALID_HANDLE
);
4698 else if (!DeviceInfoData
)
4699 SetLastError(ERROR_INVALID_PARAMETER
);
4700 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4701 SetLastError(ERROR_INVALID_USER_BUFFER
);
4702 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4703 SetLastError(ERROR_INVALID_PARAMETER
);
4704 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4705 SetLastError(ERROR_INVALID_PARAMETER
);
4706 else if (InfHandle
&& !InfSectionName
)
4707 SetLastError(ERROR_INVALID_PARAMETER
);
4708 else if (!InfHandle
&& InfSectionName
)
4709 SetLastError(ERROR_INVALID_PARAMETER
);
4712 LPWSTR lpGuidString
= NULL
;
4713 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4714 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4715 DWORD Index
; /* Index used in the DriverKey name */
4717 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4718 HKEY hEnumKey
= NULL
;
4719 HKEY hClassKey
= NULL
;
4720 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4724 if (Scope
== DICS_FLAG_GLOBAL
)
4725 RootKey
= list
->HKLM
;
4726 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4728 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4729 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4731 RootKey
= hHWProfileKey
;
4734 if (KeyType
== DIREG_DEV
)
4736 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4738 rc
= RegCreateKeyExW(
4740 REGSTR_PATH_SYSTEMENUM
,
4743 REG_OPTION_NON_VOLATILE
,
4748 if (rc
!= ERROR_SUCCESS
)
4753 rc
= RegCreateKeyExW(
4755 deviceInfo
->DeviceName
,
4758 REG_OPTION_NON_VOLATILE
,
4759 #if _WIN32_WINNT >= 0x502
4760 KEY_READ
| KEY_WRITE
,
4767 if (rc
!= ERROR_SUCCESS
)
4773 else /* KeyType == DIREG_DRV */
4775 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4777 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4778 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4781 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4784 strcpyW(DriverKey
, L
"{");
4785 strcatW(DriverKey
, lpGuidString
);
4786 strcatW(DriverKey
, L
"}\\");
4787 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
4788 rc
= RegOpenKeyExW(RootKey
,
4789 REGSTR_PATH_CLASS_NT
,
4793 if (rc
!= ERROR_SUCCESS
)
4799 /* Try all values for Index between 0 and 9999 */
4801 while (Index
<= 9999)
4804 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4805 rc
= RegCreateKeyEx(hClassKey
,
4809 REG_OPTION_NON_VOLATILE
,
4810 #if _WIN32_WINNT >= 0x502
4811 KEY_READ
| KEY_WRITE
,
4818 if (rc
!= ERROR_SUCCESS
)
4823 if (Disposition
== REG_CREATED_NEW_KEY
)
4826 hKey
= INVALID_HANDLE_VALUE
;
4831 /* Unable to create more than 9999 devices within the same class */
4832 SetLastError(ERROR_GEN_FAILURE
);
4836 /* Open device key, to write Driver value */
4837 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4838 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4840 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
4841 if (rc
!= ERROR_SUCCESS
)
4848 /* Do installation of the specified section */
4851 FIXME("Need to install section %s in file %p\n",
4852 debugstr_w(InfSectionName
), InfHandle
);
4858 RpcStringFreeW(&lpGuidString
);
4859 HeapFree(GetProcessHeap(), 0, DriverKey
);
4860 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4861 RegCloseKey(hHWProfileKey
);
4862 if (hEnumKey
!= NULL
)
4863 RegCloseKey(hEnumKey
);
4864 if (hClassKey
!= NULL
)
4865 RegCloseKey(hClassKey
);
4866 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4867 RegCloseKey(hDeviceKey
);
4868 if (hKey
!= NULL
&& hKey
!= ret
)
4872 TRACE("Returning 0x%p\n", ret
);
4876 /***********************************************************************
4877 * SetupDiOpenDevRegKey (SETUPAPI.@)
4879 HKEY WINAPI
SetupDiOpenDevRegKey(
4880 HDEVINFO DeviceInfoSet
,
4881 PSP_DEVINFO_DATA DeviceInfoData
,
4887 struct DeviceInfoSet
*list
;
4888 HKEY ret
= INVALID_HANDLE_VALUE
;
4890 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4891 Scope
, HwProfile
, KeyType
, samDesired
);
4894 SetLastError(ERROR_INVALID_HANDLE
);
4895 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4896 SetLastError(ERROR_INVALID_HANDLE
);
4897 else if (!DeviceInfoData
)
4898 SetLastError(ERROR_INVALID_PARAMETER
);
4899 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4900 SetLastError(ERROR_INVALID_USER_BUFFER
);
4901 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4902 SetLastError(ERROR_INVALID_PARAMETER
);
4903 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4904 SetLastError(ERROR_INVALID_PARAMETER
);
4907 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4908 LPWSTR DriverKey
= NULL
;
4912 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4913 HKEY hEnumKey
= NULL
;
4917 if (Scope
== DICS_FLAG_GLOBAL
)
4918 RootKey
= list
->HKLM
;
4919 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4921 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4922 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4924 RootKey
= hHWProfileKey
;
4929 REGSTR_PATH_SYSTEMENUM
,
4933 if (rc
!= ERROR_SUCCESS
)
4940 deviceInfo
->DeviceName
,
4942 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4944 RegCloseKey(hEnumKey
);
4946 if (rc
!= ERROR_SUCCESS
)
4951 if (KeyType
== DIREG_DEV
)
4953 /* We're done. Just return the hKey handle */
4957 /* Read the 'Driver' key */
4958 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4959 if (rc
!= ERROR_SUCCESS
)
4964 else if (dwRegType
!= REG_SZ
)
4966 SetLastError(ERROR_GEN_FAILURE
);
4969 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4972 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4975 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4976 if (rc
!= ERROR_SUCCESS
)
4983 /* Need to open the driver key */
4986 REGSTR_PATH_CLASS_NT
,
4990 if (rc
!= ERROR_SUCCESS
)
5001 if (rc
!= ERROR_SUCCESS
)
5009 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5010 RegCloseKey(hHWProfileKey
);
5011 if (hEnumKey
!= NULL
)
5012 RegCloseKey(hEnumKey
);
5013 if (hKey
!= NULL
&& hKey
!= ret
)
5017 TRACE("Returning 0x%p\n", ret
);
5021 /***********************************************************************
5022 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5024 BOOL WINAPI
SetupDiCreateDeviceInfoA(
5025 HDEVINFO DeviceInfoSet
,
5027 CONST GUID
*ClassGuid
,
5028 PCSTR DeviceDescription
,
5030 DWORD CreationFlags
,
5031 PSP_DEVINFO_DATA DeviceInfoData
)
5033 LPWSTR DeviceNameW
= NULL
;
5034 LPWSTR DeviceDescriptionW
= NULL
;
5041 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5042 if (DeviceNameW
== NULL
) return FALSE
;
5044 if (DeviceDescription
)
5046 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5047 if (DeviceDescriptionW
== NULL
)
5049 if (DeviceNameW
) MyFree(DeviceNameW
);
5054 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5055 ClassGuid
, DeviceDescriptionW
,
5056 hwndParent
, CreationFlags
,
5059 if (DeviceNameW
) MyFree(DeviceNameW
);
5060 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5065 /***********************************************************************
5066 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5068 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5069 HDEVINFO DeviceInfoSet
,
5071 CONST GUID
*ClassGuid
,
5072 PCWSTR DeviceDescription
,
5074 DWORD CreationFlags
,
5075 PSP_DEVINFO_DATA DeviceInfoData
)
5077 struct DeviceInfoSet
*list
;
5080 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
5081 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
5082 hwndParent
, CreationFlags
, DeviceInfoData
);
5085 SetLastError(ERROR_INVALID_HANDLE
);
5086 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5087 SetLastError(ERROR_INVALID_HANDLE
);
5088 else if (!ClassGuid
)
5089 SetLastError(ERROR_INVALID_PARAMETER
);
5090 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5091 SetLastError(ERROR_CLASS_MISMATCH
);
5092 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5094 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5095 SetLastError(ERROR_INVALID_FLAGS
);
5099 SP_DEVINFO_DATA DevInfo
;
5101 if (CreationFlags
& DICD_GENERATE_ID
)
5103 /* Generate a new unique ID for this device */
5104 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5105 FIXME("not implemented\n");
5109 /* Device name is fully qualified. Try to open it */
5112 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5113 rc
= SetupDiOpenDeviceInfoW(
5116 NULL
, /* hwndParent */
5117 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5122 /* SetupDiOpenDeviceInfoW has already added
5123 * the device info to the device info set
5125 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5127 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5129 struct DeviceInfoElement
*deviceInfo
;
5131 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5133 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5135 if (!DeviceInfoData
)
5139 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5141 SetLastError(ERROR_INVALID_USER_BUFFER
);
5145 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5146 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5147 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5156 TRACE("Returning %d\n", ret
);
5160 /***********************************************************************
5161 * Helper functions for SetupDiBuildDriverInfoList
5165 IN PLIST_ENTRY DriverListHead
,
5166 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5167 IN LPGUID ClassGuid
,
5168 IN INFCONTEXT ContextDevice
,
5169 IN
struct InfFileDetails
*InfFileDetails
,
5171 IN LPCWSTR ProviderName
,
5172 IN LPCWSTR ManufacturerName
,
5173 IN LPCWSTR MatchingId
,
5174 FILETIME DriverDate
,
5175 DWORDLONG DriverVersion
,
5178 struct DriverInfoElement
*driverInfo
= NULL
;
5179 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5180 DWORD RequiredSize
= 128; /* Initial buffer size */
5181 BOOL Result
= FALSE
;
5182 PLIST_ENTRY PreviousEntry
;
5183 LPWSTR InfInstallSection
= NULL
;
5186 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5189 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5192 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5194 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5195 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5197 /* Copy InfFileName field */
5198 strncpyW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5199 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5201 /* Fill InfDate field */
5202 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5203 GENERIC_READ, FILE_SHARE_READ,
5204 NULL, OPEN_EXISTING, 0, NULL);
5205 if (hFile == INVALID_HANDLE_VALUE)
5207 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5211 /* Fill SectionName field */
5212 Result
= SetupGetStringFieldW(
5215 driverInfo
->Details
.SectionName
, LINE_LEN
,
5220 /* Fill DrvDescription field */
5221 Result
= SetupGetStringFieldW(
5223 0, /* Field index */
5224 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5227 /* Copy MatchingId information */
5230 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5231 if (!driverInfo
->MatchingId
)
5233 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5236 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5239 driverInfo
->MatchingId
= NULL
;
5241 /* Get inf install section */
5243 RequiredSize
= 128; /* Initial buffer size */
5244 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5245 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5247 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5248 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5249 if (!InfInstallSection
)
5251 Result
= SetupGetStringFieldW(
5253 1, /* Field index */
5254 InfInstallSection
, RequiredSize
,
5260 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
5261 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
5262 debugstr_w(InfInstallSection
), Rank
);
5264 driverInfo
->DriverRank
= Rank
;
5265 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5266 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5267 driverInfo
->Info
.DriverType
= DriverType
;
5268 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5269 strncpyW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5270 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5271 strncpyW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5272 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5275 strncpyW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5276 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5279 driverInfo
->Info
.ProviderName
[0] = '\0';
5280 driverInfo
->Info
.DriverDate
= DriverDate
;
5281 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5282 ReferenceInfFile(InfFileDetails
);
5283 driverInfo
->InfFileDetails
= InfFileDetails
;
5285 /* Insert current driver in driver list, according to its rank */
5286 PreviousEntry
= DriverListHead
->Flink
;
5287 while (PreviousEntry
!= DriverListHead
)
5289 struct DriverInfoElement
*CurrentDriver
;
5290 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5291 if (CurrentDriver
->DriverRank
> Rank
||
5292 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5294 /* Insert before the current item */
5295 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5298 PreviousEntry
= PreviousEntry
->Flink
;
5300 if (PreviousEntry
== DriverListHead
)
5302 /* Insert at the end of the list */
5303 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5312 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5313 HeapFree(GetProcessHeap(), 0, driverInfo
);
5315 if (hFile
!= INVALID_HANDLE_VALUE
)
5317 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5323 GetVersionInformationFromInfFile(
5325 OUT LPGUID ClassGuid
,
5326 OUT LPWSTR
* pProviderName
,
5327 OUT FILETIME
* DriverDate
,
5328 OUT DWORDLONG
* DriverVersion
)
5331 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5332 LPWSTR DriverVer
= NULL
;
5333 LPWSTR ProviderName
= NULL
;
5334 LPWSTR pComma
; /* Points into DriverVer */
5335 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5336 SYSTEMTIME SystemTime
;
5338 BOOL ret
= FALSE
; /* Final result */
5340 /* Get class Guid */
5341 if (!SetupGetLineTextW(
5345 guidW
, sizeof(guidW
),
5346 NULL
/* Required size */))
5350 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5351 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5353 SetLastError(ERROR_GEN_FAILURE
);
5357 /* Get provider name */
5358 Result
= SetupGetLineTextW(
5360 hInf
, Version
, INF_PROVIDER
,
5365 /* We know know the needed buffer size */
5366 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5369 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5372 Result
= SetupGetLineTextW(
5374 hInf
, Version
, INF_PROVIDER
,
5375 ProviderName
, RequiredSize
,
5380 *pProviderName
= ProviderName
;
5382 /* Read the "DriverVer" value */
5383 Result
= SetupGetLineTextW(
5385 hInf
, Version
, INF_DRIVER_VER
,
5390 /* We know know the needed buffer size */
5391 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5394 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5397 Result
= SetupGetLineTextW(
5399 hInf
, Version
, INF_DRIVER_VER
,
5400 DriverVer
, RequiredSize
,
5406 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5407 pComma
= strchrW(DriverVer
, ',');
5410 *pComma
= UNICODE_NULL
;
5411 pVersion
= pComma
+ 1;
5413 /* Get driver date version. Invalid date = 00/00/00 */
5414 memset(DriverDate
, 0, sizeof(FILETIME
));
5415 if (strlenW(DriverVer
) == 10
5416 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5417 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5419 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5420 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5421 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5422 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5423 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5424 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5426 /* Get driver version. Invalid version = 0.0.0.0 */
5430 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5431 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5432 LARGE_INTEGER fullVersion
;
5434 pMinor
= strchrW(pVersion
, '.');
5438 pRevision
= strchrW(++pMinor
, '.');
5439 Minor
= atoiW(pMinor
);
5444 pBuild
= strchrW(++pRevision
, '.');
5445 Revision
= atoiW(pRevision
);
5451 Build
= atoiW(pBuild
);
5453 Major
= atoiW(pVersion
);
5454 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5455 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5456 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5463 HeapFree(GetProcessHeap(), 0, ProviderName
);
5464 HeapFree(GetProcessHeap(), 0, DriverVer
);
5470 GetHardwareAndCompatibleIDsLists(
5471 IN HDEVINFO DeviceInfoSet
,
5472 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
5473 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
5474 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
5475 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
5476 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
5478 LPWSTR HardwareIDs
= NULL
;
5479 LPWSTR CompatibleIDs
= NULL
;
5483 /* Get hardware IDs list */
5485 RequiredSize
= 512; /* Initial buffer size */
5486 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5487 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5489 MyFree(HardwareIDs
);
5490 HardwareIDs
= MyMalloc(RequiredSize
);
5493 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5496 Result
= SetupDiGetDeviceRegistryPropertyW(
5507 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5509 /* No hardware ID for this device */
5510 MyFree(HardwareIDs
);
5518 *pHardwareIDs
= HardwareIDs
;
5519 if (pHardwareIDsRequiredSize
)
5520 *pHardwareIDsRequiredSize
= RequiredSize
;
5522 /* Get compatible IDs list */
5524 RequiredSize
= 512; /* Initial buffer size */
5525 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5526 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5528 MyFree(CompatibleIDs
);
5529 CompatibleIDs
= MyMalloc(RequiredSize
);
5532 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5535 Result
= SetupDiGetDeviceRegistryPropertyW(
5538 SPDRP_COMPATIBLEIDS
,
5540 (PBYTE
)CompatibleIDs
,
5546 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5548 /* No compatible ID for this device */
5549 MyFree(CompatibleIDs
);
5550 CompatibleIDs
= NULL
;
5557 *pCompatibleIDs
= CompatibleIDs
;
5558 if (pCompatibleIDsRequiredSize
)
5559 *pCompatibleIDsRequiredSize
= RequiredSize
;
5566 MyFree(HardwareIDs
);
5567 MyFree(CompatibleIDs
);
5572 /***********************************************************************
5573 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5576 SetupDiBuildDriverInfoList(
5577 IN HDEVINFO DeviceInfoSet
,
5578 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5579 IN DWORD DriverType
)
5581 struct DeviceInfoSet
*list
;
5582 SP_DEVINSTALL_PARAMS_W InstallParams
;
5583 PVOID Buffer
= NULL
;
5584 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5585 LPWSTR ProviderName
= NULL
;
5586 LPWSTR ManufacturerName
= NULL
;
5587 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5588 LPWSTR HardwareIDs
= NULL
;
5589 LPWSTR CompatibleIDs
= NULL
;
5590 LPWSTR FullInfFileName
= NULL
;
5591 LPWSTR ExcludeFromSelect
= NULL
;
5592 FILETIME DriverDate
;
5593 DWORDLONG DriverVersion
= 0;
5597 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5600 SetLastError(ERROR_INVALID_HANDLE
);
5601 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5602 SetLastError(ERROR_INVALID_HANDLE
);
5603 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5604 SetLastError(ERROR_INVALID_HANDLE
);
5605 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5606 SetLastError(ERROR_INVALID_PARAMETER
);
5607 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5608 SetLastError(ERROR_INVALID_PARAMETER
);
5609 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5610 SetLastError(ERROR_INVALID_USER_BUFFER
);
5613 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
5616 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5617 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5623 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5624 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
5625 pDriverListHead
= &devInfo
->DriverListHead
;
5628 if (DriverType
== SPDIT_COMPATDRIVER
)
5630 /* Get hardware and compatible IDs lists */
5631 Result
= GetHardwareAndCompatibleIDsLists(
5640 if (!HardwareIDs
&& !CompatibleIDs
)
5642 SetLastError(ERROR_FILE_NOT_FOUND
);
5647 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5649 /* InstallParams.DriverPath contains the name of a .inf file */
5650 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
5651 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5654 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5657 strcpyW(Buffer
, InstallParams
.DriverPath
);
5658 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5663 /* Enumerate .inf files */
5665 RequiredSize
= 32768; /* Initial buffer size */
5666 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5667 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5669 HeapFree(GetProcessHeap(), 0, Buffer
);
5670 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5674 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5677 Result
= SetupGetInfFileListW(
5678 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5680 Buffer
, RequiredSize
,
5683 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5685 /* No .inf file in specified directory. So, we should
5686 * success as we created an empty driver info list.
5695 LPWSTR pFullFilename
;
5697 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5699 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5700 if (!FullInfFileName
)
5702 pFullFilename
= &FullInfFileName
[0];
5704 else if (*InstallParams
.DriverPath
)
5707 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5710 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5711 if (!FullInfFileName
)
5713 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5716 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
5717 strcatW(FullInfFileName
, L
"\\");
5718 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
5722 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5723 if (!FullInfFileName
)
5725 pFullFilename
= &FullInfFileName
[0];
5728 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
5730 INFCONTEXT ContextManufacturer
, ContextDevice
;
5733 strcpyW(pFullFilename
, filename
);
5734 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
5736 currentInfFileDetails
= HeapAlloc(
5739 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5740 if (!currentInfFileDetails
)
5742 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5743 strcpyW(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5745 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5746 ReferenceInfFile(currentInfFileDetails
);
5747 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5749 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5750 currentInfFileDetails
= NULL
;
5754 if (!GetVersionInformationFromInfFile(
5755 currentInfFileDetails
->hInf
,
5761 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5762 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5763 currentInfFileDetails
= NULL
;
5767 if (DriverType
== SPDIT_CLASSDRIVER
)
5769 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5770 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5776 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
5778 /* Read ExcludeFromSelect control flags */
5782 FIXME("ExcludeFromSelect list ignored\n");
5784 /* Get the manufacturers list */
5785 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
5788 Result
= SetupGetStringFieldW(
5789 &ContextManufacturer
,
5790 0, /* Field index */
5795 /* We got the needed size for the buffer */
5796 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5797 if (!ManufacturerName
)
5799 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5802 Result
= SetupGetStringFieldW(
5803 &ContextManufacturer
,
5804 0, /* Field index */
5805 ManufacturerName
, RequiredSize
,
5808 /* Get manufacturer section name */
5809 Result
= SetupGetStringFieldW(
5810 &ContextManufacturer
,
5811 1, /* Field index */
5812 ManufacturerSection
, LINE_LEN
,
5816 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5817 /* Add (possible) extension to manufacturer section name */
5818 Result
= SetupDiGetActualSectionToInstallW(
5819 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5822 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
5823 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5828 if (DriverType
== SPDIT_CLASSDRIVER
)
5830 /* FIXME: Check ExcludeFromSelect list */
5831 if (!AddDriverToList(
5836 currentInfFileDetails
,
5841 DriverDate
, DriverVersion
,
5847 else /* DriverType = SPDIT_COMPATDRIVER */
5849 /* 1. Get all fields */
5850 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5854 BOOL DriverAlreadyAdded
;
5856 for (i
= 2; i
<= FieldCount
; i
++)
5858 LPWSTR DeviceId
= NULL
;
5860 RequiredSize
= 128; /* Initial buffer size */
5861 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5862 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5864 HeapFree(GetProcessHeap(), 0, DeviceId
);
5865 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5868 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5871 Result
= SetupGetStringFieldW(
5874 DeviceId
, RequiredSize
,
5879 HeapFree(GetProcessHeap(), 0, DeviceId
);
5882 /* FIXME: Check ExcludeFromSelect list */
5883 DriverAlreadyAdded
= FALSE
;
5884 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5886 if (wcsicmp(DeviceId
, currentId
) == 0)
5893 currentInfFileDetails
,
5898 DriverDate
, DriverVersion
,
5899 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5900 DriverAlreadyAdded
= TRUE
;
5905 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5907 if (wcsicmp(DeviceId
, currentId
) == 0)
5914 currentInfFileDetails
,
5919 DriverDate
, DriverVersion
,
5920 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5921 DriverAlreadyAdded
= TRUE
;
5925 HeapFree(GetProcessHeap(), 0, DeviceId
);
5928 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5931 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5932 ManufacturerName
= NULL
;
5933 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5938 HeapFree(GetProcessHeap(), 0, ProviderName
);
5939 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5940 ProviderName
= ExcludeFromSelect
= NULL
;
5942 DereferenceInfFile(currentInfFileDetails
);
5943 currentInfFileDetails
= NULL
;
5954 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5955 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5959 InstallParams
.Flags
|= DI_DIDCLASS
;
5960 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5962 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5965 HeapFree(GetProcessHeap(), 0, ProviderName
);
5966 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5967 MyFree(HardwareIDs
);
5968 MyFree(CompatibleIDs
);
5969 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5970 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5971 if (currentInfFileDetails
)
5972 DereferenceInfFile(currentInfFileDetails
);
5973 HeapFree(GetProcessHeap(), 0, Buffer
);
5975 TRACE("Returning %d\n", ret
);
5979 /***********************************************************************
5980 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5983 SetupDiDeleteDeviceInfo(
5984 IN HDEVINFO DeviceInfoSet
,
5985 IN PSP_DEVINFO_DATA DeviceInfoData
)
5987 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5989 FIXME("not implemented\n");
5990 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5995 /***********************************************************************
5996 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5999 SetupDiDestroyDriverInfoList(
6000 IN HDEVINFO DeviceInfoSet
,
6001 IN PSP_DEVINFO_DATA DeviceInfoData
,
6002 IN DWORD DriverType
)
6004 struct DeviceInfoSet
*list
;
6007 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
6010 SetLastError(ERROR_INVALID_HANDLE
);
6011 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6012 SetLastError(ERROR_INVALID_HANDLE
);
6013 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6014 SetLastError(ERROR_INVALID_PARAMETER
);
6015 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6016 SetLastError(ERROR_INVALID_PARAMETER
);
6017 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6018 SetLastError(ERROR_INVALID_USER_BUFFER
);
6021 PLIST_ENTRY ListEntry
;
6022 struct DriverInfoElement
*driverInfo
;
6023 SP_DEVINSTALL_PARAMS_W InstallParams
;
6025 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6026 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6029 if (!DeviceInfoData
)
6030 /* Fall back to destroying class driver list */
6031 DriverType
= SPDIT_CLASSDRIVER
;
6033 if (DriverType
== SPDIT_CLASSDRIVER
)
6035 while (!IsListEmpty(&list
->DriverListHead
))
6037 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
6038 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6039 DestroyDriverInfoElement(driverInfo
);
6041 InstallParams
.Reserved
= 0;
6042 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
6043 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
6044 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
6048 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
6049 struct DeviceInfoElement
*deviceInfo
;
6051 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6052 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
6054 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6055 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
6057 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
6058 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6059 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
6061 InstallParamsSet
.Reserved
= 0;
6062 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
6064 DestroyDriverInfoElement(driverInfo
);
6066 InstallParams
.Reserved
= 0;
6067 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
6068 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
6069 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6074 TRACE("Returning %d\n", ret
);
6079 /***********************************************************************
6080 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6083 SetupDiOpenDeviceInfoA(
6084 IN HDEVINFO DeviceInfoSet
,
6085 IN PCSTR DeviceInstanceId
,
6086 IN HWND hwndParent OPTIONAL
,
6088 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6090 LPWSTR DeviceInstanceIdW
= NULL
;
6093 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6095 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
6096 if (DeviceInstanceIdW
== NULL
)
6099 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
6100 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
6102 MyFree(DeviceInstanceIdW
);
6108 /***********************************************************************
6109 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6112 SetupDiOpenDeviceInfoW(
6113 IN HDEVINFO DeviceInfoSet
,
6114 IN PCWSTR DeviceInstanceId
,
6115 IN HWND hwndParent OPTIONAL
,
6117 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6119 struct DeviceInfoSet
*list
;
6120 HKEY hEnumKey
, hKey
;
6124 TRACE("%p %s %p %lx %p\n",
6125 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
6126 hwndParent
, OpenFlags
, DeviceInfoData
);
6128 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6129 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6132 SetLastError(ERROR_INVALID_HANDLE
);
6133 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6134 SetLastError(ERROR_INVALID_HANDLE
);
6135 else if (!DeviceInstanceId
)
6136 SetLastError(ERROR_INVALID_PARAMETER
);
6137 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6139 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6140 SetLastError(ERROR_INVALID_FLAGS
);
6142 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6143 SetLastError(ERROR_INVALID_USER_BUFFER
);
6146 struct DeviceInfoElement
*deviceInfo
= NULL
;
6147 /* Search if device already exists in DeviceInfoSet.
6148 * If yes, return the existing element
6149 * If no, create a new element using informations in registry
6151 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6152 while (ItemList
!= &list
->ListHead
)
6157 FIXME("not implemented\n");
6158 ItemList
= ItemList
->Flink
;
6163 /* good one found */
6168 /* Open supposed registry key */
6171 REGSTR_PATH_SYSTEMENUM
,
6175 if (rc
!= ERROR_SUCCESS
)
6186 RegCloseKey(hEnumKey
);
6187 if (rc
!= ERROR_SUCCESS
)
6189 if (rc
== ERROR_FILE_NOT_FOUND
)
6190 rc
= ERROR_NO_SUCH_DEVINST
;
6195 /* FIXME: try to get ClassGUID from registry, instead of
6196 * sending GUID_NULL to CreateDeviceInfoElement
6198 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6203 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6209 if (ret
&& deviceInfo
&& DeviceInfoData
)
6211 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6212 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6213 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6221 /***********************************************************************
6222 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6225 SetupDiEnumDriverInfoA(
6226 IN HDEVINFO DeviceInfoSet
,
6227 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6228 IN DWORD DriverType
,
6229 IN DWORD MemberIndex
,
6230 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6232 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6235 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6236 DriverType
, MemberIndex
, DriverInfoData
);
6238 if (DriverInfoData
== NULL
)
6239 SetLastError(ERROR_INVALID_PARAMETER
);
6240 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6241 SetLastError(ERROR_INVALID_USER_BUFFER
);
6244 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6245 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6246 DriverType
, MemberIndex
, &driverInfoData2W
);
6250 /* Do W->A conversion */
6251 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6252 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6253 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6254 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6256 DriverInfoData
->Description
[0] = '\0';
6259 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6260 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6262 DriverInfoData
->MfgName
[0] = '\0';
6265 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6266 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6268 DriverInfoData
->ProviderName
[0] = '\0';
6271 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6273 /* Copy more fields */
6274 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6275 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6280 TRACE("Returning %d\n", ret
);
6285 /***********************************************************************
6286 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6289 SetupDiEnumDriverInfoW(
6290 IN HDEVINFO DeviceInfoSet
,
6291 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6292 IN DWORD DriverType
,
6293 IN DWORD MemberIndex
,
6294 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6296 PLIST_ENTRY ListHead
;
6299 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6300 DriverType
, MemberIndex
, DriverInfoData
);
6302 if (!DeviceInfoSet
|| !DriverInfoData
)
6303 SetLastError(ERROR_INVALID_PARAMETER
);
6304 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6305 SetLastError(ERROR_INVALID_HANDLE
);
6306 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6307 SetLastError(ERROR_INVALID_HANDLE
);
6308 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6309 SetLastError(ERROR_INVALID_PARAMETER
);
6310 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6311 SetLastError(ERROR_INVALID_PARAMETER
);
6312 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6313 SetLastError(ERROR_INVALID_USER_BUFFER
);
6316 struct DeviceInfoElement
*devInfo
= NULL
;
6317 PLIST_ENTRY ItemList
;
6319 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6320 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6322 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6326 ListHead
= &devInfo
->DriverListHead
;
6329 ItemList
= ListHead
->Flink
;
6330 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6331 ItemList
= ItemList
->Flink
;
6332 if (ItemList
== ListHead
)
6333 SetLastError(ERROR_NO_MORE_ITEMS
);
6336 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6339 &DriverInfoData
->DriverType
,
6340 &DrvInfo
->Info
.DriverType
,
6341 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6346 TRACE("Returning %d\n", ret
);
6351 /***********************************************************************
6352 * SetupDiGetSelectedDevice (SETUPAPI.@)
6355 SetupDiGetSelectedDevice(
6356 IN HDEVINFO DeviceInfoSet
,
6357 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6359 struct DeviceInfoSet
*list
;
6362 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6365 SetLastError(ERROR_INVALID_HANDLE
);
6366 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6367 SetLastError(ERROR_INVALID_HANDLE
);
6368 else if (list
->SelectedDevice
== NULL
)
6369 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6370 else if (!DeviceInfoData
)
6371 SetLastError(ERROR_INVALID_PARAMETER
);
6372 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6373 SetLastError(ERROR_INVALID_USER_BUFFER
);
6376 memcpy(&DeviceInfoData
->ClassGuid
,
6377 &list
->SelectedDevice
->ClassGuid
,
6379 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6380 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6384 TRACE("Returning %d\n", ret
);
6389 /***********************************************************************
6390 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6393 SetupDiGetSelectedDriverA(
6394 IN HDEVINFO DeviceInfoSet
,
6395 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6396 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6398 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6401 if (DriverInfoData
== NULL
)
6402 SetLastError(ERROR_INVALID_PARAMETER
);
6403 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6404 SetLastError(ERROR_INVALID_USER_BUFFER
);
6407 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6409 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6415 /* Do W->A conversion */
6416 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6417 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6418 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6419 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6421 DriverInfoData
->Description
[0] = '\0';
6424 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6425 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6427 DriverInfoData
->MfgName
[0] = '\0';
6430 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6431 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6433 DriverInfoData
->ProviderName
[0] = '\0';
6436 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6438 /* Copy more fields */
6439 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6440 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6449 /***********************************************************************
6450 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6453 SetupDiGetSelectedDriverW(
6454 IN HDEVINFO DeviceInfoSet
,
6455 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6456 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6460 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6462 if (!DeviceInfoSet
|| !DriverInfoData
)
6463 SetLastError(ERROR_INVALID_PARAMETER
);
6464 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6465 SetLastError(ERROR_INVALID_HANDLE
);
6466 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6467 SetLastError(ERROR_INVALID_HANDLE
);
6468 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6469 SetLastError(ERROR_INVALID_USER_BUFFER
);
6470 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6471 SetLastError(ERROR_INVALID_USER_BUFFER
);
6474 SP_DEVINSTALL_PARAMS InstallParams
;
6476 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6477 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6479 struct DriverInfoElement
*driverInfo
;
6480 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6481 if (driverInfo
== NULL
)
6482 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6486 &DriverInfoData
->DriverType
,
6487 &driverInfo
->Info
.DriverType
,
6488 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6494 TRACE("Returning %d\n", ret
);
6499 /***********************************************************************
6500 * SetupDiSetSelectedDevice (SETUPAPI.@)
6503 SetupDiSetSelectedDevice(
6504 IN HDEVINFO DeviceInfoSet
,
6505 IN PSP_DEVINFO_DATA DeviceInfoData
)
6507 struct DeviceInfoSet
*list
;
6510 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6513 SetLastError(ERROR_INVALID_HANDLE
);
6514 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6515 SetLastError(ERROR_INVALID_HANDLE
);
6516 else if (!DeviceInfoData
)
6517 SetLastError(ERROR_INVALID_PARAMETER
);
6518 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6519 SetLastError(ERROR_INVALID_USER_BUFFER
);
6520 else if (DeviceInfoData
->Reserved
== 0)
6521 SetLastError(ERROR_INVALID_USER_BUFFER
);
6524 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6528 TRACE("Returning %d\n", ret
);
6533 /***********************************************************************
6534 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6537 SetupDiSetSelectedDriverA(
6538 IN HDEVINFO DeviceInfoSet
,
6539 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6540 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6542 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6543 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6546 if (DriverInfoData
!= NULL
)
6548 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6549 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6551 SetLastError(ERROR_INVALID_PARAMETER
);
6555 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6556 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6558 if (DriverInfoDataW
.Reserved
== 0)
6560 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6562 /* convert the strings to unicode */
6563 if (!MultiByteToWideChar(CP_ACP
,
6565 DriverInfoData
->Description
,
6567 DriverInfoDataW
.Description
,
6569 !MultiByteToWideChar(CP_ACP
,
6571 DriverInfoData
->ProviderName
,
6573 DriverInfoDataW
.ProviderName
,
6580 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6583 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6587 if (ret
&& pDriverInfoDataW
!= NULL
)
6589 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6596 /***********************************************************************
6597 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6600 SetupDiSetSelectedDriverW(
6601 IN HDEVINFO DeviceInfoSet
,
6602 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6603 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6607 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6610 SetLastError(ERROR_INVALID_PARAMETER
);
6611 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6612 SetLastError(ERROR_INVALID_HANDLE
);
6613 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6614 SetLastError(ERROR_INVALID_HANDLE
);
6615 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6616 SetLastError(ERROR_INVALID_USER_BUFFER
);
6617 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6618 SetLastError(ERROR_INVALID_USER_BUFFER
);
6621 struct DriverInfoElement
**pDriverInfo
;
6622 PLIST_ENTRY ListHead
, ItemList
;
6626 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6627 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6631 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6632 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6635 if (!DriverInfoData
)
6637 *pDriverInfo
= NULL
;
6642 /* Search selected driver in list */
6643 ItemList
= ListHead
->Flink
;
6644 while (ItemList
!= ListHead
)
6646 if (DriverInfoData
->Reserved
!= 0)
6648 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6653 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6654 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6655 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6656 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6657 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6662 ItemList
= ItemList
->Flink
;
6664 if (ItemList
== ListHead
)
6665 SetLastError(ERROR_INVALID_PARAMETER
);
6668 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6669 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6671 TRACE("Choosing driver whose rank is 0x%lx\n",
6672 (*pDriverInfo
)->DriverRank
);
6674 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6679 TRACE("Returning %d\n", ret
);
6683 /***********************************************************************
6684 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6687 SetupDiGetDriverInfoDetailA(
6688 IN HDEVINFO DeviceInfoSet
,
6689 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6690 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6691 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6692 IN DWORD DriverInfoDetailDataSize
,
6693 OUT PDWORD RequiredSize OPTIONAL
)
6695 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6696 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6698 DWORD HardwareIDLen
= 0;
6701 /* do some sanity checks, the unicode version might do more thorough checks */
6702 if (DriverInfoData
== NULL
||
6703 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6704 (DriverInfoDetailData
!= NULL
&&
6705 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6706 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6708 SetLastError(ERROR_INVALID_PARAMETER
);
6712 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6713 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6715 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6717 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6719 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6723 SetLastError(ERROR_INVALID_PARAMETER
);
6726 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6727 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6729 /* convert the strings to unicode */
6730 if (MultiByteToWideChar(CP_ACP
,
6732 DriverInfoData
->Description
,
6734 DriverInfoDataW
.Description
,
6736 MultiByteToWideChar(CP_ACP
,
6738 DriverInfoData
->MfgName
,
6740 DriverInfoDataW
.MfgName
,
6742 MultiByteToWideChar(CP_ACP
,
6744 DriverInfoData
->ProviderName
,
6746 DriverInfoDataW
.ProviderName
,
6749 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6751 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6752 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6755 if (DriverInfoDetailData
!= NULL
)
6757 /* calculate the unicode buffer size from the ansi buffer size */
6758 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6759 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6760 (HardwareIDLen
* sizeof(WCHAR
));
6762 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6763 if (DriverInfoDetailDataW
== NULL
)
6765 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6769 /* initialize the buffer */
6770 ZeroMemory(DriverInfoDetailDataW
,
6772 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6775 /* call the unicode version */
6776 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6779 DriverInfoDetailDataW
,
6785 if (DriverInfoDetailDataW
!= NULL
)
6787 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6788 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6789 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6790 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6791 if (WideCharToMultiByte(CP_ACP
,
6793 DriverInfoDetailDataW
->SectionName
,
6795 DriverInfoDetailData
->SectionName
,
6799 WideCharToMultiByte(CP_ACP
,
6801 DriverInfoDetailDataW
->InfFileName
,
6803 DriverInfoDetailData
->InfFileName
,
6807 WideCharToMultiByte(CP_ACP
,
6809 DriverInfoDetailDataW
->DrvDescription
,
6811 DriverInfoDetailData
->DrvDescription
,
6815 WideCharToMultiByte(CP_ACP
,
6817 DriverInfoDetailDataW
->HardwareID
,
6819 DriverInfoDetailData
->HardwareID
,
6825 DWORD hwidlen
= HardwareIDLen
;
6826 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6828 /* count the strings in the list */
6831 len
= lstrlenA(s
) + 1;
6840 /* looks like the string list wasn't terminated... */
6841 SetLastError(ERROR_INVALID_USER_BUFFER
);
6847 /* make sure CompatIDsOffset points to the second string in the
6851 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6852 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6853 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6857 DriverInfoDetailData
->CompatIDsOffset
= 0;
6858 DriverInfoDetailData
->CompatIDsLength
= 0;
6867 if (RequiredSize
!= NULL
)
6869 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6870 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6876 if (DriverInfoDetailDataW
!= NULL
)
6878 MyFree(DriverInfoDetailDataW
);
6884 /***********************************************************************
6885 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6888 SetupDiGetDriverInfoDetailW(
6889 IN HDEVINFO DeviceInfoSet
,
6890 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6891 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6892 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6893 IN DWORD DriverInfoDetailDataSize
,
6894 OUT PDWORD RequiredSize OPTIONAL
)
6898 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6899 DriverInfoData
, DriverInfoDetailData
,
6900 DriverInfoDetailDataSize
, RequiredSize
);
6903 SetLastError(ERROR_INVALID_PARAMETER
);
6904 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6905 SetLastError(ERROR_INVALID_HANDLE
);
6906 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6907 SetLastError(ERROR_INVALID_HANDLE
);
6908 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6909 SetLastError(ERROR_INVALID_USER_BUFFER
);
6910 else if (!DriverInfoData
)
6911 SetLastError(ERROR_INVALID_PARAMETER
);
6912 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6913 SetLastError(ERROR_INVALID_PARAMETER
);
6914 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6915 SetLastError(ERROR_INVALID_PARAMETER
);
6916 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6917 SetLastError(ERROR_INVALID_USER_BUFFER
);
6918 else if (DriverInfoData
->Reserved
== 0)
6919 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6922 struct DriverInfoElement
*driverInfoElement
;
6923 LPWSTR HardwareIDs
= NULL
;
6924 LPWSTR CompatibleIDs
= NULL
;
6925 LPWSTR pBuffer
= NULL
;
6926 LPCWSTR DeviceID
= NULL
;
6927 ULONG HardwareIDsSize
, CompatibleIDsSize
;
6928 ULONG sizeNeeded
, sizeLeft
, size
;
6931 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6933 /* Get hardware and compatible IDs lists */
6934 Result
= GetHardwareAndCompatibleIDsLists(
6937 &HardwareIDs
, &HardwareIDsSize
,
6938 &CompatibleIDs
, &CompatibleIDsSize
);
6942 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
6943 + HardwareIDsSize
+ CompatibleIDsSize
;
6945 *RequiredSize
= sizeNeeded
;
6947 if (!DriverInfoDetailData
)
6954 DriverInfoDetailData
,
6955 &driverInfoElement
->Details
,
6956 driverInfoElement
->Details
.cbSize
);
6957 DriverInfoDetailData
->CompatIDsOffset
= 0;
6958 DriverInfoDetailData
->CompatIDsLength
= 0;
6960 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
6961 pBuffer
= DriverInfoDetailData
->HardwareID
;
6962 /* Add as many as possible HardwareIDs in the list */
6963 DeviceID
= HardwareIDs
;
6964 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
6966 TRACE("Adding %S to list\n", DeviceID
);
6967 wcscpy(pBuffer
, DeviceID
);
6968 DeviceID
+= size
+ 1;
6969 pBuffer
+= size
+ 1;
6970 sizeLeft
-= size
+ 1;
6971 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
6975 *pBuffer
= UNICODE_NULL
;
6977 DriverInfoDetailData
->CompatIDsOffset
++;
6979 /* Add as many as possible CompatibleIDs in the list */
6980 DeviceID
= CompatibleIDs
;
6981 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
6983 TRACE("Adding %S to list\n", DeviceID
);
6984 wcscpy(pBuffer
, DeviceID
);
6985 DeviceID
+= size
+ 1;
6986 pBuffer
+= size
+ 1;
6987 sizeLeft
-= size
+ 1;
6988 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
6992 *pBuffer
= UNICODE_NULL
;
6994 DriverInfoDetailData
->CompatIDsLength
++;
6997 if (sizeNeeded
> DriverInfoDetailDataSize
)
6998 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
7003 MyFree(HardwareIDs
);
7004 MyFree(CompatibleIDs
);
7007 TRACE("Returning %d\n", ret
);
7011 /* Return the current hardware profile id, or -1 if error */
7013 GetCurrentHwProfile(
7014 IN HDEVINFO DeviceInfoSet
)
7017 DWORD dwRegType
, dwLength
;
7020 DWORD ret
= (DWORD
)-1;
7023 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
7024 REGSTR_PATH_IDCONFIGDB
,
7028 if (rc
!= ERROR_SUCCESS
)
7034 dwLength
= sizeof(DWORD
);
7035 rc
= RegQueryValueExW(
7037 REGSTR_VAL_CURRENTCONFIG
,
7040 (LPBYTE
)&hwProfile
, &dwLength
);
7041 if (rc
!= ERROR_SUCCESS
)
7046 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7048 SetLastError(ERROR_GEN_FAILURE
);
7063 IN HDEVINFO DeviceInfoSet
,
7064 IN PSP_DEVINFO_DATA DeviceInfoData
)
7067 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
7068 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
7071 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
7073 /* At the moment, I only know how to start local devices */
7074 SetLastError(ERROR_INVALID_COMPUTERNAME
);
7078 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
7079 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7080 SetLastError(RtlNtStatusToDosError(Status
));
7081 return NT_SUCCESS(Status
);
7083 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7088 static BOOL
StopDevice(
7089 IN HDEVINFO DeviceInfoSet
,
7090 IN PSP_DEVINFO_DATA DeviceInfoData
)
7092 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7096 /***********************************************************************
7097 * SetupDiChangeState (SETUPAPI.@)
7101 IN HDEVINFO DeviceInfoSet
,
7102 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7104 PSP_PROPCHANGE_PARAMS PropChange
;
7105 HKEY hKey
= INVALID_HANDLE_VALUE
;
7106 LPCWSTR RegistryValueName
;
7107 DWORD dwConfigFlags
, dwLength
, dwRegType
;
7111 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7113 if (!DeviceInfoData
)
7114 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
7116 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
7119 SetLastError(ERROR_INVALID_PARAMETER
);
7123 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
7124 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
7126 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
7128 switch (PropChange
->StateChange
)
7133 /* Enable/disable device in registry */
7134 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
7135 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7136 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
7137 if (hKey
== INVALID_HANDLE_VALUE
)
7139 dwLength
= sizeof(DWORD
);
7140 rc
= RegQueryValueExW(
7145 (LPBYTE
)&dwConfigFlags
, &dwLength
);
7146 if (rc
== ERROR_FILE_NOT_FOUND
)
7148 else if (rc
!= ERROR_SUCCESS
)
7153 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7155 SetLastError(ERROR_GEN_FAILURE
);
7158 if (PropChange
->StateChange
== DICS_ENABLE
)
7159 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7161 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7167 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
7168 if (rc
!= ERROR_SUCCESS
)
7174 /* Enable/disable device if needed */
7175 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
7176 || PropChange
->HwProfile
== 0
7177 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
7179 if (PropChange
->StateChange
== DICS_ENABLE
)
7180 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7182 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
7188 case DICS_PROPCHANGE
:
7190 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7195 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7196 SetLastError(ERROR_NOT_SUPPORTED
);
7201 if (hKey
!= INVALID_HANDLE_VALUE
)
7204 TRACE("Returning %d\n", ret
);
7208 /***********************************************************************
7209 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7212 SetupDiSelectBestCompatDrv(
7213 IN HDEVINFO DeviceInfoSet
,
7214 IN PSP_DEVINFO_DATA DeviceInfoData
)
7216 SP_DRVINFO_DATA_W drvInfoData
;
7219 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7221 /* Drivers are sorted by rank in the driver list, so
7222 * the first driver in the list is the best one.
7224 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7225 ret
= SetupDiEnumDriverInfoW(
7229 0, /* Member index */
7234 ret
= SetupDiSetSelectedDriverW(
7240 TRACE("Returning %d\n", ret
);
7244 /***********************************************************************
7245 * SetupDiInstallDriverFiles (SETUPAPI.@)
7248 SetupDiInstallDriverFiles(
7249 IN HDEVINFO DeviceInfoSet
,
7250 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7254 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7257 SetLastError(ERROR_INVALID_PARAMETER
);
7258 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7259 SetLastError(ERROR_INVALID_HANDLE
);
7260 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7261 SetLastError(ERROR_INVALID_HANDLE
);
7262 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7263 SetLastError(ERROR_INVALID_USER_BUFFER
);
7264 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7265 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7266 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7267 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7270 SP_DEVINSTALL_PARAMS_W InstallParams
;
7271 struct DriverInfoElement
*SelectedDriver
;
7272 WCHAR SectionName
[MAX_PATH
];
7273 DWORD SectionNameLength
= 0;
7274 PVOID InstallMsgHandler
;
7275 PVOID InstallMsgHandlerContext
;
7276 PVOID Context
= NULL
;
7278 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7279 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7283 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7284 if (!SelectedDriver
)
7286 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7290 ret
= SetupDiGetActualSectionToInstallW(
7291 SelectedDriver
->InfFileDetails
->hInf
,
7292 SelectedDriver
->Details
.SectionName
,
7293 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7297 if (InstallParams
.InstallMsgHandler
)
7299 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7300 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7304 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7307 InstallMsgHandler
= SetupDefaultQueueCallback
;
7308 InstallMsgHandlerContext
= Context
;
7310 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7311 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7312 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7313 InstallMsgHandler
, InstallMsgHandlerContext
,
7314 DeviceInfoSet
, DeviceInfoData
);
7318 /* Install files from .CoInstallers section */
7319 lstrcatW(SectionName
, DotCoInstallers
);
7320 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7321 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7322 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7323 InstallMsgHandler
, InstallMsgHandlerContext
,
7324 DeviceInfoSet
, DeviceInfoData
);
7328 /* Set the DI_NOFILECOPY flag to prevent another
7329 * installation during SetupDiInstallDevice */
7330 InstallParams
.Flags
|= DI_NOFILECOPY
;
7331 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7335 SetupTermDefaultQueueCallback(Context
);
7339 TRACE("Returning %d\n", ret
);
7343 /***********************************************************************
7344 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7347 SetupDiRegisterCoDeviceInstallers(
7348 IN HDEVINFO DeviceInfoSet
,
7349 IN PSP_DEVINFO_DATA DeviceInfoData
)
7351 BOOL ret
= FALSE
; /* Return value */
7353 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7356 SetLastError(ERROR_INVALID_PARAMETER
);
7357 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7358 SetLastError(ERROR_INVALID_HANDLE
);
7359 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7360 SetLastError(ERROR_INVALID_HANDLE
);
7361 else if (!DeviceInfoData
)
7362 SetLastError(ERROR_INVALID_PARAMETER
);
7363 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7364 SetLastError(ERROR_INVALID_USER_BUFFER
);
7367 SP_DEVINSTALL_PARAMS_W InstallParams
;
7368 struct DriverInfoElement
*SelectedDriver
;
7371 WCHAR SectionName
[MAX_PATH
];
7372 DWORD SectionNameLength
= 0;
7373 HKEY hKey
= INVALID_HANDLE_VALUE
;
7374 PVOID Context
= NULL
;
7376 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7377 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7381 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7382 if (SelectedDriver
== NULL
)
7384 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7388 /* Get .CoInstallers section name */
7389 Result
= SetupDiGetActualSectionToInstallW(
7390 SelectedDriver
->InfFileDetails
->hInf
,
7391 SelectedDriver
->Details
.SectionName
,
7392 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7393 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7395 lstrcatW(SectionName
, DotCoInstallers
);
7397 /* Open/Create driver key information */
7398 #if _WIN32_WINNT >= 0x502
7399 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7401 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7403 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7404 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7405 if (hKey
== INVALID_HANDLE_VALUE
)
7408 /* Install .CoInstallers section */
7409 DoAction
= SPINST_REGISTRY
;
7410 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7412 DoAction
|= SPINST_FILES
;
7413 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7417 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7418 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7419 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7420 SetupDefaultQueueCallback
, Context
,
7421 DeviceInfoSet
, DeviceInfoData
);
7429 SetupTermDefaultQueueCallback(Context
);
7430 if (hKey
!= INVALID_HANDLE_VALUE
)
7434 TRACE("Returning %d\n", ret
);
7439 InstallOneInterface(
7440 IN LPGUID InterfaceGuid
,
7441 IN LPCWSTR ReferenceString
,
7442 IN LPCWSTR InterfaceSection
,
7443 IN UINT InterfaceFlags
)
7445 if (InterfaceFlags
!= 0)
7447 SetLastError(ERROR_INVALID_PARAMETER
);
7451 FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7452 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7456 /***********************************************************************
7457 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7460 SetupDiInstallDeviceInterfaces(
7461 IN HDEVINFO DeviceInfoSet
,
7462 IN PSP_DEVINFO_DATA DeviceInfoData
)
7464 struct DeviceInfoSet
*list
= NULL
;
7467 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7470 SetLastError(ERROR_INVALID_PARAMETER
);
7471 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7472 SetLastError(ERROR_INVALID_HANDLE
);
7473 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7474 SetLastError(ERROR_INVALID_HANDLE
);
7475 else if (!DeviceInfoData
)
7476 SetLastError(ERROR_INVALID_PARAMETER
);
7477 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7478 SetLastError(ERROR_INVALID_USER_BUFFER
);
7481 struct DriverInfoElement
*SelectedDriver
;
7482 SP_DEVINSTALL_PARAMS_W InstallParams
;
7483 WCHAR SectionName
[MAX_PATH
];
7484 DWORD SectionNameLength
= 0;
7485 INFCONTEXT ContextInterface
;
7486 LPWSTR InterfaceGuidString
= NULL
;
7487 LPWSTR ReferenceString
= NULL
;
7488 LPWSTR InterfaceSection
= NULL
;
7493 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7494 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7498 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7499 if (SelectedDriver
== NULL
)
7501 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7506 /* Get .Interfaces section name */
7507 Result
= SetupDiGetActualSectionToInstallW(
7508 SelectedDriver
->InfFileDetails
->hInf
,
7509 SelectedDriver
->Details
.SectionName
,
7510 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7511 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotInterfaces
) - 1)
7513 strcatW(SectionName
, DotInterfaces
);
7516 Result
= SetupFindFirstLineW(
7517 SelectedDriver
->InfFileDetails
->hInf
,
7521 while (ret
&& Result
)
7523 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7526 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7528 SetLastError(ERROR_INVALID_PARAMETER
);
7533 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7534 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7536 /* Bad GUID, skip the entry */
7537 SetLastError(ERROR_INVALID_PARAMETER
);
7542 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7546 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7550 ret
= SetupGetIntField(
7552 4, /* Field index */
7556 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7558 /* The field may be empty. Ignore the error */
7566 /* Install Interface */
7567 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7570 MyFree(InterfaceGuidString
);
7571 MyFree(ReferenceString
);
7572 MyFree(InterfaceSection
);
7573 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7574 Result
= SetupFindNextMatchLineW(&ContextInterface
, AddInterface
, &ContextInterface
);
7578 TRACE("Returning %d\n", ret
);
7583 InfIsFromOEMLocation(
7585 OUT LPBOOL IsOEMLocation
)
7589 last
= strrchrW(FullName
, '\\');
7592 /* No directory specified */
7593 *IsOEMLocation
= FALSE
;
7597 WCHAR Windir
[MAX_PATH
];
7600 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7601 if (ret
== 0 || ret
>= MAX_PATH
)
7603 SetLastError(ERROR_GEN_FAILURE
);
7607 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7609 /* The path is %WINDIR%\Inf */
7610 *IsOEMLocation
= FALSE
;
7614 /* The file is in another place */
7615 *IsOEMLocation
= TRUE
;
7621 /***********************************************************************
7622 * SetupDiInstallDevice (SETUPAPI.@)
7625 SetupDiInstallDevice(
7626 IN HDEVINFO DeviceInfoSet
,
7627 IN PSP_DEVINFO_DATA DeviceInfoData
)
7629 SP_DEVINSTALL_PARAMS_W InstallParams
;
7630 struct DriverInfoElement
*SelectedDriver
;
7631 SYSTEMTIME DriverDate
;
7632 WCHAR SectionName
[MAX_PATH
];
7634 DWORD SectionNameLength
= 0;
7635 BOOL Result
= FALSE
;
7638 LPWSTR pSectionName
= NULL
;
7639 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7641 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7642 BOOL RebootRequired
= FALSE
;
7643 HKEY hKey
= INVALID_HANDLE_VALUE
;
7644 BOOL NeedtoCopyFile
;
7645 LARGE_INTEGER fullVersion
;
7647 PVOID Context
= NULL
;
7648 BOOL ret
= FALSE
; /* Return value */
7650 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7653 SetLastError(ERROR_INVALID_PARAMETER
);
7654 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7655 SetLastError(ERROR_INVALID_HANDLE
);
7656 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7657 SetLastError(ERROR_INVALID_HANDLE
);
7658 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7659 SetLastError(ERROR_INVALID_USER_BUFFER
);
7665 /* One parameter is bad */
7669 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7670 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7674 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7676 /* Set FAILEDINSTALL in ConfigFlags registry value */
7677 DWORD ConfigFlags
, regType
;
7678 Result
= SetupDiGetDeviceRegistryPropertyW(
7683 (PBYTE
)&ConfigFlags
,
7684 sizeof(ConfigFlags
),
7686 if (!Result
|| regType
!= REG_DWORD
)
7688 SetLastError(ERROR_GEN_FAILURE
);
7691 ConfigFlags
|= DNF_DISABLED
;
7692 Result
= SetupDiSetDeviceRegistryPropertyW(
7696 (PBYTE
)&ConfigFlags
,
7697 sizeof(ConfigFlags
));
7700 SetLastError(ERROR_GEN_FAILURE
);
7708 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7709 if (SelectedDriver
== NULL
)
7711 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7715 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7717 Result
= SetupDiGetActualSectionToInstallW(
7718 SelectedDriver
->InfFileDetails
->hInf
,
7719 SelectedDriver
->Details
.SectionName
,
7720 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7721 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
7723 pSectionName
= &SectionName
[strlenW(SectionName
)];
7725 /* Get information from [Version] section */
7726 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7728 /* Format ClassGuid to a string */
7729 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7731 RequiredSize
= lstrlenW(lpGuidString
);
7732 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7733 if (!lpFullGuidString
)
7735 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7738 lpFullGuidString
[0] = '{';
7739 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7740 lpFullGuidString
[RequiredSize
+ 1] = '}';
7741 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7743 /* Open/Create driver key information */
7744 #if _WIN32_WINNT >= 0x502
7745 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7747 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7749 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7750 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7751 if (hKey
== INVALID_HANDLE_VALUE
)
7754 /* Install main section */
7756 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7757 DoAction
|= SPINST_REGISTRY
;
7758 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7760 DoAction
|= SPINST_FILES
;
7761 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7765 *pSectionName
= '\0';
7766 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7767 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7768 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7769 SetupDefaultQueueCallback
, Context
,
7770 DeviceInfoSet
, DeviceInfoData
);
7773 InstallParams
.Flags
|= DI_NOFILECOPY
;
7774 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7776 /* Write information to driver key */
7777 *pSectionName
= UNICODE_NULL
;
7778 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7779 TRACE("Write information to driver key\n");
7780 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7781 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7782 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7783 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->Details
.InfFileName
));
7784 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
7785 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
7786 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
7787 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
7788 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7789 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7790 if (rc
== ERROR_SUCCESS
)
7791 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7792 if (rc
== ERROR_SUCCESS
)
7793 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7794 if (rc
== ERROR_SUCCESS
)
7796 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7797 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7799 if (rc
== ERROR_SUCCESS
)
7800 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (strlenW(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7801 if (rc
== ERROR_SUCCESS
)
7802 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7803 if (rc
== ERROR_SUCCESS
)
7804 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)], (strlenW(SectionName
) - strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7805 if (rc
== ERROR_SUCCESS
)
7806 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7807 if (rc
== ERROR_SUCCESS
)
7808 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7809 if (rc
!= ERROR_SUCCESS
)
7815 hKey
= INVALID_HANDLE_VALUE
;
7817 /* FIXME: Process .LogConfigOverride section */
7819 /* Install .Services section */
7820 strcpyW(pSectionName
, DotServices
);
7821 Result
= SetupInstallServicesFromInfSectionExW(
7822 SelectedDriver
->InfFileDetails
->hInf
,
7831 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7832 RebootRequired
= TRUE
;
7834 /* Copy .inf file to Inf\ directory (if needed) */
7835 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7840 Result
= SetupCopyOEMInfW(
7841 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7844 SP_COPY_NOOVERWRITE
,
7850 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7851 * to release use of current InfFile */
7854 /* Open device registry key */
7855 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7856 if (hKey
== INVALID_HANDLE_VALUE
)
7859 /* Install .HW section */
7861 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7862 DoAction
|= SPINST_REGISTRY
;
7863 strcpyW(pSectionName
, DotHW
);
7864 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7865 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7866 DoAction
, hKey
, NULL
, 0,
7868 DeviceInfoSet
, DeviceInfoData
);
7872 /* Write information to enum key */
7873 TRACE("Write information to enum key\n");
7874 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
7875 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
7876 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7877 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
7878 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
7879 if (rc
== ERROR_SUCCESS
)
7880 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7881 if (rc
== ERROR_SUCCESS
)
7882 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7883 if (rc
== ERROR_SUCCESS
)
7884 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7885 if (rc
!= ERROR_SUCCESS
)
7891 /* Start the device */
7892 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7893 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7898 /* End of installation */
7899 if (hKey
!= INVALID_HANDLE_VALUE
)
7902 RpcStringFreeW(&lpGuidString
);
7903 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7905 SetupTermDefaultQueueCallback(Context
);
7906 TRACE("Returning %d\n", ret
);