Author: ssawant
Date: Mon Aug 14 18:29:44 2017
New Revision: 75546
URL:
http://svn.reactos.org/svn/reactos?rev=75546&view=rev
Log:
[STOBJECT]
-Added Balloon notification for safely removal icon.
-Added familiar warning dialog when device ejection fails.
-Figured out that 'Problem number' of a device is perhaps an important enumeration
filter.
-Minor code cleanup and whitespace fixes.
-Test in win xpvm looks fine, but needs further testing.
Modified:
branches/GSoC_2017/shellext/reactos/dll/shellext/stobject/hotplug.cpp
Modified: branches/GSoC_2017/shellext/reactos/dll/shellext/stobject/hotplug.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2017/shellext/reactos/dll/…
==============================================================================
--- branches/GSoC_2017/shellext/reactos/dll/shellext/stobject/hotplug.cpp [iso-8859-1]
(original)
+++ branches/GSoC_2017/shellext/reactos/dll/shellext/stobject/hotplug.cpp [iso-8859-1] Mon
Aug 14 18:29:44 2017
@@ -24,8 +24,9 @@
static HDEVNOTIFY g_hDevNotify = NULL;
static HICON g_hIconHotplug = NULL;
static LPWSTR g_strTooltip = L"Safely Remove Hardware and Eject Media";
+static WCHAR g_strMenuSel[DISPLAY_NAME_LEN];
static BOOL g_IsRunning = FALSE;
-static BOOL g_IsRemoved = FALSE;
+static BOOL g_IsRemoving = FALSE;
// Enumerate the connected removable devices
// TODO: Require proper enumeration and filters.
@@ -40,12 +41,12 @@
for (int idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); idev++)
{
- DWORD dwCapabilities = 0, dwSize = sizeof(dwCapabilities);
+ DWORD dwCapabilities = 0, dwSize = sizeof(dwCapabilities);
WCHAR dispName[DISPLAY_NAME_LEN];
ULONG ulStatus = 0, ulPnum = 0, ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
CONFIGRET cr = CM_Get_DevNode_Status(&ulStatus, &ulPnum, did.DevInst,
0);
if (cr != CR_SUCCESS)
- continue;
+ continue;
cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_DEVICEDESC, NULL,
dispName, &ulLength, 0);
if (cr != CR_SUCCESS)
continue;
@@ -53,9 +54,9 @@
if (cr != CR_SUCCESS)
continue;
- if ((dwCapabilities & CM_DEVCAP_REMOVABLE) && (dwCapabilities &
CM_DEVCAP_UNIQUEID))
- {
- devList.Add(did.DevInst);
+ if ((dwCapabilities & CM_DEVCAP_REMOVABLE) && (dwCapabilities &
CM_DEVCAP_UNIQUEID) && !ulPnum)
+ {
+ devList.Add(did.DevInst);
}
}
SetupDiDestroyDeviceInfoList(hdev);
@@ -66,6 +67,31 @@
}
return S_OK;
+}
+
+// Pops a balloon notification
+HRESULT NotifyBalloon(CSysTray* pSysTray, LPCWSTR szTitle = NULL, LPCWSTR szInfo = NULL,
UINT uId = ID_ICON_HOTPLUG)
+{
+ NOTIFYICONDATA nim = { 0 };
+ nim.cbSize = sizeof(NOTIFYICONDATA);
+ nim.uID = uId;
+ nim.hWnd = pSysTray->GetHWnd();
+
+ nim.uFlags = NIF_INFO;
+ nim.uTimeout = 10;
+ nim.dwInfoFlags = NIIF_INFO;
+
+ StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), szTitle);
+ StringCchCopy(nim.szInfo, _countof(nim.szInfo), szInfo);
+ BOOL ret = Shell_NotifyIcon(NIM_MODIFY, &nim);
+
+ Sleep(8000);
+ StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), L"");
+ StringCchCopy(nim.szInfo, _countof(nim.szInfo), L"");
+ ret = Shell_NotifyIcon(NIM_MODIFY, &nim);
+ g_IsRemoving = FALSE;
+
+ return ret ? S_OK : E_FAIL;
}
HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray)
@@ -73,16 +99,16 @@
TRACE("Hotplug_Init\n");
g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_HOTPLUG_OK));
g_IsRunning = TRUE;
- EnumHotpluggedDevices(g_devList);
+ EnumHotpluggedDevices(g_devList);
return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_HOTPLUG, g_hIconHotplug,
g_strTooltip, NIS_HIDDEN);
}
HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray)
{
- TRACE("Hotplug_Update\n");
-
- if(g_devList.GetSize())
+ TRACE("Hotplug_Update\n");
+
+ if(g_devList.GetSize() || g_IsRemoving)
return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug,
g_strTooltip);
else
return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug,
g_strTooltip, NIS_HIDDEN);
@@ -104,18 +130,18 @@
static void _ShowContextMenu(CSysTray * pSysTray)
{
HMENU hPopup = CreatePopupMenu();
-
+ ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
+
for (UINT index = 0; index < g_devList.GetSize(); index++)
{
WCHAR dispName[DISPLAY_NAME_LEN], menuName[DISPLAY_NAME_LEN + 10];
- ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[index],
CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0);
if (cr != CR_SUCCESS)
StrCpyW(dispName, L"Unknown Device");
swprintf(menuName, L"Eject %wS", dispName);
AppendMenuW(hPopup, MF_STRING, index+1, menuName);
- }
+ }
SetForegroundWindow(pSysTray->GetHWnd());
DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
@@ -128,15 +154,25 @@
if (id > 0)
{
- id--; // since array indices starts from zero.
- CONFIGRET cr = CM_Request_Device_Eject_Ex(g_devList[id], 0, 0, 0, 0, 0);
- if (cr != CR_SUCCESS)
- MessageBox(0, L"Device ejection failed!! Please try again after closing
any open programs on device!", L"Safely Remove Hardware", MB_OKCANCEL |
MB_ICONEXCLAMATION);
- else
+ id--; // since array indices starts from zero.
+ CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[id], CM_DRP_DEVICEDESC,
NULL, g_strMenuSel, &ulLength, 0);
+ if (cr != CR_SUCCESS)
+ StrCpyW(g_strMenuSel, L"Unknown Device");
+
+ cr = CM_Request_Device_Eject_Ex(g_devList[id], 0, 0, 0, 0, 0);
+ if (cr != CR_SUCCESS)
{
- MessageBox(0, L"Device ejected successfully!! You can safely remove the
device now!", L"Safely Remove Hardware", MB_OKCANCEL |
MB_ICONINFORMATION);
- g_devList.RemoveAt(id);
+ WCHAR strInfo[128];
+ swprintf(strInfo, L"Problem Ejecting %wS", g_strMenuSel);
+ MessageBox(0, L"The device cannot be stopped right now! Try stopping it
again later!", strInfo, MB_OKCANCEL | MB_ICONEXCLAMATION);
}
+ else //TODO
+ {
+ //MessageBox(0, L"Device ejected successfully!! You can safely remove
the device now!", L"Safely Remove Hardware", MB_OKCANCEL |
MB_ICONINFORMATION);
+ g_IsRemoving = TRUE;
+ g_devList.RemoveAt(id); // thing is.. even after removing id at this point,
the devnode_change occurs after some seconds of sucessful removal
+ // and since pendrive is still plugged in it gets
enumerated, if problem number is not filtered.
+ }
}
DestroyMenu(hPopup);
@@ -145,8 +181,8 @@
static void _ShowContextMenuR(CSysTray * pSysTray)
{
CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2);
- HMENU hPopup = CreatePopupMenu();
- AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu);
+ HMENU hPopup = CreatePopupMenu();
+ AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu);
SetForegroundWindow(pSysTray->GetHWnd());
DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
@@ -167,7 +203,8 @@
HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM
wParam, LPARAM lParam, LRESULT &lResult)
{
- TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam,
lParam);
+ HRESULT hr = E_FAIL;
+ TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam,
lParam);
switch (uMsg)
{
@@ -177,7 +214,7 @@
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
- NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
g_hDevNotify = RegisterDeviceNotification(pSysTray->GetHWnd(),
&NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE |
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
if (g_hDevNotify != NULL)
@@ -227,7 +264,7 @@
break;
case WM_RBUTTONUP:
- _ShowContextMenuR(pSysTray);
+ _ShowContextMenuR(pSysTray);
break;
case WM_RBUTTONDBLCLK:
@@ -238,16 +275,32 @@
}
return S_OK;
- case WM_DEVICECHANGE:
+ case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVNODES_CHANGED:
- HRESULT hr = EnumHotpluggedDevices(g_devList);
+ hr = EnumHotpluggedDevices(g_devList);
if (FAILED(hr))
return hr;
- }
-
- lResult = true;
+
+ lResult = true;
+ break;
+ case DBT_DEVICEARRIVAL:
+ break;
+ case DBT_DEVICEQUERYREMOVE:
+ break;
+ case DBT_DEVICEQUERYREMOVEFAILED:
+ break;
+ case DBT_DEVICEREMOVECOMPLETE:
+ WCHAR strInfo[128];
+ swprintf(strInfo, L"The %wS can now be safely removed from the
system.", g_strMenuSel);
+ NotifyBalloon(pSysTray, L"Safe to Remove Hardware",
strInfo);
+
+ lResult = true;
+ break;
+ case DBT_DEVICEREMOVEPENDING:
+ break;
+ }
return S_OK;
/*case WM_CLOSE:
@@ -255,7 +308,7 @@
{
return S_FALSE;
}
- return S_OK;*/
+ return S_OK;*/
default:
TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n");