mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[DEVMGR]
- Make class and device nodes polymorphic and move the code into separate files - Add an abstract base class which we attach to the listview nodes - Add double clicking of nodes svn path=/trunk/; revision=68180
This commit is contained in:
parent
a29eac1548
commit
66bbc9e4c1
9 changed files with 537 additions and 489 deletions
170
reactos/dll/win32/devmgr/devmgmt/ClassNode.cpp
Normal file
170
reactos/dll/win32/devmgr/devmgmt/ClassNode.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Device Manager
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: dll/win32/devmgr/devmgr/ClassNode.cpp
|
||||
* PURPOSE: Class object for
|
||||
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "devmgmt.h"
|
||||
#include "ClassNode.h"
|
||||
|
||||
|
||||
CClassNode::CClassNode(
|
||||
_In_ LPGUID ClassGuid,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
) :
|
||||
CNode(ImageListData)
|
||||
{
|
||||
CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
|
||||
}
|
||||
|
||||
|
||||
CClassNode::~CClassNode()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CClassNode::SetupNode()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
CClassNode::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;
|
||||
}
|
24
reactos/dll/win32/devmgr/devmgmt/ClassNode.h
Normal file
24
reactos/dll/win32/devmgr/devmgmt/ClassNode.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "Node.h"
|
||||
|
||||
class CClassNode : public CNode
|
||||
{
|
||||
public:
|
||||
|
||||
CClassNode(
|
||||
_In_ LPGUID ClassGuid,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
);
|
||||
|
||||
~CClassNode();
|
||||
|
||||
virtual bool SetupNode();
|
||||
|
||||
private:
|
||||
|
||||
DWORD ConvertResourceDescriptorToString(
|
||||
_Inout_z_ LPWSTR ResourceDescriptor,
|
||||
_In_ DWORD ResourceDescriptorSize
|
||||
);
|
||||
};
|
||||
|
233
reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp
Normal file
233
reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Device Manager
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: dll/win32/devmgr/devmgr/ClassNode.cpp
|
||||
* PURPOSE: Class object for
|
||||
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "devmgmt.h"
|
||||
#include "DeviceNode.h"
|
||||
|
||||
|
||||
CDeviceNode::CDeviceNode(
|
||||
_In_opt_ DEVINST Device,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
) :
|
||||
CNode(ImageListData),
|
||||
m_DevInst(Device),
|
||||
m_Status(0),
|
||||
m_ProblemNumber(0),
|
||||
m_OverlayImage(0)
|
||||
{
|
||||
}
|
||||
|
||||
CDeviceNode::~CDeviceNode()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CDeviceNode::SetupNode()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CDeviceNode::IsHidden()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_NO_SHOW_IN_DM) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CDeviceNode::CanDisable()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_DISABLEABLE) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CDeviceNode::IsDisabled()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED)) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CDeviceNode::IsStarted()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_STARTED) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CDeviceNode::IsInstalled()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_HAS_PROBLEM) != 0 ||
|
||||
(m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
34
reactos/dll/win32/devmgr/devmgmt/DeviceNode.h
Normal file
34
reactos/dll/win32/devmgr/devmgmt/DeviceNode.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include "Node.h"
|
||||
|
||||
class CDeviceNode : public CNode
|
||||
{
|
||||
private:
|
||||
DEVINST m_DevInst;
|
||||
ULONG m_Status;
|
||||
ULONG m_ProblemNumber;
|
||||
int m_OverlayImage;
|
||||
|
||||
public:
|
||||
CDeviceNode(
|
||||
_In_opt_ DEVINST Device,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
);
|
||||
|
||||
~CDeviceNode();
|
||||
|
||||
virtual bool SetupNode();
|
||||
|
||||
DEVINST GetDeviceInst() { return m_DevInst; }
|
||||
int GetOverlayImage() { return m_OverlayImage; }
|
||||
|
||||
bool HasProblem() { return !!(m_ProblemNumber); }
|
||||
bool IsHidden();
|
||||
bool CanDisable();
|
||||
bool IsDisabled();
|
||||
bool IsStarted();
|
||||
bool IsInstalled();
|
||||
bool CanInstall() { return TRUE; } // unimplemented
|
||||
bool CanUninstall() { return TRUE; } // unimplemented
|
||||
};
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
*/
|
||||
* 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"
|
||||
|
@ -13,10 +13,11 @@
|
|||
#include "DeviceView.h"
|
||||
|
||||
|
||||
/* DATA *********************************************/
|
||||
// DATA ********************************************/
|
||||
|
||||
#define CLASS_NAME_LEN 256
|
||||
#define CLASS_DESC_LEN 256
|
||||
#define ROOT_NAME_SIZE MAX_COMPUTERNAME_LENGTH + 1
|
||||
|
||||
INT_PTR
|
||||
WINAPI
|
||||
|
@ -38,7 +39,7 @@ struct RefreshThreadData
|
|||
};
|
||||
|
||||
|
||||
/* PUBLIC METHODS *************************************/
|
||||
// PUBLIC METHODS ************************************/
|
||||
|
||||
CDeviceView::CDeviceView(
|
||||
HWND hMainWnd
|
||||
|
@ -269,7 +270,7 @@ CDeviceView::IsDisabled(
|
|||
_In_ LPTV_ITEMW TvItem
|
||||
)
|
||||
{
|
||||
CNode *Node = GetNode(TvItem);
|
||||
CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetNode(TvItem));
|
||||
if (Node)
|
||||
{
|
||||
return Node->IsDisabled();
|
||||
|
@ -282,16 +283,16 @@ CDeviceView::CanDisable(
|
|||
_In_ LPTV_ITEMW TvItem
|
||||
)
|
||||
{
|
||||
CNode *Node = GetNode(TvItem);
|
||||
CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetNode(TvItem));
|
||||
if (Node)
|
||||
{
|
||||
return Node->CanDisable();
|
||||
Node->CanDisable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* PRIVATE METHODS ********************************************/
|
||||
// PRIVATE METHODS *******************************************/
|
||||
|
||||
bool
|
||||
CDeviceView::AddRootDevice()
|
||||
|
@ -312,7 +313,7 @@ CDeviceView::AddRootDevice()
|
|||
DeleteObject(hRootImage);
|
||||
}
|
||||
|
||||
/* Get the root instance */
|
||||
// Get the root instance
|
||||
CONFIGRET cr;
|
||||
cr = CM_Locate_DevNodeW(&m_RootDevInst,
|
||||
NULL,
|
||||
|
@ -322,7 +323,7 @@ CDeviceView::AddRootDevice()
|
|||
return false;
|
||||
}
|
||||
|
||||
/* The root name is the computer name */
|
||||
// The root name is the computer name
|
||||
WCHAR RootDeviceName[ROOT_NAME_SIZE];
|
||||
DWORD Size = ROOT_NAME_SIZE;
|
||||
if (GetComputerNameW(RootDeviceName, &Size))
|
||||
|
@ -425,7 +426,8 @@ unsigned int __stdcall CDeviceView::RefreshThread(void *Param)
|
|||
bool
|
||||
CDeviceView::ListDevicesByType()
|
||||
{
|
||||
CNode *ClassNode, *DeviceNode;
|
||||
CClassNode *ClassNode;
|
||||
CDeviceNode *DeviceNode;
|
||||
HDEVINFO hDevInfo;
|
||||
HTREEITEM hTreeItem = NULL;
|
||||
GUID ClassGuid;
|
||||
|
@ -574,10 +576,10 @@ CDeviceView::ListDevicesByConnection()
|
|||
bSuccess = AddRootDevice();
|
||||
if (bSuccess == false) return false;
|
||||
|
||||
/* Walk the device tree and add all the devices */
|
||||
// Walk the device tree and add all the devices
|
||||
RecurseChildDevices(m_RootDevInst, m_hTreeRoot);
|
||||
|
||||
/* Expand the root item */
|
||||
// Expand the root item
|
||||
(VOID)TreeView_Expand(m_hTreeView,
|
||||
m_hTreeRoot,
|
||||
TVE_EXPAND);
|
||||
|
@ -596,13 +598,13 @@ CDeviceView::RecurseChildDevices(
|
|||
DEVINST Device;
|
||||
BOOL bSuccess;
|
||||
|
||||
/* Check if the parent has any child devices */
|
||||
// Check if the parent has any child devices
|
||||
if (GetChildDevice(ParentDevice, &Device) == FALSE)
|
||||
return;
|
||||
|
||||
// Get the cached device node
|
||||
CNode *DeviceNode;
|
||||
DeviceNode = GetDeviceNode(Device);
|
||||
CDeviceNode *DeviceNode;
|
||||
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
|
||||
if (DeviceNode == NULL)
|
||||
{
|
||||
ATLASSERT(FALSE);
|
||||
|
@ -610,17 +612,17 @@ CDeviceView::RecurseChildDevices(
|
|||
}
|
||||
|
||||
|
||||
/* Check if this is a hidden device */
|
||||
// Check if this is a hidden device
|
||||
if ((m_ShowHidden == TRUE) || (!(DeviceNode->IsHidden())))
|
||||
{
|
||||
/* Add this device to the tree under its parent */
|
||||
// Add this device to the tree under its parent
|
||||
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
||||
DeviceNode);
|
||||
|
||||
|
||||
if (hDevItem)
|
||||
{
|
||||
/* Check if this child has any children itself */
|
||||
// Check if this child has any children itself
|
||||
RecurseChildDevices(Device, hDevItem);
|
||||
}
|
||||
}
|
||||
|
@ -628,29 +630,29 @@ CDeviceView::RecurseChildDevices(
|
|||
|
||||
for (;;)
|
||||
{
|
||||
/* Check if the parent device has anything at the same level */
|
||||
// Check if the parent device has anything at the same level
|
||||
bSuccess = GetSiblingDevice(Device, &Device);
|
||||
if (bSuccess == FALSE) break;
|
||||
|
||||
DeviceNode = GetDeviceNode(Device);
|
||||
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
|
||||
if (DeviceNode == NULL)
|
||||
{
|
||||
ATLASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Check if this is a hidden device */
|
||||
// Check if this is a hidden device
|
||||
if (DeviceNode->IsHidden())
|
||||
{
|
||||
if (m_ShowHidden == FALSE)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add this device to the tree under its parent */
|
||||
// Add this device to the tree under its parent
|
||||
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
||||
DeviceNode);
|
||||
if (hDevItem)
|
||||
{
|
||||
/* Check if this child has any children itself */
|
||||
// Check if this child has any children itself
|
||||
RecurseChildDevices(Device, hDevItem);
|
||||
}
|
||||
}
|
||||
|
@ -709,11 +711,13 @@ CDeviceView::InsertIntoTreeView(
|
|||
tvi.iImage = Node->GetClassImage();
|
||||
tvi.iSelectedImage = Node->GetClassImage();
|
||||
|
||||
if (Node->GetOverlayImage())
|
||||
// try to cast it to a device node. This will only suceed 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(Node->GetOverlayImage());
|
||||
tvi.state = INDEXTOOVERLAYMASK(DeviceNode->GetOverlayImage());
|
||||
}
|
||||
|
||||
tvins.item = tvi;
|
||||
|
@ -763,7 +767,7 @@ CDeviceView::RecurseDeviceView(
|
|||
// delete reinterpret_cast<CNode *>(tvItem.lParam);
|
||||
}
|
||||
|
||||
/* This node may have its own children */
|
||||
// This node may have its own children
|
||||
RecurseDeviceView(hItem);
|
||||
}
|
||||
}
|
||||
|
@ -788,11 +792,11 @@ CDeviceView::EmptyDeviceView()
|
|||
|
||||
|
||||
|
||||
CNode*
|
||||
CClassNode*
|
||||
CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
|
||||
{
|
||||
POSITION Pos;
|
||||
CNode *Node;
|
||||
CClassNode *Node;
|
||||
|
||||
Pos = m_ClassNodeList.GetHeadPosition();
|
||||
|
||||
|
@ -812,11 +816,11 @@ CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
|
|||
return Node;
|
||||
}
|
||||
|
||||
CNode*
|
||||
CDeviceNode*
|
||||
CDeviceView::GetDeviceNode(_In_ DEVINST Device)
|
||||
{
|
||||
POSITION Pos;
|
||||
CNode *Node;
|
||||
CDeviceNode *Node;
|
||||
|
||||
Pos = m_DeviceNodeList.GetHeadPosition();
|
||||
|
||||
|
@ -843,6 +847,7 @@ CNode* CDeviceView::GetNode(LPTV_ITEMW TvItem)
|
|||
{
|
||||
return (CNode *)TvItem->lParam;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CNode* CDeviceView::GetSelectedNode()
|
||||
|
@ -885,7 +890,8 @@ bool
|
|||
CDeviceView::RefreshDeviceList()
|
||||
{
|
||||
GUID ClassGuid;
|
||||
CNode *Node;
|
||||
CClassNode *ClassNode;
|
||||
CDeviceNode *DeviceNode;
|
||||
HDEVINFO hDevInfo;
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
DWORD i;
|
||||
|
@ -895,22 +901,24 @@ CDeviceView::RefreshDeviceList()
|
|||
|
||||
EmptyLists();
|
||||
|
||||
// Loop through all the classes
|
||||
do
|
||||
{
|
||||
Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
|
||||
if (Success)
|
||||
{
|
||||
/* Create a new class node */
|
||||
Node = new CNode(&ClassGuid, &m_ImageListData);
|
||||
if (Node->Setup())
|
||||
// Create a new class node and add it to the list
|
||||
ClassNode = new CClassNode(&ClassGuid, &m_ImageListData);
|
||||
if (ClassNode->SetupNode())
|
||||
{
|
||||
m_ClassNodeList.AddTail(Node);
|
||||
m_ClassNodeList.AddTail(ClassNode);
|
||||
}
|
||||
}
|
||||
ClassIndex++;
|
||||
} while (Success);
|
||||
|
||||
|
||||
// Get all the devices on the local machine
|
||||
hDevInfo = SetupDiGetClassDevsW(NULL,
|
||||
0,
|
||||
0,
|
||||
|
@ -920,17 +928,20 @@ CDeviceView::RefreshDeviceList()
|
|||
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;
|
||||
|
||||
|
||||
Node = new CNode(DeviceInfoData.DevInst, &m_ImageListData);
|
||||
Node->Setup();
|
||||
m_DeviceNodeList.AddTail(Node);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "Node.h"
|
||||
#include "DeviceNode.h"
|
||||
#include "ClassNode.h"
|
||||
|
||||
enum ViewType
|
||||
{
|
||||
|
@ -12,8 +13,8 @@ enum ViewType
|
|||
|
||||
class CDeviceView
|
||||
{
|
||||
CAtlList<CNode *> m_ClassNodeList;
|
||||
CAtlList<CNode *> m_DeviceNodeList;
|
||||
CAtlList<CClassNode *> m_ClassNodeList;
|
||||
CAtlList<CDeviceNode *> m_DeviceNodeList;
|
||||
|
||||
SP_CLASSIMAGELIST_DATA m_ImageListData;
|
||||
|
||||
|
@ -128,8 +129,8 @@ private:
|
|||
CNode* GetNode(_In_ LPTV_ITEMW TvItem);
|
||||
CNode* GetSelectedNode();
|
||||
|
||||
CNode* GetClassNode(_In_ LPGUID ClassGuid);
|
||||
CNode* GetDeviceNode(_In_ DEVINST Device);
|
||||
CClassNode* GetClassNode(_In_ LPGUID ClassGuid);
|
||||
CDeviceNode* GetDeviceNode(_In_ DEVINST Device);
|
||||
void EmptyLists();
|
||||
};
|
||||
|
||||
|
|
|
@ -456,6 +456,13 @@ CMainWindow::OnNotify(LPARAM lParam)
|
|||
break;
|
||||
}
|
||||
|
||||
case NM_DBLCLK:
|
||||
{
|
||||
LPNMTREEVIEW NmTreeView = (LPNMTREEVIEW)lParam;
|
||||
m_DeviceView->DisplayPropertySheet();
|
||||
break;
|
||||
}
|
||||
|
||||
case NM_RCLICK:
|
||||
{
|
||||
Ret = m_DeviceView->OnRightClick(NmHdr);
|
||||
|
|
|
@ -14,34 +14,12 @@
|
|||
|
||||
/* PUBLIC METHODS *******************************************/
|
||||
|
||||
CNode::CNode(_In_ LPGUID ClassGuid,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
||||
CNode::CNode(_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_ClassImage(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()
|
||||
|
@ -49,306 +27,9 @@ 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()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_NO_SHOW_IN_DM) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CNode::CanDisable()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return (m_NodeType == NodeDevice && ((m_Status & DN_DISABLEABLE) != 0));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CNode::IsDisabled()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED)) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CNode::IsStarted()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_STARTED) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CNode::IsInstalled()
|
||||
{
|
||||
CONFIGRET cr;
|
||||
cr = CM_Get_DevNode_Status_Ex(&m_Status,
|
||||
&m_ProblemNumber,
|
||||
m_DevInst,
|
||||
0,
|
||||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_HAS_PROBLEM) != 0 ||
|
||||
(m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* 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()
|
||||
|
@ -359,72 +40,3 @@ CNode::Cleanup()
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1,78 +1,34 @@
|
|||
#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:
|
||||
protected:
|
||||
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; }
|
||||
virtual bool SetupNode() = 0;
|
||||
|
||||
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
||||
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
|
||||
bool HasProperties() { return (m_DeviceId != NULL); }
|
||||
|
||||
private:
|
||||
bool SetupClassNode();
|
||||
bool SetupDeviceNode();
|
||||
void Cleanup();
|
||||
|
||||
DWORD ConvertResourceDescriptorToString(
|
||||
_Inout_z_ LPWSTR ResourceDescriptor,
|
||||
_In_ DWORD ResourceDescriptorSize
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue