mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 16:36:07 +00:00
[DEVMGR]
- Move the devmgmt code to devmgr where it belongs and start to rewrite it (devmgmt_new wasn't a good design). It's not part of devmgr yet, I'll merge it and add it to the build when it's more complete. - Add support for caching devices to speed up switching device views - start to add dynamic context support so we can enable/disable, update and uninstall devices depending on its state. - WIP svn path=/trunk/; revision=68165
This commit is contained in:
parent
89f1ac6897
commit
a676d524c9
14 changed files with 2565 additions and 0 deletions
873
reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp
Normal file
873
reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp
Normal file
|
@ -0,0 +1,873 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Device Manager
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: dll/win32/devmgr/devmgr/DeviceView.cpp
|
||||||
|
* PURPOSE: Implements the tree view which contains the devices
|
||||||
|
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "devmgmt.h"
|
||||||
|
#include "DeviceView.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* DATA *********************************************/
|
||||||
|
|
||||||
|
#define CLASS_NAME_LEN 256
|
||||||
|
#define CLASS_DESC_LEN 256
|
||||||
|
|
||||||
|
INT_PTR
|
||||||
|
WINAPI
|
||||||
|
DevicePropertiesExW(
|
||||||
|
IN HWND hWndParent OPTIONAL,
|
||||||
|
IN LPCWSTR lpMachineName OPTIONAL,
|
||||||
|
IN LPCWSTR lpDeviceID OPTIONAL,
|
||||||
|
IN DWORD dwFlags OPTIONAL,
|
||||||
|
IN BOOL bShowDevMgr
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef INT_PTR(WINAPI *pDevicePropertiesExW)(HWND,LPCWSTR,LPCWSTR,DWORD,BOOL);
|
||||||
|
|
||||||
|
struct RefreshThreadData
|
||||||
|
{
|
||||||
|
CDeviceView *This;
|
||||||
|
BOOL ScanForChanges;
|
||||||
|
BOOL UpdateView;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* PUBLIC METHODS *************************************/
|
||||||
|
|
||||||
|
CDeviceView::CDeviceView(
|
||||||
|
HWND hMainWnd
|
||||||
|
) :
|
||||||
|
m_hMainWnd(hMainWnd),
|
||||||
|
m_hTreeView(NULL),
|
||||||
|
m_hPropertyDialog(NULL),
|
||||||
|
m_hShortcutMenu(NULL),
|
||||||
|
m_ViewType(DevicesByType),
|
||||||
|
m_ShowHidden(FALSE),
|
||||||
|
m_RootClassImage(-1),
|
||||||
|
m_RootDevInst(0)
|
||||||
|
{
|
||||||
|
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
||||||
|
}
|
||||||
|
|
||||||
|
CDeviceView::~CDeviceView(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::Initialize()
|
||||||
|
{
|
||||||
|
// Get the device image list
|
||||||
|
m_ImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
|
||||||
|
BOOL bSuccess = SetupDiGetClassImageList(&m_ImageListData);
|
||||||
|
if (bSuccess == FALSE) return false;
|
||||||
|
|
||||||
|
// Create the main treeview
|
||||||
|
m_hTreeView = CreateWindowExW(WS_EX_CLIENTEDGE,
|
||||||
|
WC_TREEVIEW,
|
||||||
|
NULL,
|
||||||
|
WS_CHILD | WS_VISIBLE | WS_BORDER | TVS_HASLINES |
|
||||||
|
TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_LINESATROOT,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
m_hMainWnd,
|
||||||
|
(HMENU)IDC_TREEVIEW,
|
||||||
|
g_hInstance,
|
||||||
|
NULL);
|
||||||
|
if (m_hTreeView)
|
||||||
|
{
|
||||||
|
// Set the image list against the treeview
|
||||||
|
(void)TreeView_SetImageList(m_hTreeView,
|
||||||
|
m_ImageListData.ImageList,
|
||||||
|
TVSIL_NORMAL);
|
||||||
|
|
||||||
|
// Give the treeview arrows instead of +/- boxes (on Win7)
|
||||||
|
SetWindowTheme(m_hTreeView, L"explorer", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!(m_hTreeView);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::Uninitialize()
|
||||||
|
{
|
||||||
|
EmptyDeviceView();
|
||||||
|
|
||||||
|
if (m_ImageListData.ImageList != NULL)
|
||||||
|
{
|
||||||
|
SetupDiDestroyClassImageList(&m_ImageListData);
|
||||||
|
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::Size(
|
||||||
|
_In_ int x,
|
||||||
|
_In_ int y,
|
||||||
|
_In_ int cx,
|
||||||
|
_In_ int cy
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Resize the treeview
|
||||||
|
SetWindowPos(m_hTreeView,
|
||||||
|
NULL,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
SWP_NOZORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::Refresh(_In_ ViewType Type,
|
||||||
|
_In_ bool ScanForChanges,
|
||||||
|
_In_ bool UpdateView)
|
||||||
|
{
|
||||||
|
// Enum devices on a seperate thread to keep the gui responsive
|
||||||
|
|
||||||
|
m_ViewType = Type;
|
||||||
|
|
||||||
|
RefreshThreadData *ThreadData;
|
||||||
|
ThreadData = new RefreshThreadData();
|
||||||
|
ThreadData->This = this;
|
||||||
|
ThreadData->ScanForChanges = ScanForChanges;
|
||||||
|
ThreadData->UpdateView = UpdateView;
|
||||||
|
|
||||||
|
HANDLE hThread;
|
||||||
|
hThread = (HANDLE)_beginthreadex(NULL,
|
||||||
|
0,
|
||||||
|
&RefreshThread,
|
||||||
|
ThreadData,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (hThread) CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::DisplayPropertySheet()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// In ReactOS we can link to DevicePropertiesEx but
|
||||||
|
// not in windows as it's not part of the SDK
|
||||||
|
|
||||||
|
#ifndef __REACTOS__
|
||||||
|
HMODULE hModule = LoadLibraryW(L"devmgr.dll");
|
||||||
|
if (hModule == NULL) return;
|
||||||
|
|
||||||
|
pDevicePropertiesExW DevicePropertiesExW;
|
||||||
|
DevicePropertiesExW = (pDevicePropertiesExW)GetProcAddress(hModule,
|
||||||
|
"DevicePropertiesExW");
|
||||||
|
if (DevicePropertiesExW == NULL)
|
||||||
|
{
|
||||||
|
FreeLibrary(hModule);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CNode *Node = GetSelectedNode();
|
||||||
|
if (Node && Node->HasProperties())
|
||||||
|
{
|
||||||
|
DevicePropertiesExW(m_hTreeView,
|
||||||
|
NULL,
|
||||||
|
Node->GetDeviceId(),
|
||||||
|
1,//DPF_EXTENDED,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __REACTOS__
|
||||||
|
FreeLibrary(hModule);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::SetFocus()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::HasProperties(_In_ LPTV_ITEMW TvItem)
|
||||||
|
{
|
||||||
|
CNode *Node = GetNode(TvItem);
|
||||||
|
if (Node)
|
||||||
|
{
|
||||||
|
return Node->HasProperties();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::IsDisabled(_In_ LPTV_ITEMW TvItem)
|
||||||
|
{
|
||||||
|
CNode *Node = GetNode(TvItem);
|
||||||
|
if (Node)
|
||||||
|
{
|
||||||
|
return Node->IsDisabled();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::CanDisable(_In_ LPTV_ITEMW TvItem)
|
||||||
|
{
|
||||||
|
CNode *Node = GetNode(TvItem);
|
||||||
|
if (Node)
|
||||||
|
{
|
||||||
|
return Node->CanDisable();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PRIVATE METHODS ********************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::AddRootDevice()
|
||||||
|
{
|
||||||
|
// Check whether we've loaded the root bitmap into the imagelist (done on first run)
|
||||||
|
if (m_RootClassImage == -1)
|
||||||
|
{
|
||||||
|
// Load the bitmap we'll be using as the root image
|
||||||
|
HBITMAP hRootImage;
|
||||||
|
hRootImage = LoadBitmapW(g_hInstance,
|
||||||
|
MAKEINTRESOURCEW(IDB_ROOT_IMAGE));
|
||||||
|
if (hRootImage == NULL) return FALSE;
|
||||||
|
|
||||||
|
// Add this bitmap to the device image list. This is a bit hacky, but it's safe
|
||||||
|
m_RootClassImage = ImageList_Add(m_ImageListData.ImageList,
|
||||||
|
hRootImage,
|
||||||
|
NULL);
|
||||||
|
DeleteObject(hRootImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the root instance */
|
||||||
|
CONFIGRET cr;
|
||||||
|
cr = CM_Locate_DevNodeW(&m_RootDevInst,
|
||||||
|
NULL,
|
||||||
|
CM_LOCATE_DEVNODE_NORMAL);
|
||||||
|
if (cr != CR_SUCCESS)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The root name is the computer name */
|
||||||
|
WCHAR RootDeviceName[ROOT_NAME_SIZE];
|
||||||
|
DWORD Size = ROOT_NAME_SIZE;
|
||||||
|
if (GetComputerNameW(RootDeviceName, &Size))
|
||||||
|
_wcslwr_s(RootDeviceName);
|
||||||
|
|
||||||
|
TV_ITEMW tvi;
|
||||||
|
TV_INSERTSTRUCT tvins;
|
||||||
|
ZeroMemory(&tvi, sizeof(tvi));
|
||||||
|
ZeroMemory(&tvins, sizeof(tvins));
|
||||||
|
|
||||||
|
// Insert the root / parent item into our treeview
|
||||||
|
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
|
||||||
|
tvi.pszText = RootDeviceName;
|
||||||
|
tvi.cchTextMax = wcslen(RootDeviceName);
|
||||||
|
tvi.iImage = m_RootClassImage;
|
||||||
|
tvi.iSelectedImage = m_RootClassImage;
|
||||||
|
tvins.item = tvi;
|
||||||
|
m_hTreeRoot = TreeView_InsertItem(m_hTreeView, &tvins);
|
||||||
|
|
||||||
|
return (m_hTreeRoot != NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::GetNextClass(_In_ ULONG ClassIndex,
|
||||||
|
_Out_ LPGUID ClassGuid,
|
||||||
|
_Out_ HDEVINFO *hDevInfo)
|
||||||
|
{
|
||||||
|
CONFIGRET cr;
|
||||||
|
|
||||||
|
// Get the next class in the list
|
||||||
|
cr = CM_Enumerate_Classes(ClassIndex,
|
||||||
|
ClassGuid,
|
||||||
|
0);
|
||||||
|
if (cr != CR_SUCCESS) return false;
|
||||||
|
|
||||||
|
// Check for devices without a class
|
||||||
|
if (IsEqualGUID(*ClassGuid, GUID_DEVCLASS_UNKNOWN))
|
||||||
|
{
|
||||||
|
// Get device info for all devices for all classes
|
||||||
|
*hDevInfo = SetupDiGetClassDevsW(NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
DIGCF_ALLCLASSES);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We only want the devices for this class
|
||||||
|
*hDevInfo = SetupDiGetClassDevsW(ClassGuid,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
DIGCF_PRESENT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (hDevInfo != INVALID_HANDLE_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __stdcall CDeviceView::RefreshThread(void *Param)
|
||||||
|
{
|
||||||
|
RefreshThreadData *ThreadData = (RefreshThreadData *)Param;
|
||||||
|
CDeviceView *This = ThreadData->This;
|
||||||
|
|
||||||
|
|
||||||
|
// Empty the treeview
|
||||||
|
This->EmptyDeviceView();
|
||||||
|
This->m_hTreeRoot = NULL;
|
||||||
|
|
||||||
|
// Refresh the devices only if requested. This means
|
||||||
|
// switching views uses the cache and remains fast
|
||||||
|
if (ThreadData->ScanForChanges)
|
||||||
|
{
|
||||||
|
This->RefreshDeviceList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// display the type of view the user wants
|
||||||
|
switch (This->m_ViewType)
|
||||||
|
{
|
||||||
|
case DevicesByType:
|
||||||
|
(void)This->ListDevicesByType();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DevicesByConnection:
|
||||||
|
(VOID)This->ListDevicesByConnection();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ResourcesByType:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ResourcesByConnection:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ThreadData;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::ListDevicesByType()
|
||||||
|
{
|
||||||
|
CNode *ClassNode, *DeviceNode;
|
||||||
|
HDEVINFO hDevInfo;
|
||||||
|
HTREEITEM hTreeItem = NULL;
|
||||||
|
GUID ClassGuid;
|
||||||
|
INT ClassIndex;
|
||||||
|
LPTSTR DeviceId = NULL;
|
||||||
|
BOOL bClassSuccess, bSuccess;
|
||||||
|
|
||||||
|
// Start by adding the root node to the tree
|
||||||
|
bSuccess = AddRootDevice();
|
||||||
|
if (bSuccess == false) return false;
|
||||||
|
|
||||||
|
ClassIndex = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Loop through all the device classes
|
||||||
|
bClassSuccess = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
|
||||||
|
if (bClassSuccess)
|
||||||
|
{
|
||||||
|
bool bClassUnknown = false;
|
||||||
|
bool AddedParent = false;
|
||||||
|
INT DeviceIndex = 0;
|
||||||
|
BOOL MoreItems;
|
||||||
|
|
||||||
|
// Get the cached class node
|
||||||
|
ClassNode = GetClassNode(&ClassGuid);
|
||||||
|
if (ClassNode == NULL)
|
||||||
|
{
|
||||||
|
ATLASSERT(FALSE);
|
||||||
|
ClassIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a flag is this is the (special case) unknown class
|
||||||
|
if (IsEqualGUID(ClassGuid, GUID_DEVCLASS_UNKNOWN))
|
||||||
|
bClassUnknown = true;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Get a handle to all the devices in this class
|
||||||
|
SP_DEVINFO_DATA DeviceInfoData;
|
||||||
|
ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
|
||||||
|
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||||
|
bSuccess = SetupDiEnumDeviceInfo(hDevInfo,
|
||||||
|
DeviceIndex,
|
||||||
|
&DeviceInfoData);
|
||||||
|
if (bSuccess == FALSE && GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||||
|
MoreItems = FALSE;
|
||||||
|
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
MoreItems = TRUE;
|
||||||
|
|
||||||
|
// The unknown class handle contains all devices on the system,
|
||||||
|
// and we're just looking for the ones with a null GUID
|
||||||
|
if (bClassUnknown)
|
||||||
|
{
|
||||||
|
if (IsEqualGUID(DeviceInfoData.ClassGuid, GUID_NULL) == FALSE)
|
||||||
|
{
|
||||||
|
// This is a known device, we aren't interested in it
|
||||||
|
DeviceIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the cached device node
|
||||||
|
DeviceNode = GetDeviceNode(DeviceInfoData.DevInst);
|
||||||
|
if (DeviceNode == NULL)
|
||||||
|
{
|
||||||
|
ATLASSERT(bClassUnknown == true);
|
||||||
|
DeviceIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a hidden device
|
||||||
|
if (DeviceNode->IsHidden())
|
||||||
|
{
|
||||||
|
// Ignore this device if we aren't displaying hidden devices
|
||||||
|
if (m_ShowHidden == FALSE)
|
||||||
|
{
|
||||||
|
DeviceIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a device, we need to add the parent if it hasn't yet been added
|
||||||
|
if (AddedParent == false)
|
||||||
|
{
|
||||||
|
// Insert the new class under the root item
|
||||||
|
hTreeItem = InsertIntoTreeView(m_hTreeRoot,
|
||||||
|
ClassNode);
|
||||||
|
AddedParent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the device under the class item node
|
||||||
|
(void)InsertIntoTreeView(hTreeItem, DeviceNode);
|
||||||
|
|
||||||
|
// Expand the class if it has a problem device
|
||||||
|
if (DeviceNode->HasProblem())
|
||||||
|
{
|
||||||
|
(void)TreeView_Expand(m_hTreeView,
|
||||||
|
hTreeItem,
|
||||||
|
TVE_EXPAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceIndex++;
|
||||||
|
|
||||||
|
} while (MoreItems);
|
||||||
|
|
||||||
|
// If this class has devices, sort them alphabetically
|
||||||
|
if (AddedParent == true)
|
||||||
|
{
|
||||||
|
(void)TreeView_SortChildren(m_hTreeView,
|
||||||
|
hTreeItem,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassIndex++;
|
||||||
|
|
||||||
|
} while (bClassSuccess);
|
||||||
|
|
||||||
|
// Sort the classes alphabetically
|
||||||
|
(void)TreeView_SortChildren(m_hTreeView,
|
||||||
|
m_hTreeRoot,
|
||||||
|
0);
|
||||||
|
|
||||||
|
// Expand the root item
|
||||||
|
(void)TreeView_Expand(m_hTreeView,
|
||||||
|
m_hTreeRoot,
|
||||||
|
TVE_EXPAND);
|
||||||
|
|
||||||
|
// Pre-select the root item
|
||||||
|
(VOID)TreeView_SelectItem(m_hTreeView,
|
||||||
|
m_hTreeRoot);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::ListDevicesByConnection()
|
||||||
|
{
|
||||||
|
BOOL bSuccess;
|
||||||
|
|
||||||
|
// Start by adding the root node to the tree
|
||||||
|
bSuccess = AddRootDevice();
|
||||||
|
if (bSuccess == false) return false;
|
||||||
|
|
||||||
|
/* Walk the device tree and add all the devices */
|
||||||
|
RecurseChildDevices(m_RootDevInst, m_hTreeRoot);
|
||||||
|
|
||||||
|
/* Expand the root item */
|
||||||
|
(VOID)TreeView_Expand(m_hTreeView,
|
||||||
|
m_hTreeRoot,
|
||||||
|
TVE_EXPAND);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CDeviceView::RecurseChildDevices(
|
||||||
|
_In_ DEVINST ParentDevice,
|
||||||
|
_In_ HTREEITEM hParentTreeItem
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
HTREEITEM hDevItem = NULL;
|
||||||
|
DEVINST Device;
|
||||||
|
BOOL bSuccess;
|
||||||
|
|
||||||
|
/* Check if the parent has any child devices */
|
||||||
|
if (GetChildDevice(ParentDevice, &Device) == FALSE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the cached device node
|
||||||
|
CNode *DeviceNode;
|
||||||
|
DeviceNode = GetDeviceNode(Device);
|
||||||
|
if (DeviceNode == NULL)
|
||||||
|
{
|
||||||
|
ATLASSERT(FALSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check if this is a hidden device */
|
||||||
|
if ((m_ShowHidden == TRUE) || (!(DeviceNode->IsHidden())))
|
||||||
|
{
|
||||||
|
/* Add this device to the tree under its parent */
|
||||||
|
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
||||||
|
DeviceNode);
|
||||||
|
|
||||||
|
|
||||||
|
if (hDevItem)
|
||||||
|
{
|
||||||
|
/* Check if this child has any children itself */
|
||||||
|
RecurseChildDevices(Device, hDevItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Check if the parent device has anything at the same level */
|
||||||
|
bSuccess = GetSiblingDevice(Device, &Device);
|
||||||
|
if (bSuccess == FALSE) break;
|
||||||
|
|
||||||
|
DeviceNode = GetDeviceNode(Device);
|
||||||
|
if (DeviceNode == NULL)
|
||||||
|
{
|
||||||
|
ATLASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is a hidden device */
|
||||||
|
if (DeviceNode->IsHidden())
|
||||||
|
{
|
||||||
|
if (m_ShowHidden == FALSE)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add this device to the tree under its parent */
|
||||||
|
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
||||||
|
DeviceNode);
|
||||||
|
if (hDevItem)
|
||||||
|
{
|
||||||
|
/* Check if this child has any children itself */
|
||||||
|
RecurseChildDevices(Device, hDevItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)TreeView_SortChildren(m_hTreeView,
|
||||||
|
hParentTreeItem,
|
||||||
|
0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::GetChildDevice(
|
||||||
|
_In_ DEVINST ParentDevInst,
|
||||||
|
_Out_ PDEVINST DevInst
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CONFIGRET cr;
|
||||||
|
cr = CM_Get_Child(DevInst,
|
||||||
|
ParentDevInst,
|
||||||
|
0);
|
||||||
|
return (cr == CR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::GetSiblingDevice(
|
||||||
|
_In_ DEVINST PrevDevice,
|
||||||
|
_Out_ PDEVINST DevInst
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CONFIGRET cr;
|
||||||
|
cr = CM_Get_Sibling(DevInst,
|
||||||
|
PrevDevice,
|
||||||
|
0);
|
||||||
|
return (cr == CR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
HTREEITEM
|
||||||
|
CDeviceView::InsertIntoTreeView(
|
||||||
|
_In_ HTREEITEM hParent,
|
||||||
|
_In_ CNode *Node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
LPWSTR lpLabel;
|
||||||
|
lpLabel = Node->GetDisplayName();
|
||||||
|
|
||||||
|
TV_ITEMW tvi;
|
||||||
|
TV_INSERTSTRUCT tvins;
|
||||||
|
ZeroMemory(&tvi, sizeof(tvi));
|
||||||
|
ZeroMemory(&tvins, sizeof(tvins));
|
||||||
|
|
||||||
|
tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
|
||||||
|
tvi.pszText = lpLabel;
|
||||||
|
tvi.cchTextMax = wcslen(lpLabel);
|
||||||
|
tvi.lParam = (LPARAM)Node;
|
||||||
|
tvi.iImage = Node->GetClassImage();
|
||||||
|
tvi.iSelectedImage = Node->GetClassImage();
|
||||||
|
|
||||||
|
if (Node->GetOverlayImage())
|
||||||
|
{
|
||||||
|
tvi.mask |= TVIF_STATE;
|
||||||
|
tvi.stateMask = TVIS_OVERLAYMASK;
|
||||||
|
tvi.state = INDEXTOOVERLAYMASK(Node->GetOverlayImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
tvins.item = tvi;
|
||||||
|
tvins.hParent = hParent;
|
||||||
|
|
||||||
|
return TreeView_InsertItem(m_hTreeView, &tvins);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::RecurseDeviceView(
|
||||||
|
_In_ HTREEITEM hParentItem
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HTREEITEM hItem;
|
||||||
|
TVITEMW tvItem;
|
||||||
|
|
||||||
|
// Check if this node has any children
|
||||||
|
hItem = TreeView_GetChild(m_hTreeView, hParentItem);
|
||||||
|
if (hItem == NULL) return;
|
||||||
|
|
||||||
|
// The lParam contains the node pointer data
|
||||||
|
tvItem.hItem = hItem;
|
||||||
|
tvItem.mask = TVIF_PARAM;
|
||||||
|
if (TreeView_GetItem(m_hTreeView, &tvItem) &&
|
||||||
|
tvItem.lParam != NULL)
|
||||||
|
{
|
||||||
|
// Delete the node class
|
||||||
|
//delete reinterpret_cast<CNode *>(tvItem.lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This node may have its own children
|
||||||
|
RecurseDeviceView(hItem);
|
||||||
|
|
||||||
|
// Delete all the siblings
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Get the next item at this level
|
||||||
|
hItem = TreeView_GetNextSibling(m_hTreeView, hItem);
|
||||||
|
if (hItem == NULL) break;
|
||||||
|
|
||||||
|
// The lParam contains the node pointer data
|
||||||
|
tvItem.hItem = hItem;
|
||||||
|
tvItem.mask = TVIF_PARAM;
|
||||||
|
if (TreeView_GetItem(m_hTreeView, &tvItem))
|
||||||
|
{
|
||||||
|
//if (tvItem.lParam != NULL)
|
||||||
|
// delete reinterpret_cast<CNode *>(tvItem.lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This node may have its own children */
|
||||||
|
RecurseDeviceView(hItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::EmptyDeviceView()
|
||||||
|
{
|
||||||
|
HTREEITEM hItem;
|
||||||
|
|
||||||
|
// Check if there are any items in the tree
|
||||||
|
hItem = TreeView_GetRoot(m_hTreeView);
|
||||||
|
if (hItem == NULL) return;
|
||||||
|
|
||||||
|
// Free all the class nodes
|
||||||
|
//RecurseDeviceView(hItem);
|
||||||
|
|
||||||
|
// Delete all the items
|
||||||
|
(VOID)TreeView_DeleteAllItems(m_hTreeView);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CNode*
|
||||||
|
CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
|
||||||
|
{
|
||||||
|
POSITION Pos;
|
||||||
|
CNode *Node;
|
||||||
|
|
||||||
|
Pos = m_ClassNodeList.GetHeadPosition();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Node = m_ClassNodeList.GetNext(Pos);
|
||||||
|
if (IsEqualGUID(*Node->GetClassGuid(), *ClassGuid))
|
||||||
|
{
|
||||||
|
//ATLASSERT(Node->GetType() == NodeClass);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node = NULL;
|
||||||
|
|
||||||
|
} while (Pos != NULL);
|
||||||
|
|
||||||
|
return Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNode*
|
||||||
|
CDeviceView::GetDeviceNode(_In_ DEVINST Device)
|
||||||
|
{
|
||||||
|
POSITION Pos;
|
||||||
|
CNode *Node;
|
||||||
|
|
||||||
|
Pos = m_DeviceNodeList.GetHeadPosition();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Node = m_DeviceNodeList.GetNext(Pos);
|
||||||
|
if (Node->GetDeviceInst() == Device)
|
||||||
|
{
|
||||||
|
//ATLASSERT(Node->GetType() == NodeDevice);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node = NULL;
|
||||||
|
|
||||||
|
} while (Pos != NULL);
|
||||||
|
|
||||||
|
return Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNode* CDeviceView::GetNode(LPTV_ITEMW TvItem)
|
||||||
|
{
|
||||||
|
TvItem->mask = TVIF_PARAM;
|
||||||
|
if (TreeView_GetItem(m_hTreeView, TvItem))
|
||||||
|
{
|
||||||
|
return (CNode *)TvItem->lParam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CNode* CDeviceView::GetSelectedNode()
|
||||||
|
{
|
||||||
|
TV_ITEM TvItem;
|
||||||
|
TvItem.hItem = TreeView_GetSelection(m_hTreeView);
|
||||||
|
return GetNode(&TvItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::EmptyLists()
|
||||||
|
{
|
||||||
|
POSITION Pos;
|
||||||
|
CNode *Node;
|
||||||
|
|
||||||
|
if (!m_ClassNodeList.IsEmpty())
|
||||||
|
{
|
||||||
|
Pos = m_ClassNodeList.GetHeadPosition();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Node = m_ClassNodeList.GetNext(Pos);
|
||||||
|
delete Node;
|
||||||
|
|
||||||
|
} while (Pos != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_DeviceNodeList.IsEmpty())
|
||||||
|
{
|
||||||
|
Pos = m_DeviceNodeList.GetHeadPosition();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Node = m_DeviceNodeList.GetNext(Pos);
|
||||||
|
delete Node;
|
||||||
|
|
||||||
|
} while (Pos != NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CDeviceView::RefreshDeviceList()
|
||||||
|
{
|
||||||
|
GUID ClassGuid;
|
||||||
|
CNode *Node;
|
||||||
|
HDEVINFO hDevInfo;
|
||||||
|
SP_DEVINFO_DATA DeviceInfoData;
|
||||||
|
DWORD i;
|
||||||
|
BOOL Success;
|
||||||
|
|
||||||
|
ULONG ClassIndex = 0;
|
||||||
|
|
||||||
|
EmptyLists();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
/* Create a new class node */
|
||||||
|
Node = new CNode(&ClassGuid, &m_ImageListData);
|
||||||
|
if (Node->Setup())
|
||||||
|
{
|
||||||
|
m_ClassNodeList.AddTail(Node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClassIndex++;
|
||||||
|
} while (Success);
|
||||||
|
|
||||||
|
|
||||||
|
hDevInfo = SetupDiGetClassDevsW(NULL,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DIGCF_PRESENT | DIGCF_ALLCLASSES);
|
||||||
|
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||||
|
for (i = 0;; i++)
|
||||||
|
{
|
||||||
|
Success = SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);
|
||||||
|
if (Success == FALSE) break;
|
||||||
|
|
||||||
|
|
||||||
|
Node = new CNode(DeviceInfoData.DevInst, &m_ImageListData);
|
||||||
|
Node->Setup();
|
||||||
|
m_DeviceNodeList.AddTail(Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
131
reactos/dll/win32/devmgr/devmgmt/DeviceView.h
Normal file
131
reactos/dll/win32/devmgr/devmgmt/DeviceView.h
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
enum ViewType
|
||||||
|
{
|
||||||
|
DevicesByType,
|
||||||
|
DevicesByConnection,
|
||||||
|
ResourcesByType,
|
||||||
|
ResourcesByConnection
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CDeviceView
|
||||||
|
{
|
||||||
|
CAtlList<CNode *> m_ClassNodeList;
|
||||||
|
CAtlList<CNode *> m_DeviceNodeList;
|
||||||
|
|
||||||
|
SP_CLASSIMAGELIST_DATA m_ImageListData;
|
||||||
|
|
||||||
|
HWND m_hMainWnd;
|
||||||
|
HWND m_hTreeView;
|
||||||
|
HWND m_hPropertyDialog;
|
||||||
|
HWND m_hShortcutMenu;
|
||||||
|
ViewType m_ViewType;
|
||||||
|
|
||||||
|
HTREEITEM m_hTreeRoot;
|
||||||
|
DEVINST m_RootDevInst;
|
||||||
|
|
||||||
|
bool m_ShowHidden;
|
||||||
|
int m_RootClassImage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CDeviceView(
|
||||||
|
HWND hMainWnd
|
||||||
|
);
|
||||||
|
|
||||||
|
~CDeviceView(void);
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
bool Uninitialize();
|
||||||
|
|
||||||
|
VOID Size(
|
||||||
|
_In_ int x,
|
||||||
|
_In_ int y,
|
||||||
|
_In_ int cx,
|
||||||
|
_In_ int cy
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID Refresh(
|
||||||
|
_In_ ViewType Type,
|
||||||
|
_In_ bool ScanForChanges,
|
||||||
|
_In_ bool UpdateView
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID DisplayPropertySheet();
|
||||||
|
VOID SetFocus();
|
||||||
|
|
||||||
|
//VOID SetDeviceListType(ListDevices List)
|
||||||
|
//{
|
||||||
|
// m_ListDevices = List;
|
||||||
|
//}
|
||||||
|
|
||||||
|
VOID ShowHiddenDevices(_In_ bool ShowHidden)
|
||||||
|
{
|
||||||
|
m_ShowHidden = ShowHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewType GetCurrentView() { return m_ViewType; }
|
||||||
|
|
||||||
|
bool HasProperties(_In_ LPTV_ITEMW TvItem);
|
||||||
|
//bool SelDeviceIsHidden();
|
||||||
|
bool CanDisable(_In_ LPTV_ITEMW TvItem);
|
||||||
|
bool IsDisabled(_In_ LPTV_ITEMW TvItem);
|
||||||
|
bool SelDeviceIsStarted();
|
||||||
|
bool SelDeviceIsInstalled();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool AddRootDevice();
|
||||||
|
|
||||||
|
bool RefreshDeviceList();
|
||||||
|
|
||||||
|
static unsigned int __stdcall RefreshThread(
|
||||||
|
void *Param
|
||||||
|
);
|
||||||
|
|
||||||
|
bool ListDevicesByConnection(
|
||||||
|
);
|
||||||
|
bool ListDevicesByType(
|
||||||
|
);
|
||||||
|
|
||||||
|
bool GetNextClass(
|
||||||
|
_In_ ULONG ClassIndex,
|
||||||
|
_Out_ LPGUID ClassGuid,
|
||||||
|
_Out_ HDEVINFO *hDevInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID RecurseChildDevices(
|
||||||
|
_In_ DEVINST ParentDevice,
|
||||||
|
_In_ HTREEITEM hParentTreeItem
|
||||||
|
);
|
||||||
|
|
||||||
|
bool GetChildDevice(
|
||||||
|
_In_ DEVINST ParentDevInst,
|
||||||
|
_Out_ PDEVINST DevInst
|
||||||
|
);
|
||||||
|
|
||||||
|
bool GetSiblingDevice(
|
||||||
|
_In_ DEVINST PrevDevice,
|
||||||
|
_Out_ PDEVINST DevInst
|
||||||
|
);
|
||||||
|
|
||||||
|
HTREEITEM InsertIntoTreeView(
|
||||||
|
_In_ HTREEITEM hParent,
|
||||||
|
_In_ CNode *Node
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID RecurseDeviceView(
|
||||||
|
_In_ HTREEITEM hParentItem
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID EmptyDeviceView(
|
||||||
|
);
|
||||||
|
|
||||||
|
CNode* GetNode(_In_ LPTV_ITEMW TvItem);
|
||||||
|
CNode* GetSelectedNode();
|
||||||
|
|
||||||
|
CNode* GetClassNode(_In_ LPGUID ClassGuid);
|
||||||
|
CNode* GetDeviceNode(_In_ DEVINST Device);
|
||||||
|
void EmptyLists();
|
||||||
|
};
|
||||||
|
|
764
reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp
Normal file
764
reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp
Normal file
|
@ -0,0 +1,764 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Device Manager
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: dll/win32/devmgr/devmgr/MainWindow.cpp
|
||||||
|
* PURPOSE: Implements the main container window for the device view
|
||||||
|
* COPYRIGHT: Copyright 2014 - 2015 Ged Murphy <gedmurphy@reactos.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "devmgmt.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* DATA *****************************************************/
|
||||||
|
|
||||||
|
#define BTN_PROPERTIES 0
|
||||||
|
#define BTN_SCAN_HARDWARE 1
|
||||||
|
#define BTN_SEPERATOR -1
|
||||||
|
#define BTN_ENABLE_DRV 2
|
||||||
|
#define BTN_DISABLE_DRV 3
|
||||||
|
#define BTN_UPDATE_DRV 4
|
||||||
|
#define BTN_UNINSTALL_DRV 5
|
||||||
|
|
||||||
|
|
||||||
|
// menu hints
|
||||||
|
static const MENU_HINT MainMenuHintTable[] =
|
||||||
|
{
|
||||||
|
// File Menu
|
||||||
|
{ IDC_EXIT, IDS_HINT_EXIT },
|
||||||
|
|
||||||
|
// Action Menu
|
||||||
|
{ IDC_UPDATE_DRV, NULL },
|
||||||
|
{ IDC_DISABLE_DRV, NULL },
|
||||||
|
{ IDC_UNINSTALL_DRV, NULL },
|
||||||
|
{ IDC_SCAN_HARDWARE, IDS_HINT_REFRESH },
|
||||||
|
{ IDC_ADD_HARDWARE, NULL },
|
||||||
|
{ IDC_PROPERTIES, IDS_HINT_PROP},
|
||||||
|
|
||||||
|
// View Menu
|
||||||
|
{ IDC_DEVBYTYPE, IDS_HINT_DEV_BY_TYPE},
|
||||||
|
{ IDC_DEVBYCONN, IDS_HINT_DEV_BY_CONN},
|
||||||
|
{ IDC_RESBYTYPE, IDS_HINT_RES_BY_TYPE},
|
||||||
|
{ IDC_RESBYCONN, IDS_HINT_RES_BY_TYPE},
|
||||||
|
|
||||||
|
{ IDC_ABOUT, IDS_HINT_ABOUT }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// system menu hints
|
||||||
|
static const MENU_HINT SystemMenuHintTable[] =
|
||||||
|
{
|
||||||
|
{SC_RESTORE, IDS_HINT_SYS_RESTORE},
|
||||||
|
{SC_MOVE, IDS_HINT_SYS_MOVE},
|
||||||
|
{SC_SIZE, IDS_HINT_SYS_SIZE},
|
||||||
|
{SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
|
||||||
|
{SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
|
||||||
|
{SC_CLOSE, IDS_HINT_SYS_CLOSE},
|
||||||
|
};
|
||||||
|
|
||||||
|
static TBBUTTON TbButtons[] =
|
||||||
|
{
|
||||||
|
{ BTN_PROPERTIES, IDC_PROPERTIES, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
|
||||||
|
{ BTN_SCAN_HARDWARE, IDC_SCAN_HARDWARE, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
|
||||||
|
{ 2, IDC_STATIC, TBSTATE_ENABLED, BTNS_SEP, 0, 0 },
|
||||||
|
{ BTN_ENABLE_DRV, IDC_ENABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
|
||||||
|
{ BTN_DISABLE_DRV, IDC_DISABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
|
||||||
|
{ BTN_UPDATE_DRV, IDC_UPDATE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
|
||||||
|
{ BTN_UNINSTALL_DRV, IDC_UNINSTALL_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* PUBLIC METHODS **********************************************/
|
||||||
|
|
||||||
|
CMainWindow::CMainWindow(void) :
|
||||||
|
m_ToolbarhImageList(NULL),
|
||||||
|
m_hMainWnd(NULL),
|
||||||
|
m_hStatusBar(NULL),
|
||||||
|
m_hToolBar(NULL),
|
||||||
|
m_CmdShow(0)
|
||||||
|
{
|
||||||
|
m_szMainWndClass = L"DevMgmtWndClass";
|
||||||
|
}
|
||||||
|
|
||||||
|
CMainWindow::~CMainWindow(void)
|
||||||
|
{
|
||||||
|
// Destroy any previous list
|
||||||
|
if (m_ToolbarhImageList) ImageList_Destroy(m_ToolbarhImageList);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::Initialize(LPCTSTR lpCaption,
|
||||||
|
int nCmdShow)
|
||||||
|
{
|
||||||
|
CAtlStringW szCaption;
|
||||||
|
WNDCLASSEXW wc = {0};
|
||||||
|
|
||||||
|
// Store the show window value
|
||||||
|
m_CmdShow = nCmdShow;
|
||||||
|
|
||||||
|
// Setup the window class struct
|
||||||
|
wc.cbSize = sizeof(WNDCLASSEXW);
|
||||||
|
wc.lpfnWndProc = MainWndProc;
|
||||||
|
wc.hInstance = g_hInstance;
|
||||||
|
wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCEW(IDI_MAIN_ICON));
|
||||||
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
||||||
|
wc.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
|
||||||
|
wc.lpszClassName = m_szMainWndClass;
|
||||||
|
wc.hIconSm = (HICON)LoadImage(g_hInstance,
|
||||||
|
MAKEINTRESOURCE(IDI_MAIN_ICON),
|
||||||
|
IMAGE_ICON,
|
||||||
|
16,
|
||||||
|
16,
|
||||||
|
LR_SHARED);
|
||||||
|
|
||||||
|
// Register the window
|
||||||
|
if (RegisterClassExW(&wc))
|
||||||
|
{
|
||||||
|
// Create the main window and store the object pointer
|
||||||
|
m_hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
|
||||||
|
m_szMainWndClass,
|
||||||
|
lpCaption,
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
500,
|
||||||
|
500,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_hInstance,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return creation result
|
||||||
|
return !!(m_hMainWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMainWindow::Uninitialize()
|
||||||
|
{
|
||||||
|
// Unregister the window class
|
||||||
|
UnregisterClassW(m_szMainWndClass, g_hInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CMainWindow::Run()
|
||||||
|
{
|
||||||
|
MSG Msg;
|
||||||
|
|
||||||
|
// Pump the message queue
|
||||||
|
while (GetMessageW(&Msg, NULL, 0, 0 ) != 0)
|
||||||
|
{
|
||||||
|
TranslateMessage(&Msg);
|
||||||
|
DispatchMessageW(&Msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PRIVATE METHODS **********************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::MainWndMenuHint(WORD CmdId,
|
||||||
|
const MENU_HINT *HintArray,
|
||||||
|
DWORD HintsCount,
|
||||||
|
UINT DefHintId)
|
||||||
|
{
|
||||||
|
bool Found = false;
|
||||||
|
const MENU_HINT *LastHint;
|
||||||
|
UINT HintId = DefHintId;
|
||||||
|
|
||||||
|
LastHint = HintArray + HintsCount;
|
||||||
|
while (HintArray != LastHint)
|
||||||
|
{
|
||||||
|
if (HintArray->CmdId == CmdId)
|
||||||
|
{
|
||||||
|
HintId = HintArray->HintId;
|
||||||
|
Found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HintArray++;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBarLoadString(m_hStatusBar,
|
||||||
|
SB_SIMPLEID,
|
||||||
|
g_hInstance,
|
||||||
|
HintId);
|
||||||
|
|
||||||
|
return Found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::RefreshView(ViewType Type)
|
||||||
|
{
|
||||||
|
UINT CheckId;
|
||||||
|
BOOL bSuccess;
|
||||||
|
|
||||||
|
// Refreshed the cached view
|
||||||
|
m_DeviceView->Refresh(Type, FALSE, TRUE);
|
||||||
|
|
||||||
|
// Get the menu item id
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case DevicesByType: CheckId = IDC_DEVBYTYPE; break;
|
||||||
|
case DevicesByConnection: CheckId = IDC_DEVBYCONN; break;
|
||||||
|
case ResourcesByType: CheckId = IDC_RESBYTYPE; break;
|
||||||
|
case ResourcesByConnection: CheckId = IDC_RESBYCONN; break;
|
||||||
|
default: ATLASSERT(FALSE); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new check item
|
||||||
|
bSuccess = CheckMenuRadioItem(m_hMenu,
|
||||||
|
IDC_DEVBYTYPE,
|
||||||
|
IDC_RESBYCONN,
|
||||||
|
CheckId,
|
||||||
|
MF_BYCOMMAND);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::ScanForHardwareChanges()
|
||||||
|
{
|
||||||
|
// Refresh the cache and and display
|
||||||
|
m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
|
||||||
|
true,
|
||||||
|
true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::CreateToolBar()
|
||||||
|
{
|
||||||
|
TBADDBITMAP TbAddBitmap;
|
||||||
|
INT Index;
|
||||||
|
|
||||||
|
DWORD dwStyles = WS_CHILDWINDOW | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER;
|
||||||
|
DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
|
||||||
|
|
||||||
|
// Create the toolbar window
|
||||||
|
m_hToolBar = CreateWindowExW(dwExStyles,
|
||||||
|
TOOLBARCLASSNAME,
|
||||||
|
NULL,
|
||||||
|
dwStyles,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
m_hMainWnd,
|
||||||
|
(HMENU)IDC_TOOLBAR,
|
||||||
|
g_hInstance,
|
||||||
|
NULL);
|
||||||
|
if (m_hToolBar == NULL) return FALSE;
|
||||||
|
|
||||||
|
// Don't show clipped buttons
|
||||||
|
SendMessageW(m_hToolBar,
|
||||||
|
TB_SETEXTENDEDSTYLE,
|
||||||
|
0,
|
||||||
|
TBSTYLE_EX_HIDECLIPPEDBUTTONS);
|
||||||
|
|
||||||
|
SendMessageW(m_hToolBar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 16));
|
||||||
|
|
||||||
|
// Set the struct size, the toobar needs this...
|
||||||
|
SendMessageW(m_hToolBar,
|
||||||
|
TB_BUTTONSTRUCTSIZE,
|
||||||
|
sizeof(TBBUTTON),
|
||||||
|
0);
|
||||||
|
|
||||||
|
TbAddBitmap.hInst = g_hInstance;
|
||||||
|
TbAddBitmap.nID = IDB_TOOLBAR;
|
||||||
|
Index = SendMessageW(m_hToolBar, TB_ADDBITMAP, _countof(TbButtons), (LPARAM)&TbAddBitmap);
|
||||||
|
|
||||||
|
SendMessageW(m_hToolBar, TB_ADDBUTTONSW, _countof(TbButtons), (LPARAM)TbButtons);
|
||||||
|
SendMessageW(m_hToolBar, TB_AUTOSIZE, 0, 0);
|
||||||
|
|
||||||
|
if (TRUE)
|
||||||
|
{
|
||||||
|
ShowWindow(m_hToolBar, SW_SHOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::CreateStatusBar()
|
||||||
|
{
|
||||||
|
int StatWidths[] = {110, -1}; // widths of status bar
|
||||||
|
bool bRet = FALSE;
|
||||||
|
|
||||||
|
// Create the status bar
|
||||||
|
m_hStatusBar = CreateWindowExW(0,
|
||||||
|
STATUSCLASSNAME,
|
||||||
|
NULL,
|
||||||
|
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
m_hMainWnd,
|
||||||
|
(HMENU)IDC_STATUSBAR,
|
||||||
|
g_hInstance,
|
||||||
|
NULL);
|
||||||
|
if (m_hStatusBar)
|
||||||
|
{
|
||||||
|
// Set the width
|
||||||
|
bRet = (SendMessageW(m_hStatusBar,
|
||||||
|
SB_SETPARTS,
|
||||||
|
sizeof(StatWidths) / sizeof(int),
|
||||||
|
(LPARAM)StatWidths) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMainWindow::UpdateContext(_In_ LPTV_ITEMW TvItem)
|
||||||
|
{
|
||||||
|
WORD State;
|
||||||
|
|
||||||
|
// properties button
|
||||||
|
if (m_DeviceView->HasProperties(TvItem))
|
||||||
|
{
|
||||||
|
State = TBSTATE_ENABLED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State = TBSTATE_HIDDEN;
|
||||||
|
}
|
||||||
|
SendMessageW(m_hToolBar, TB_SETSTATE, IDC_PROPERTIES, MAKELPARAM(State, 0));
|
||||||
|
SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UPDATE_DRV, MAKELPARAM(State, 0)); //hack
|
||||||
|
SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UNINSTALL_DRV, MAKELPARAM(State, 0)); // hack
|
||||||
|
|
||||||
|
// enable driver button
|
||||||
|
if (m_DeviceView->IsDisabled(TvItem))
|
||||||
|
{
|
||||||
|
State = TBSTATE_ENABLED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State = TBSTATE_HIDDEN;
|
||||||
|
}
|
||||||
|
SendMessageW(m_hToolBar, TB_SETSTATE, IDC_ENABLE_DRV, MAKELPARAM(State, 0));
|
||||||
|
|
||||||
|
// disable driver button
|
||||||
|
if (m_DeviceView->CanDisable(TvItem) && !m_DeviceView->IsDisabled(TvItem))
|
||||||
|
{
|
||||||
|
State = TBSTATE_ENABLED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State = TBSTATE_HIDDEN;
|
||||||
|
}
|
||||||
|
SendMessageW(m_hToolBar, TB_SETSTATE, IDC_DISABLE_DRV, MAKELPARAM(State, 0));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMainWindow::StatusBarLoadString(IN HWND hStatusBar,
|
||||||
|
IN INT PartId,
|
||||||
|
IN HINSTANCE hInstance,
|
||||||
|
IN UINT uID)
|
||||||
|
{
|
||||||
|
CAtlStringW szMessage;
|
||||||
|
bool bRet = false;
|
||||||
|
|
||||||
|
// Load the string
|
||||||
|
if (szMessage.LoadStringW(hInstance, uID))
|
||||||
|
{
|
||||||
|
// Show the string on the status bar
|
||||||
|
bRet = (SendMessageW(hStatusBar,
|
||||||
|
SB_SETTEXT,
|
||||||
|
(WPARAM)PartId,
|
||||||
|
(LPARAM)szMessage.GetBuffer()) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT
|
||||||
|
CMainWindow::OnCreate(HWND hwnd)
|
||||||
|
{
|
||||||
|
LRESULT RetCode;
|
||||||
|
|
||||||
|
RetCode = -1;
|
||||||
|
m_hMainWnd = hwnd;
|
||||||
|
|
||||||
|
// Store a handle to the main menu
|
||||||
|
m_hMenu = GetMenu(m_hMainWnd);
|
||||||
|
|
||||||
|
// Create the toolbar and statusbar
|
||||||
|
if (CreateToolBar() && CreateStatusBar())
|
||||||
|
{
|
||||||
|
// Create the device view object
|
||||||
|
m_DeviceView = new CDeviceView(m_hMainWnd);
|
||||||
|
if (m_DeviceView->Initialize())
|
||||||
|
{
|
||||||
|
// Do the initial scan
|
||||||
|
ScanForHardwareChanges();
|
||||||
|
|
||||||
|
// Display the window according to the user request
|
||||||
|
ShowWindow(hwnd, m_CmdShow);
|
||||||
|
RetCode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RetCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT
|
||||||
|
CMainWindow::OnSize()
|
||||||
|
{
|
||||||
|
RECT rcClient, rcTool, rcStatus;
|
||||||
|
INT lvHeight, iToolHeight, iStatusHeight;
|
||||||
|
|
||||||
|
// Autosize the toolbar
|
||||||
|
SendMessage(m_hToolBar, TB_AUTOSIZE, 0, 0);
|
||||||
|
|
||||||
|
// Get the toolbar rect and save the height
|
||||||
|
GetWindowRect(m_hToolBar, &rcTool);
|
||||||
|
iToolHeight = rcTool.bottom - rcTool.top;
|
||||||
|
|
||||||
|
// Resize the status bar
|
||||||
|
SendMessage(m_hStatusBar, WM_SIZE, 0, 0);
|
||||||
|
|
||||||
|
// Get the statusbar rect and save the height
|
||||||
|
GetWindowRect(m_hStatusBar, &rcStatus);
|
||||||
|
iStatusHeight = rcStatus.bottom - rcStatus.top;
|
||||||
|
|
||||||
|
// Get the full client rect
|
||||||
|
GetClientRect(m_hMainWnd, &rcClient);
|
||||||
|
|
||||||
|
// Calculate the remaining height for the treeview
|
||||||
|
lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
|
||||||
|
|
||||||
|
// Resize the device view
|
||||||
|
m_DeviceView->Size(0,
|
||||||
|
iToolHeight,
|
||||||
|
rcClient.right,
|
||||||
|
lvHeight);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT
|
||||||
|
CMainWindow::OnNotify(LPARAM lParam)
|
||||||
|
{
|
||||||
|
LPNMHDR NmHdr = (LPNMHDR)lParam;
|
||||||
|
|
||||||
|
switch (NmHdr->code)
|
||||||
|
{
|
||||||
|
case TVN_SELCHANGED:
|
||||||
|
{
|
||||||
|
LPNMTREEVIEW NmTreeView = (LPNMTREEVIEW)lParam;
|
||||||
|
UpdateContext(&NmTreeView->itemNew);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TVN_DELETEITEMW:
|
||||||
|
{
|
||||||
|
LPNMTREEVIEW NmTreeView = (LPNMTREEVIEW)lParam;
|
||||||
|
NmTreeView->action = NmTreeView->action;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NM_DBLCLK:
|
||||||
|
{
|
||||||
|
m_DeviceView->DisplayPropertySheet();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NM_RETURN:
|
||||||
|
{
|
||||||
|
m_DeviceView->DisplayPropertySheet();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT
|
||||||
|
CMainWindow::OnContext(LPARAM lParam)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT
|
||||||
|
CMainWindow::OnCommand(WPARAM wParam,
|
||||||
|
LPARAM lParam)
|
||||||
|
{
|
||||||
|
LRESULT RetCode = 0;
|
||||||
|
WORD Msg;
|
||||||
|
|
||||||
|
// Get the message
|
||||||
|
Msg = LOWORD(wParam);
|
||||||
|
|
||||||
|
switch (Msg)
|
||||||
|
{
|
||||||
|
case IDC_PROPERTIES:
|
||||||
|
{
|
||||||
|
m_DeviceView->DisplayPropertySheet();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_SCAN_HARDWARE:
|
||||||
|
{
|
||||||
|
ScanForHardwareChanges();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_DEVBYTYPE:
|
||||||
|
{
|
||||||
|
RefreshView(DevicesByType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_DEVBYCONN:
|
||||||
|
{
|
||||||
|
RefreshView(DevicesByConnection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_SHOWHIDDEN:
|
||||||
|
{
|
||||||
|
UINT CurCheckState, NewCheckState;
|
||||||
|
|
||||||
|
// Get the current state
|
||||||
|
CurCheckState = GetMenuState(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND);
|
||||||
|
|
||||||
|
if (CurCheckState == MF_CHECKED)
|
||||||
|
{
|
||||||
|
// Inform the device view of the change
|
||||||
|
m_DeviceView->ShowHiddenDevices(false);
|
||||||
|
NewCheckState = MF_UNCHECKED;
|
||||||
|
}
|
||||||
|
else if (CurCheckState == MF_UNCHECKED)
|
||||||
|
{
|
||||||
|
m_DeviceView->ShowHiddenDevices(true);
|
||||||
|
NewCheckState = MF_CHECKED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ATLASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new check state
|
||||||
|
CheckMenuItem(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND | NewCheckState);
|
||||||
|
|
||||||
|
// Refresh the device view
|
||||||
|
m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
|
||||||
|
false,
|
||||||
|
true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_ABOUT:
|
||||||
|
{
|
||||||
|
// Apportion blame
|
||||||
|
MessageBoxW(m_hMainWnd,
|
||||||
|
L"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
|
||||||
|
L"About",
|
||||||
|
MB_OK | MB_APPLMODAL);
|
||||||
|
|
||||||
|
// Set focus back to the treeview
|
||||||
|
m_DeviceView->SetFocus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_EXIT:
|
||||||
|
{
|
||||||
|
// Post a close message to the window
|
||||||
|
PostMessageW(m_hMainWnd,
|
||||||
|
WM_CLOSE,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// We didn't handle it
|
||||||
|
RetCode = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RetCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT
|
||||||
|
CMainWindow::OnDestroy()
|
||||||
|
{
|
||||||
|
// Uninitialize the device view
|
||||||
|
m_DeviceView->Uninitialize();
|
||||||
|
|
||||||
|
// Kill the object
|
||||||
|
delete m_DeviceView;
|
||||||
|
m_DeviceView = NULL;
|
||||||
|
|
||||||
|
// Clear the user data pointer
|
||||||
|
SetWindowLongPtr(m_hMainWnd, GWLP_USERDATA, 0);
|
||||||
|
|
||||||
|
// Break the message loop
|
||||||
|
PostQuitMessage(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK
|
||||||
|
CMainWindow::MainWndProc(HWND hwnd,
|
||||||
|
UINT msg,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam)
|
||||||
|
{
|
||||||
|
CMainWindow *pThis;
|
||||||
|
LRESULT RetCode = 0;
|
||||||
|
|
||||||
|
// Get the object pointer from window context
|
||||||
|
pThis = (CMainWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
|
if (pThis == NULL)
|
||||||
|
{
|
||||||
|
// Check that this isn't a create message
|
||||||
|
if (msg != WM_CREATE)
|
||||||
|
{
|
||||||
|
// Don't handle null info pointer
|
||||||
|
goto HandleDefaultMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(msg)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
{
|
||||||
|
// Get the object pointer from the create param
|
||||||
|
pThis = (CMainWindow *)((LPCREATESTRUCT)lParam)->lpCreateParams;
|
||||||
|
|
||||||
|
// Store the pointer in the window's global user data
|
||||||
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
|
||||||
|
|
||||||
|
// Call the create handler
|
||||||
|
RetCode = pThis->OnCreate(hwnd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
RetCode = pThis->OnSize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_NOTIFY:
|
||||||
|
{
|
||||||
|
RetCode = pThis->OnNotify(lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_CONTEXTMENU:
|
||||||
|
{
|
||||||
|
RetCode = pThis->OnContext(lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_MENUSELECT:
|
||||||
|
{
|
||||||
|
if (pThis->m_hStatusBar != NULL)
|
||||||
|
{
|
||||||
|
if (!pThis->MainWndMenuHint(LOWORD(wParam),
|
||||||
|
MainMenuHintTable,
|
||||||
|
sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
|
||||||
|
IDS_HINT_BLANK))
|
||||||
|
{
|
||||||
|
pThis->MainWndMenuHint(LOWORD(wParam),
|
||||||
|
SystemMenuHintTable,
|
||||||
|
sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
|
||||||
|
IDS_HINT_BLANK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
{
|
||||||
|
// Handle the command message
|
||||||
|
RetCode = pThis->OnCommand(wParam, lParam);
|
||||||
|
if (RetCode == -1)
|
||||||
|
{
|
||||||
|
// Hand it off to the default message handler
|
||||||
|
goto HandleDefaultMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
{
|
||||||
|
// Destroy the main window
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
{
|
||||||
|
// Call the destroy handler
|
||||||
|
RetCode = pThis->OnDestroy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
HandleDefaultMessage:
|
||||||
|
RetCode = DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RetCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////// MOVE ME ////////////////
|
||||||
|
|
||||||
|
HINSTANCE g_hInstance = NULL;
|
||||||
|
HANDLE ProcessHeap = NULL;
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WINAPI
|
||||||
|
DeviceManager_ExecuteW(HWND hWndParent,
|
||||||
|
HINSTANCE hInst,
|
||||||
|
LPCWSTR lpMachineName,
|
||||||
|
int nCmdShow)
|
||||||
|
{
|
||||||
|
CMainWindow MainWindow;
|
||||||
|
INITCOMMONCONTROLSEX icex;
|
||||||
|
CAtlStringW szAppName;
|
||||||
|
int Ret = 1;
|
||||||
|
|
||||||
|
// Store the global values
|
||||||
|
g_hInstance = hInst;
|
||||||
|
ProcessHeap = GetProcessHeap();
|
||||||
|
|
||||||
|
// Initialize common controls
|
||||||
|
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
||||||
|
icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES;
|
||||||
|
InitCommonControlsEx(&icex);
|
||||||
|
|
||||||
|
// Load the application name
|
||||||
|
if (szAppName.LoadStringW(g_hInstance, IDS_APPNAME))
|
||||||
|
{
|
||||||
|
// Initialize the main window
|
||||||
|
if (MainWindow.Initialize(szAppName, nCmdShow))
|
||||||
|
{
|
||||||
|
// Run the application
|
||||||
|
Ret = MainWindow.Run();
|
||||||
|
|
||||||
|
// Uninitialize the main window
|
||||||
|
MainWindow.Uninitialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
70
reactos/dll/win32/devmgr/devmgmt/MainWindow.h
Normal file
70
reactos/dll/win32/devmgr/devmgmt/MainWindow.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#pragma once
|
||||||
|
#include "DeviceView.h"
|
||||||
|
|
||||||
|
typedef struct _MENU_HINT
|
||||||
|
{
|
||||||
|
WORD CmdId;
|
||||||
|
UINT HintId;
|
||||||
|
} MENU_HINT, *PMENU_HINT;
|
||||||
|
|
||||||
|
class CMainWindow
|
||||||
|
{
|
||||||
|
CAtlStringW m_szMainWndClass;
|
||||||
|
CDeviceView *m_DeviceView;
|
||||||
|
HWND m_hMainWnd;
|
||||||
|
HWND m_hStatusBar;
|
||||||
|
HWND m_hToolBar;
|
||||||
|
HIMAGELIST m_ToolbarhImageList;
|
||||||
|
HMENU m_hMenu;
|
||||||
|
int m_CmdShow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMainWindow(void);
|
||||||
|
~CMainWindow(void);
|
||||||
|
|
||||||
|
bool Initialize(LPCTSTR lpCaption, int nCmdShow);
|
||||||
|
int Run();
|
||||||
|
void Uninitialize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static LRESULT CALLBACK MainWndProc(
|
||||||
|
HWND hwnd,
|
||||||
|
UINT msg,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam
|
||||||
|
);
|
||||||
|
|
||||||
|
LRESULT OnCreate(HWND hwnd);
|
||||||
|
LRESULT OnDestroy();
|
||||||
|
LRESULT OnSize();
|
||||||
|
LRESULT OnNotify(LPARAM lParam);
|
||||||
|
LRESULT OnContext(LPARAM lParam);
|
||||||
|
LRESULT OnCommand(WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
bool CreateToolBar();
|
||||||
|
bool CreateStatusBar();
|
||||||
|
|
||||||
|
void UpdateContext(_In_ LPTV_ITEMW TvItem);
|
||||||
|
|
||||||
|
bool StatusBarLoadString(
|
||||||
|
HWND hStatusBar,
|
||||||
|
INT PartId,
|
||||||
|
HINSTANCE hInstance,
|
||||||
|
UINT uID
|
||||||
|
);
|
||||||
|
|
||||||
|
bool MainWndMenuHint(
|
||||||
|
WORD CmdId,
|
||||||
|
const MENU_HINT *HintArray,
|
||||||
|
DWORD HintsCount,
|
||||||
|
UINT DefHintId
|
||||||
|
);
|
||||||
|
|
||||||
|
bool RefreshView(
|
||||||
|
ViewType Type
|
||||||
|
);
|
||||||
|
|
||||||
|
bool ScanForHardwareChanges(
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
375
reactos/dll/win32/devmgr/devmgmt/Node.cpp
Normal file
375
reactos/dll/win32/devmgr/devmgmt/Node.cpp
Normal file
|
@ -0,0 +1,375 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Device Manager
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: dll/win32/devmgr/devmgr/node.cpp
|
||||||
|
* PURPOSE: Object for each device in the tree
|
||||||
|
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "devmgmt.h"
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* PUBLIC METHODS *******************************************/
|
||||||
|
|
||||||
|
CNode::CNode(_In_ LPGUID ClassGuid,
|
||||||
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
||||||
|
m_ImageListData(ImageListData),
|
||||||
|
m_NodeType(NodeClass),
|
||||||
|
m_DevInst(0),
|
||||||
|
m_DeviceId(NULL),
|
||||||
|
m_ClassImage(0),
|
||||||
|
m_Status(0),
|
||||||
|
m_ProblemNumber(0),
|
||||||
|
m_OverlayImage(0)
|
||||||
|
{
|
||||||
|
m_DisplayName[0] = UNICODE_NULL;
|
||||||
|
CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
CNode::CNode(_In_opt_ DEVINST Device,
|
||||||
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
||||||
|
m_ImageListData(ImageListData),
|
||||||
|
m_NodeType(NodeDevice),
|
||||||
|
m_DevInst(Device),
|
||||||
|
m_DeviceId(NULL),
|
||||||
|
m_ClassImage(0),
|
||||||
|
m_Status(0),
|
||||||
|
m_ProblemNumber(0),
|
||||||
|
m_OverlayImage(0)
|
||||||
|
{
|
||||||
|
m_DisplayName[0] = UNICODE_NULL;
|
||||||
|
CopyMemory(&m_ClassGuid, &GUID_NULL, sizeof(GUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
CNode::~CNode()
|
||||||
|
{
|
||||||
|
Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::Setup()
|
||||||
|
{
|
||||||
|
// TODO: Make this polymorphic
|
||||||
|
|
||||||
|
if (m_NodeType == NodeClass)
|
||||||
|
{
|
||||||
|
return SetupClassNode();
|
||||||
|
}
|
||||||
|
else if (m_NodeType == NodeDevice)
|
||||||
|
{
|
||||||
|
return SetupDeviceNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::HasProperties()
|
||||||
|
{
|
||||||
|
return (m_DeviceId != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::IsHidden()
|
||||||
|
{
|
||||||
|
return ((m_Status & DN_NO_SHOW_IN_DM) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::CanDisable()
|
||||||
|
{
|
||||||
|
return (m_NodeType == NodeDevice && ((m_Status & DN_DISABLEABLE) != 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::IsDisabled()
|
||||||
|
{
|
||||||
|
return ((m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::IsStarted()
|
||||||
|
{
|
||||||
|
return ((m_Status & DN_STARTED) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::IsInstalled()
|
||||||
|
{
|
||||||
|
return ((m_Status & DN_HAS_PROBLEM) != 0 ||
|
||||||
|
(m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PRIVATE METHODS ******************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::SetupClassNode()
|
||||||
|
{
|
||||||
|
DWORD RequiredSize, Type, Size;
|
||||||
|
DWORD Success;
|
||||||
|
HKEY hKey;
|
||||||
|
|
||||||
|
// Open the registry key for this class
|
||||||
|
hKey = SetupDiOpenClassRegKeyExW(&m_ClassGuid,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
DIOCR_INSTALLER,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (hKey != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
Size = DISPLAY_NAME_LEN;
|
||||||
|
Type = REG_SZ;
|
||||||
|
|
||||||
|
// Lookup the class description (win7+)
|
||||||
|
Success = RegQueryValueExW(hKey,
|
||||||
|
L"ClassDesc",
|
||||||
|
NULL,
|
||||||
|
&Type,
|
||||||
|
(LPBYTE)m_DisplayName,
|
||||||
|
&Size);
|
||||||
|
if (Success == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// Check if the string starts with an @
|
||||||
|
if (m_DisplayName[0] == L'@')
|
||||||
|
{
|
||||||
|
// The description is located in a module resource
|
||||||
|
Success = ConvertResourceDescriptorToString(m_DisplayName, DISPLAY_NAME_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Success == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
// WinXP stores the description in the default value
|
||||||
|
Success = RegQueryValueExW(hKey,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&Type,
|
||||||
|
(LPBYTE)m_DisplayName,
|
||||||
|
&Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the registry key
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Success = GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we failed to get the class description
|
||||||
|
if (Success != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// Use the class name as the description
|
||||||
|
RequiredSize = DISPLAY_NAME_LEN;
|
||||||
|
(VOID)SetupDiClassNameFromGuidW(&m_ClassGuid,
|
||||||
|
m_DisplayName,
|
||||||
|
RequiredSize,
|
||||||
|
&RequiredSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the image index for this class
|
||||||
|
(VOID)SetupDiGetClassImageIndex(m_ImageListData,
|
||||||
|
&m_ClassGuid,
|
||||||
|
&m_ClassImage);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CNode::SetupDeviceNode()
|
||||||
|
{
|
||||||
|
WCHAR ClassGuidString[MAX_GUID_STRING_LEN];
|
||||||
|
ULONG ulLength;
|
||||||
|
CONFIGRET cr;
|
||||||
|
|
||||||
|
// ATLASSERT(m_DeviceId == NULL);
|
||||||
|
|
||||||
|
// 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 = (LPWSTR)HeapAlloc(GetProcessHeap(),
|
||||||
|
0,
|
||||||
|
(ulLength + 1) * sizeof(WCHAR));
|
||||||
|
if (m_DeviceId)
|
||||||
|
{
|
||||||
|
// Now get the actual device id
|
||||||
|
cr = CM_Get_Device_IDW(m_DevInst,
|
||||||
|
m_DeviceId,
|
||||||
|
ulLength + 1,
|
||||||
|
0);
|
||||||
|
if (cr != CR_SUCCESS)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, m_DeviceId);
|
||||||
|
m_DeviceId = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we got the string
|
||||||
|
if (m_DeviceId == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get the current status of the device
|
||||||
|
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||||
|
&m_ProblemNumber,
|
||||||
|
m_DevInst,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
if (cr != CR_SUCCESS)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, m_DeviceId);
|
||||||
|
m_DeviceId = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the device has a problem
|
||||||
|
if (m_Status & DN_HAS_PROBLEM)
|
||||||
|
{
|
||||||
|
m_OverlayImage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The disabled overlay takes precidence over the problem overlay
|
||||||
|
if (m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED))
|
||||||
|
{
|
||||||
|
m_OverlayImage = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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 = DISPLAY_NAME_LEN * sizeof(WCHAR);
|
||||||
|
cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
|
||||||
|
CM_DRP_FRIENDLYNAME,
|
||||||
|
NULL,
|
||||||
|
m_DisplayName,
|
||||||
|
&ulLength,
|
||||||
|
0);
|
||||||
|
if (cr != CR_SUCCESS)
|
||||||
|
{
|
||||||
|
ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
|
||||||
|
cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
|
||||||
|
CM_DRP_DEVICEDESC,
|
||||||
|
NULL,
|
||||||
|
m_DisplayName,
|
||||||
|
&ulLength,
|
||||||
|
0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup if something failed
|
||||||
|
if (cr != CR_SUCCESS)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, m_DeviceId);
|
||||||
|
m_DeviceId = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (cr == CR_SUCCESS ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CNode::Cleanup()
|
||||||
|
{
|
||||||
|
if (m_DeviceId)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, m_DeviceId);
|
||||||
|
m_DeviceId = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
CNode::ConvertResourceDescriptorToString(
|
||||||
|
_Inout_z_ LPWSTR ResourceDescriptor,
|
||||||
|
_In_ DWORD ResourceDescriptorSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
WCHAR ModulePath[MAX_PATH];
|
||||||
|
WCHAR ResString[256];
|
||||||
|
INT ResourceId;
|
||||||
|
HMODULE hModule;
|
||||||
|
LPWSTR ptr;
|
||||||
|
DWORD Size;
|
||||||
|
DWORD dwError;
|
||||||
|
|
||||||
|
|
||||||
|
// First check for a semi colon */
|
||||||
|
ptr = wcschr(ResourceDescriptor, L';');
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
// This must be an inf based descriptor, the desc is after the semi colon
|
||||||
|
wcscpy_s(ResourceDescriptor, ResourceDescriptorSize, ++ptr);
|
||||||
|
dwError = ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This must be a dll resource based descriptor. Find the comma
|
||||||
|
ptr = wcschr(ResourceDescriptor, L',');
|
||||||
|
if (ptr == NULL) return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
|
// Terminate the string where the comma was
|
||||||
|
*ptr = UNICODE_NULL;
|
||||||
|
|
||||||
|
// Expand any environment strings
|
||||||
|
Size = ExpandEnvironmentStringsW(&ResourceDescriptor[1], ModulePath, MAX_PATH);
|
||||||
|
if (Size > MAX_PATH) return ERROR_BUFFER_OVERFLOW;
|
||||||
|
if (Size == 0) return GetLastError();
|
||||||
|
|
||||||
|
// Put the comma back and move past it
|
||||||
|
*ptr = L',';
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
// Load the dll
|
||||||
|
hModule = LoadLibraryExW(ModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||||
|
if (hModule == NULL) return GetLastError();
|
||||||
|
|
||||||
|
// Convert the resource id to a number
|
||||||
|
ResourceId = _wtoi(ptr);
|
||||||
|
|
||||||
|
// If the number is negative, make it positive
|
||||||
|
if (ResourceId < 0) ResourceId = -ResourceId;
|
||||||
|
|
||||||
|
// Load the string from the dll
|
||||||
|
if (LoadStringW(hModule, ResourceId, ResString, 256))
|
||||||
|
{
|
||||||
|
wcscpy_s(ResourceDescriptor, ResourceDescriptorSize, ResString);
|
||||||
|
dwError = ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwError = GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the library
|
||||||
|
FreeLibrary(hModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dwError;
|
||||||
|
}
|
78
reactos/dll/win32/devmgr/devmgmt/Node.h
Normal file
78
reactos/dll/win32/devmgr/devmgmt/Node.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define DISPLAY_NAME_LEN 256
|
||||||
|
#define ROOT_NAME_SIZE MAX_COMPUTERNAME_LENGTH + 1
|
||||||
|
|
||||||
|
enum NodeType
|
||||||
|
{
|
||||||
|
NodeClass,
|
||||||
|
NodeDevice
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ULONG Actions;
|
||||||
|
#define Update 0x01
|
||||||
|
#define Enable 0x02
|
||||||
|
#define Disable 0x04
|
||||||
|
#define Uninstall 0x08
|
||||||
|
|
||||||
|
|
||||||
|
class CNode
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
PSP_CLASSIMAGELIST_DATA m_ImageListData;
|
||||||
|
NodeType m_NodeType;
|
||||||
|
DEVINST m_DevInst;
|
||||||
|
Actions m_Actions;
|
||||||
|
LPWSTR m_DeviceId;
|
||||||
|
WCHAR m_DisplayName[DISPLAY_NAME_LEN];
|
||||||
|
GUID m_ClassGuid;
|
||||||
|
INT m_ClassImage;
|
||||||
|
ULONG m_Status;
|
||||||
|
ULONG m_ProblemNumber;
|
||||||
|
INT m_OverlayImage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CNode(
|
||||||
|
_In_ LPGUID ClassGuid,
|
||||||
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||||
|
);
|
||||||
|
|
||||||
|
CNode(
|
||||||
|
_In_ DEVINST Device,
|
||||||
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||||
|
);
|
||||||
|
|
||||||
|
~CNode();
|
||||||
|
|
||||||
|
bool Setup();
|
||||||
|
|
||||||
|
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
||||||
|
DEVINST GetDeviceInst() { return m_DevInst; }
|
||||||
|
|
||||||
|
LPWSTR GetDisplayName() { return m_DisplayName; }
|
||||||
|
INT GetClassImage() { return m_ClassImage; }
|
||||||
|
INT GetOverlayImage() { return m_OverlayImage; }
|
||||||
|
LPWSTR GetDeviceId() { return m_DeviceId; }
|
||||||
|
Actions GetActions() { return m_Actions; }
|
||||||
|
|
||||||
|
bool HasProblem() { return !!(m_ProblemNumber); }
|
||||||
|
bool HasProperties();
|
||||||
|
bool IsHidden();
|
||||||
|
bool CanDisable();
|
||||||
|
bool IsDisabled();
|
||||||
|
bool IsStarted();
|
||||||
|
bool IsInstalled();
|
||||||
|
bool CanInstall() { return TRUE; } // unimplemented
|
||||||
|
bool CanUninstall() { return TRUE; } // unimplemented
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool SetupClassNode();
|
||||||
|
bool SetupDeviceNode();
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
DWORD ConvertResourceDescriptorToString(
|
||||||
|
_Inout_z_ LPWSTR ResourceDescriptor,
|
||||||
|
_In_ DWORD ResourceDescriptorSize
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
63
reactos/dll/win32/devmgr/devmgmt/Resource.h
Normal file
63
reactos/dll/win32/devmgr/devmgmt/Resource.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#define IDC_STATIC -1
|
||||||
|
|
||||||
|
#define IDI_MAIN_ICON 20
|
||||||
|
#define IDB_ROOT_IMAGE 21
|
||||||
|
#define IDB_TOOLBAR 22
|
||||||
|
|
||||||
|
/* windows */
|
||||||
|
#define IDC_TREEVIEW 50
|
||||||
|
#define IDC_TOOLBAR 51
|
||||||
|
#define IDC_STATUSBAR 52
|
||||||
|
#define IDR_MAINMENU 53
|
||||||
|
#define IDR_POPUP 54
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
#define IDC_PROPERTIES 100
|
||||||
|
#define IDC_SCAN_HARDWARE 101
|
||||||
|
#define IDC_ENABLE_DRV 102
|
||||||
|
#define IDC_DISABLE_DRV 103
|
||||||
|
#define IDC_UPDATE_DRV 104
|
||||||
|
#define IDC_UNINSTALL_DRV 105
|
||||||
|
#define IDC_ADD_HARDWARE 106
|
||||||
|
#define IDC_ABOUT 107
|
||||||
|
#define IDC_EXIT 108
|
||||||
|
|
||||||
|
/* view menu */
|
||||||
|
#define IDC_DEVBYTYPE 200
|
||||||
|
#define IDC_DEVBYCONN 201
|
||||||
|
#define IDC_RESBYTYPE 202
|
||||||
|
#define IDC_RESBYCONN 203
|
||||||
|
#define IDC_SHOWHIDDEN 204
|
||||||
|
|
||||||
|
/* about box info */
|
||||||
|
#define IDD_ABOUTBOX 300
|
||||||
|
#define IDC_LICENSE_EDIT 301
|
||||||
|
#define IDS_APPNAME 302
|
||||||
|
#define IDS_LICENSE 303
|
||||||
|
|
||||||
|
/* tooltips */
|
||||||
|
#define IDS_TOOLTIP_PROP 6000
|
||||||
|
#define IDS_TOOLTIP_REFRESH 6001
|
||||||
|
#define IDS_TOOLTIP_HELP 6002
|
||||||
|
|
||||||
|
/* menu hints */
|
||||||
|
#define IDS_HINT_BLANK 20000
|
||||||
|
#define IDS_HINT_REFRESH 20002
|
||||||
|
#define IDS_HINT_PROP 20003
|
||||||
|
#define IDS_HINT_HELP 20004
|
||||||
|
#define IDS_HINT_ABOUT 20005
|
||||||
|
#define IDS_HINT_EXIT 20006
|
||||||
|
|
||||||
|
#define IDS_HINT_DEV_BY_TYPE 20020
|
||||||
|
#define IDS_HINT_DEV_BY_CONN 20021
|
||||||
|
#define IDS_HINT_RES_BY_TYPE 20022
|
||||||
|
#define IDS_HINT_RES_BY_CONN 20023
|
||||||
|
|
||||||
|
/* system menu hints */
|
||||||
|
#define IDS_HINT_SYS_RESTORE 21001
|
||||||
|
#define IDS_HINT_SYS_MOVE 21002
|
||||||
|
#define IDS_HINT_SYS_SIZE 21003
|
||||||
|
#define IDS_HINT_SYS_MINIMIZE 21004
|
||||||
|
#define IDS_HINT_SYS_MAXIMIZE 21005
|
||||||
|
#define IDS_HINT_SYS_CLOSE 21006
|
||||||
|
|
9
reactos/dll/win32/devmgr/devmgmt/devmgmt.h
Normal file
9
reactos/dll/win32/devmgr/devmgmt/devmgmt.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#pragma once
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
extern HINSTANCE g_hInstance;
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
|
72
reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc
Normal file
72
reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
IDR_MAINMENU MENU
|
||||||
|
BEGIN
|
||||||
|
POPUP "&File"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "E&xit", IDC_EXIT
|
||||||
|
END
|
||||||
|
POPUP "Action"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Update driver software..." IDC_UPDATE_DRV
|
||||||
|
MENUITEM "Disable" IDC_DISABLE_DRV
|
||||||
|
MENUITEM "Uninstall" IDC_UNINSTALL_DRV
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Scan for hardware changes" IDC_SCAN_HARDWARE
|
||||||
|
MENUITEM "Add hardware" IDC_ADD_HARDWARE, GRAYED
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Properties", IDC_PROPERTIES
|
||||||
|
END
|
||||||
|
POPUP "View"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Devices by type", IDC_DEVBYTYPE
|
||||||
|
MENUITEM "Devices by connection", IDC_DEVBYCONN
|
||||||
|
MENUITEM "Resources by type", IDC_RESBYTYPE, GRAYED
|
||||||
|
MENUITEM "Resources by connection", IDC_RESBYCONN, GRAYED
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Show hidden devices", IDC_SHOWHIDDEN
|
||||||
|
END
|
||||||
|
POPUP "Help"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "About", IDC_ABOUT
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
IDR_POPUP MENU
|
||||||
|
BEGIN
|
||||||
|
POPUP "popup"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Properties", IDC_PROPERTIES, GRAYED
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TOOLTIP_PROP "Properties"
|
||||||
|
IDS_TOOLTIP_REFRESH "Scan for hardware changes"
|
||||||
|
IDS_TOOLTIP_HELP "Help"
|
||||||
|
END
|
||||||
|
|
||||||
|
/* Hints */
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_APPNAME "ReactOS Device Manager"
|
||||||
|
IDS_HINT_BLANK " "
|
||||||
|
IDS_HINT_EXIT " Exits the program."
|
||||||
|
IDS_HINT_REFRESH " Scan for changed or new Plug and Play devices."
|
||||||
|
IDS_HINT_PROP " Open property dialog for the current selection."
|
||||||
|
IDS_HINT_HELP " Display help window."
|
||||||
|
IDS_HINT_ABOUT " About ReactOS Device Manager."
|
||||||
|
|
||||||
|
IDS_HINT_DEV_BY_TYPE "Displays devices by hardware type"
|
||||||
|
IDS_HINT_DEV_BY_CONN "Displays devices by connection"
|
||||||
|
IDS_HINT_RES_BY_TYPE "Diaplays resources by type"
|
||||||
|
IDS_HINT_RES_BY_CONN "Displays resources by connection type"
|
||||||
|
|
||||||
|
IDS_HINT_SYS_RESTORE " Restores this window to normal size."
|
||||||
|
IDS_HINT_SYS_MOVE " Moves this window."
|
||||||
|
IDS_HINT_SYS_SIZE " Resizes this window."
|
||||||
|
IDS_HINT_SYS_MINIMIZE " Collapses this window to an icon."
|
||||||
|
IDS_HINT_SYS_MAXIMIZE " Expands this window to fill this screen."
|
||||||
|
IDS_HINT_SYS_CLOSE " Closes this window."
|
||||||
|
END
|
BIN
reactos/dll/win32/devmgr/devmgmt/res/computer.ico
Normal file
BIN
reactos/dll/win32/devmgr/devmgmt/res/computer.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
BIN
reactos/dll/win32/devmgr/devmgmt/res/root.bmp
Normal file
BIN
reactos/dll/win32/devmgr/devmgmt/res/root.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 822 B |
BIN
reactos/dll/win32/devmgr/devmgmt/res/toolbar.bmp
Normal file
BIN
reactos/dll/win32/devmgr/devmgmt/res/toolbar.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
80
reactos/dll/win32/devmgr/devmgmt/rsrc.rc
Normal file
80
reactos/dll/win32/devmgr/devmgmt/rsrc.rc
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include <windows.h>
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
|
||||||
|
IDI_MAIN_ICON ICON "res/computer.ico"
|
||||||
|
IDB_ROOT_IMAGE BITMAP "res/root.bmp"
|
||||||
|
|
||||||
|
/* main toolbar icons */
|
||||||
|
IDB_TOOLBAR BITMAP DISCARDABLE "res/toolbar.bmp"
|
||||||
|
|
||||||
|
// UTF-8
|
||||||
|
#pragma code_page(65001)
|
||||||
|
|
||||||
|
#ifdef LANGUAGE_BG_BG
|
||||||
|
#include "lang/bg-BG.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_DE_DE
|
||||||
|
#include "lang/de-DE.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_EL_GR
|
||||||
|
#include "lang/el-GR.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_EN_US
|
||||||
|
#include "lang/en-US.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_ES_ES
|
||||||
|
#include "lang/es-ES.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_FR_FR
|
||||||
|
#include "lang/fr-FR.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_HE_IL
|
||||||
|
#include "lang/he-IL.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_ID_ID
|
||||||
|
#include "lang/id-ID.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_IT_IT
|
||||||
|
#include "lang/it-IT.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_JA_JP
|
||||||
|
#include "lang/ja-JP.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_KO_KR
|
||||||
|
#include "lang/ko-KR.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_NB_NO
|
||||||
|
#include "lang/no-NO.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_PL_PL
|
||||||
|
#include "lang/pl-PL.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_PT_BR
|
||||||
|
#include "lang/pt-BR.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_RO_RO
|
||||||
|
#include "lang/ro-RO.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_RU_RU
|
||||||
|
#include "lang/ru-RU.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_SK_SK
|
||||||
|
#include "lang/sk-SK.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_SV_SE
|
||||||
|
#include "lang/sv-SE.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_TH_TH
|
||||||
|
#include "lang/th-TH.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_TR_TR
|
||||||
|
#include "lang/tr-TR.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_UK_UA
|
||||||
|
#include "lang/uk-UA.rc"
|
||||||
|
#endif
|
||||||
|
#ifdef LANGUAGE_ZH_CN
|
||||||
|
#include "lang/zh-CN.rc"
|
||||||
|
#endif
|
50
reactos/dll/win32/devmgr/devmgmt/stdafx.h
Normal file
50
reactos/dll/win32/devmgr/devmgmt/stdafx.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __REACTOS___
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <setupapi.h>
|
||||||
|
#include <cfgmgr32.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <Uxtheme.h>
|
||||||
|
#include <Cfgmgr32.h>
|
||||||
|
#include <devguid.h>
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <atlbase.h>
|
||||||
|
#include <atlstr.h>
|
||||||
|
#include <atlcoll.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#include <windef.h>
|
||||||
|
#include <winbase.h>
|
||||||
|
#include <winreg.h>
|
||||||
|
#include <wingdi.h>
|
||||||
|
#include <winnls.h>
|
||||||
|
#include <wincon.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include <setupapi.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <cfgmgr32.h>
|
||||||
|
#include <Uxtheme.h>
|
||||||
|
|
||||||
|
#include <atlbase.h>
|
||||||
|
#include <atlcom.h>
|
||||||
|
#include <atlwin.h>
|
||||||
|
#include <atlstr.h>
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue