2 * PROJECT: ReactOS Device Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/devmgr/devmgmt/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
19 CNode(DeviceNode
, ImageListData
),
26 ZeroMemory(&m_DevinfoData
, sizeof(SP_DEVINFO_DATA
));
29 CDeviceNode::~CDeviceNode()
35 CDeviceNode::SetupNode()
37 WCHAR ClassGuidString
[MAX_GUID_STRING_LEN
];
41 // Get the length of the device id string
42 cr
= CM_Get_Device_ID_Size(&ulLength
, m_DevInst
, 0);
45 // We alloc heap here because this will be stored in the lParam of the TV
46 m_DeviceId
= new WCHAR
[ulLength
+ 1];
48 // Now get the actual device id
49 cr
= CM_Get_Device_IDW(m_DevInst
,
61 // Make sure we got the string
62 if (m_DeviceId
== NULL
)
65 // Build up a handle a and devinfodata struct
66 m_hDevInfo
= SetupDiCreateDeviceInfoListExW(NULL
,
70 if (m_hDevInfo
!= INVALID_HANDLE_VALUE
)
72 m_DevinfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
73 SetupDiOpenDeviceInfoW(m_hDevInfo
,
81 // Set the overlay if the device has a problem
87 // The disabled overlay takes precidence over the problem overlay
94 // Get the class guid for this device
95 ulLength
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
96 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
102 if (cr
== CR_SUCCESS
)
104 // Convert the string to a proper guid
105 CLSIDFromString(ClassGuidString
, &m_ClassGuid
);
109 // It's a device with no driver
110 m_ClassGuid
= GUID_DEVCLASS_UNKNOWN
;
114 // Get the image for the class this device is in
115 SetupDiGetClassImageIndex(m_ImageListData
,
120 // Get the description for the device
121 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
122 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
128 if (cr
!= CR_SUCCESS
)
130 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
131 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
140 if (cr
!= CR_SUCCESS
)
143 if (str
.LoadStringW(g_hThisInstance
, IDS_UNKNOWNDEVICE
))
144 StringCchCopyW(m_DisplayName
, MAX_PATH
, str
.GetBuffer());
151 CDeviceNode::HasProblem()
154 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
159 if (cr
== CR_SUCCESS
)
161 return ((m_Status
& (DN_HAS_PROBLEM
| DN_PRIVATE_PROBLEM
)) != 0);
168 CDeviceNode::IsHidden()
171 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
176 if (cr
== CR_SUCCESS
)
178 return ((m_Status
& DN_NO_SHOW_IN_DM
) != 0);
185 CDeviceNode::CanDisable()
188 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
193 if (cr
== CR_SUCCESS
)
195 return ((m_Status
& DN_DISABLEABLE
) != 0);
202 CDeviceNode::IsDisabled()
205 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
210 if (cr
== CR_SUCCESS
)
212 return ((m_ProblemNumber
& (CM_PROB_DISABLED
| CM_PROB_HARDWARE_DISABLED
)) != 0);
219 CDeviceNode::IsStarted()
222 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
227 if (cr
== CR_SUCCESS
)
229 return ((m_Status
& DN_STARTED
) != 0);
236 CDeviceNode::IsInstalled()
239 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
244 if (cr
== CR_SUCCESS
)
246 return ((m_Status
& DN_HAS_PROBLEM
) != 0 ||
247 (m_Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
254 CDeviceNode::CanUninstall()
257 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
262 if (cr
== CR_SUCCESS
)
264 if ((m_Status
& DN_ROOT_ENUMERATED
) != 0 &&
265 (m_Status
& DN_DISABLEABLE
) == 0)
273 CDeviceNode::EnableDevice(
275 _Out_
bool &NeedsReboot
278 bool Canceled
= false;
280 SetFlags(DI_NODI_DEFAULTACTION
, 0);
282 SP_PROPCHANGE_PARAMS pcp
;
283 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
284 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
285 pcp
.StateChange
= (Enable
? DICS_ENABLE
: DICS_DISABLE
);
289 // check both scopes to make sure we can make the change
290 for (int i
= 0; i
< 2; i
++)
292 // Check globally first, then check config specific
293 pcp
.Scope
= (i
== 0) ? DICS_FLAG_GLOBAL
: DICS_FLAG_CONFIGSPECIFIC
;
295 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
297 &pcp
.ClassInstallHeader
,
298 sizeof(SP_PROPCHANGE_PARAMS
)))
300 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
305 if (GetLastError() == ERROR_CANCELLED
)
312 if (Canceled
== false)
314 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
315 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
317 &pcp
.ClassInstallHeader
,
318 sizeof(SP_PROPCHANGE_PARAMS
)))
320 SetupDiChangeState(m_hDevInfo
, &m_DevinfoData
);
325 // config specific enabling first, then global enabling.
326 // The global appears to be the one that starts the device
327 pcp
.Scope
= DICS_FLAG_GLOBAL
;
328 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
330 &pcp
.ClassInstallHeader
,
331 sizeof(SP_PROPCHANGE_PARAMS
)))
333 SetupDiChangeState(m_hDevInfo
, &m_DevinfoData
);
337 SetFlags(DI_PROPERTIES_CHANGE
, 0);
339 NeedsReboot
= ((GetFlags() & (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
342 RemoveFlags(DI_NODI_DEFAULTACTION
, 0);
348 CDeviceNode::UninstallDevice()
351 if (CanUninstall() == false)
354 SP_REMOVEDEVICE_PARAMS RemoveDevParams
;
355 RemoveDevParams
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
356 RemoveDevParams
.ClassInstallHeader
.InstallFunction
= DIF_REMOVE
;
357 RemoveDevParams
.Scope
= DI_REMOVEDEVICE_GLOBAL
;
358 RemoveDevParams
.HwProfile
= 0;
361 // We probably need to walk all the siblings of this
362 // device and ask if they're happy with the uninstall
367 SetupDiSetClassInstallParamsW(m_hDevInfo
,
369 &RemoveDevParams
.ClassInstallHeader
,
370 sizeof(SP_REMOVEDEVICE_PARAMS
));
371 SetupDiCallClassInstaller(DIF_REMOVE
, m_hDevInfo
, &m_DevinfoData
);
373 // Clear the install params
374 SetupDiSetClassInstallParamsW(m_hDevInfo
,
383 /* PRIVATE METHODS ******************************************************/
386 CDeviceNode::Cleanup()
395 SetupDiDestroyDeviceInfoList(m_hDevInfo
);
401 CDeviceNode::GetFlags(
404 SP_DEVINSTALL_PARAMS DevInstallParams
;
405 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
406 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
410 return DevInstallParams
.Flags
;
416 CDeviceNode::SetFlags(
421 SP_DEVINSTALL_PARAMS DevInstallParams
;
422 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
423 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
427 DevInstallParams
.Flags
|= Flags
;
428 DevInstallParams
.FlagsEx
|= FlagsEx
;
429 return (SetupDiSetDeviceInstallParamsW(m_hDevInfo
,
431 &DevInstallParams
) != 0);
437 CDeviceNode::RemoveFlags(
442 SP_DEVINSTALL_PARAMS DevInstallParams
;
443 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
444 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
448 DevInstallParams
.Flags
&= ~Flags
;
449 DevInstallParams
.FlagsEx
&= ~FlagsEx
;
450 return (SetupDiSetDeviceInstallParamsW(m_hDevInfo
,
452 &DevInstallParams
) != 0);