Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387/* * PROJECT: ReactOS Device Manager * LICENSE: GPL - See COPYING in the top level directory * FILE: dll/win32/devmgr/devmgmt/DeviceView.cpp * PURPOSE: Implements the tree view which contains the devices * COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org> */
#include "precomp.h"#include "restypes.h"#include "devmgmt.h"#include "DeviceView.h"
// DATA ********************************************/
#define CLASS_NAME_LEN 256#define CLASS_DESC_LEN 256#define ROOT_NAME_SIZE MAX_COMPUTERNAME_LENGTH + 1
typedef VOID(WINAPI *PADDHARDWAREWIZARD)(HWND hwnd, LPWSTR lpName);
struct RefreshThreadData{ CDeviceView *This; BOOL ScanForChanges; BOOL UpdateView;};
// PUBLIC METHODS ************************************/
CDeviceView::CDeviceView( HWND hMainWnd ) : m_hMainWnd(hMainWnd), m_hTreeView(NULL), m_hPropertyDialog(NULL), m_hMenu(NULL), m_ViewType(DevicesByType), m_ShowHidden(false), m_RootNode(NULL){ ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));}
CDeviceView::~CDeviceView(void){}
boolCDeviceView::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_hThisInstance, 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);
// Create the root node m_RootNode = new CRootNode(&m_ImageListData); m_RootNode->SetupNode(); }
return !!(m_hTreeView);}
boolCDeviceView::Uninitialize(){ EmptyDeviceView();
if (m_ImageListData.ImageList != NULL) { SetupDiDestroyClassImageList(&m_ImageListData); ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA)); }
return true;}
LRESULTCDeviceView::OnSize( _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);
return 0;}
LRESULTCDeviceView::OnDoubleClick( _In_ LPNMHDR NmHdr ){ TVHITTESTINFO hitInfo; HTREEITEM hItem;
GetCursorPos(&hitInfo.pt); ScreenToClient(m_hTreeView, &hitInfo.pt);
// Check if we are trying to double-click an item hItem = TreeView_HitTest(m_hTreeView, &hitInfo); if (hItem != NULL && (hitInfo.flags & (TVHT_ONITEM | TVHT_ONITEMICON))) { DisplayPropertySheet(); }
return 0;}
LRESULTCDeviceView::OnRightClick( _In_ LPNMHDR NmHdr ){ TVHITTESTINFO hitInfo; HTREEITEM hItem;
GetCursorPos(&hitInfo.pt); ScreenToClient(m_hTreeView, &hitInfo.pt);
hItem = TreeView_HitTest(m_hTreeView, &hitInfo); if (hItem != NULL && (hitInfo.flags & (TVHT_ONITEM | TVHT_ONITEMICON))) { TreeView_SelectItem(m_hTreeView, hItem); }
return 0;}
LRESULTCDeviceView::OnContextMenu( _In_ LPARAM lParam ){ HTREEITEM hSelected = TreeView_GetSelection(m_hTreeView);
RECT rc; if (TreeView_GetItemRect(m_hTreeView, hSelected, &rc, TRUE)) { POINT pt; if (GetCursorPos(&pt) && ScreenToClient(m_hTreeView, &pt) && PtInRect(&rc, pt)) { CNode *Node = GetSelectedNode(); if (Node) { // Create the context menu HMENU hContextMenu = CreatePopupMenu();
// Add the actions for this node BuildActionMenuForNode(hContextMenu, Node, false);
INT xPos = GET_X_LPARAM(lParam); INT yPos = GET_Y_LPARAM(lParam);
// Display the menu TrackPopupMenuEx(hContextMenu, TPM_RIGHTBUTTON, xPos, yPos, m_hMainWnd, NULL);
DestroyMenu(hContextMenu); } } }
return 0;}
voidCDeviceView::Refresh( _In_ ViewType Type, _In_ bool ScanForChanges, _In_ bool UpdateView ){ // Enum devices on a separate 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);}
LRESULTCDeviceView::OnAction( _In_ UINT Action){ switch (Action) { case IDM_PROPERTIES: { DisplayPropertySheet(); break; }
case IDM_SCAN_HARDWARE: { Refresh(GetCurrentView(), true, true); break; }
case IDM_ENABLE_DRV: { bool NeedsReboot; if (EnableSelectedDevice(true, NeedsReboot) && NeedsReboot) { MessageBox(m_hMainWnd, L"Rebooting", L"Enable", MB_OK); } break; }
case IDM_DISABLE_DRV: { bool NeedsReboot; EnableSelectedDevice(false, NeedsReboot); break; }
case IDM_UPDATE_DRV: { bool NeedsReboot; UpdateSelectedDevice(NeedsReboot); break; }
case IDM_UNINSTALL_DRV: { UninstallSelectedDevice(); break; }
case IDM_ADD_HARDWARE: { RunAddHardwareWizard(); break; } }
return 0;}
voidCDeviceView::DisplayPropertySheet(){ CNode *Node = GetSelectedNode(); if (Node && Node->HasProperties()) { DevicePropertiesExW(m_hTreeView, NULL, Node->GetDeviceId(), 1,//DPF_EXTENDED, FALSE); }}
voidCDeviceView::SetFocus(){ ::SetFocus(m_hTreeView);}
boolCDeviceView::CreateActionMenu( _In_ HMENU OwnerMenu, _In_ bool MainMenu ){ CNode *Node = GetSelectedNode(); if (Node) { BuildActionMenuForNode(OwnerMenu, Node, MainMenu); return true; }
return false;}
CNode*CDeviceView::GetSelectedNode(){ TV_ITEM TvItem; TvItem.hItem = TreeView_GetSelection(m_hTreeView); return GetNode(&TvItem);}
// PRIVATE METHODS *******************************************/
boolCDeviceView::AddRootDevice(){ m_hTreeRoot = InsertIntoTreeView(NULL, m_RootNode); return (m_hTreeRoot != NULL);}
boolCDeviceView::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;
// 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;
// Get a copy of the currently selected node CNode *LastSelectedNode = This->GetSelectedNode(); if (LastSelectedNode == nullptr || (LastSelectedNode->GetNodeType() == RootNode)) { LastSelectedNode = new CRootNode(*This->m_RootNode); } else if (LastSelectedNode->GetNodeType() == ClassNode) { LastSelectedNode = new CClassNode(*dynamic_cast<CClassNode *>(LastSelectedNode)); } else if (LastSelectedNode->GetNodeType() == DeviceNode) { LastSelectedNode = new CDeviceNode(*dynamic_cast<CDeviceNode *>(LastSelectedNode)); }
// Empty the treeview This->EmptyDeviceView();
// Re-add the root node to the tree if (This->AddRootDevice() == false) return 0;
// Refresh the devices only if requested 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: (VOID)This->ListResourcesByType(); break;
case ResourcesByConnection: break; }
This->SelectNode(LastSelectedNode);
delete ThreadData;
return 0;}
boolCDeviceView::ListDevicesByType(){ CClassNode *ClassNode; CDeviceNode *DeviceNode; HDEVINFO hDevInfo; HTREEITEM hTreeItem = NULL; GUID ClassGuid; INT ClassIndex; BOOL bClassSuccess, bSuccess;
ClassIndex = 0; do { // Loop through all the device classes bClassSuccess = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo); if (bClassSuccess) { bool AddedParent = false; INT DeviceIndex = 0; bool MoreItems = false;
// Get the cached class node ClassNode = GetClassNode(&ClassGuid); if (ClassNode == nullptr) { ClassIndex++; continue; }
// Check if this is a hidden class if (IsEqualGUID(ClassGuid, GUID_DEVCLASS_LEGACYDRIVER) || IsEqualGUID(ClassGuid, GUID_DEVCLASS_VOLUME)) { // Ignore this device if we aren't displaying hidden devices if (m_ShowHidden == FALSE) { ClassIndex++; continue; } }
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;
// Get the cached device node DeviceNode = GetDeviceNode(DeviceInfoData.DevInst); if (DeviceNode == nullptr) { 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;}
boolCDeviceView::ListDevicesByConnection(){ // Walk the device tree and add all the devices (void)RecurseChildDevices(m_RootNode->GetDeviceInst(), m_hTreeRoot);
// Expand the root item (void)TreeView_Expand(m_hTreeView, m_hTreeRoot, TVE_EXPAND);
return true;}
boolCDeviceView::ListResourcesByType(){ HTREEITEM hMemoryTreeItem = NULL; HTREEITEM hPortTreeItem = NULL; HTREEITEM hDmaTreeItem = NULL; HTREEITEM hIrqTreeItem = NULL;
CResourceTypeNode *MemoryNode = new CResourceTypeNode(IDS_TYPE_MEMORY, &m_ImageListData); hMemoryTreeItem = InsertIntoTreeView(m_hTreeRoot, MemoryNode);
CResourceTypeNode *PortNode = new CResourceTypeNode(IDS_TYPE_PORT, &m_ImageListData); hPortTreeItem = InsertIntoTreeView(m_hTreeRoot, PortNode);
CResourceTypeNode *DmaNode = new CResourceTypeNode(IDS_TYPE_DMA, &m_ImageListData); hDmaTreeItem = InsertIntoTreeView(m_hTreeRoot, DmaNode);
CResourceTypeNode *IrqNode = new CResourceTypeNode(IDS_TYPE_IRQ, &m_ImageListData); hIrqTreeItem = InsertIntoTreeView(m_hTreeRoot, IrqNode);
// Walk the device tree and add all the resources (void)RecurseResources(m_RootNode->GetDeviceInst(), hMemoryTreeItem, hPortTreeItem, hDmaTreeItem, hIrqTreeItem);
// Sort the resource types alphabetically (void)TreeView_SortChildren(m_hTreeView, m_hTreeRoot, 0);
// Expand the root item (void)TreeView_Expand(m_hTreeView, m_hTreeRoot, TVE_EXPAND);
return true;}
boolCDeviceView::RecurseResources( _In_ DEVINST ParentDevice, _In_ HTREEITEM hMemoryTreeItem, _In_ HTREEITEM hPortTreeItem, _In_ HTREEITEM hDmaTreeItem, _In_ HTREEITEM hIrqTreeItem ){ DEVINST Device; bool bSuccess; ULONG Index;
// Check if the parent has any child devices if (GetChildDevice(ParentDevice, &Device) == FALSE) return true;
// Get the cached device node CDeviceNode *DeviceNode; DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device)); if (DeviceNode == nullptr) { return false; }
PCM_RESOURCE_LIST pResourceList = (PCM_RESOURCE_LIST)GetResourceList(DeviceNode->GetDeviceId()); if (pResourceList) {
for (Index = 0; Index < pResourceList->List[0].PartialResourceList.Count; Index++) { PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &pResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
if (Descriptor->Type == CmResourceTypeInterrupt) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hIrqTreeItem, resNode); } else if (Descriptor->Type == CmResourceTypePort) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hPortTreeItem, resNode); } else if (Descriptor->Type == CmResourceTypeMemory) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hMemoryTreeItem, resNode); } else if (Descriptor->Type == CmResourceTypeDma) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hDmaTreeItem, resNode); } }
HeapFree(GetProcessHeap(), 0, pResourceList); }
RecurseResources(Device, hMemoryTreeItem, hPortTreeItem, hDmaTreeItem, hIrqTreeItem);
// Check for siblings for (;;) { // Check if the parent device has anything at the same level bSuccess = GetSiblingDevice(Device, &Device); if (bSuccess == FALSE) break;
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device)); if (DeviceNode == nullptr) { continue; }
PCM_RESOURCE_LIST pResourceList = (PCM_RESOURCE_LIST)GetResourceList(DeviceNode->GetDeviceId()); if (pResourceList) { for (Index = 0; Index < pResourceList->List[0].PartialResourceList.Count; Index++) { PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &pResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
if (Descriptor->Type == CmResourceTypeInterrupt) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hIrqTreeItem, resNode); } else if (Descriptor->Type == CmResourceTypePort) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hPortTreeItem, resNode); } else if (Descriptor->Type == CmResourceTypeMemory) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hMemoryTreeItem, resNode); } else if (Descriptor->Type == CmResourceTypeDma) { CResourceNode *resNode = new CResourceNode(DeviceNode, Descriptor, &m_ImageListData); InsertIntoTreeView(hDmaTreeItem, resNode); } }
HeapFree(GetProcessHeap(), 0, pResourceList); }
RecurseResources(Device, hMemoryTreeItem, hPortTreeItem, hDmaTreeItem, hIrqTreeItem); }
(void)TreeView_SortChildren(m_hTreeView, hMemoryTreeItem, 0);
(void)TreeView_SortChildren(m_hTreeView, hPortTreeItem, 0);
(void)TreeView_SortChildren(m_hTreeView, hIrqTreeItem, 0);
(void)TreeView_SortChildren(m_hTreeView, hDmaTreeItem, 0);
return true;}
boolCDeviceView::RecurseChildDevices( _In_ DEVINST ParentDevice, _In_ HTREEITEM hParentTreeItem ){ HTREEITEM hDevItem = NULL; DEVINST Device; bool HasProblem = false; bool bSuccess;
// Check if the parent has any child devices if (GetChildDevice(ParentDevice, &Device) == FALSE) return true;
// Get the cached device node CDeviceNode *DeviceNode; DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device)); if (DeviceNode == nullptr) { return false; }
// Don't show hidden devices if not requested 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 if (!RecurseChildDevices(Device, hDevItem)) HasProblem = true; }
if (DeviceNode->HasProblem()) { HasProblem = true; } }
// Check for siblings for (;;) { // Check if the parent device has anything at the same level bSuccess = GetSiblingDevice(Device, &Device); if (bSuccess == FALSE) break;
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device)); if (DeviceNode == nullptr) { continue; }
// Don't show hidden devices if not requested if ((m_ShowHidden == TRUE) || (!(DeviceNode->IsHidden()))) { if (DeviceNode->HasProblem()) { HasProblem = true; }
// Add this device to the tree under its parent hDevItem = InsertIntoTreeView(hParentTreeItem, DeviceNode); if (hDevItem) { // Check if this child has any children itself if (!RecurseChildDevices(Device, hDevItem)) HasProblem = true; } } }
(void)TreeView_SortChildren(m_hTreeView, hParentTreeItem, 0);
// Expand the class if it has a problem device if (HasProblem == true) { (void)TreeView_Expand(m_hTreeView, hParentTreeItem, TVE_EXPAND); }
// If there was a problem, expand the ancestors if (HasProblem) return false;
return true;}
boolCDeviceView::EnableSelectedDevice( _In_ bool Enable, _Out_ bool &NeedsReboot ){ CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode()); if (Node == nullptr) return false;
if (Enable == false) { CAtlStringW str; if (str.LoadStringW(g_hThisInstance, IDS_CONFIRM_DISABLE)) { if (MessageBoxW(m_hMainWnd, str, Node->GetDisplayName(), MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES) { return false; } } }
return Node->EnableDevice(Enable, NeedsReboot);}
boolCDeviceView::UpdateSelectedDevice( _Out_ bool &NeedsReboot ){ CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode()); if (Node == nullptr) return false;
DWORD dwReboot; if (InstallDevInst(m_hMainWnd, Node->GetDeviceId(), TRUE, &dwReboot)) { NeedsReboot = false; return true; }
return false;}
boolCDeviceView::UninstallSelectedDevice( ){ CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode()); if (Node == nullptr) return false;
CAtlStringW str; if (str.LoadStringW(g_hThisInstance, IDS_CONFIRM_UNINSTALL)) { if (MessageBoxW(m_hMainWnd, str, Node->GetDisplayName(), MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES) { return false; } }
return Node->UninstallDevice();}
boolCDeviceView::RunAddHardwareWizard(){ PADDHARDWAREWIZARD pAddHardwareWizard; HMODULE hModule;
hModule = LoadLibraryW(L"hdwwiz.cpl"); if (hModule == NULL) return false;
pAddHardwareWizard = (PADDHARDWAREWIZARD)GetProcAddress(hModule, "AddHardwareWizard"); if (pAddHardwareWizard == NULL) { FreeLibrary(hModule); return false; }
pAddHardwareWizard(m_hMainWnd, NULL);
FreeLibrary(hModule); return true;}
boolCDeviceView::GetChildDevice( _In_ DEVINST ParentDevInst, _Out_ PDEVINST DevInst){ CONFIGRET cr; cr = CM_Get_Child(DevInst, ParentDevInst, 0); return (cr == CR_SUCCESS);}
boolCDeviceView::GetSiblingDevice( _In_ DEVINST PrevDevice, _Out_ PDEVINST DevInst){ CONFIGRET cr; cr = CM_Get_Sibling(DevInst, PrevDevice, 0); return (cr == CR_SUCCESS);}
HTREEITEMCDeviceView::InsertIntoTreeView( _In_opt_ 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();
// try to cast it to a device node. This will only succeed if it's the correct type CDeviceNode *DeviceNode = dynamic_cast<CDeviceNode *>(Node); if (DeviceNode && DeviceNode->GetOverlayImage()) { tvi.mask |= TVIF_STATE; tvi.stateMask = TVIS_OVERLAYMASK; tvi.state = INDEXTOOVERLAYMASK(DeviceNode->GetOverlayImage()); }
tvins.item = tvi; tvins.hParent = hParent;
return TreeView_InsertItem(m_hTreeView, &tvins);}
voidCDeviceView::BuildActionMenuForNode( _In_ HMENU OwnerMenu, _In_ CNode *Node, _In_ bool MainMenu ){ // Create a separator structure MENUITEMINFOW MenuSeparator = { 0 }; MenuSeparator.cbSize = sizeof(MENUITEMINFOW); MenuSeparator.fType = MFT_SEPARATOR;
// Setup the MENUITEMINFOW MenuItemInfo = { 0 }; MenuItemInfo.cbSize = sizeof(MENUITEMINFOW); MenuItemInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_SUBMENU; MenuItemInfo.fType = MFT_STRING;
CAtlStringW String; int i = 0;
// Device nodes have extra data if (Node->GetNodeType() == DeviceNode) { CDeviceNode *DeviceNode = dynamic_cast<CDeviceNode *>(Node);
if (DeviceNode->CanUpdate()) { String.LoadStringW(g_hThisInstance, IDS_MENU_UPDATE); MenuItemInfo.wID = IDM_UPDATE_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; }
if (DeviceNode->IsDisabled()) { String.LoadStringW(g_hThisInstance, IDS_MENU_ENABLE); MenuItemInfo.wID = IDM_ENABLE_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; }
if (DeviceNode->CanDisable() && !DeviceNode->IsDisabled()) { String.LoadStringW(g_hThisInstance, IDS_MENU_DISABLE); MenuItemInfo.wID = IDM_DISABLE_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; }
if (DeviceNode->CanUninstall()) { String.LoadStringW(g_hThisInstance, IDS_MENU_UNINSTALL); MenuItemInfo.wID = IDM_UNINSTALL_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; }
InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeparator); i++; }
// All nodes have the scan option String.LoadStringW(g_hThisInstance, IDS_MENU_SCAN); MenuItemInfo.wID = IDM_SCAN_HARDWARE; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++;
if ((Node->GetNodeType() == RootNode) || (MainMenu == true)) { String.LoadStringW(g_hThisInstance, IDS_MENU_ADD); MenuItemInfo.wID = IDM_ADD_HARDWARE; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; }
if (Node->HasProperties()) { InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeparator); i++;
String.LoadStringW(g_hThisInstance, IDS_MENU_PROPERTIES); MenuItemInfo.wID = IDM_PROPERTIES; MenuItemInfo.dwTypeData = String.GetBuffer(); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++;
SetMenuDefaultItem(OwnerMenu, IDC_PROPERTIES, FALSE); }}
HTREEITEMCDeviceView::RecurseFindDevice( _In_ HTREEITEM hParentItem, _In_ CNode *Node ){ HTREEITEM FoundItem; HTREEITEM hItem; TVITEMW tvItem; CNode *FoundNode;
// Check if this node has any children hItem = TreeView_GetChild(m_hTreeView, hParentItem); if (hItem == NULL) return NULL;
// The lParam contains the node pointer data tvItem.hItem = hItem; tvItem.mask = TVIF_PARAM; if (TreeView_GetItem(m_hTreeView, &tvItem) && tvItem.lParam != NULL) { // check for a matching node FoundNode = reinterpret_cast<CNode *>(tvItem.lParam); if ((FoundNode->GetNodeType() == Node->GetNodeType()) && (IsEqualGUID(*FoundNode->GetClassGuid(), *Node->GetClassGuid()))) { // check if this is a class node, or a device with matching ID's if ((FoundNode->GetNodeType() == ClassNode) || (wcscmp(FoundNode->GetDeviceId(), Node->GetDeviceId()) == 0)) { return hItem; } } }
// This node may have its own children FoundItem = RecurseFindDevice(hItem, Node); if (FoundItem) return FoundItem;
// Loop 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)) { // check for a matching class FoundNode = reinterpret_cast<CNode *>(tvItem.lParam); if ((FoundNode->GetNodeType() == Node->GetNodeType()) && (IsEqualGUID(*FoundNode->GetClassGuid(), *Node->GetClassGuid()))) { // check if this is a class node, or a device with matching ID's if ((FoundNode->GetNodeType() == ClassNode) || (wcscmp(FoundNode->GetDeviceId(), Node->GetDeviceId()) == 0)) { return hItem; } } }
// This node may have its own children FoundItem = RecurseFindDevice(hItem, Node); if (FoundItem) return FoundItem; }
return hItem;}
voidCDeviceView::SelectNode( _In_ CNode *Node ){ HTREEITEM hRoot, hItem;
// Check if there are any items in the tree hRoot = TreeView_GetRoot(m_hTreeView); if (hRoot == NULL) return;
// If we don't want to set select a node, just select root if (Node == nullptr || Node->GetNodeType() == RootNode) { TreeView_SelectItem(m_hTreeView, hRoot); return; }
// Scan the tree looking for the node we want hItem = RecurseFindDevice(hRoot, Node); if (hItem) { TreeView_SelectItem(m_hTreeView, hItem); } else { TreeView_SelectItem(m_hTreeView, hRoot); }}
voidCDeviceView::EmptyDeviceView(){ (VOID)TreeView_DeleteAllItems(m_hTreeView);}
CClassNode*CDeviceView::GetClassNode( _In_ LPGUID ClassGuid ){ POSITION Pos; CClassNode *Node = nullptr;
Pos = m_ClassNodeList.GetHeadPosition(); if (Pos == NULL) return nullptr;
do { Node = m_ClassNodeList.GetNext(Pos); if (IsEqualGUID(*Node->GetClassGuid(), *ClassGuid)) { ATLASSERT(Node->GetNodeType() == ClassNode); break; }
Node = nullptr;
} while (Pos != NULL);
return Node;}
CDeviceNode*CDeviceView::GetDeviceNode( _In_ DEVINST Device ){ POSITION Pos; CDeviceNode *Node = nullptr;
Pos = m_DeviceNodeList.GetHeadPosition(); if (Pos == NULL) return nullptr;
do { Node = m_DeviceNodeList.GetNext(Pos); if (Node->GetDeviceInst() == Device) { ATLASSERT(Node->GetNodeType() == DeviceNode); break; }
Node = nullptr;
} while (Pos != NULL);
return Node;}
CNode* CDeviceView::GetNode( _In_ LPTV_ITEMW TvItem ){ TvItem->mask = TVIF_PARAM; if (TreeView_GetItem(m_hTreeView, TvItem)) { return (CNode *)TvItem->lParam; } return nullptr;}
voidCDeviceView::EmptyLists(){ CNode *Node;
while (!m_ClassNodeList.IsEmpty()) { Node = m_ClassNodeList.RemoveTail(); delete Node; }
while (!m_DeviceNodeList.IsEmpty()) { Node = m_DeviceNodeList.RemoveTail(); delete Node; }}
boolCDeviceView::RefreshDeviceList(){ GUID ClassGuid; CClassNode *ClassNode; CDeviceNode *DeviceNode; HDEVINFO hDevInfo; SP_DEVINFO_DATA DeviceInfoData; DWORD i; BOOL Success;
ULONG ClassIndex = 0;
EmptyLists();
if (m_RootNode) delete m_RootNode; m_RootNode = new CRootNode(&m_ImageListData); m_RootNode->SetupNode();
// Loop through all the classes do { Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo); if (Success) { // Create a new class node and add it to the list ClassNode = new CClassNode(&ClassGuid, &m_ImageListData); if (ClassNode->SetupNode()) { m_ClassNodeList.AddTail(ClassNode); }
SetupDiDestroyDeviceInfoList(hDevInfo); } ClassIndex++; } while (Success);
// Get all the devices on the local machine hDevInfo = SetupDiGetClassDevsW(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) { return false; }
// loop though all the devices DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (i = 0;; i++) { // Get the devinst for this device Success = SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); if (Success == FALSE) break;
// create a new device node and add it to the list DeviceNode = new CDeviceNode(DeviceInfoData.DevInst, &m_ImageListData); if (DeviceNode->SetupNode()) { m_DeviceNodeList.AddTail(DeviceNode); } else { ATLASSERT(FALSE); } }
SetupDiDestroyDeviceInfoList(hDevInfo);
return TRUE;}