mirror of
https://github.com/reactos/reactos.git
synced 2025-06-03 08:20:27 +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…
Reference in a new issue