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
)
62 // Create the main treeview
63 m_hTreeView
= CreateWindowExW(WS_EX_CLIENTEDGE
,
66 WS_CHILD
| WS_VISIBLE
| WS_BORDER
| TVS_HASLINES
|
67 TVS_HASBUTTONS
| TVS_SHOWSELALWAYS
| TVS_LINESATROOT
,
75 // Set the image list against the treeview
76 (void)TreeView_SetImageList(m_hTreeView
,
77 m_ImageListData
.ImageList
,
80 // Give the treeview arrows instead of +/- boxes (on Win7)
81 SetWindowTheme(m_hTreeView
, L
"explorer", NULL
);
83 // Create the root node
84 m_RootNode
= new CRootNode(&m_ImageListData
);
85 m_RootNode
->SetupNode();
90 return !!(m_hTreeView
);
94 CDeviceView::Uninitialize()
98 if (m_ImageListData
.ImageList
!= NULL
)
100 SetupDiDestroyClassImageList(&m_ImageListData
);
101 ZeroMemory(&m_ImageListData
, sizeof(SP_CLASSIMAGELIST_DATA
));
115 // Resize the treeview
116 SetWindowPos(m_hTreeView
,
128 CDeviceView::OnRightClick(
132 TVHITTESTINFO hitInfo
;
135 GetCursorPos(&hitInfo
.pt
);
136 ScreenToClient(m_hTreeView
, &hitInfo
.pt
);
138 hItem
= TreeView_HitTest(m_hTreeView
, &hitInfo
);
139 if (hItem
!= NULL
&& (hitInfo
.flags
& (TVHT_ONITEM
| TVHT_ONITEMICON
)))
141 TreeView_SelectItem(m_hTreeView
, hItem
);
148 CDeviceView::OnContextMenu(
152 HTREEITEM hSelected
= TreeView_GetSelection(m_hTreeView
);
155 if (TreeView_GetItemRect(m_hTreeView
,
161 if (GetCursorPos(&pt
) &&
162 ScreenToClient(m_hTreeView
, &pt
) &&
165 CNode
*Node
= GetSelectedNode();
168 // Create the context menu
169 HMENU hContextMenu
= CreatePopupMenu();
171 // Add the actions for this node
172 BuildActionMenuForNode(hContextMenu
, Node
, false);
174 INT xPos
= GET_X_LPARAM(lParam
);
175 INT yPos
= GET_Y_LPARAM(lParam
);
178 TrackPopupMenuEx(hContextMenu
,
185 DestroyMenu(hContextMenu
);
195 CDeviceView::Refresh(
197 _In_
bool ScanForChanges
,
201 // Enum devices on a separate thread to keep the gui responsive
205 RefreshThreadData
*ThreadData
;
206 ThreadData
= new RefreshThreadData
;
207 ThreadData
->This
= this;
208 ThreadData
->ScanForChanges
= ScanForChanges
;
209 ThreadData
->UpdateView
= UpdateView
;
212 hThread
= (HANDLE
)_beginthreadex(NULL
,
218 if (hThread
) CloseHandle(hThread
);
222 CDeviceView::OnAction(
230 DisplayPropertySheet();
234 case IDC_SCAN_HARDWARE
:
236 Refresh(GetCurrentView(),
245 if (EnableSelectedDevice(true, NeedsReboot
) &&
248 MessageBox(m_hMainWnd
, L
"Rebooting", L
"Enable", MB_OK
);
253 case IDC_DISABLE_DRV
:
256 EnableSelectedDevice(false, NeedsReboot
);
263 UpdateSelectedDevice(NeedsReboot
);
267 case IDC_UNINSTALL_DRV
:
269 UninstallSelectedDevice();
273 case IDC_ADD_HARDWARE
:
275 RunAddHardwareWizard();
284 CDeviceView::DisplayPropertySheet()
286 CNode
*Node
= GetSelectedNode();
287 if (Node
&& Node
->HasProperties())
289 DevicePropertiesExW(m_hTreeView
,
298 CDeviceView::SetFocus()
300 ::SetFocus(m_hTreeView
);
304 CDeviceView::CreateActionMenu(
305 _In_ HMENU OwnerMenu
,
309 CNode
*Node
= GetSelectedNode();
312 BuildActionMenuForNode(OwnerMenu
, Node
, MainMenu
);
320 CDeviceView::GetSelectedNode()
323 TvItem
.hItem
= TreeView_GetSelection(m_hTreeView
);
324 return GetNode(&TvItem
);
329 // PRIVATE METHODS *******************************************/
332 CDeviceView::AddRootDevice()
334 m_hTreeRoot
= InsertIntoTreeView(NULL
, m_RootNode
);
335 return (m_hTreeRoot
!= NULL
);
339 CDeviceView::GetNextClass(
340 _In_ ULONG ClassIndex
,
341 _Out_ LPGUID ClassGuid
,
342 _Out_ HDEVINFO
*hDevInfo
347 // Get the next class in the list
348 cr
= CM_Enumerate_Classes(ClassIndex
,
351 if (cr
!= CR_SUCCESS
)
354 // Check if this is the unknown class
355 if (IsEqualGUID(*ClassGuid
, GUID_DEVCLASS_UNKNOWN
))
357 // Get device info for all devices
358 *hDevInfo
= SetupDiGetClassDevsW(NULL
,
365 // We only want the devices for this class
366 *hDevInfo
= SetupDiGetClassDevsW(ClassGuid
,
372 return (hDevInfo
!= INVALID_HANDLE_VALUE
);
375 unsigned int __stdcall
CDeviceView::RefreshThread(void *Param
)
377 RefreshThreadData
*ThreadData
= (RefreshThreadData
*)Param
;
378 CDeviceView
*This
= ThreadData
->This
;
380 // Get a copy of the currently selected node
381 CNode
*LastSelectedNode
= This
->GetSelectedNode();
382 if (LastSelectedNode
== nullptr || (LastSelectedNode
->GetNodeType() == RootNode
))
384 LastSelectedNode
= new CRootNode(*This
->m_RootNode
);
386 else if (LastSelectedNode
->GetNodeType() == ClassNode
)
388 LastSelectedNode
= new CClassNode(*dynamic_cast<CClassNode
*>(LastSelectedNode
));
390 else if (LastSelectedNode
->GetNodeType() == DeviceNode
)
392 LastSelectedNode
= new CDeviceNode(*dynamic_cast<CDeviceNode
*>(LastSelectedNode
));
395 // Empty the treeview
396 This
->EmptyDeviceView();
398 // Re-add the root node to the tree
399 if (This
->AddRootDevice() == false)
402 // Refresh the devices only if requested
403 if (ThreadData
->ScanForChanges
)
405 This
->RefreshDeviceList();
408 // display the type of view the user wants
409 switch (This
->m_ViewType
)
412 (void)This
->ListDevicesByType();
415 case DevicesByConnection
:
416 (VOID
)This
->ListDevicesByConnection();
419 case ResourcesByType
:
422 case ResourcesByConnection
:
426 This
->SelectNode(LastSelectedNode
);
435 CDeviceView::ListDevicesByType()
437 CClassNode
*ClassNode
;
438 CDeviceNode
*DeviceNode
;
440 HTREEITEM hTreeItem
= NULL
;
443 BOOL bClassSuccess
, bSuccess
;
448 // Loop through all the device classes
449 bClassSuccess
= GetNextClass(ClassIndex
, &ClassGuid
, &hDevInfo
);
452 bool bClassUnknown
= false;
453 bool AddedParent
= false;
455 bool MoreItems
= false;
457 // Get the cached class node
458 ClassNode
= GetClassNode(&ClassGuid
);
459 if (ClassNode
== nullptr)
466 // Set a flag is this is the (special case) unknown class
467 if (IsEqualGUID(ClassGuid
, GUID_DEVCLASS_UNKNOWN
))
468 bClassUnknown
= true;
470 // Check if this is a hidden class
471 if (IsEqualGUID(ClassGuid
, GUID_DEVCLASS_LEGACYDRIVER
) ||
472 IsEqualGUID(ClassGuid
, GUID_DEVCLASS_VOLUME
))
474 // Ignore this device if we aren't displaying hidden devices
475 if (m_ShowHidden
== FALSE
)
484 // Get a handle to all the devices in this class
485 SP_DEVINFO_DATA DeviceInfoData
;
486 ZeroMemory(&DeviceInfoData
, sizeof(SP_DEVINFO_DATA
));
487 DeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
488 bSuccess
= SetupDiEnumDeviceInfo(hDevInfo
,
491 if (bSuccess
== FALSE
&& GetLastError() == ERROR_NO_MORE_ITEMS
)
498 // The unknown class handle contains all devices on the system,
499 // and we're just looking for the ones with a null GUID
502 if (IsEqualGUID(DeviceInfoData
.ClassGuid
, GUID_NULL
) == FALSE
)
504 // This is a known device, we aren't interested in it
510 // Get the cached device node
511 DeviceNode
= GetDeviceNode(DeviceInfoData
.DevInst
);
512 if (DeviceNode
== nullptr)
514 ATLASSERT(bClassUnknown
== true);
519 // Check if this is a hidden device
520 if (DeviceNode
->IsHidden())
522 // Ignore this device if we aren't displaying hidden devices
523 if (m_ShowHidden
== FALSE
)
530 // We have a device, we need to add the parent if it hasn't yet been added
531 if (AddedParent
== false)
533 // Insert the new class under the root item
534 hTreeItem
= InsertIntoTreeView(m_hTreeRoot
,
539 // Add the device under the class item node
540 (void)InsertIntoTreeView(hTreeItem
, DeviceNode
);
542 // Expand the class if it has a problem device
543 if (DeviceNode
->HasProblem())
545 (void)TreeView_Expand(m_hTreeView
,
555 // If this class has devices, sort them alphabetically
556 if (AddedParent
== true)
558 (void)TreeView_SortChildren(m_hTreeView
,
566 } while (bClassSuccess
);
568 // Sort the classes alphabetically
569 (void)TreeView_SortChildren(m_hTreeView
,
573 // Expand the root item
574 (void)TreeView_Expand(m_hTreeView
,
578 // Pre-select the root item
579 (VOID
)TreeView_SelectItem(m_hTreeView
,
586 CDeviceView::ListDevicesByConnection()
588 // Walk the device tree and add all the devices
589 (void)RecurseChildDevices(m_RootNode
->GetDeviceInst(), m_hTreeRoot
);
591 // Expand the root item
592 (void)TreeView_Expand(m_hTreeView
,
600 CDeviceView::RecurseChildDevices(
601 _In_ DEVINST ParentDevice
,
602 _In_ HTREEITEM hParentTreeItem
605 HTREEITEM hDevItem
= NULL
;
607 bool HasProblem
= false;
610 // Check if the parent has any child devices
611 if (GetChildDevice(ParentDevice
, &Device
) == FALSE
)
614 // Get the cached device node
615 CDeviceNode
*DeviceNode
;
616 DeviceNode
= dynamic_cast<CDeviceNode
*>(GetDeviceNode(Device
));
617 if (DeviceNode
== nullptr)
623 // Don't show hidden devices if not requested
624 if ((m_ShowHidden
== TRUE
) || (!(DeviceNode
->IsHidden())))
626 // Add this device to the tree under its parent
627 hDevItem
= InsertIntoTreeView(hParentTreeItem
,
631 // Check if this child has any children itself
632 if (!RecurseChildDevices(Device
, hDevItem
))
636 if (DeviceNode
->HasProblem())
643 // Check for siblings
646 // Check if the parent device has anything at the same level
647 bSuccess
= GetSiblingDevice(Device
, &Device
);
648 if (bSuccess
== FALSE
)
651 DeviceNode
= dynamic_cast<CDeviceNode
*>(GetDeviceNode(Device
));
652 if (DeviceNode
== nullptr)
657 // Don't show hidden devices if not requested
658 if ((m_ShowHidden
== TRUE
) || (!(DeviceNode
->IsHidden())))
660 if (DeviceNode
->HasProblem())
665 // Add this device to the tree under its parent
666 hDevItem
= InsertIntoTreeView(hParentTreeItem
,
670 // Check if this child has any children itself
671 if (!RecurseChildDevices(Device
, hDevItem
))
677 (void)TreeView_SortChildren(m_hTreeView
,
681 // Expand the class if it has a problem device
682 if (HasProblem
== true)
684 (void)TreeView_Expand(m_hTreeView
,
689 // If there was a problem, expand the ancestors
697 CDeviceView::EnableSelectedDevice(
699 _Out_
bool &NeedsReboot
702 CDeviceNode
*Node
= dynamic_cast<CDeviceNode
*>(GetSelectedNode());
709 if (str
.LoadStringW(g_hThisInstance
, IDS_CONFIRM_DISABLE
))
711 if (MessageBoxW(m_hMainWnd
,
713 Node
->GetDisplayName(),
714 MB_YESNO
| MB_ICONWARNING
| MB_DEFBUTTON2
) != IDYES
)
721 return Node
->EnableDevice(Enable
, NeedsReboot
);
725 CDeviceView::UpdateSelectedDevice(
726 _Out_
bool &NeedsReboot
729 CDeviceNode
*Node
= dynamic_cast<CDeviceNode
*>(GetSelectedNode());
734 if (InstallDevInst(m_hMainWnd
, Node
->GetDeviceId(), TRUE
, &dwReboot
))
744 CDeviceView::UninstallSelectedDevice(
747 CDeviceNode
*Node
= dynamic_cast<CDeviceNode
*>(GetSelectedNode());
752 if (str
.LoadStringW(g_hThisInstance
, IDS_CONFIRM_UNINSTALL
))
754 if (MessageBoxW(m_hMainWnd
,
756 Node
->GetDisplayName(),
757 MB_YESNO
| MB_ICONWARNING
| MB_DEFBUTTON2
) != IDYES
)
763 return Node
->UninstallDevice();
767 CDeviceView::RunAddHardwareWizard()
769 PADDHARDWAREWIZARD pAddHardwareWizard
;
772 hModule
= LoadLibraryW(L
"hdwwiz.cpl");
776 pAddHardwareWizard
= (PADDHARDWAREWIZARD
)GetProcAddress(hModule
,
777 "AddHardwareWizard");
778 if (pAddHardwareWizard
== NULL
)
780 FreeLibrary(hModule
);
784 pAddHardwareWizard(m_hMainWnd
, NULL
);
786 FreeLibrary(hModule
);
791 CDeviceView::GetChildDevice(
792 _In_ DEVINST ParentDevInst
,
793 _Out_ PDEVINST DevInst
797 cr
= CM_Get_Child(DevInst
,
800 return (cr
== CR_SUCCESS
);
804 CDeviceView::GetSiblingDevice(
805 _In_ DEVINST PrevDevice
,
806 _Out_ PDEVINST DevInst
810 cr
= CM_Get_Sibling(DevInst
,
813 return (cr
== CR_SUCCESS
);
817 CDeviceView::InsertIntoTreeView(
818 _In_opt_ HTREEITEM hParent
,
823 lpLabel
= Node
->GetDisplayName();
826 TV_INSERTSTRUCT tvins
;
827 ZeroMemory(&tvi
, sizeof(tvi
));
828 ZeroMemory(&tvins
, sizeof(tvins
));
830 tvi
.mask
= TVIF_TEXT
| TVIF_PARAM
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
831 tvi
.pszText
= lpLabel
;
832 tvi
.cchTextMax
= wcslen(lpLabel
);
833 tvi
.lParam
= (LPARAM
)Node
;
834 tvi
.iImage
= Node
->GetClassImage();
835 tvi
.iSelectedImage
= Node
->GetClassImage();
837 // try to cast it to a device node. This will only succeed if it's the correct type
838 CDeviceNode
*DeviceNode
= dynamic_cast<CDeviceNode
*>(Node
);
839 if (DeviceNode
&& DeviceNode
->GetOverlayImage())
841 tvi
.mask
|= TVIF_STATE
;
842 tvi
.stateMask
= TVIS_OVERLAYMASK
;
843 tvi
.state
= INDEXTOOVERLAYMASK(DeviceNode
->GetOverlayImage());
847 tvins
.hParent
= hParent
;
849 return TreeView_InsertItem(m_hTreeView
, &tvins
);
853 CDeviceView::BuildActionMenuForNode(
854 _In_ HMENU OwnerMenu
,
859 // Create a separator structure
860 MENUITEMINFOW MenuSeparator
= { 0 };
861 MenuSeparator
.cbSize
= sizeof(MENUITEMINFOW
);
862 MenuSeparator
.fType
= MFT_SEPARATOR
;
865 MENUITEMINFOW MenuItemInfo
= { 0 };
866 MenuItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
867 MenuItemInfo
.fMask
= MIIM_ID
| MIIM_STRING
| MIIM_DATA
| MIIM_SUBMENU
;
868 MenuItemInfo
.fType
= MFT_STRING
;
873 // Device nodes have extra data
874 if (Node
->GetNodeType() == DeviceNode
)
876 CDeviceNode
*DeviceNode
= dynamic_cast<CDeviceNode
*>(Node
);
878 if (DeviceNode
->CanUpdate())
880 String
.LoadStringW(g_hThisInstance
, IDS_MENU_UPDATE
);
881 MenuItemInfo
.wID
= IDC_UPDATE_DRV
;
882 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
883 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
887 if (DeviceNode
->IsDisabled())
889 String
.LoadStringW(g_hThisInstance
, IDS_MENU_ENABLE
);
890 MenuItemInfo
.wID
= IDC_ENABLE_DRV
;
891 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
892 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
896 if (DeviceNode
->CanDisable() && !DeviceNode
->IsDisabled())
898 String
.LoadStringW(g_hThisInstance
, IDS_MENU_DISABLE
);
899 MenuItemInfo
.wID
= IDC_DISABLE_DRV
;
900 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
901 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
905 if (DeviceNode
->CanUninstall())
907 String
.LoadStringW(g_hThisInstance
, IDS_MENU_UNINSTALL
);
908 MenuItemInfo
.wID
= IDC_UNINSTALL_DRV
;
909 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
910 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
914 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuSeparator
);
918 // All nodes have the scan option
919 String
.LoadStringW(g_hThisInstance
, IDS_MENU_SCAN
);
920 MenuItemInfo
.wID
= IDC_SCAN_HARDWARE
;
921 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
922 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
925 if ((Node
->GetNodeType() == RootNode
) || (MainMenu
== true))
927 String
.LoadStringW(g_hThisInstance
, IDS_MENU_ADD
);
928 MenuItemInfo
.wID
= IDC_ADD_HARDWARE
;
929 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
930 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
934 if (Node
->HasProperties())
936 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuSeparator
);
939 String
.LoadStringW(g_hThisInstance
, IDS_MENU_PROPERTIES
);
940 MenuItemInfo
.wID
= IDC_PROPERTIES
;
941 MenuItemInfo
.dwTypeData
= String
.GetBuffer();
942 InsertMenuItemW(OwnerMenu
, i
, TRUE
, &MenuItemInfo
);
945 SetMenuDefaultItem(OwnerMenu
, IDC_PROPERTIES
, FALSE
);
950 CDeviceView::RecurseFindDevice(
951 _In_ HTREEITEM hParentItem
,
960 // Check if this node has any children
961 hItem
= TreeView_GetChild(m_hTreeView
, hParentItem
);
965 // The lParam contains the node pointer data
966 tvItem
.hItem
= hItem
;
967 tvItem
.mask
= TVIF_PARAM
;
968 if (TreeView_GetItem(m_hTreeView
, &tvItem
) &&
969 tvItem
.lParam
!= NULL
)
971 // check for a matching node
972 FoundNode
= reinterpret_cast<CNode
*>(tvItem
.lParam
);
973 if ((FoundNode
->GetNodeType() == Node
->GetNodeType()) &&
974 (IsEqualGUID(*FoundNode
->GetClassGuid(), *Node
->GetClassGuid())))
976 // check if this is a class node, or a device with matching ID's
977 if ((FoundNode
->GetNodeType() == ClassNode
) ||
978 (wcscmp(FoundNode
->GetDeviceId(), Node
->GetDeviceId()) == 0))
985 // This node may have its own children
986 FoundItem
= RecurseFindDevice(hItem
, Node
);
990 // Loop all the siblings
993 // Get the next item at this level
994 hItem
= TreeView_GetNextSibling(m_hTreeView
, hItem
);
998 // The lParam contains the node pointer data
999 tvItem
.hItem
= hItem
;
1000 tvItem
.mask
= TVIF_PARAM
;
1001 if (TreeView_GetItem(m_hTreeView
, &tvItem
))
1003 // check for a matching class
1004 FoundNode
= reinterpret_cast<CNode
*>(tvItem
.lParam
);
1005 if ((FoundNode
->GetNodeType() == Node
->GetNodeType()) &&
1006 (IsEqualGUID(*FoundNode
->GetClassGuid(), *Node
->GetClassGuid())))
1008 // check if this is a class node, or a device with matching ID's
1009 if ((FoundNode
->GetNodeType() == ClassNode
) ||
1010 (wcscmp(FoundNode
->GetDeviceId(), Node
->GetDeviceId()) == 0))
1017 // This node may have its own children
1018 FoundItem
= RecurseFindDevice(hItem
, Node
);
1027 CDeviceView::SelectNode(
1031 HTREEITEM hRoot
, hItem
;
1033 // Check if there are any items in the tree
1034 hRoot
= TreeView_GetRoot(m_hTreeView
);
1038 // If we don't want to set select a node, just select root
1039 if (Node
== nullptr || Node
->GetNodeType() == RootNode
)
1041 TreeView_SelectItem(m_hTreeView
, hRoot
);
1045 // Scan the tree looking for the node we want
1046 hItem
= RecurseFindDevice(hRoot
, Node
);
1049 TreeView_SelectItem(m_hTreeView
, hItem
);
1053 TreeView_SelectItem(m_hTreeView
, hRoot
);
1059 CDeviceView::EmptyDeviceView()
1061 (VOID
)TreeView_DeleteAllItems(m_hTreeView
);
1066 CDeviceView::GetClassNode(
1067 _In_ LPGUID ClassGuid
1071 CClassNode
*Node
= nullptr;
1073 Pos
= m_ClassNodeList
.GetHeadPosition();
1079 Node
= m_ClassNodeList
.GetNext(Pos
);
1080 if (IsEqualGUID(*Node
->GetClassGuid(), *ClassGuid
))
1082 ATLASSERT(Node
->GetNodeType() == ClassNode
);
1088 } while (Pos
!= NULL
);
1094 CDeviceView::GetDeviceNode(
1099 CDeviceNode
*Node
= nullptr;
1101 Pos
= m_DeviceNodeList
.GetHeadPosition();
1107 Node
= m_DeviceNodeList
.GetNext(Pos
);
1108 if (Node
->GetDeviceInst() == Device
)
1110 ATLASSERT(Node
->GetNodeType() == DeviceNode
);
1116 } while (Pos
!= NULL
);
1121 CNode
* CDeviceView::GetNode(
1122 _In_ LPTV_ITEMW TvItem
1125 TvItem
->mask
= TVIF_PARAM
;
1126 if (TreeView_GetItem(m_hTreeView
, TvItem
))
1128 return (CNode
*)TvItem
->lParam
;
1134 CDeviceView::EmptyLists()
1138 while (!m_ClassNodeList
.IsEmpty())
1140 Node
= m_ClassNodeList
.RemoveTail();
1144 while (!m_DeviceNodeList
.IsEmpty())
1146 Node
= m_DeviceNodeList
.RemoveTail();
1152 CDeviceView::RefreshDeviceList()
1155 CClassNode
*ClassNode
;
1156 CDeviceNode
*DeviceNode
;
1158 SP_DEVINFO_DATA DeviceInfoData
;
1162 ULONG ClassIndex
= 0;
1166 if (m_RootNode
) delete m_RootNode
;
1167 m_RootNode
= new CRootNode(&m_ImageListData
);
1168 m_RootNode
->SetupNode();
1170 // Loop through all the classes
1173 Success
= GetNextClass(ClassIndex
, &ClassGuid
, &hDevInfo
);
1176 // Create a new class node and add it to the list
1177 ClassNode
= new CClassNode(&ClassGuid
, &m_ImageListData
);
1178 if (ClassNode
->SetupNode())
1180 m_ClassNodeList
.AddTail(ClassNode
);
1183 SetupDiDestroyDeviceInfoList(hDevInfo
);
1188 // Get all the devices on the local machine
1189 hDevInfo
= SetupDiGetClassDevsW(NULL
,
1192 DIGCF_PRESENT
| DIGCF_ALLCLASSES
);
1193 if (hDevInfo
== INVALID_HANDLE_VALUE
)
1198 // loop though all the devices
1199 DeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1202 // Get the devinst for this device
1203 Success
= SetupDiEnumDeviceInfo(hDevInfo
, i
, &DeviceInfoData
);
1204 if (Success
== FALSE
)
1207 // create a new device node and add it to the list
1208 DeviceNode
= new CDeviceNode(DeviceInfoData
.DevInst
, &m_ImageListData
);
1209 if (DeviceNode
->SetupNode())
1211 m_DeviceNodeList
.AddTail(DeviceNode
);
1219 SetupDiDestroyDeviceInfoList(hDevInfo
);