mirror of
https://github.com/reactos/reactos.git
synced 2025-06-20 07:36:05 +00:00
[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 svn path=/trunk/; revision=68265
This commit is contained in:
parent
32e831b904
commit
b9e36d1c46
5 changed files with 260 additions and 13 deletions
|
@ -22,10 +22,12 @@ CDeviceNode::CDeviceNode(
|
||||||
m_ProblemNumber(0),
|
m_ProblemNumber(0),
|
||||||
m_OverlayImage(0)
|
m_OverlayImage(0)
|
||||||
{
|
{
|
||||||
|
ZeroMemory(&m_DevinfoData, sizeof(SP_DEVINFO_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
CDeviceNode::~CDeviceNode()
|
CDeviceNode::~CDeviceNode()
|
||||||
{
|
{
|
||||||
|
SetupDiDestroyDeviceInfoList(m_hDevInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -37,6 +39,7 @@ CDeviceNode::SetupNode()
|
||||||
|
|
||||||
// ATLASSERT(m_DeviceId == NULL);
|
// ATLASSERT(m_DeviceId == NULL);
|
||||||
|
|
||||||
|
|
||||||
// Get the length of the device id string
|
// Get the length of the device id string
|
||||||
cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0);
|
cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0);
|
||||||
if (cr == CR_SUCCESS)
|
if (cr == CR_SUCCESS)
|
||||||
|
@ -64,6 +67,23 @@ CDeviceNode::SetupNode()
|
||||||
if (m_DeviceId == NULL)
|
if (m_DeviceId == NULL)
|
||||||
return false;
|
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
|
// Get the current status of the device
|
||||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||||
&m_ProblemNumber,
|
&m_ProblemNumber,
|
||||||
|
@ -145,6 +165,22 @@ CDeviceNode::SetupNode()
|
||||||
return (cr == CR_SUCCESS ? true : false);
|
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
|
bool
|
||||||
CDeviceNode::IsHidden()
|
CDeviceNode::IsHidden()
|
||||||
|
@ -231,3 +267,154 @@ CDeviceNode::IsInstalled()
|
||||||
|
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
class CDeviceNode : public CNode
|
class CDeviceNode : public CNode
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
SP_DEVINFO_DATA m_DevinfoData;
|
||||||
|
HDEVINFO m_hDevInfo;
|
||||||
DEVINST m_DevInst;
|
DEVINST m_DevInst;
|
||||||
ULONG m_Status;
|
ULONG m_Status;
|
||||||
ULONG m_ProblemNumber;
|
ULONG m_ProblemNumber;
|
||||||
|
@ -22,13 +24,31 @@ public:
|
||||||
DEVINST GetDeviceInst() { return m_DevInst; }
|
DEVINST GetDeviceInst() { return m_DevInst; }
|
||||||
int GetOverlayImage() { return m_OverlayImage; }
|
int GetOverlayImage() { return m_OverlayImage; }
|
||||||
|
|
||||||
bool HasProblem() { return !!(m_ProblemNumber); }
|
bool HasProblem();
|
||||||
bool IsHidden();
|
bool IsHidden();
|
||||||
bool CanDisable();
|
bool CanDisable();
|
||||||
bool IsDisabled();
|
bool IsDisabled();
|
||||||
bool IsStarted();
|
bool IsStarted();
|
||||||
bool IsInstalled();
|
bool IsInstalled();
|
||||||
bool CanInstall() { return TRUE; } // unimplemented
|
bool CanUninstall();
|
||||||
bool CanUninstall() { return TRUE; } // unimplemented
|
|
||||||
|
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(
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -92,8 +92,7 @@ CDeviceView::Initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the context menu and make properties the default item
|
// Create the context menu and make properties the default item
|
||||||
m_hMenu = LoadMenuW(g_hInstance, MAKEINTRESOURCEW(IDR_POPUP));
|
m_hContextMenu = CreatePopupMenu();
|
||||||
m_hContextMenu = GetSubMenu(m_hMenu, 0);
|
|
||||||
SetMenuDefaultItem(m_hContextMenu, IDC_PROPERTIES, FALSE);
|
SetMenuDefaultItem(m_hContextMenu, IDC_PROPERTIES, FALSE);
|
||||||
|
|
||||||
return !!(m_hTreeView);
|
return !!(m_hTreeView);
|
||||||
|
@ -110,7 +109,7 @@ CDeviceView::Uninitialize()
|
||||||
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyMenu(m_hMenu);
|
DestroyMenu(m_hContextMenu);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +166,18 @@ CDeviceView::OnContextMenu(
|
||||||
ScreenToClient(m_hTreeView, &pt) &&
|
ScreenToClient(m_hTreeView, &pt) &&
|
||||||
PtInRect(&rc, pt))
|
PtInRect(&rc, pt))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
CNode *Node = GetSelectedNode();
|
||||||
|
if (Node && Node->HasProperties())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INT xPos = GET_X_LPARAM(lParam);
|
INT xPos = GET_X_LPARAM(lParam);
|
||||||
INT yPos = GET_Y_LPARAM(lParam);
|
INT yPos = GET_Y_LPARAM(lParam);
|
||||||
|
|
||||||
|
@ -291,6 +302,24 @@ CDeviceView::CanDisable(
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE METHODS *******************************************/
|
// PRIVATE METHODS *******************************************/
|
||||||
|
|
||||||
|
@ -362,10 +391,10 @@ CDeviceView::GetNextClass(
|
||||||
0);
|
0);
|
||||||
if (cr != CR_SUCCESS) return false;
|
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))
|
if (IsEqualGUID(*ClassGuid, GUID_DEVCLASS_UNKNOWN))
|
||||||
{
|
{
|
||||||
// Get device info for all devices for all classes
|
// Get device info for all devices
|
||||||
*hDevInfo = SetupDiGetClassDevsW(NULL,
|
*hDevInfo = SetupDiGetClassDevsW(NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -378,7 +407,6 @@ CDeviceView::GetNextClass(
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
DIGCF_PRESENT);
|
DIGCF_PRESENT);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (hDevInfo != INVALID_HANDLE_VALUE);
|
return (hDevInfo != INVALID_HANDLE_VALUE);
|
||||||
|
|
|
@ -78,6 +78,12 @@ public:
|
||||||
bool IsDisabled(
|
bool IsDisabled(
|
||||||
_In_ LPTV_ITEMW TvItem
|
_In_ LPTV_ITEMW TvItem
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool EnableSelectedDevice(
|
||||||
|
_In_ bool Enable,
|
||||||
|
_Out_ bool &NeedsReboot
|
||||||
|
);
|
||||||
|
|
||||||
bool SelDeviceIsStarted();
|
bool SelDeviceIsStarted();
|
||||||
bool SelDeviceIsInstalled();
|
bool SelDeviceIsInstalled();
|
||||||
|
|
||||||
|
|
|
@ -507,7 +507,7 @@ CMainWindow::OnNotify(LPARAM lParam)
|
||||||
{
|
{
|
||||||
LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam;
|
LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam;
|
||||||
|
|
||||||
UINT_PTR idButton = (UINT)lpttt->hdr.idFrom;
|
UINT_PTR idButton = lpttt->hdr.idFrom;
|
||||||
switch (idButton)
|
switch (idButton)
|
||||||
{
|
{
|
||||||
case IDC_PROPERTIES:
|
case IDC_PROPERTIES:
|
||||||
|
@ -568,13 +568,19 @@ CMainWindow::OnCommand(WPARAM wParam,
|
||||||
|
|
||||||
case IDC_ENABLE_DRV:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IDC_DISABLE_DRV:
|
case IDC_DISABLE_DRV:
|
||||||
{
|
{
|
||||||
MessageBox(m_hMainWnd, L"Not yet implemented", L"Disable Driver", MB_OK);
|
bool NeedsReboot;
|
||||||
|
m_DeviceView->EnableSelectedDevice(false, NeedsReboot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue