ReactOS 0.4.15-dev-7842-g558ab78
enum.c
Go to the documentation of this file.
1/*
2 * PROJECT: Safely Remove Hardware Applet
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Device enumeration
5 * COPYRIGHT: Copyright 2020 Eric Kohl <eric.kohl@reactos.org>
6 * Copyright 2023 Thamatip Chitpong <thamatip.chitpong@reactos.org>
7 */
8
9#include "hotplug.h"
10
11#include <initguid.h>
12#include <devguid.h>
13
14#define MAX_DEVICE_DISPLAYNAME_LEN 256
15
16static
17VOID
19 _In_ DEVINST DevInst,
20 _In_ PHOTPLUG_DATA pHotplugData,
21 _Out_writes_z_(cchDesc) LPWSTR pszDesc,
22 _In_ ULONG cchDesc,
23 _Out_ PINT pImageIndex)
24{
25 WCHAR szGuidString[MAX_GUID_STRING_LEN];
26 GUID ClassGuid;
27 ULONG ulSize;
28 CONFIGRET cr;
29
30 /* Get the device description */
31 ulSize = cchDesc * sizeof(WCHAR);
34 NULL,
35 pszDesc,
36 &ulSize,
37 0);
38 if (cr != CR_SUCCESS)
39 {
40 ulSize = cchDesc * sizeof(WCHAR);
43 NULL,
44 pszDesc,
45 &ulSize,
46 0);
47 if (cr != CR_SUCCESS)
48 LoadStringW(hApplet, IDS_UNKNOWN_DEVICE, pszDesc, cchDesc);
49 }
50
51 /* Get the class GUID */
52 ulSize = sizeof(szGuidString);
55 NULL,
56 szGuidString,
57 &ulSize,
58 0);
59 if (cr == CR_SUCCESS)
60 {
61 pSetupGuidFromString(szGuidString, &ClassGuid);
62 }
63 else
64 {
65 ClassGuid = GUID_DEVCLASS_UNKNOWN;
66 }
67
68 /* Get the image for the class this device is in */
69 SetupDiGetClassImageIndex(&pHotplugData->ImageListData,
70 &ClassGuid,
71 pImageIndex);
72}
73
74static
77 _In_ HTREEITEM hParent,
78 _In_ DEVINST DevInst,
79 _In_ PHOTPLUG_DATA pHotplugData)
80{
81 WCHAR szDisplayName[MAX_DEVICE_DISPLAYNAME_LEN];
82 INT nClassImage;
83 TVINSERTSTRUCTW tvItem;
84
86 pHotplugData,
87 szDisplayName,
88 ARRAYSIZE(szDisplayName),
89 &nClassImage);
90
91 ZeroMemory(&tvItem, sizeof(tvItem));
92 tvItem.hParent = hParent;
93 tvItem.hInsertAfter = TVI_LAST;
94
96 tvItem.item.state = TVIS_EXPANDED;
97 tvItem.item.stateMask = TVIS_EXPANDED;
98 tvItem.item.pszText = szDisplayName;
99 tvItem.item.iImage = nClassImage;
100 tvItem.item.iSelectedImage = nClassImage;
101 tvItem.item.lParam = (LPARAM)DevInst;
102
103 return TreeView_InsertItem(pHotplugData->hwndDeviceTree, &tvItem);
104}
105
106static
107VOID
109 _In_ HTREEITEM hParentItem,
110 _In_ DEVINST ParentDevInst,
111 _In_ PHOTPLUG_DATA pHotplugData)
112{
113 HTREEITEM hTreeItem;
114 DEVINST ChildDevInst;
115 CONFIGRET cr;
116
117 cr = CM_Get_Child(&ChildDevInst, ParentDevInst, 0);
118 if (cr != CR_SUCCESS)
119 return;
120
121 hTreeItem = InsertDeviceTreeItem(hParentItem,
122 ChildDevInst,
123 pHotplugData);
124 if (hTreeItem != NULL)
125 {
127 ChildDevInst,
128 pHotplugData);
129 }
130
131 for (;;)
132 {
133 cr = CM_Get_Sibling(&ChildDevInst, ChildDevInst, 0);
134 if (cr != CR_SUCCESS)
135 return;
136
137 hTreeItem = InsertDeviceTreeItem(hParentItem,
138 ChildDevInst,
139 pHotplugData);
140 if (hTreeItem != NULL)
141 {
143 ChildDevInst,
144 pHotplugData);
145 }
146 }
147}
148
149VOID
151 _In_ PHOTPLUG_DATA pHotplugData)
152{
153 SP_DEVINFO_DATA did = { 0 };
155 int idev;
156 DWORD dwCapabilities, dwSize;
157 ULONG ulStatus, ulProblem;
158 HTREEITEM hTreeItem;
159 CONFIGRET cr;
160
161 TreeView_DeleteAllItems(pHotplugData->hwndDeviceTree);
162
165 return;
166
167 did.cbSize = sizeof(did);
168
169 /* Enumerate all the attached devices */
170 for (idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); idev++)
171 {
172 ulStatus = 0;
173 ulProblem = 0;
174
175 cr = CM_Get_DevNode_Status(&ulStatus,
176 &ulProblem,
177 did.DevInst,
178 0);
179 if (cr != CR_SUCCESS)
180 continue;
181
182 dwCapabilities = 0,
183 dwSize = sizeof(dwCapabilities);
186 NULL,
187 &dwCapabilities,
188 &dwSize,
189 0);
190 if (cr != CR_SUCCESS)
191 continue;
192
193 /* Add devices that require safe removal to the device tree */
194 if ( (dwCapabilities & CM_DEVCAP_REMOVABLE) &&
195 !(dwCapabilities & CM_DEVCAP_DOCKDEVICE) &&
196 !(dwCapabilities & CM_DEVCAP_SURPRISEREMOVALOK) &&
197 ((dwCapabilities & CM_DEVCAP_EJECTSUPPORTED) || (ulStatus & DN_DISABLEABLE)) &&
198 ulProblem == 0)
199 {
200 hTreeItem = InsertDeviceTreeItem(TVI_ROOT,
201 did.DevInst,
202 pHotplugData);
203
204 if ((hTreeItem != NULL) && (pHotplugData->dwFlags & HOTPLUG_DISPLAY_DEVICE_COMPONENTS))
205 {
207 did.DevInst,
208 pHotplugData);
209 }
210 }
211 }
212
214}
215
216static
217VOID
219 _In_ HWND hwndCfmDeviceList,
220 _In_ DEVINST DevInst,
221 _In_ PHOTPLUG_DATA pHotplugData)
222{
223 WCHAR szDisplayName[MAX_DEVICE_DISPLAYNAME_LEN];
224 INT nClassImage;
225 LVITEMW lvItem;
226
227 GetDeviceDisplayInfo(DevInst,
228 pHotplugData,
229 szDisplayName,
230 ARRAYSIZE(szDisplayName),
231 &nClassImage);
232
233 ZeroMemory(&lvItem, sizeof(lvItem));
234 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
235 lvItem.iItem = ListView_GetItemCount(hwndCfmDeviceList);
236 lvItem.pszText = szDisplayName;
237 lvItem.iImage = nClassImage;
238 lvItem.lParam = (LPARAM)DevInst;
239
240 ListView_InsertItem(hwndCfmDeviceList, &lvItem);
241}
242
243static
244VOID
246 _In_ HWND hwndCfmDeviceList,
247 _In_ DEVINST ParentDevInst,
248 _In_ PHOTPLUG_DATA pHotplugData)
249{
250 DEVINST ChildDevInst;
251 CONFIGRET cr;
252
253 cr = CM_Get_Child(&ChildDevInst, ParentDevInst, 0);
254 if (cr != CR_SUCCESS)
255 return;
256
257 InsertConfirmDeviceListItem(hwndCfmDeviceList, ChildDevInst, pHotplugData);
258 CfmListRecursiveInsertSubDevices(hwndCfmDeviceList, ChildDevInst, pHotplugData);
259
260 for (;;)
261 {
262 cr = CM_Get_Sibling(&ChildDevInst, ChildDevInst, 0);
263 if (cr != CR_SUCCESS)
264 return;
265
266 InsertConfirmDeviceListItem(hwndCfmDeviceList, ChildDevInst, pHotplugData);
267 CfmListRecursiveInsertSubDevices(hwndCfmDeviceList, ChildDevInst, pHotplugData);
268 }
269}
270
271VOID
273 _In_ HWND hwndCfmDeviceList,
274 _In_ PHOTPLUG_DATA pHotplugData)
275{
276 DEVINST DevInst;
277
278 DevInst = GetDeviceInstForRemoval(pHotplugData);
279 if (DevInst != 0)
280 {
281 InsertConfirmDeviceListItem(hwndCfmDeviceList, DevInst, pHotplugData);
282 CfmListRecursiveInsertSubDevices(hwndCfmDeviceList, DevInst, pHotplugData);
283 }
284}
#define DN_DISABLEABLE
Definition: cfg.h:131
#define CM_DEVCAP_EJECTSUPPORTED
Definition: cfgmgr32.h:736
#define CM_DRP_CAPABILITIES
Definition: cfgmgr32.h:691
#define CM_DRP_CLASSGUID
Definition: cfgmgr32.h:684
#define CM_DRP_DEVICEDESC
Definition: cfgmgr32.h:676
DWORD DEVINST
Definition: cfgmgr32.h:76
#define CM_Get_DevNode_Registry_Property
Definition: cfgmgr32.h:1733
#define CM_DEVCAP_SURPRISEREMOVALOK
Definition: cfgmgr32.h:742
#define CM_DRP_FRIENDLYNAME
Definition: cfgmgr32.h:688
#define CM_DEVCAP_DOCKDEVICE
Definition: cfgmgr32.h:738
#define CM_DEVCAP_REMOVABLE
Definition: cfgmgr32.h:737
RETURN_TYPE CONFIGRET
Definition: cfgmgr32.h:74
#define CR_SUCCESS
Definition: cfgmgr32.h:842
CONFIGRET WINAPI CM_Get_DevNode_Status(_Out_ PULONG pulStatus, _Out_ PULONG pulProblemNumber, _In_ DEVINST dnDevInst, _In_ ULONG ulFlags)
Definition: cfgmgr.c:3572
CONFIGRET WINAPI CM_Get_Child(_Out_ PDEVINST pdnDevInst, _In_ DEVINST dnDevInst, _In_ ULONG ulFlags)
Definition: cfgmgr.c:2530
CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyW(_In_ DEVINST dnDevInst, _In_ ULONG ulProperty, _Out_opt_ PULONG pulRegDataType, _Out_writes_bytes_opt_(*pulLength) PVOID Buffer, _Inout_ PULONG pulLength, _In_ ULONG ulFlags)
Definition: cfgmgr.c:3378
CONFIGRET WINAPI CM_Get_Sibling(_Out_ PDEVINST pdnDevInst, _In_ DEVINST dnDevInst, _In_ ULONG ulFlags)
Definition: cfgmgr.c:5529
#define NULL
Definition: types.h:112
#define MAX_GUID_STRING_LEN
Definition: apphelp.c:29
HINSTANCE hApplet
Definition: access.c:17
static VOID GetDeviceDisplayInfo(_In_ DEVINST DevInst, _In_ PHOTPLUG_DATA pHotplugData, _Out_writes_z_(cchDesc) LPWSTR pszDesc, _In_ ULONG cchDesc, _Out_ PINT pImageIndex)
Definition: enum.c:18
VOID EnumHotpluggedDevices(_In_ PHOTPLUG_DATA pHotplugData)
Definition: enum.c:150
static VOID InsertConfirmDeviceListItem(_In_ HWND hwndCfmDeviceList, _In_ DEVINST DevInst, _In_ PHOTPLUG_DATA pHotplugData)
Definition: enum.c:218
static VOID CfmListRecursiveInsertSubDevices(_In_ HWND hwndCfmDeviceList, _In_ DEVINST ParentDevInst, _In_ PHOTPLUG_DATA pHotplugData)
Definition: enum.c:245
#define MAX_DEVICE_DISPLAYNAME_LEN
Definition: enum.c:14
static HTREEITEM InsertDeviceTreeItem(_In_ HTREEITEM hParent, _In_ DEVINST DevInst, _In_ PHOTPLUG_DATA pHotplugData)
Definition: enum.c:76
VOID CfmListEnumDevices(_In_ HWND hwndCfmDeviceList, _In_ PHOTPLUG_DATA pHotplugData)
Definition: enum.c:272
static VOID DevTreeRecursiveInsertSubDevices(_In_ HTREEITEM hParentItem, _In_ DEVINST ParentDevInst, _In_ PHOTPLUG_DATA pHotplugData)
Definition: enum.c:108
#define IDS_UNKNOWN_DEVICE
Definition: resource.h:28
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI pSetupGuidFromString(PCWSTR pString, LPGUID lpGUID)
Definition: misc.c:1751
BOOL WINAPI SetupDiGetClassImageIndex(IN PSP_CLASSIMAGELIST_DATA ClassImageListData, IN CONST GUID *ClassGuid, OUT PINT ImageIndex)
Definition: devclass.c:277
BOOL WINAPI SetupDiEnumDeviceInfo(HDEVINFO devinfo, DWORD index, PSP_DEVINFO_DATA info)
Definition: devinst.c:1787
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
Definition: devinst.c:2893
DEVINST GetDeviceInstForRemoval(_In_ PHOTPLUG_DATA pHotplugData)
Definition: eject.c:13
unsigned long DWORD
Definition: ntddk_ex.h:95
#define HOTPLUG_DISPLAY_DEVICE_COMPONENTS
Definition: hotplug.h:24
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define _Out_writes_z_(size)
Definition: ms_sal.h:352
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define ListView_InsertItem(hwnd, pitem)
Definition: commctrl.h:2408
#define TVI_LAST
Definition: commctrl.h:3370
#define TreeView_DeleteAllItems(hwnd)
Definition: commctrl.h:3417
#define TVIF_TEXT
Definition: commctrl.h:3266
#define TVIF_IMAGE
Definition: commctrl.h:3267
#define ListView_GetItemCount(hwnd)
Definition: commctrl.h:2307
#define TVI_ROOT
Definition: commctrl.h:3368
#define LVIF_PARAM
Definition: commctrl.h:2311
#define LVIF_TEXT
Definition: commctrl.h:2309
#define TVIS_EXPANDED
Definition: commctrl.h:3284
#define LVIF_IMAGE
Definition: commctrl.h:2310
#define TVIF_PARAM
Definition: commctrl.h:3268
#define TreeView_InsertItem(hwnd, lpis)
Definition: commctrl.h:3412
#define TVIF_SELECTEDIMAGE
Definition: commctrl.h:3271
#define TVIF_STATE
Definition: commctrl.h:3269
#define DIGCF_ALLCLASSES
Definition: setupapi.h:172
#define SetupDiGetClassDevs
Definition: setupapi.h:2593
#define DIGCF_PRESENT
Definition: setupapi.h:171
LPWSTR pszText
Definition: commctrl.h:2365
UINT mask
Definition: commctrl.h:2360
LPARAM lParam
Definition: commctrl.h:2368
int iImage
Definition: commctrl.h:2367
HTREEITEM hParent
Definition: commctrl.h:3393
HTREEITEM hInsertAfter
Definition: commctrl.h:3394
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define ZeroMemory
Definition: winbase.h:1712
_In_ HDEV hdev
Definition: winddi.h:3449
LONG_PTR LPARAM
Definition: windef.h:208
int * PINT
Definition: windef.h:177
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184