Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489/** PROJECT: ReactOS Device Manager* LICENSE: GPL - See COPYING in the top level directory* FILE: dll/win32/devmgr/devmgmt/ClassNode.cpp* PURPOSE: Class object for* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>**/
#include "precomp.h"#include "devmgmt.h"#include "DeviceNode.h"
CDeviceNode::CDeviceNode( _In_opt_ DEVINST Device, _In_ PSP_CLASSIMAGELIST_DATA ImageListData ) : CNode(DeviceNode, ImageListData), m_DevInst(Device), m_hDevInfo(NULL), m_Status(0), m_ProblemNumber(0), m_OverlayImage(0){ ZeroMemory(&m_DevinfoData, sizeof(SP_DEVINFO_DATA));}
CDeviceNode::CDeviceNode( _In_ const CDeviceNode &Node ) : CNode(Node){ m_DevInst = Node.m_DevInst; m_hDevInfo = Node.m_hDevInfo; m_Status = Node.m_Status; m_ProblemNumber = Node.m_ProblemNumber; m_OverlayImage = Node.m_OverlayImage; CopyMemory(&m_DevinfoData, &Node.m_DevinfoData, sizeof(SP_DEVINFO_DATA));
size_t size = wcslen(Node.m_DeviceId) + 1; m_DeviceId = new WCHAR[size]; StringCbCopyW(m_DeviceId, size * sizeof(WCHAR), Node.m_DeviceId);}
CDeviceNode::~CDeviceNode(){ Cleanup();}
boolCDeviceNode::SetupNode(){ WCHAR ClassGuidString[MAX_GUID_STRING_LEN]; ULONG ulLength; CONFIGRET cr;
// Get the length of the device id string cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0); if (cr == CR_SUCCESS) { // We alloc heap here because this will be stored in the lParam of the TV m_DeviceId = new WCHAR[ulLength + 1];
// Now get the actual device id cr = CM_Get_Device_IDW(m_DevInst, m_DeviceId, ulLength + 1, 0); if (cr != CR_SUCCESS || wcscmp(m_DeviceId, L"HTREE\\ROOT\\0") == 0) { delete[] m_DeviceId; m_DeviceId = NULL; } }
// Make sure we got the string if (m_DeviceId == NULL) return false;
// Build up a handle a and devinfodata struct m_hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); if (m_hDevInfo != INVALID_HANDLE_VALUE) { m_DevinfoData.cbSize = sizeof(SP_DEVINFO_DATA); SetupDiOpenDeviceInfoW(m_hDevInfo, m_DeviceId, NULL, 0, &m_DevinfoData); }
// Check if the device has a problem if (HasProblem()) { if (IsDisabled()) { m_OverlayImage = OverlayDisabled; } else { m_OverlayImage = OverlayProblem; } }
// Get the class guid for this device ulLength = MAX_GUID_STRING_LEN * sizeof(WCHAR); cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst, CM_DRP_CLASSGUID, NULL, ClassGuidString, &ulLength, 0); if (cr == CR_SUCCESS) { // Convert the string to a proper guid CLSIDFromString(ClassGuidString, &m_ClassGuid); } else { // It's a device with no driver m_ClassGuid = GUID_DEVCLASS_UNKNOWN; }
// Get the image for the class this device is in SetupDiGetClassImageIndex(m_ImageListData, &m_ClassGuid, &m_ClassImage);
// Get the description for the device ulLength = sizeof(m_DisplayName); cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst, CM_DRP_FRIENDLYNAME, NULL, m_DisplayName, &ulLength, 0); if (cr != CR_SUCCESS) { ulLength = sizeof(m_DisplayName); cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst, CM_DRP_DEVICEDESC, NULL, m_DisplayName, &ulLength, 0); }
if (cr != CR_SUCCESS) { CAtlStringW str; if (str.LoadStringW(g_hThisInstance, IDS_UNKNOWNDEVICE)) StringCchCopyW(m_DisplayName, MAX_PATH, str.GetBuffer()); }
return true;}
boolCDeviceNode::HasProblem(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { return ((m_Status & (DN_HAS_PROBLEM | DN_PRIVATE_PROBLEM)) != 0); }
return false;}
boolCDeviceNode::IsHidden(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { if (m_Status & DN_NO_SHOW_IN_DM) return true; }
if (IsEqualGUID(*GetClassGuid(), GUID_DEVCLASS_LEGACYDRIVER) || IsEqualGUID(*GetClassGuid(), GUID_DEVCLASS_VOLUME)) return true;
return false;}
boolCDeviceNode::CanDisable(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { return ((m_Status & DN_DISABLEABLE) != 0); }
return false;}
boolCDeviceNode::IsDisabled(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { return ((m_ProblemNumber == CM_PROB_DISABLED) || (m_ProblemNumber == CM_PROB_HARDWARE_DISABLED)); }
return false;}
boolCDeviceNode::IsStarted(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { return ((m_Status & DN_STARTED) != 0); }
return false;}
boolCDeviceNode::IsInstalled(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { return ((m_Status & DN_HAS_PROBLEM) != 0 || (m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0); }
return false;}
boolCDeviceNode::CanUninstall(){ CONFIGRET cr; cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, m_DevInst, 0, NULL); if (cr == CR_SUCCESS) { if ((m_Status & DN_ROOT_ENUMERATED) != 0 && (m_Status & DN_DISABLEABLE) == 0) return false; }
return true;}
boolCDeviceNode::EnableDevice( _In_ bool Enable, _Out_ bool &NeedsReboot ){ bool Canceled = false;
SetFlags(DI_NODI_DEFAULTACTION, 0);
SP_PROPCHANGE_PARAMS pcp; pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; pcp.StateChange = (Enable ? DICS_ENABLE : DICS_DISABLE); pcp.HwProfile = 0;
// check both scopes to make sure we can make the change for (int i = 0; i < 2; i++) { // Check globally first, then check config specific pcp.Scope = (i == 0) ? DICS_FLAG_CONFIGGENERAL : DICS_FLAG_CONFIGSPECIFIC;
if (SetupDiSetClassInstallParamsW(m_hDevInfo, &m_DevinfoData, &pcp.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS))) { SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, m_hDevInfo, &m_DevinfoData); }
if (GetLastError() == ERROR_CANCELLED) { Canceled = true; break; } }
if (Canceled == false) { pcp.Scope = DICS_FLAG_CONFIGSPECIFIC; if (SetupDiSetClassInstallParamsW(m_hDevInfo, &m_DevinfoData, &pcp.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS))) { SetupDiChangeState(m_hDevInfo, &m_DevinfoData); }
if (Enable) { // config specific enabling first, then global enabling. // The global appears to be the one that starts the device pcp.Scope = DICS_FLAG_GLOBAL; if (SetupDiSetClassInstallParamsW(m_hDevInfo, &m_DevinfoData, &pcp.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS))) { SetupDiChangeState(m_hDevInfo, &m_DevinfoData); } }
SetFlags(DI_PROPERTIES_CHANGE, 0);
NeedsReboot = ((GetFlags() & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0); }
RemoveFlags(DI_NODI_DEFAULTACTION, 0);
return true;}
boolCDeviceNode::UninstallDevice(){ if (CanUninstall() == false) return false;
SP_REMOVEDEVICE_PARAMS RemoveDevParams; RemoveDevParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); RemoveDevParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; RemoveDevParams.Scope = DI_REMOVEDEVICE_GLOBAL; RemoveDevParams.HwProfile = 0;
// // We probably need to walk all the siblings of this // device and ask if they're happy with the uninstall //
// Remove it SetupDiSetClassInstallParamsW(m_hDevInfo, &m_DevinfoData, &RemoveDevParams.ClassInstallHeader, sizeof(SP_REMOVEDEVICE_PARAMS)); SetupDiCallClassInstaller(DIF_REMOVE, m_hDevInfo, &m_DevinfoData);
// Clear the install params SetupDiSetClassInstallParamsW(m_hDevInfo, &m_DevinfoData, NULL, 0);
return true;}
boolCDeviceNode::HasResources(){ HKEY hKey = NULL; DWORD dwError, dwSize = 0;
CStringW keyName = L"SYSTEM\\CurrentControlSet\\Enum\\"; keyName += m_DeviceId; keyName += L"\\Control";
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &hKey); if (dwError == ERROR_SUCCESS) { RegQueryValueExW(hKey, L"AllocConfig", NULL, NULL, NULL, &dwSize); RegCloseKey(hKey); }
return (dwSize != 0);}
/* PRIVATE METHODS ******************************************************/
voidCDeviceNode::Cleanup(){ if (m_DeviceId) { delete[] m_DeviceId; m_DeviceId = NULL; } if (m_hDevInfo) { SetupDiDestroyDeviceInfoList(m_hDevInfo); m_hDevInfo = NULL; }}
DWORDCDeviceNode::GetFlags(){ SP_DEVINSTALL_PARAMS DevInstallParams; DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParamsW(m_hDevInfo, &m_DevinfoData, &DevInstallParams)) { return DevInstallParams.Flags; } return 0;}
boolCDeviceNode::SetFlags( _In_ DWORD Flags, _In_ DWORD FlagsEx ){ SP_DEVINSTALL_PARAMS DevInstallParams; DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParamsW(m_hDevInfo, &m_DevinfoData, &DevInstallParams)) { DevInstallParams.Flags |= Flags; DevInstallParams.FlagsEx |= FlagsEx; return (SetupDiSetDeviceInstallParamsW(m_hDevInfo, &m_DevinfoData, &DevInstallParams) != 0); } return false;}
boolCDeviceNode::RemoveFlags( _In_ DWORD Flags, _In_ DWORD FlagsEx ){ SP_DEVINSTALL_PARAMS DevInstallParams; DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParamsW(m_hDevInfo, &m_DevinfoData, &DevInstallParams)) { DevInstallParams.Flags &= ~Flags; DevInstallParams.FlagsEx &= ~FlagsEx; return (SetupDiSetDeviceInstallParamsW(m_hDevInfo, &m_DevinfoData, &DevInstallParams) != 0); } return false;}