2 * PROJECT: ReactOS Device Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/devmgr/devmgr/ClassNode.cpp
5 * PURPOSE: Class object for
6 * COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
12 #include "DeviceNode.h"
15 CDeviceNode::CDeviceNode(
16 _In_opt_ DEVINST Device
,
17 _In_ PSP_CLASSIMAGELIST_DATA ImageListData
25 ZeroMemory(&m_DevinfoData
, sizeof(SP_DEVINFO_DATA
));
28 CDeviceNode::~CDeviceNode()
30 SetupDiDestroyDeviceInfoList(m_hDevInfo
);
34 CDeviceNode::SetupNode()
36 WCHAR ClassGuidString
[MAX_GUID_STRING_LEN
];
40 // ATLASSERT(m_DeviceId == NULL);
43 // Get the length of the device id string
44 cr
= CM_Get_Device_ID_Size(&ulLength
, m_DevInst
, 0);
47 // We alloc heap here because this will be stored in the lParam of the TV
48 m_DeviceId
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
50 (ulLength
+ 1) * sizeof(WCHAR
));
53 // Now get the actual device id
54 cr
= CM_Get_Device_IDW(m_DevInst
,
60 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
66 // Make sure we got the string
67 if (m_DeviceId
== NULL
)
70 //SP_DEVINFO_DATA DevinfoData;
71 m_hDevInfo
= SetupDiCreateDeviceInfoListExW(NULL
,
75 if (m_hDevInfo
!= INVALID_HANDLE_VALUE
)
77 m_DevinfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
78 SetupDiOpenDeviceInfoW(m_hDevInfo
,
87 // Get the current status of the device
88 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
95 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
100 // Check if the device has a problem
101 if (m_Status
& DN_HAS_PROBLEM
)
106 // The disabled overlay takes precidence over the problem overlay
107 if (m_ProblemNumber
& (CM_PROB_DISABLED
| CM_PROB_HARDWARE_DISABLED
))
113 // Get the class guid for this device
114 ulLength
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
115 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
121 if (cr
== CR_SUCCESS
)
123 // Convert the string to a proper guid
124 CLSIDFromString(ClassGuidString
, &m_ClassGuid
);
128 // It's a device with no driver
129 m_ClassGuid
= GUID_DEVCLASS_UNKNOWN
;
133 // Get the image for the class this device is in
134 SetupDiGetClassImageIndex(m_ImageListData
,
138 // Get the description for the device
139 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
140 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
146 if (cr
!= CR_SUCCESS
)
148 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
149 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
158 // Cleanup if something failed
159 if (cr
!= CR_SUCCESS
)
161 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
165 return (cr
== CR_SUCCESS
? true : false);
169 CDeviceNode::HasProblem()
172 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
177 if (cr
== CR_SUCCESS
)
179 return ((m_Status
& (DN_HAS_PROBLEM
| DN_PRIVATE_PROBLEM
)) != 0);
186 CDeviceNode::IsHidden()
189 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
194 if (cr
== CR_SUCCESS
)
196 return ((m_Status
& DN_NO_SHOW_IN_DM
) != 0);
203 CDeviceNode::CanDisable()
206 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
211 if (cr
== CR_SUCCESS
)
213 return ((m_Status
& DN_DISABLEABLE
) != 0);
220 CDeviceNode::IsDisabled()
223 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
228 if (cr
== CR_SUCCESS
)
230 return ((m_ProblemNumber
& (CM_PROB_DISABLED
| CM_PROB_HARDWARE_DISABLED
)) != 0);
237 CDeviceNode::IsStarted()
240 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
245 if (cr
== CR_SUCCESS
)
247 return ((m_Status
& DN_STARTED
) != 0);
254 CDeviceNode::IsInstalled()
257 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
262 if (cr
== CR_SUCCESS
)
264 return ((m_Status
& DN_HAS_PROBLEM
) != 0 ||
265 (m_Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
272 CDeviceNode::CanUninstall()
275 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
280 if (cr
== CR_SUCCESS
)
282 return ((m_Status
& DN_DISABLEABLE
) != 0 &&
283 (m_Status
& DN_ROOT_ENUMERATED
) == 0);
290 CDeviceNode::EnableDevice(
292 _Out_
bool &NeedsReboot
296 bool Canceled
= false;
298 SetFlags(DI_NODI_DEFAULTACTION
, 0);
300 SP_PROPCHANGE_PARAMS pcp
;
301 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
302 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
303 pcp
.StateChange
= (Enable
? DICS_ENABLE
: DICS_DISABLE
);
307 // check both scopes to make sure we can make the change
308 for (int i
= 0; i
< 2; i
++)
310 // Check globally first, then check config specific
311 pcp
.Scope
= (i
== 0) ? DICS_FLAG_GLOBAL
: DICS_FLAG_CONFIGSPECIFIC
;
313 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
315 &pcp
.ClassInstallHeader
,
316 sizeof(SP_PROPCHANGE_PARAMS
)))
318 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
323 if (GetLastError() == ERROR_CANCELLED
)
330 if (Canceled
== false)
332 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
333 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
335 &pcp
.ClassInstallHeader
,
336 sizeof(SP_PROPCHANGE_PARAMS
)))
338 SetupDiChangeState(m_hDevInfo
, &m_DevinfoData
);
343 pcp
.Scope
= DICS_FLAG_GLOBAL
;
344 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
346 &pcp
.ClassInstallHeader
,
347 sizeof(SP_PROPCHANGE_PARAMS
)))
349 SetupDiChangeState(m_hDevInfo
, &m_DevinfoData
);
353 SetFlags(DI_PROPERTIES_CHANGE
, 0);
355 NeedsReboot
= ((GetFlags() & (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
358 RemoveFlags(DI_NODI_DEFAULTACTION
, 0);
364 CDeviceNode::GetFlags(
367 SP_DEVINSTALL_PARAMS DevInstallParams
;
368 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
369 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
373 return DevInstallParams
.Flags
;
379 CDeviceNode::SetFlags(
384 SP_DEVINSTALL_PARAMS DevInstallParams
;
385 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
386 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
390 DevInstallParams
.Flags
|= Flags
;
391 DevInstallParams
.FlagsEx
|= FlagsEx
;
392 return SetupDiSetDeviceInstallParamsW(m_hDevInfo
,
400 CDeviceNode::RemoveFlags(
405 SP_DEVINSTALL_PARAMS DevInstallParams
;
406 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
407 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
411 DevInstallParams
.Flags
&= ~Flags
;
412 DevInstallParams
.FlagsEx
&= ~FlagsEx
;
413 return SetupDiSetDeviceInstallParamsW(m_hDevInfo
,