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
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
,
119 // Get the description for the device
120 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
121 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
127 if (cr
!= CR_SUCCESS
)
129 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
130 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
139 // Cleanup if something failed
140 if (cr
!= CR_SUCCESS
)
150 CDeviceNode::HasProblem()
153 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
158 if (cr
== CR_SUCCESS
)
160 return ((m_Status
& (DN_HAS_PROBLEM
| DN_PRIVATE_PROBLEM
)) != 0);
167 CDeviceNode::IsHidden()
170 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
175 if (cr
== CR_SUCCESS
)
177 return ((m_Status
& DN_NO_SHOW_IN_DM
) != 0);
184 CDeviceNode::CanDisable()
187 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
192 if (cr
== CR_SUCCESS
)
194 return ((m_Status
& DN_DISABLEABLE
) != 0);
201 CDeviceNode::IsDisabled()
204 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
209 if (cr
== CR_SUCCESS
)
211 return ((m_ProblemNumber
& (CM_PROB_DISABLED
| CM_PROB_HARDWARE_DISABLED
)) != 0);
218 CDeviceNode::IsStarted()
221 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
226 if (cr
== CR_SUCCESS
)
228 return ((m_Status
& DN_STARTED
) != 0);
235 CDeviceNode::IsInstalled()
238 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
243 if (cr
== CR_SUCCESS
)
245 return ((m_Status
& DN_HAS_PROBLEM
) != 0 ||
246 (m_Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
253 CDeviceNode::CanUninstall()
256 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
261 if (cr
== CR_SUCCESS
)
263 if ((m_Status
& DN_ROOT_ENUMERATED
) != 0 &&
264 (m_Status
& DN_DISABLEABLE
) == 0)
272 CDeviceNode::EnableDevice(
274 _Out_
bool &NeedsReboot
277 bool Canceled
= false;
279 SetFlags(DI_NODI_DEFAULTACTION
, 0);
281 SP_PROPCHANGE_PARAMS pcp
;
282 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
283 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
284 pcp
.StateChange
= (Enable
? DICS_ENABLE
: DICS_DISABLE
);
288 // check both scopes to make sure we can make the change
289 for (int i
= 0; i
< 2; i
++)
291 // Check globally first, then check config specific
292 pcp
.Scope
= (i
== 0) ? DICS_FLAG_GLOBAL
: DICS_FLAG_CONFIGSPECIFIC
;
294 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
296 &pcp
.ClassInstallHeader
,
297 sizeof(SP_PROPCHANGE_PARAMS
)))
299 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
304 if (GetLastError() == ERROR_CANCELLED
)
311 if (Canceled
== false)
313 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
314 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
316 &pcp
.ClassInstallHeader
,
317 sizeof(SP_PROPCHANGE_PARAMS
)))
319 SetupDiChangeState(m_hDevInfo
, &m_DevinfoData
);
324 // config specific enabling first, then global enabling.
325 // The global appears to be the one that starts the device
326 pcp
.Scope
= DICS_FLAG_GLOBAL
;
327 if (SetupDiSetClassInstallParamsW(m_hDevInfo
,
329 &pcp
.ClassInstallHeader
,
330 sizeof(SP_PROPCHANGE_PARAMS
)))
332 SetupDiChangeState(m_hDevInfo
, &m_DevinfoData
);
336 SetFlags(DI_PROPERTIES_CHANGE
, 0);
338 NeedsReboot
= ((GetFlags() & (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
341 RemoveFlags(DI_NODI_DEFAULTACTION
, 0);
347 CDeviceNode::UninstallDevice()
350 if (CanUninstall() == false)
353 SP_REMOVEDEVICE_PARAMS RemoveDevParams
;
354 RemoveDevParams
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
355 RemoveDevParams
.ClassInstallHeader
.InstallFunction
= DIF_REMOVE
;
356 RemoveDevParams
.Scope
= DI_REMOVEDEVICE_GLOBAL
;
357 RemoveDevParams
.HwProfile
= 0;
360 // We probably need to walk all the siblings of this
361 // device and ask if they're happy with the uninstall
366 SetupDiSetClassInstallParamsW(m_hDevInfo
,
368 &RemoveDevParams
.ClassInstallHeader
,
369 sizeof(SP_REMOVEDEVICE_PARAMS
));
370 SetupDiCallClassInstaller(DIF_REMOVE
, m_hDevInfo
, &m_DevinfoData
);
372 // Clear the install params
373 SetupDiSetClassInstallParamsW(m_hDevInfo
,
382 /* PRIVATE METHODS ******************************************************/
385 CDeviceNode::Cleanup()
394 SetupDiDestroyDeviceInfoList(m_hDevInfo
);
400 CDeviceNode::GetFlags(
403 SP_DEVINSTALL_PARAMS DevInstallParams
;
404 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
405 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
409 return DevInstallParams
.Flags
;
415 CDeviceNode::SetFlags(
420 SP_DEVINSTALL_PARAMS DevInstallParams
;
421 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
422 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
426 DevInstallParams
.Flags
|= Flags
;
427 DevInstallParams
.FlagsEx
|= FlagsEx
;
428 return (SetupDiSetDeviceInstallParamsW(m_hDevInfo
,
430 &DevInstallParams
) != 0);
436 CDeviceNode::RemoveFlags(
441 SP_DEVINSTALL_PARAMS DevInstallParams
;
442 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
443 if (SetupDiGetDeviceInstallParamsW(m_hDevInfo
,
447 DevInstallParams
.Flags
&= ~Flags
;
448 DevInstallParams
.FlagsEx
&= ~FlagsEx
;
449 return (SetupDiSetDeviceInstallParamsW(m_hDevInfo
,
451 &DevInstallParams
) != 0);