mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +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
|
||||||
|
};
|
||||||
|
|
|
@ -4,19 +4,20 @@
|
||||||
* FILE: dll/win32/devmgr/devmgr/DeviceView.cpp
|
* FILE: dll/win32/devmgr/devmgr/DeviceView.cpp
|
||||||
* PURPOSE: Implements the tree view which contains the devices
|
* PURPOSE: Implements the tree view which contains the devices
|
||||||
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
|
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "devmgmt.h"
|
#include "devmgmt.h"
|
||||||
#include "DeviceView.h"
|
#include "DeviceView.h"
|
||||||
|
|
||||||
|
|
||||||
/* DATA *********************************************/
|
// DATA ********************************************/
|
||||||
|
|
||||||
#define CLASS_NAME_LEN 256
|
#define CLASS_NAME_LEN 256
|
||||||
#define CLASS_DESC_LEN 256
|
#define CLASS_DESC_LEN 256
|
||||||
|
#define ROOT_NAME_SIZE MAX_COMPUTERNAME_LENGTH + 1
|
||||||
|
|
||||||
INT_PTR
|
INT_PTR
|
||||||
WINAPI
|
WINAPI
|
||||||
|
@ -38,7 +39,7 @@ struct RefreshThreadData
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* PUBLIC METHODS *************************************/
|
// PUBLIC METHODS ************************************/
|
||||||
|
|
||||||
CDeviceView::CDeviceView(
|
CDeviceView::CDeviceView(
|
||||||
HWND hMainWnd
|
HWND hMainWnd
|
||||||
|
@ -269,7 +270,7 @@ CDeviceView::IsDisabled(
|
||||||
_In_ LPTV_ITEMW TvItem
|
_In_ LPTV_ITEMW TvItem
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
CNode *Node = GetNode(TvItem);
|
CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetNode(TvItem));
|
||||||
if (Node)
|
if (Node)
|
||||||
{
|
{
|
||||||
return Node->IsDisabled();
|
return Node->IsDisabled();
|
||||||
|
@ -282,16 +283,16 @@ CDeviceView::CanDisable(
|
||||||
_In_ LPTV_ITEMW TvItem
|
_In_ LPTV_ITEMW TvItem
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
CNode *Node = GetNode(TvItem);
|
CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetNode(TvItem));
|
||||||
if (Node)
|
if (Node)
|
||||||
{
|
{
|
||||||
return Node->CanDisable();
|
Node->CanDisable();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PRIVATE METHODS ********************************************/
|
// PRIVATE METHODS *******************************************/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CDeviceView::AddRootDevice()
|
CDeviceView::AddRootDevice()
|
||||||
|
@ -312,7 +313,7 @@ CDeviceView::AddRootDevice()
|
||||||
DeleteObject(hRootImage);
|
DeleteObject(hRootImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the root instance */
|
// Get the root instance
|
||||||
CONFIGRET cr;
|
CONFIGRET cr;
|
||||||
cr = CM_Locate_DevNodeW(&m_RootDevInst,
|
cr = CM_Locate_DevNodeW(&m_RootDevInst,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -322,7 +323,7 @@ CDeviceView::AddRootDevice()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The root name is the computer name */
|
// The root name is the computer name
|
||||||
WCHAR RootDeviceName[ROOT_NAME_SIZE];
|
WCHAR RootDeviceName[ROOT_NAME_SIZE];
|
||||||
DWORD Size = ROOT_NAME_SIZE;
|
DWORD Size = ROOT_NAME_SIZE;
|
||||||
if (GetComputerNameW(RootDeviceName, &Size))
|
if (GetComputerNameW(RootDeviceName, &Size))
|
||||||
|
@ -425,7 +426,8 @@ unsigned int __stdcall CDeviceView::RefreshThread(void *Param)
|
||||||
bool
|
bool
|
||||||
CDeviceView::ListDevicesByType()
|
CDeviceView::ListDevicesByType()
|
||||||
{
|
{
|
||||||
CNode *ClassNode, *DeviceNode;
|
CClassNode *ClassNode;
|
||||||
|
CDeviceNode *DeviceNode;
|
||||||
HDEVINFO hDevInfo;
|
HDEVINFO hDevInfo;
|
||||||
HTREEITEM hTreeItem = NULL;
|
HTREEITEM hTreeItem = NULL;
|
||||||
GUID ClassGuid;
|
GUID ClassGuid;
|
||||||
|
@ -574,10 +576,10 @@ CDeviceView::ListDevicesByConnection()
|
||||||
bSuccess = AddRootDevice();
|
bSuccess = AddRootDevice();
|
||||||
if (bSuccess == false) return false;
|
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);
|
RecurseChildDevices(m_RootDevInst, m_hTreeRoot);
|
||||||
|
|
||||||
/* Expand the root item */
|
// Expand the root item
|
||||||
(VOID)TreeView_Expand(m_hTreeView,
|
(VOID)TreeView_Expand(m_hTreeView,
|
||||||
m_hTreeRoot,
|
m_hTreeRoot,
|
||||||
TVE_EXPAND);
|
TVE_EXPAND);
|
||||||
|
@ -596,13 +598,13 @@ CDeviceView::RecurseChildDevices(
|
||||||
DEVINST Device;
|
DEVINST Device;
|
||||||
BOOL bSuccess;
|
BOOL bSuccess;
|
||||||
|
|
||||||
/* Check if the parent has any child devices */
|
// Check if the parent has any child devices
|
||||||
if (GetChildDevice(ParentDevice, &Device) == FALSE)
|
if (GetChildDevice(ParentDevice, &Device) == FALSE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the cached device node
|
// Get the cached device node
|
||||||
CNode *DeviceNode;
|
CDeviceNode *DeviceNode;
|
||||||
DeviceNode = GetDeviceNode(Device);
|
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
|
||||||
if (DeviceNode == NULL)
|
if (DeviceNode == NULL)
|
||||||
{
|
{
|
||||||
ATLASSERT(FALSE);
|
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())))
|
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,
|
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
||||||
DeviceNode);
|
DeviceNode);
|
||||||
|
|
||||||
|
|
||||||
if (hDevItem)
|
if (hDevItem)
|
||||||
{
|
{
|
||||||
/* Check if this child has any children itself */
|
// Check if this child has any children itself
|
||||||
RecurseChildDevices(Device, hDevItem);
|
RecurseChildDevices(Device, hDevItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -628,29 +630,29 @@ CDeviceView::RecurseChildDevices(
|
||||||
|
|
||||||
for (;;)
|
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);
|
bSuccess = GetSiblingDevice(Device, &Device);
|
||||||
if (bSuccess == FALSE) break;
|
if (bSuccess == FALSE) break;
|
||||||
|
|
||||||
DeviceNode = GetDeviceNode(Device);
|
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
|
||||||
if (DeviceNode == NULL)
|
if (DeviceNode == NULL)
|
||||||
{
|
{
|
||||||
ATLASSERT(FALSE);
|
ATLASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is a hidden device */
|
// Check if this is a hidden device
|
||||||
if (DeviceNode->IsHidden())
|
if (DeviceNode->IsHidden())
|
||||||
{
|
{
|
||||||
if (m_ShowHidden == FALSE)
|
if (m_ShowHidden == FALSE)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add this device to the tree under its parent */
|
// Add this device to the tree under its parent
|
||||||
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
hDevItem = InsertIntoTreeView(hParentTreeItem,
|
||||||
DeviceNode);
|
DeviceNode);
|
||||||
if (hDevItem)
|
if (hDevItem)
|
||||||
{
|
{
|
||||||
/* Check if this child has any children itself */
|
// Check if this child has any children itself
|
||||||
RecurseChildDevices(Device, hDevItem);
|
RecurseChildDevices(Device, hDevItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,11 +711,13 @@ CDeviceView::InsertIntoTreeView(
|
||||||
tvi.iImage = Node->GetClassImage();
|
tvi.iImage = Node->GetClassImage();
|
||||||
tvi.iSelectedImage = 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.mask |= TVIF_STATE;
|
||||||
tvi.stateMask = TVIS_OVERLAYMASK;
|
tvi.stateMask = TVIS_OVERLAYMASK;
|
||||||
tvi.state = INDEXTOOVERLAYMASK(Node->GetOverlayImage());
|
tvi.state = INDEXTOOVERLAYMASK(DeviceNode->GetOverlayImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
tvins.item = tvi;
|
tvins.item = tvi;
|
||||||
|
@ -763,7 +767,7 @@ CDeviceView::RecurseDeviceView(
|
||||||
// delete reinterpret_cast<CNode *>(tvItem.lParam);
|
// delete reinterpret_cast<CNode *>(tvItem.lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This node may have its own children */
|
// This node may have its own children
|
||||||
RecurseDeviceView(hItem);
|
RecurseDeviceView(hItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,11 +792,11 @@ CDeviceView::EmptyDeviceView()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CNode*
|
CClassNode*
|
||||||
CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
|
CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
|
||||||
{
|
{
|
||||||
POSITION Pos;
|
POSITION Pos;
|
||||||
CNode *Node;
|
CClassNode *Node;
|
||||||
|
|
||||||
Pos = m_ClassNodeList.GetHeadPosition();
|
Pos = m_ClassNodeList.GetHeadPosition();
|
||||||
|
|
||||||
|
@ -812,11 +816,11 @@ CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
|
||||||
return Node;
|
return Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
CNode*
|
CDeviceNode*
|
||||||
CDeviceView::GetDeviceNode(_In_ DEVINST Device)
|
CDeviceView::GetDeviceNode(_In_ DEVINST Device)
|
||||||
{
|
{
|
||||||
POSITION Pos;
|
POSITION Pos;
|
||||||
CNode *Node;
|
CDeviceNode *Node;
|
||||||
|
|
||||||
Pos = m_DeviceNodeList.GetHeadPosition();
|
Pos = m_DeviceNodeList.GetHeadPosition();
|
||||||
|
|
||||||
|
@ -843,6 +847,7 @@ CNode* CDeviceView::GetNode(LPTV_ITEMW TvItem)
|
||||||
{
|
{
|
||||||
return (CNode *)TvItem->lParam;
|
return (CNode *)TvItem->lParam;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CNode* CDeviceView::GetSelectedNode()
|
CNode* CDeviceView::GetSelectedNode()
|
||||||
|
@ -885,7 +890,8 @@ bool
|
||||||
CDeviceView::RefreshDeviceList()
|
CDeviceView::RefreshDeviceList()
|
||||||
{
|
{
|
||||||
GUID ClassGuid;
|
GUID ClassGuid;
|
||||||
CNode *Node;
|
CClassNode *ClassNode;
|
||||||
|
CDeviceNode *DeviceNode;
|
||||||
HDEVINFO hDevInfo;
|
HDEVINFO hDevInfo;
|
||||||
SP_DEVINFO_DATA DeviceInfoData;
|
SP_DEVINFO_DATA DeviceInfoData;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
@ -895,22 +901,24 @@ CDeviceView::RefreshDeviceList()
|
||||||
|
|
||||||
EmptyLists();
|
EmptyLists();
|
||||||
|
|
||||||
|
// Loop through all the classes
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
|
Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
|
||||||
if (Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
/* Create a new class node */
|
// Create a new class node and add it to the list
|
||||||
Node = new CNode(&ClassGuid, &m_ImageListData);
|
ClassNode = new CClassNode(&ClassGuid, &m_ImageListData);
|
||||||
if (Node->Setup())
|
if (ClassNode->SetupNode())
|
||||||
{
|
{
|
||||||
m_ClassNodeList.AddTail(Node);
|
m_ClassNodeList.AddTail(ClassNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClassIndex++;
|
ClassIndex++;
|
||||||
} while (Success);
|
} while (Success);
|
||||||
|
|
||||||
|
|
||||||
|
// Get all the devices on the local machine
|
||||||
hDevInfo = SetupDiGetClassDevsW(NULL,
|
hDevInfo = SetupDiGetClassDevsW(NULL,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -920,17 +928,20 @@ CDeviceView::RefreshDeviceList()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loop though all the devices
|
||||||
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||||
for (i = 0;; i++)
|
for (i = 0;; i++)
|
||||||
{
|
{
|
||||||
|
// Get the devinst for this device
|
||||||
Success = SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);
|
Success = SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);
|
||||||
if (Success == FALSE) break;
|
if (Success == FALSE) break;
|
||||||
|
|
||||||
|
// create a new device node and add it to the list
|
||||||
Node = new CNode(DeviceInfoData.DevInst, &m_ImageListData);
|
DeviceNode = new CDeviceNode(DeviceInfoData.DevInst, &m_ImageListData);
|
||||||
Node->Setup();
|
if (DeviceNode->SetupNode())
|
||||||
m_DeviceNodeList.AddTail(Node);
|
{
|
||||||
|
m_DeviceNodeList.AddTail(DeviceNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Node.h"
|
#include "DeviceNode.h"
|
||||||
|
#include "ClassNode.h"
|
||||||
|
|
||||||
enum ViewType
|
enum ViewType
|
||||||
{
|
{
|
||||||
|
@ -12,8 +13,8 @@ enum ViewType
|
||||||
|
|
||||||
class CDeviceView
|
class CDeviceView
|
||||||
{
|
{
|
||||||
CAtlList<CNode *> m_ClassNodeList;
|
CAtlList<CClassNode *> m_ClassNodeList;
|
||||||
CAtlList<CNode *> m_DeviceNodeList;
|
CAtlList<CDeviceNode *> m_DeviceNodeList;
|
||||||
|
|
||||||
SP_CLASSIMAGELIST_DATA m_ImageListData;
|
SP_CLASSIMAGELIST_DATA m_ImageListData;
|
||||||
|
|
||||||
|
@ -128,8 +129,8 @@ private:
|
||||||
CNode* GetNode(_In_ LPTV_ITEMW TvItem);
|
CNode* GetNode(_In_ LPTV_ITEMW TvItem);
|
||||||
CNode* GetSelectedNode();
|
CNode* GetSelectedNode();
|
||||||
|
|
||||||
CNode* GetClassNode(_In_ LPGUID ClassGuid);
|
CClassNode* GetClassNode(_In_ LPGUID ClassGuid);
|
||||||
CNode* GetDeviceNode(_In_ DEVINST Device);
|
CDeviceNode* GetDeviceNode(_In_ DEVINST Device);
|
||||||
void EmptyLists();
|
void EmptyLists();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -456,6 +456,13 @@ CMainWindow::OnNotify(LPARAM lParam)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NM_DBLCLK:
|
||||||
|
{
|
||||||
|
LPNMTREEVIEW NmTreeView = (LPNMTREEVIEW)lParam;
|
||||||
|
m_DeviceView->DisplayPropertySheet();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NM_RCLICK:
|
case NM_RCLICK:
|
||||||
{
|
{
|
||||||
Ret = m_DeviceView->OnRightClick(NmHdr);
|
Ret = m_DeviceView->OnRightClick(NmHdr);
|
||||||
|
|
|
@ -14,34 +14,12 @@
|
||||||
|
|
||||||
/* PUBLIC METHODS *******************************************/
|
/* PUBLIC METHODS *******************************************/
|
||||||
|
|
||||||
CNode::CNode(_In_ LPGUID ClassGuid,
|
CNode::CNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
||||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
|
||||||
m_ImageListData(ImageListData),
|
m_ImageListData(ImageListData),
|
||||||
m_NodeType(NodeClass),
|
|
||||||
m_DevInst(0),
|
|
||||||
m_DeviceId(NULL),
|
m_DeviceId(NULL),
|
||||||
m_ClassImage(0),
|
m_ClassImage(0)
|
||||||
m_Status(0),
|
|
||||||
m_ProblemNumber(0),
|
|
||||||
m_OverlayImage(0)
|
|
||||||
{
|
{
|
||||||
m_DisplayName[0] = UNICODE_NULL;
|
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()
|
CNode::~CNode()
|
||||||
|
@ -49,306 +27,9 @@ CNode::~CNode()
|
||||||
Cleanup();
|
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 ******************************************/
|
/* 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
|
void
|
||||||
CNode::Cleanup()
|
CNode::Cleanup()
|
||||||
|
@ -359,72 +40,3 @@ CNode::Cleanup()
|
||||||
m_DeviceId = NULL;
|
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
|
#pragma once
|
||||||
|
|
||||||
#define DISPLAY_NAME_LEN 256
|
#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
|
class CNode
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
PSP_CLASSIMAGELIST_DATA m_ImageListData;
|
PSP_CLASSIMAGELIST_DATA m_ImageListData;
|
||||||
NodeType m_NodeType;
|
|
||||||
DEVINST m_DevInst;
|
|
||||||
Actions m_Actions;
|
|
||||||
LPWSTR m_DeviceId;
|
LPWSTR m_DeviceId;
|
||||||
WCHAR m_DisplayName[DISPLAY_NAME_LEN];
|
WCHAR m_DisplayName[DISPLAY_NAME_LEN];
|
||||||
GUID m_ClassGuid;
|
GUID m_ClassGuid;
|
||||||
INT m_ClassImage;
|
INT m_ClassImage;
|
||||||
ULONG m_Status;
|
|
||||||
ULONG m_ProblemNumber;
|
|
||||||
INT m_OverlayImage;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CNode(
|
CNode(
|
||||||
_In_ LPGUID ClassGuid,
|
|
||||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
|
||||||
);
|
|
||||||
|
|
||||||
CNode(
|
|
||||||
_In_ DEVINST Device,
|
|
||||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||||
);
|
);
|
||||||
|
|
||||||
~CNode();
|
~CNode();
|
||||||
|
|
||||||
bool Setup();
|
virtual bool SetupNode() = 0;
|
||||||
|
|
||||||
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
||||||
DEVINST GetDeviceInst() { return m_DevInst; }
|
|
||||||
|
|
||||||
LPWSTR GetDisplayName() { return m_DisplayName; }
|
LPWSTR GetDisplayName() { return m_DisplayName; }
|
||||||
INT GetClassImage() { return m_ClassImage; }
|
INT GetClassImage() { return m_ClassImage; }
|
||||||
INT GetOverlayImage() { return m_OverlayImage; }
|
|
||||||
LPWSTR GetDeviceId() { return m_DeviceId; }
|
LPWSTR GetDeviceId() { return m_DeviceId; }
|
||||||
Actions GetActions() { return m_Actions; }
|
|
||||||
|
|
||||||
bool HasProblem() { return !!(m_ProblemNumber); }
|
bool HasProperties() { return (m_DeviceId != NULL); }
|
||||||
bool HasProperties();
|
|
||||||
bool IsHidden();
|
|
||||||
bool CanDisable();
|
|
||||||
bool IsDisabled();
|
|
||||||
bool IsStarted();
|
|
||||||
bool IsInstalled();
|
|
||||||
bool CanInstall() { return TRUE; } // unimplemented
|
|
||||||
bool CanUninstall() { return TRUE; } // unimplemented
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool SetupClassNode();
|
|
||||||
bool SetupDeviceNode();
|
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
DWORD ConvertResourceDescriptorToString(
|
|
||||||
_Inout_z_ LPWSTR ResourceDescriptor,
|
|
||||||
_In_ DWORD ResourceDescriptorSize
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue