- Add support for selecting any device when refreshing the view. This allows us to re-select a device after it's been enabled instead of collapsing the tree and losing track of what you did.
- Plug some memory leaks
- HeapAlloc -> new

svn path=/trunk/; revision=68272
This commit is contained in:
Ged Murphy 2015-06-26 08:45:49 +00:00
parent eb33bb164d
commit 656342ff11
6 changed files with 148 additions and 105 deletions

View file

@ -18,6 +18,7 @@ CDeviceNode::CDeviceNode(
) : ) :
CNode(ImageListData), CNode(ImageListData),
m_DevInst(Device), m_DevInst(Device),
m_hDevInfo(NULL),
m_Status(0), m_Status(0),
m_ProblemNumber(0), m_ProblemNumber(0),
m_OverlayImage(0) m_OverlayImage(0)
@ -27,7 +28,7 @@ CDeviceNode::CDeviceNode(
CDeviceNode::~CDeviceNode() CDeviceNode::~CDeviceNode()
{ {
SetupDiDestroyDeviceInfoList(m_hDevInfo); Cleanup();
} }
bool bool
@ -37,37 +38,31 @@ CDeviceNode::SetupNode()
ULONG ulLength; ULONG ulLength;
CONFIGRET cr; CONFIGRET cr;
// ATLASSERT(m_DeviceId == NULL);
// Get the length of the device id string // Get the length of the device id string
cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0); cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0);
if (cr == CR_SUCCESS) if (cr == CR_SUCCESS)
{ {
// We alloc heap here because this will be stored in the lParam of the TV // We alloc heap here because this will be stored in the lParam of the TV
m_DeviceId = (LPWSTR)HeapAlloc(GetProcessHeap(), m_DeviceId = new WCHAR[ulLength + 1];
0,
(ulLength + 1) * sizeof(WCHAR)); // Now get the actual device id
if (m_DeviceId) cr = CM_Get_Device_IDW(m_DevInst,
m_DeviceId,
ulLength + 1,
0);
if (cr != CR_SUCCESS)
{ {
// Now get the actual device id delete[] m_DeviceId;
cr = CM_Get_Device_IDW(m_DevInst, m_DeviceId = NULL;
m_DeviceId,
ulLength + 1,
0);
if (cr != CR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, m_DeviceId);
m_DeviceId = NULL;
}
} }
} }
// Make sure we got the string // Make sure we got the string
if (m_DeviceId == NULL) if (m_DeviceId == NULL)
return false; return false;
//SP_DEVINFO_DATA DevinfoData; // Build up a handle a and devinfodata struct
m_hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, m_hDevInfo = SetupDiCreateDeviceInfoListExW(NULL,
NULL, NULL,
NULL, NULL,
@ -83,28 +78,14 @@ CDeviceNode::SetupNode()
} }
// Set the overlay if the device has a problem
// Get the current status of the device if (HasProblem())
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; m_OverlayImage = 1;
} }
// The disabled overlay takes precidence over the problem overlay // The disabled overlay takes precidence over the problem overlay
if (m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED)) if (IsDisabled())
{ {
m_OverlayImage = 2; m_OverlayImage = 2;
} }
@ -158,11 +139,11 @@ CDeviceNode::SetupNode()
// Cleanup if something failed // Cleanup if something failed
if (cr != CR_SUCCESS) if (cr != CR_SUCCESS)
{ {
HeapFree(GetProcessHeap(), 0, m_DeviceId); Cleanup();
m_DeviceId = NULL; return false;
} }
return (cr == CR_SUCCESS ? true : false); return true;
} }
bool bool
@ -340,7 +321,7 @@ CDeviceNode::EnableDevice(
if (Enable) if (Enable)
{ {
// config specific enablling first, then global enabling. // config specific enabling first, then global enabling.
// The global appears to be the one that starts the device // The global appears to be the one that starts the device
pcp.Scope = DICS_FLAG_GLOBAL; pcp.Scope = DICS_FLAG_GLOBAL;
if (SetupDiSetClassInstallParamsW(m_hDevInfo, if (SetupDiSetClassInstallParamsW(m_hDevInfo,
@ -362,6 +343,23 @@ CDeviceNode::EnableDevice(
return true; return true;
} }
/* PRIVATE METHODS ******************************************************/
void
CDeviceNode::Cleanup()
{
if (m_DeviceId)
{
delete[] m_DeviceId;
m_DeviceId = NULL;
}
if (m_hDevInfo)
{
SetupDiDestroyDeviceInfoList(m_hDevInfo);
m_hDevInfo = NULL;
}
}
DWORD DWORD
CDeviceNode::GetFlags( CDeviceNode::GetFlags(
) )

View file

@ -38,6 +38,9 @@ public:
); );
private: private:
void Cleanup(
);
bool SetFlags( bool SetFlags(
_In_ DWORD Flags, _In_ DWORD Flags,
_In_ DWORD FlagsEx _In_ DWORD FlagsEx

View file

@ -36,6 +36,7 @@ struct RefreshThreadData
CDeviceView *This; CDeviceView *This;
BOOL ScanForChanges; BOOL ScanForChanges;
BOOL UpdateView; BOOL UpdateView;
LPWSTR DeviceId;
}; };
@ -198,7 +199,8 @@ void
CDeviceView::Refresh( CDeviceView::Refresh(
_In_ ViewType Type, _In_ ViewType Type,
_In_ bool ScanForChanges, _In_ bool ScanForChanges,
_In_ bool UpdateView _In_ bool UpdateView,
_In_opt_ LPWSTR DeviceId
) )
{ {
// Enum devices on a seperate thread to keep the gui responsive // Enum devices on a seperate thread to keep the gui responsive
@ -210,6 +212,16 @@ CDeviceView::Refresh(
ThreadData->This = this; ThreadData->This = this;
ThreadData->ScanForChanges = ScanForChanges; ThreadData->ScanForChanges = ScanForChanges;
ThreadData->UpdateView = UpdateView; ThreadData->UpdateView = UpdateView;
ThreadData->DeviceId = NULL;
if (DeviceId)
{
// Node gets deleted on refresh so we copy it to another block
size_t Length = wcslen(DeviceId) + 1;
ThreadData->DeviceId = new WCHAR[Length];
wcscpy_s(ThreadData->DeviceId, Length, DeviceId);
}
HANDLE hThread; HANDLE hThread;
hThread = (HANDLE)_beginthreadex(NULL, hThread = (HANDLE)_beginthreadex(NULL,
@ -309,29 +321,29 @@ CDeviceView::EnableSelectedDevice(
) )
{ {
CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode()); CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode());
if (Node) if (Node == nullptr) return false;
if (Enable == false)
{ {
if (Enable == false) CAtlStringW str;
if (str.LoadStringW(g_hInstance, IDS_CONFIRM_DISABLE))
{ {
CAtlStringW str; if (MessageBoxW(m_hMainWnd,
if (str.LoadStringW(g_hInstance, IDS_CONFIRM_DISABLE)) str,
Node->GetDisplayName(),
MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES)
{ {
if (MessageBoxW(m_hMainWnd, return false;
str,
Node->GetDisplayName(),
MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES)
{
return false;
}
} }
} }
if (Node->EnableDevice(Enable, NeedsReboot))
{
Refresh(m_ViewType, true, true);
return true;
}
} }
if (Node->EnableDevice(Enable, NeedsReboot))
{
Refresh(m_ViewType, true, true, Node->GetDeviceId());
return true;
}
return false; return false;
} }
@ -462,6 +474,11 @@ unsigned int __stdcall CDeviceView::RefreshThread(void *Param)
break; break;
} }
This->SelectNode(ThreadData->DeviceId);
if (ThreadData->DeviceId)
delete[] ThreadData->DeviceId;
delete ThreadData; delete ThreadData;
return 0; return 0;
@ -650,7 +667,7 @@ CDeviceView::RecurseChildDevices(
// Get the cached device node // Get the cached device node
CDeviceNode *DeviceNode; CDeviceNode *DeviceNode;
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device)); DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
if (DeviceNode == NULL) if (DeviceNode == nullptr)
{ {
ATLASSERT(FALSE); ATLASSERT(FALSE);
return false; return false;
@ -684,7 +701,7 @@ CDeviceView::RecurseChildDevices(
if (bSuccess == FALSE) break; if (bSuccess == FALSE) break;
DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device)); DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
if (DeviceNode == NULL) if (DeviceNode == nullptr)
{ {
ATLASSERT(FALSE); ATLASSERT(FALSE);
} }
@ -790,17 +807,20 @@ CDeviceView::InsertIntoTreeView(
return TreeView_InsertItem(m_hTreeView, &tvins); return TreeView_InsertItem(m_hTreeView, &tvins);
} }
void HTREEITEM
CDeviceView::RecurseDeviceView( CDeviceView::RecurseFindDevice(
_In_ HTREEITEM hParentItem _In_ HTREEITEM hParentItem,
_In_ LPWSTR DeviceId
) )
{ {
HTREEITEM FoundItem;
HTREEITEM hItem; HTREEITEM hItem;
TVITEMW tvItem; TVITEMW tvItem;
CNode *Node;
// Check if this node has any children // Check if this node has any children
hItem = TreeView_GetChild(m_hTreeView, hParentItem); hItem = TreeView_GetChild(m_hTreeView, hParentItem);
if (hItem == NULL) return; if (hItem == NULL) return NULL;
// The lParam contains the node pointer data // The lParam contains the node pointer data
tvItem.hItem = hItem; tvItem.hItem = hItem;
@ -808,12 +828,17 @@ CDeviceView::RecurseDeviceView(
if (TreeView_GetItem(m_hTreeView, &tvItem) && if (TreeView_GetItem(m_hTreeView, &tvItem) &&
tvItem.lParam != NULL) tvItem.lParam != NULL)
{ {
// Delete the node class Node = reinterpret_cast<CNode *>(tvItem.lParam);
//delete reinterpret_cast<CNode *>(tvItem.lParam); if (Node->GetDeviceId() &&
(wcscmp(Node->GetDeviceId(), DeviceId) == 0))
{
return hItem;
}
} }
// This node may have its own children // This node may have its own children
RecurseDeviceView(hItem); FoundItem = RecurseFindDevice(hItem, DeviceId);
if (FoundItem) return FoundItem;
// Delete all the siblings // Delete all the siblings
for (;;) for (;;)
@ -827,12 +852,45 @@ CDeviceView::RecurseDeviceView(
tvItem.mask = TVIF_PARAM; tvItem.mask = TVIF_PARAM;
if (TreeView_GetItem(m_hTreeView, &tvItem)) if (TreeView_GetItem(m_hTreeView, &tvItem))
{ {
//if (tvItem.lParam != NULL) Node = reinterpret_cast<CNode *>(tvItem.lParam);
// delete reinterpret_cast<CNode *>(tvItem.lParam); if (Node->GetDeviceId() &&
wcscmp(Node->GetDeviceId(), DeviceId) == 0)
{
return hItem;
}
} }
// This node may have its own children // This node may have its own children
RecurseDeviceView(hItem); FoundItem = RecurseFindDevice(hItem, DeviceId);
if (FoundItem) return FoundItem;
}
return hItem;
}
void
CDeviceView::SelectNode(
_In_ LPWSTR DeviceId
)
{
HTREEITEM hRoot, hItem;
// Check if there are any items in the tree
hRoot = TreeView_GetRoot(m_hTreeView);
if (hRoot == NULL) return;
if (DeviceId)
{
hItem = RecurseFindDevice(hRoot, DeviceId);
if (hItem)
{
TreeView_SelectItem(m_hTreeView, hItem);
TreeView_Expand(m_hTreeView, hItem, TVM_EXPAND);
}
}
else
{
TreeView_SelectItem(m_hTreeView, hRoot);
} }
} }
@ -840,22 +898,10 @@ CDeviceView::RecurseDeviceView(
void void
CDeviceView::EmptyDeviceView() CDeviceView::EmptyDeviceView()
{ {
HTREEITEM hItem;
// Check if there are any items in the tree
hItem = TreeView_GetRoot(m_hTreeView);
if (hItem == NULL) return;
// Free all the class nodes
//RecurseDeviceView(hItem);
// Delete all the items
(VOID)TreeView_DeleteAllItems(m_hTreeView); (VOID)TreeView_DeleteAllItems(m_hTreeView);
} }
CClassNode* CClassNode*
CDeviceView::GetClassNode( CDeviceView::GetClassNode(
_In_ LPGUID ClassGuid _In_ LPGUID ClassGuid
@ -972,6 +1018,8 @@ CDeviceView::RefreshDeviceList()
{ {
m_ClassNodeList.AddTail(ClassNode); m_ClassNodeList.AddTail(ClassNode);
} }
SetupDiDestroyDeviceInfoList(hDevInfo);
} }
ClassIndex++; ClassIndex++;
} while (Success); } while (Success);

View file

@ -55,7 +55,8 @@ public:
VOID Refresh( VOID Refresh(
_In_ ViewType Type, _In_ ViewType Type,
_In_ bool ScanForChanges, _In_ bool ScanForChanges,
_In_ bool UpdateView _In_ bool UpdateView,
_In_opt_ LPWSTR DeviceId
); );
VOID DisplayPropertySheet(); VOID DisplayPropertySheet();
@ -127,11 +128,16 @@ private:
_In_ CNode *Node _In_ CNode *Node
); );
VOID RecurseDeviceView( HTREEITEM RecurseFindDevice(
_In_ HTREEITEM hParentItem _In_ HTREEITEM hParentItem,
_In_ LPWSTR DeviceId
); );
VOID EmptyDeviceView( void SelectNode(
_In_ LPWSTR DeviceId
);
void EmptyDeviceView(
); );
CNode* GetNode( CNode* GetNode(
@ -145,6 +151,7 @@ private:
CDeviceNode* GetDeviceNode( CDeviceNode* GetDeviceNode(
_In_ DEVINST Device _In_ DEVINST Device
); );
void EmptyLists(); void EmptyLists(
);
}; };

View file

@ -212,7 +212,7 @@ CMainWindow::RefreshView(ViewType Type)
BOOL bSuccess; BOOL bSuccess;
// Refreshed the cached view // Refreshed the cached view
m_DeviceView->Refresh(Type, FALSE, TRUE); m_DeviceView->Refresh(Type, FALSE, TRUE, NULL);
// Get the menu item id // Get the menu item id
switch (Type) switch (Type)
@ -240,7 +240,8 @@ CMainWindow::ScanForHardwareChanges()
// Refresh the cache and and display // Refresh the cache and and display
m_DeviceView->Refresh(m_DeviceView->GetCurrentView(), m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
true, true,
true); true,
NULL);
return true; return true;
} }
@ -618,7 +619,8 @@ CMainWindow::OnCommand(WPARAM wParam,
// Refresh the device view // Refresh the device view
m_DeviceView->Refresh(m_DeviceView->GetCurrentView(), m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
false, false,
true); true,
NULL);
break; break;
} }

View file

@ -24,19 +24,4 @@ CNode::CNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
CNode::~CNode() CNode::~CNode()
{ {
Cleanup();
}
/* PRIVATE METHODS ******************************************/
void
CNode::Cleanup()
{
if (m_DeviceId)
{
HeapFree(GetProcessHeap(), 0, m_DeviceId);
m_DeviceId = NULL;
}
} }