2 * PROJECT: ReactOS Device Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/devmgr/devmgmt/DeviceView.cpp
5 * PURPOSE: Implements the tree view which contains the devices
6 * COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
13 #include "DeviceView.h"
16 // DATA ********************************************/
18 #define CLASS_NAME_LEN 256
19 #define CLASS_DESC_LEN 256
20 #define ROOT_NAME_SIZE MAX_COMPUTERNAME_LENGTH + 1
23 typedef VOID(WINAPI
*PADDHARDWAREWIZARD
)(HWND hwnd
, LPWSTR lpName
);
25 struct RefreshThreadData
33 // PUBLIC METHODS ************************************/
35 CDeviceView::CDeviceView(
40 m_hPropertyDialog(NULL
),
42 m_ViewType(DevicesByType
),
46 ZeroMemory(&m_ImageListData
, sizeof(SP_CLASSIMAGELIST_DATA
));
49 CDeviceView::~CDeviceView(void)
54 CDeviceView::Initialize()
56 // Get the device image list
57 m_ImageListData
.cbSize
= sizeof(SP_CLASSIMAGELIST_DATA
);
58 BOOL bSuccess
= SetupDiGetClassImageList(&m_ImageListData
);
59 if (bSuccess
== FALSE
) return false;
61 // Create the main treeview
62 m_hTreeView
= CreateWindowExW(WS_EX_CLIENTEDGE
,
65 WS_CHILD
| WS_VISIBLE
| WS_BORDER
| TVS_HASLINES
|
66 TVS_HASBUTTONS
| TVS_SHOWSELALWAYS
| TVS_LINESATROOT
,
74 // Set the image list against the treeview
75 (void)TreeView_SetImageList(m_hTreeView
,
76 m_ImageListData
.ImageList
,
79 // Give the treeview arrows instead of +/- boxes (on Win7)
80 SetWindowTheme(m_hTreeView
, L
"explorer", NULL
);
82 // Create the root node
83 m_RootNode
= new CRootNode(&m_ImageListData
);
84 m_RootNode
->SetupNode();
89 return !!(m_hTreeView
);
93 CDeviceView::Uninitialize()
97 if (m_ImageListData
.ImageList
!= NULL
)
99 SetupDiDestroyClassImageList(&m_ImageListData
);
100 ZeroMemory(&m_ImageListData
, sizeof(SP_CLASSIMAGELIST_DATA
));
114 // Resize the treeview
115 SetWindowPos(m_hTreeView
,
127 CDeviceView::OnRightClick(
131 HTREEITEM hItem
= TreeView_GetNextItem(NmHdr
->hwndFrom
, 0, TVGN_DROPHILITE
);
134 TreeView_SelectItem(NmHdr
->hwndFrom
, hItem
);
141 CDeviceView::OnContextMenu(
145 HTREEITEM hSelected
= TreeView_GetSelection(m_hTreeView
);
148 if (TreeView_GetItemRect(m_hTreeView
,
154 if (GetCursorPos(&pt
) &&
155 ScreenToClient(m_hTreeView
, &pt
) &&
158 CNode
*Node
= GetSelectedNode();
161 // Create the context menu
162 HMENU hContextMenu
= CreatePopupMenu();
164 // Add the actions for this node
165 BuildActionMenuForNode(hContextMenu
, Node
, false);
167 INT xPos
= GET_X_LPARAM(lParam
);
168 INT yPos
= GET_Y_LPARAM(lParam
);
171 TrackPopupMenuEx(hContextMenu
,
178 DestroyMenu(hContextMenu
);
188 CDeviceView::Refresh(
190 _In_
bool ScanForChanges
,
194 // Enum devices on a seperate thread to keep the gui responsive
198 RefreshThreadData
*ThreadData
;
199 ThreadData
= new RefreshThreadData
;
200 ThreadData
->This
= this;
201 ThreadData
->ScanForChanges
= ScanForChanges
;
202 ThreadData
->UpdateView
= UpdateView
;
206 hThread
= (HANDLE
)_beginthreadex(NULL
,
212 if (hThread
) CloseHandle(hThread
);
216 CDeviceView::OnAction(
224 DisplayPropertySheet();
228 case IDC_SCAN_HARDWARE
:
230 Refresh(GetCurrentView(),
239 if (EnableSelectedDevice(true, NeedsReboot
) &&
242 MessageBox(m_hMainWnd
, L
"Rebooting", L
"Enable", MB_OK
);
247 case IDC_DISABLE_DRV
:
250 EnableSelectedDevice(false, NeedsReboot
);
257 UpdateSelectedDevice(NeedsReboot
);
261 case IDC_UNINSTALL_DRV
:
263 UninstallSelectedDevice();
267 case IDC_ADD_HARDWARE
:
269 RunAddHardwareWizard();
278 CDeviceView::DisplayPropertySheet()
280 CNode
*Node
= GetSelectedNode();
281 if (Node
&& Node
->HasProperties())
283 DevicePropertiesExW(m_hTreeView
,
292 CDeviceView::SetFocus()
297 CDeviceView::CreateActionMenu(
298 _In_ HMENU OwnerMenu
,
302 CNode
*Node
= GetSelectedNode();
305 BuildActionMenuForNode(OwnerMenu
, Node
, MainMenu
);
313 CDeviceView::GetSelectedNode()
316 TvItem
.hItem
= TreeView_GetSelection(m_hTreeView
);
317 return GetNode(&TvItem
);
322 // PRIVATE METHODS *******************************************/
325 CDeviceView::AddRootDevice()
327 m_hTreeRoot
= InsertIntoTreeView(NULL
, m_RootNode
);
328 return (m_hTreeRoot
!= NULL
);
332 CDeviceView::GetNextClass(
333 _In_ ULONG ClassIndex
,
334 _Out_ LPGUID ClassGuid
,
335 _Out_ HDEVINFO
*hDevInfo
340 // Get the next class in the list
341 cr
= CM_Enumerate_Classes(ClassIndex
,
344 if (cr
!= CR_SUCCESS
) return false;
346 // Check if this is the unknown class
347 if (IsEqualGUID(*ClassGuid
, GUID_DEVCLASS_UNKNOWN
))
349 // Get device info for all devices
350 *hDevInfo
= SetupDiGetClassDevsW(NULL
,
357 // We only want the devices for this class
358 *hDevInfo
= SetupDiGetClassDevsW(ClassGuid
,
364 return (hDevInfo
!= INVALID_HANDLE_VALUE
);
367 unsigned int __stdcall
CDeviceView::RefreshThread(void *Param
)
369 RefreshThreadData
*ThreadData
= (RefreshThreadData
*)Param
;
370 CDeviceView
*This
= ThreadData
->This
;
372 // Get a copy of the currently selected node
373 CNode
*LastSelectedNode
= This
->GetSelectedNode();
374 if (LastSelectedNode
== nullptr || (LastSelectedNode
->GetNodeType() == RootNode
))
376 LastSelectedNode
= new CRootNode(*This
->m_RootNode
);
378 else if (LastSelectedNode
->GetNodeType() == ClassNode
)
380 LastSelectedNode
= new CClassNode(*dynamic_cast<CClassNode
*>(LastSelectedNode
));
382 else if (LastSelectedNode
->GetNodeType() == DeviceNode
)
384 LastSelectedNode
= new CDeviceNode(*dynamic_cast<CDeviceNode
*>(LastSelectedNode
));
387 // Empty the treeview
388 This
->EmptyDeviceView();
390 // Re-add the root node to the tree
391 if (This
->AddRootDevice() == false)
394 // Refresh the devices only if requested
395 if (ThreadData
->ScanForChanges
)
397 This
->RefreshDeviceList();
400 // display the type of view the user wants
401 switch (This
->m_ViewType
)
404 (void)This
->ListDevicesByType();
407 case DevicesByConnection
:
408 (VOID
)This
->ListDevicesByConnection();
411 case ResourcesByType
:
414 case ResourcesByConnection
:
419 This
->SelectNode(LastSelectedNode
);
428 CDeviceView::ListDevicesByType()
430 CClassNode
*ClassNode
;
431 CDeviceNode
*DeviceNode
;
433 HTREEITEM hTreeItem
= NULL
;
436 BOOL bClassSuccess
, bSuccess
;
441 // Loop through all the device classes
442 bClassSuccess
= GetNextClass(ClassIndex
, &ClassGuid
, &hDevInfo
);
445 bool bClassUnknown
= false;
446 bool AddedParent
= false;
448 bool MoreItems
= false;
450 // Get the cached class node
451 ClassNode
= GetClassNode(&ClassGuid
);
452 if (ClassNode
== nullptr)
459 // Set a flag is this is the (special case) unknown class
460 if (IsEqualGUID(ClassGuid
, GUID_DEVCLASS_UNKNOWN
))
461 bClassUnknown
= true;
465 // Get a handle to all the devices in this class
466 SP_DEVINFO_DATA DeviceInfoData
;
467 ZeroMemory(&DeviceInfoData
, sizeof(SP_DEVINFO_DATA
));
468 DeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
469 bSuccess
= SetupDiEnumDeviceInfo(hDevInfo
,
472 if (bSuccess
== FALSE
&& GetLastError() == ERROR_NO_MORE_ITEMS
)
479 // The unknown class handle contains all devices on the system,
480 // and we're just looking for the ones with a null GUID
483 if (IsEqualGUID(DeviceInfoData
.ClassGuid
, GUID_NULL
) == FALSE
)
485 // This is a known device, we aren't interested in it
491 // Get the cached device node
492 DeviceNode
= GetDeviceNode(DeviceInfoData
.DevInst
);
493 if (DeviceNode
== nullptr)
495 ATLASSERT(bClassUnknown
== true);
500 // Check if this is a hidden device
501 if (DeviceNode
->IsHidden())
503 // Ignore this device if we aren't displaying hidden devices
504 if (m_ShowHidden
== FALSE
)
511 // We have a device, we need to add the parent if it hasn't yet been added
512 if (AddedParent
== false)
514 // Insert the new class under the root item
515 hTreeItem
= InsertIntoTreeView(m_hTreeRoot
,
520 // Add the device under the class item node
521 (void)InsertIntoTreeView(hTreeItem
, DeviceNode
);
523 // Expand the class if it has a problem device
524 if (DeviceNode
->HasProblem())
526 (void)TreeView_Expand(m_hTreeView
,
536 // If this class has devices, sort them alphabetically
537 if (AddedParent
== true)
539 (void)TreeView_SortChildren(m_hTreeView
,
547 } while (bClassSuccess
);
549 // Sort the classes alphabetically
550 (void)TreeView_SortChildren(m_hTreeView
,
554 // Expand the root item
555 (void)TreeView_Expand(m_hTreeView
,
559 // Pre-select the root item
560 (VOID
)TreeView_SelectItem(m_hTreeView
,
567 CDeviceView::ListDevicesByConnection()
569 // Walk the device tree and add all the devices
570 (void)RecurseChildDevices(m_RootNode
->GetDeviceInst(), m_hTreeRoot
);
572 // Expand the root item
573 (void)TreeView_Expand(m_hTreeView
,
581 CDeviceView::RecurseChildDevices(
582 _In_ DEVINST ParentDevice
,
583 _In_ HTREEITEM hParentTreeItem
586 HTREEITEM hDevItem
= NULL
;
588 bool HasProblem
= false;
591 // Check if the parent has any child devices
592 if (GetChildDevice(ParentDevice
, &Device
) == FALSE
)
595 // Get the cached device node
596 CDeviceNode
*DeviceNode
;
597 DeviceNode
= dynamic_cast<CDeviceNode
*>(GetDeviceNode(Device
));
598 if (DeviceNode
== nullptr)
604 // Don't show hidden devices if not requested
605 if ((m_ShowHidden
== TRUE
) || (!(DeviceNode
->IsHidden())))
607 // Add this device to the tree under its parent
608 hDevItem
= InsertIntoTreeView(hParentTreeItem
,
612 // Check if this child has any children itself
613 if (!RecurseChildDevices(Device
, hDevItem
))
617 if (DeviceNode
->HasProblem())
624 // Check for siblings
627 // Check if the parent device has anything at the same level
628 bSuccess
= GetSiblingDevice(Device
, &Device
);
629 if (bSuccess
== FALSE
) break;
631 DeviceNode
= dynamic_cast<CDeviceNode
*>(GetDeviceNode(Device
));
632 if (DeviceNode
== nullptr)
637 // Don't show hidden devices if not requested
638 if ((m_ShowHidden
== TRUE
) || (!(DeviceNode
->IsHidden())))
640 if (DeviceNode
->HasProblem())
645 // Add this device to the tree under its parent
646 hDevItem
= InsertIntoTreeView(hParentTreeItem
,
650 // Check if this child has any children itself
651 if (!RecurseChildDevices(Device
, hDevItem
))
657 (void)TreeView_SortChildren(m_hTreeView
,
661 // Expand the class if it has a problem device
662 if (HasProblem
== true)
664 (void)TreeView_Expand(m_hTreeView
,
669 // If there was a problem, expand the ancestors
670 if (HasProblem
) return false;
676 CDeviceView::EnableSelectedDevice(
678 _Out_
bool &NeedsReboot
681 CDeviceNode
*Node
= dynamic_cast<CDeviceNode
*>(GetSelectedNode());
682 if (Node
== nullptr) return false;
687 if (str
.LoadStringW(g_hThisInstance
, IDS_CONFIRM_DISABLE
))
689 if (MessageBoxW(m_hMainWnd
,
691 Node
->GetDisplayName(),
692 MB_YESNO
| MB_ICONWARNING
| MB_DEFBUTTON2
) != IDYES
)
699 return Node
->EnableDevice(Enable
, NeedsReboot
);
703 CDeviceView::UpdateSelectedDevice(
704 _Out_
bool &NeedsReboot
707 CDeviceNode
*Node
= dynamic_cast<CDeviceNode
*>(GetSelectedNode());
708 if (Node
== nullptr) return false;
711 if (InstallDevInst(m_hMainWnd
, Node
->GetDeviceId(), TRUE
, &dwReboot
))
721 CDeviceView::UninstallSelectedDevice(
724 CDeviceNode
*Node
= dynamic_cast<CDeviceNode
*>(GetSelectedNode());
725 if (Node
== nullptr) return false;
728 if (str
.LoadStringW(g_hThisInstance
, IDS_CONFIRM_UNINSTALL
))
730 if (MessageBoxW(m_hMainWnd
,
732 Node
->GetDisplayName(),
733 MB_YESNO
| MB_ICONWARNING
| MB_DEFBUTTON2
) != IDYES
)
739 return Node
->UninstallDevice();
743 CDeviceView::RunAddHardwareWizard()
745 PADDHARDWAREWIZARD pAddHardwareWizard
;
748 hModule
= LoadLibraryW(L
"hdwwiz.cpl");
749 if (hModule
== NULL
) return false;
751 pAddHardwareWizard
= (PADDHARDWAREWIZARD
)GetProcAddress(hModule
,
752 "AddHardwareWizard");
753 if (pAddHardwareWizard
== NULL
)
755 FreeLibrary(hModule
);
759 pAddHardwareWizard(m_hMainWnd
, NULL
);
761 FreeLibrary(hModule
);
766 CDeviceView::GetChildDevice(
767 _In_ DEVINST ParentDevInst
,
768 _Out_ PDEVINST DevInst
772 cr
= CM_Get_Child(DevInst
,
775 return (cr
== CR_SUCCESS
);
779 CDeviceView::GetSiblingDevice(
780 _In_ DEVINST PrevDevice
,
781 _Out_ PDEVINST DevInst
785 cr
= CM_Get_Sibling(DevInst
,
788 return (cr
== CR_SUCCESS
);
792 CDeviceView::InsertIntoTreeView(
793 _In_opt_ HTREEITEM hParent
,
798 lpLabel
= Node
->GetDisplayName();
801 TV_INSERTSTRUCT tvins
;
802 ZeroMemory(&tvi
, sizeof(tvi
));
803 ZeroMemory(&tvins
, sizeof(tvins
));
805 tvi
.mask
= TVIF_TEXT
| TVIF_PARAM
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
806 tvi
.pszText
= lpLabel
;
807 tvi
.cchTextMax
= wcslen(lpLabel
);
808 tvi
.lParam
= (LPARAM
)Node
;
809 tvi
.iImage
= Node
->GetClassImage();
810 tvi
.iSelectedImage
= Node
->GetClassImage();
812 // try to cast it to a device node. This will only suceed if it's the correct type
813 CDeviceNode
*DeviceNode
= dynamic_cast<CDeviceNode
*>(Node
);
814 if (DeviceNode
&& DeviceNode
->GetOverlayImage())
816 tvi
.mask
|= TVIF_STATE
;
817 tvi
.stateMask
= TVIS_OVERLAYMASK
;
818 tvi
.state
= INDEXTOOVERLAYMASK(DeviceNode
->GetOverlayImage());
822 tvins
.hParent
= hParent
;
824 return TreeView_InsertItem(m_hTreeView
, &tvins
);
828 CDeviceView::BuildActionMenuForNode(
829 _In_ HMENU OwnerMenu
,
834 // Create a seperator structure
835 MENUITEMINFOW MenuSeperator
= { 0 };
836 MenuSeperator
.cbSize
= sizeof(MENUITEMINFOW
);
837 MenuSeperator
.fType
= MFT_SEPARATOR
;
840 MENUITEMINFOW MenuItemInfo
= { 0 };
841 MenuItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
842 MenuItemInfo
.fMask
= MIIM_ID
| MIIM_STRING
| MIIM_DATA
| MIIM_SUBMENU
;
843 MenuItemInfo
.fType
= MFT_STRING
;
848 // Device nodes have extra data
849 if (Node
->GetNodeType() == DeviceNode
)
851 CDeviceNode
*DeviceNode
= dynamic_cast<CDeviceNode
*>(Node
);
853 if (DeviceNode
->CanUpdate())
855 String
.LoadStringW(g_hThisInstance
, IDS_MENU_UPDATE
);
856 MenuItemInfo
.wID
= IDC_UPDATE_DRV
;
857 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
858 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
862 if (DeviceNode
->IsDisabled())
864 String
.LoadStringW(g_hThisInstance
, IDS_MENU_ENABLE
);
865 MenuItemInfo
.wID
= IDC_ENABLE_DRV
;
866 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
867 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
871 if (DeviceNode
->CanDisable() && !DeviceNode
->IsDisabled())
873 String
.LoadStringW(g_hThisInstance
, IDS_MENU_DISABLE
);
874 MenuItemInfo
.wID
= IDC_DISABLE_DRV
;
875 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
876 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
880 if (DeviceNode
->CanUninstall())
882 String
.LoadStringW(g_hThisInstance
, IDS_MENU_UNINSTALL
);
883 MenuItemInfo
.wID
= IDC_UNINSTALL_DRV
;
884 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
885 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
889 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuSeperator
);
893 // All nodes have the scan option
894 String
.LoadStringW(g_hThisInstance
, IDS_MENU_SCAN
);
895 MenuItemInfo
.wID
= IDC_SCAN_HARDWARE
;
896 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
897 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
900 if ((Node
->GetNodeType() == RootNode
) || (MainMenu
== true))
902 String
.LoadStringW(g_hThisInstance
, IDS_MENU_ADD
);
903 MenuItemInfo
.wID
= IDC_ADD_HARDWARE
;
904 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
905 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
909 if (Node
->HasProperties())
911 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuSeperator
);
914 String
.LoadStringW(g_hThisInstance
, IDS_MENU_PROPERTIES
);
915 MenuItemInfo
.wID
= IDC_PROPERTIES
;
916 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
917 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
920 SetMenuDefaultItem(OwnerMenu
, IDC_PROPERTIES
, FALSE
);
925 CDeviceView::RecurseFindDevice(
926 _In_ HTREEITEM hParentItem
,
935 // Check if this node has any children
936 hItem
= TreeView_GetChild(m_hTreeView
, hParentItem
);
937 if (hItem
== NULL
) return NULL
;
939 // The lParam contains the node pointer data
940 tvItem
.hItem
= hItem
;
941 tvItem
.mask
= TVIF_PARAM
;
942 if (TreeView_GetItem(m_hTreeView
, &tvItem
) &&
943 tvItem
.lParam
!= NULL
)
945 // check for a matching node
946 FoundNode
= reinterpret_cast<CNode
*>(tvItem
.lParam
);
947 if ((FoundNode
->GetNodeType() == Node
->GetNodeType()) &&
948 (IsEqualGUID(*FoundNode
->GetClassGuid(), *Node
->GetClassGuid())))
950 // check if this is a class node, or a device with matching ID's
951 if ((FoundNode
->GetNodeType() == ClassNode
) ||
952 (wcscmp(FoundNode
->GetDeviceId(), Node
->GetDeviceId()) == 0))
959 // This node may have its own children
960 FoundItem
= RecurseFindDevice(hItem
, Node
);
961 if (FoundItem
) return FoundItem
;
963 // Loop all the siblings
966 // Get the next item at this level
967 hItem
= TreeView_GetNextSibling(m_hTreeView
, hItem
);
968 if (hItem
== NULL
) break;
970 // The lParam contains the node pointer data
971 tvItem
.hItem
= hItem
;
972 tvItem
.mask
= TVIF_PARAM
;
973 if (TreeView_GetItem(m_hTreeView
, &tvItem
))
975 // check for a matching class
976 FoundNode
= reinterpret_cast<CNode
*>(tvItem
.lParam
);
977 if ((FoundNode
->GetNodeType() == Node
->GetNodeType()) &&
978 (IsEqualGUID(*FoundNode
->GetClassGuid(), *Node
->GetClassGuid())))
980 // check if this is a class node, or a device with matching ID's
981 if ((FoundNode
->GetNodeType() == ClassNode
) ||
982 (wcscmp(FoundNode
->GetDeviceId(), Node
->GetDeviceId()) == 0))
989 // This node may have its own children
990 FoundItem
= RecurseFindDevice(hItem
, Node
);
991 if (FoundItem
) return FoundItem
;
998 CDeviceView::SelectNode(
1002 HTREEITEM hRoot
, hItem
;
1004 // Check if there are any items in the tree
1005 hRoot
= TreeView_GetRoot(m_hTreeView
);
1006 if (hRoot
== NULL
) return;
1008 // If we don't want to set select a node, just select root
1009 if (Node
== nullptr || Node
->GetNodeType() == RootNode
)
1011 TreeView_SelectItem(m_hTreeView
, hRoot
);
1015 // Scan the tree looking for the node we want
1016 hItem
= RecurseFindDevice(hRoot
, Node
);
1019 TreeView_SelectItem(m_hTreeView
, hItem
);
1023 TreeView_SelectItem(m_hTreeView
, hRoot
);
1029 CDeviceView::EmptyDeviceView()
1031 (VOID
)TreeView_DeleteAllItems(m_hTreeView
);
1036 CDeviceView::GetClassNode(
1037 _In_ LPGUID ClassGuid
1041 CClassNode
*Node
= nullptr;
1043 Pos
= m_ClassNodeList
.GetHeadPosition();
1044 if (Pos
== NULL
) return nullptr;
1048 Node
= m_ClassNodeList
.GetNext(Pos
);
1049 if (IsEqualGUID(*Node
->GetClassGuid(), *ClassGuid
))
1051 ATLASSERT(Node
->GetNodeType() == ClassNode
);
1057 } while (Pos
!= NULL
);
1063 CDeviceView::GetDeviceNode(
1068 CDeviceNode
*Node
= nullptr;
1070 Pos
= m_DeviceNodeList
.GetHeadPosition();
1071 if (Pos
== NULL
) return nullptr;
1075 Node
= m_DeviceNodeList
.GetNext(Pos
);
1076 if (Node
->GetDeviceInst() == Device
)
1078 ATLASSERT(Node
->GetNodeType() == DeviceNode
);
1084 } while (Pos
!= NULL
);
1089 CNode
* CDeviceView::GetNode(
1090 _In_ LPTV_ITEMW TvItem
1093 TvItem
->mask
= TVIF_PARAM
;
1094 if (TreeView_GetItem(m_hTreeView
, TvItem
))
1096 return (CNode
*)TvItem
->lParam
;
1102 CDeviceView::EmptyLists()
1106 while (!m_ClassNodeList
.IsEmpty())
1108 Node
= m_ClassNodeList
.RemoveTail();
1112 while (!m_DeviceNodeList
.IsEmpty())
1114 Node
= m_DeviceNodeList
.RemoveTail();
1120 CDeviceView::RefreshDeviceList()
1123 CClassNode
*ClassNode
;
1124 CDeviceNode
*DeviceNode
;
1126 SP_DEVINFO_DATA DeviceInfoData
;
1130 ULONG ClassIndex
= 0;
1134 if (m_RootNode
) delete m_RootNode
;
1135 m_RootNode
= new CRootNode(&m_ImageListData
);
1136 m_RootNode
->SetupNode();
1138 // Loop through all the classes
1141 Success
= GetNextClass(ClassIndex
, &ClassGuid
, &hDevInfo
);
1144 // Create a new class node and add it to the list
1145 ClassNode
= new CClassNode(&ClassGuid
, &m_ImageListData
);
1146 if (ClassNode
->SetupNode())
1148 m_ClassNodeList
.AddTail(ClassNode
);
1151 SetupDiDestroyDeviceInfoList(hDevInfo
);
1157 // Get all the devices on the local machine
1158 hDevInfo
= SetupDiGetClassDevsW(NULL
,
1161 DIGCF_PRESENT
| DIGCF_ALLCLASSES
);
1162 if (hDevInfo
== INVALID_HANDLE_VALUE
)
1167 // loop though all the devices
1168 DeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1171 // Get the devinst for this device
1172 Success
= SetupDiEnumDeviceInfo(hDevInfo
, i
, &DeviceInfoData
);
1173 if (Success
== FALSE
) break;
1175 // create a new device node and add it to the list
1176 DeviceNode
= new CDeviceNode(DeviceInfoData
.DevInst
, &m_ImageListData
);
1177 if (DeviceNode
->SetupNode())
1179 m_DeviceNodeList
.AddTail(DeviceNode
);
1188 SetupDiDestroyDeviceInfoList(hDevInfo
);