Author: gedmurphy Date: Thu Jun 25 18:59:23 2015 New Revision: 68265
URL: http://svn.reactos.org/svn/reactos?rev=68265&view=rev Log: [DEVMGR] - Add basic functionality for enabling and disabling devices. Make it accessible via the toolbar and main menu - Implement checking whether a device has a problem and if a device can be uninstalled - Implement getting, setting and removing device flags in the install params - Fix creating and destroying the (currently empty) context menu
Modified: trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.h trunk/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp
Modified: trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/devmgr/devmgmt/De... ============================================================================== --- trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp [iso-8859-1] Thu Jun 25 18:59:23 2015 @@ -22,10 +22,12 @@ m_ProblemNumber(0), m_OverlayImage(0) { + ZeroMemory(&m_DevinfoData, sizeof(SP_DEVINFO_DATA)); }
CDeviceNode::~CDeviceNode() { + SetupDiDestroyDeviceInfoList(m_hDevInfo); }
bool @@ -36,6 +38,7 @@ CONFIGRET cr;
// ATLASSERT(m_DeviceId == NULL); +
// Get the length of the device id string cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0); @@ -64,6 +67,23 @@ if (m_DeviceId == NULL) return false;
+ //SP_DEVINFO_DATA DevinfoData; + 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); + } + + + // Get the current status of the device cr = CM_Get_DevNode_Status_Ex(&m_Status, &m_ProblemNumber, @@ -145,6 +165,22 @@ return (cr == CR_SUCCESS ? true : false); }
+bool +CDeviceNode::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; +}
bool CDeviceNode::IsHidden() @@ -230,4 +266,155 @@ }
return false; -} +} + +bool +CDeviceNode::CanUninstall() +{ + 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 && + (m_Status & DN_ROOT_ENUMERATED) == 0); + } + + return false; +} + +bool +CDeviceNode::EnableDevice( + _In_ bool Enable, + _Out_ bool &NeedsReboot + ) +{ + bool Ret = false; + 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_GLOBAL : 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) + { + 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; +} + +DWORD +CDeviceNode::GetFlags( + ) +{ + SP_DEVINSTALL_PARAMS DevInstallParams; + DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); + if (SetupDiGetDeviceInstallParamsW(m_hDevInfo, + &m_DevinfoData, + &DevInstallParams)) + { + return DevInstallParams.Flags; + } + return 0; +} + +bool +CDeviceNode::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); + } + return false; +} + +bool +CDeviceNode::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); + } + return false; +} + +
Modified: trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/devmgr/devmgmt/De... ============================================================================== --- trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h [iso-8859-1] Thu Jun 25 18:59:23 2015 @@ -4,6 +4,8 @@ class CDeviceNode : public CNode { private: + SP_DEVINFO_DATA m_DevinfoData; + HDEVINFO m_hDevInfo; DEVINST m_DevInst; ULONG m_Status; ULONG m_ProblemNumber; @@ -22,13 +24,31 @@ DEVINST GetDeviceInst() { return m_DevInst; } int GetOverlayImage() { return m_OverlayImage; }
- bool HasProblem() { return !!(m_ProblemNumber); } + bool HasProblem(); bool IsHidden(); bool CanDisable(); bool IsDisabled(); bool IsStarted(); bool IsInstalled(); - bool CanInstall() { return TRUE; } // unimplemented - bool CanUninstall() { return TRUE; } // unimplemented + bool CanUninstall(); + + bool EnableDevice( + _In_ bool Enable, + _Out_ bool &NeedsReboot + ); + +private: + bool SetFlags( + _In_ DWORD Flags, + _In_ DWORD FlagsEx + ); + + bool RemoveFlags( + _In_ DWORD Flags, + _In_ DWORD FlagsEx + ); + + DWORD GetFlags( + ); };
Modified: trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/devmgr/devmgmt/De... ============================================================================== --- trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp [iso-8859-1] Thu Jun 25 18:59:23 2015 @@ -92,8 +92,7 @@ }
// Create the context menu and make properties the default item - m_hMenu = LoadMenuW(g_hInstance, MAKEINTRESOURCEW(IDR_POPUP)); - m_hContextMenu = GetSubMenu(m_hMenu, 0); + m_hContextMenu = CreatePopupMenu(); SetMenuDefaultItem(m_hContextMenu, IDC_PROPERTIES, FALSE);
return !!(m_hTreeView); @@ -110,7 +109,7 @@ ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA)); }
- DestroyMenu(m_hMenu); + DestroyMenu(m_hContextMenu);
return true; } @@ -167,6 +166,18 @@ ScreenToClient(m_hTreeView, &pt) && PtInRect(&rc, pt)) { + + CNode *Node = GetSelectedNode(); + if (Node && Node->HasProperties()) + { + + } + + + + + + INT xPos = GET_X_LPARAM(lParam); INT yPos = GET_Y_LPARAM(lParam);
@@ -287,6 +298,24 @@ if (Node) { return Node->CanDisable(); + } + return false; +} + +bool +CDeviceView::EnableSelectedDevice( + _In_ bool Enable, + _Out_ bool &NeedsReboot + ) +{ + CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode()); + if (Node) + { + if (Node->EnableDevice(Enable, NeedsReboot)) + { + Refresh(m_ViewType, true, true); + return true; + } } return false; } @@ -362,10 +391,10 @@ 0); if (cr != CR_SUCCESS) return false;
- // Check for devices without a class + // Check if this is the unknown class if (IsEqualGUID(*ClassGuid, GUID_DEVCLASS_UNKNOWN)) { - // Get device info for all devices for all classes + // Get device info for all devices *hDevInfo = SetupDiGetClassDevsW(NULL, NULL, NULL, @@ -378,7 +407,6 @@ NULL, NULL, DIGCF_PRESENT); - }
return (hDevInfo != INVALID_HANDLE_VALUE);
Modified: trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/devmgr/devmgmt/De... ============================================================================== --- trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/devmgr/devmgmt/DeviceView.h [iso-8859-1] Thu Jun 25 18:59:23 2015 @@ -78,6 +78,12 @@ bool IsDisabled( _In_ LPTV_ITEMW TvItem ); + + bool EnableSelectedDevice( + _In_ bool Enable, + _Out_ bool &NeedsReboot + ); + bool SelDeviceIsStarted(); bool SelDeviceIsInstalled();
Modified: trunk/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/devmgr/devmgmt/Ma... ============================================================================== --- trunk/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp [iso-8859-1] Thu Jun 25 18:59:23 2015 @@ -507,7 +507,7 @@ { LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam;
- UINT_PTR idButton = (UINT)lpttt->hdr.idFrom; + UINT_PTR idButton = lpttt->hdr.idFrom; switch (idButton) { case IDC_PROPERTIES: @@ -568,13 +568,19 @@
case IDC_ENABLE_DRV: { - MessageBox(m_hMainWnd, L"Not yet implemented", L"Enable Driver", MB_OK); + bool NeedsReboot; + if (m_DeviceView->EnableSelectedDevice(true, NeedsReboot) && + NeedsReboot) + { + MessageBox(m_hMainWnd, L"Rebooting", L"Enable", MB_OK); + } break; }
case IDC_DISABLE_DRV: { - MessageBox(m_hMainWnd, L"Not yet implemented", L"Disable Driver", MB_OK); + bool NeedsReboot; + m_DeviceView->EnableSelectedDevice(false, NeedsReboot); break; }