[STOBJECT]

-Added new battery icons and hotplug icons, thanks to Pi_User5.
-Modified resources for the same.
-Modified CSysTray to support icon hiding feature.
-Modified hotplug.cpp by adding experimental enumeration to test icon behavior.
-Icon behavior successfully tested.
-Added code to eject device, works fine.
-Fixed a bug which didn't showed attached devices after reloading. (like after system restart or explorer restart.)
-Now at least pen-drives are safely removable. (Still experimental though, use at your own risk ;P)
-Tested in winxp vm, needs further testing.

svn path=/branches/GSoC_2017/shellext/; revision=75497
This commit is contained in:
Shriraj Sawant 2017-08-06 16:33:27 +00:00
parent b421d735af
commit 93a5cfc0ef
19 changed files with 176 additions and 38 deletions

View file

@ -4,6 +4,7 @@
* FILE: dll/shellext/stobject/csystray.cpp
* PURPOSE: Systray shell service object implementation
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
* Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
*/
#include "precomp.h"
@ -97,7 +98,7 @@ HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, LR
return S_FALSE;
}
HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip)
HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip, DWORD dwstate)
{
NOTIFYICONDATA nim = { 0 };
@ -108,8 +109,8 @@ HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip)
nim.hIcon = hIcon;
nim.uID = uId;
nim.uCallbackMessage = uId;
nim.dwState = 0;
nim.dwStateMask = 0;
nim.dwState = dwstate;
nim.dwStateMask = NIS_HIDDEN;
nim.hWnd = m_hWnd;
nim.uVersion = NOTIFYICON_VERSION;
if (szTip)

View file

@ -5,6 +5,7 @@
* PURPOSE: Systray shell service object
* PROGRAMMERS: Robert Naumann
* David Quintana <gigaherz@gmail.com>
* Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
*/
#pragma once
@ -43,7 +44,7 @@ class CSysTray :
HRESULT ShutdownNetShell();
public:
HRESULT NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip);
HRESULT NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip, DWORD dwstate = 0);
HWND GetHWnd() { return m_hWnd; }

View file

@ -5,33 +5,87 @@
* PURPOSE: Removable devices notification icon handler
* PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
*/
#include <windows.h>
#include "precomp.h"
#include <mmsystem.h>
#include <mmddk.h>
#include <atlstr.h>
#include <atlsimpcoll.h>
#include <dbt.h>
#include <setupapi.h>
#include <cfgmgr32.h>
WINE_DEFAULT_DEBUG_CHANNEL(stobject);
#define DISPLAY_NAME_LEN 40
//BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY Handle);
CSimpleArray<DEVINST> g_devList;
static HDEVNOTIFY g_hDevNotify = NULL;
static HICON g_hIconHotplug = NULL;
static LPWSTR g_strTooltip = L"Safely Remove Hardware and Eject Media";
static BOOL g_IsRunning = FALSE;
static BOOL g_IsRemoved = FALSE;
// Enumerate the connected removable devices
// TODO: Require proper enumeration and filters.
HRESULT EnumHotpluggedDevices(CSimpleArray<DEVINST> &devList)
{
devList.RemoveAll(); // Clear current devList
HDEVINFO hdev = SetupDiGetClassDevs(NULL, NULL, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE == hdev)
return E_HANDLE;
SP_DEVINFO_DATA did = { 0 };
did.cbSize = sizeof(did);
for (int idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); idev++)
{
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;
cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0);
if (cr != CR_SUCCESS)
continue;
cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_CAPABILITIES, NULL, &dwCapabilities, &dwSize, 0);
if (cr != CR_SUCCESS)
continue;
if ((dwCapabilities & CM_DEVCAP_REMOVABLE) && (dwCapabilities & CM_DEVCAP_UNIQUEID))
{
devList.Add(did.DevInst);
}
}
SetupDiDestroyDeviceInfoList(hdev);
if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError())
{
return E_UNEXPECTED;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray)
{
TRACE("Hotplug_Init\n");
g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_EXTRACT));
g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_HOTPLUG_OK));
g_IsRunning = TRUE;
EnumHotpluggedDevices(g_devList);
return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip);
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");
//g_hIconHotplug = DynamicLoadIcon(g_hInstance);
return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip);
if(g_devList.GetSize())
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);
}
HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray)
@ -42,16 +96,26 @@ HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray)
return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_HOTPLUG, NULL, NULL);
}
static void _RunHotplug()
static void _RunHotplug(CSysTray * pSysTray)
{
ShellExecuteW(NULL, NULL, L"hotplug.cpl", NULL, NULL, SW_SHOWNORMAL);
ShellExecuteW(pSysTray->GetHWnd(), L"open", L"rundll32.exe shell32.dll,Control_RunDLL hotplug.dll", NULL, NULL, SW_SHOWNORMAL);
}
static void _ShowContextMenu(CSysTray * pSysTray)
{
CString strOpen((LPCSTR)IDS_HOTPLUG_REMOVE_2);
HMENU hPopup = CreatePopupMenu();
AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strOpen);
{
HMENU hPopup = CreatePopupMenu();
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;
@ -60,23 +124,69 @@ static void _ShowContextMenu(CSysTray * pSysTray)
DWORD id = TrackPopupMenuEx(hPopup, flags,
pt.x, pt.y,
pSysTray->GetHWnd(), NULL);
switch (id)
pSysTray->GetHWnd(), NULL);
if (id > 0)
{
case IDS_HOTPLUG_REMOVE_2:
_RunHotplug();
break;
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
{
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);
}
}
DestroyMenu(hPopup);
}
static void _ShowContextMenuR(CSysTray * pSysTray)
{
CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2);
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;
POINT pt;
GetCursorPos(&pt);
DWORD id = TrackPopupMenuEx(hPopup, flags,
pt.x, pt.y,
pSysTray->GetHWnd(), NULL);
if (id == IDS_HOTPLUG_REMOVE_2)
{
_RunHotplug(pSysTray);
}
DestroyMenu(hPopup);
}
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);
TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam, lParam);
switch (uMsg)
{
/*case WM_CREATE:
TRACE("Hotplug_Message: WM_CREATE\n");
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_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)
{
lResult = true;
return S_OK;
}
return S_FALSE;*/
case WM_USER + 220:
TRACE("Hotplug_Message: WM_USER+220\n");
if (wParam == 1)
@ -106,18 +216,18 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, W
break;
case WM_LBUTTONUP:
MessageBox(0, L"Safely Remove Hardware", L"Test", MB_OKCANCEL | MB_ICONINFORMATION);
_ShowContextMenu(pSysTray);
break;
case WM_LBUTTONDBLCLK:
_RunHotplug();
_RunHotplug(pSysTray);
break;
case WM_RBUTTONDOWN:
break;
case WM_RBUTTONUP:
_ShowContextMenu(pSysTray);
_ShowContextMenuR(pSysTray);
break;
case WM_RBUTTONDBLCLK:
@ -128,6 +238,25 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, W
}
return S_OK;
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVNODES_CHANGED:
HRESULT hr = EnumHotpluggedDevices(g_devList);
if (FAILED(hr))
return hr;
}
lResult = true;
return S_OK;
/*case WM_CLOSE:
if (!UnregisterDeviceNotification(hDeviceNotify))
{
return S_FALSE;
}
return S_OK;*/
default:
TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n");
return S_FALSE;

View file

@ -39,17 +39,20 @@
#define IDS_KEYS_MOUSE 331
#define IDS_KEYS_FILTER 332
#define IDI_BATTCAP0 400
#define IDI_BATTCAP1 401
#define IDI_BATTCAP2 402
#define IDI_BATTCAP3 403
#define IDI_BATTCAP4 404
#define IDI_BATTCAP5 405
#define IDI_BATTCHA0 406
#define IDI_BATTCHA1 407
#define IDI_BATTCHA2 408
#define IDI_BATTCHA3 409
#define IDI_BATTCHA4 410
#define IDI_BATTCAP_ERR 412
#define IDI_BATTCAP0 400
#define IDI_BATTCAP1 401
#define IDI_BATTCAP2 402
#define IDI_BATTCAP3 403
#define IDI_BATTCAP4 404
#define IDI_BATTCAP5 405
#define IDI_BATTCHA0 406
#define IDI_BATTCHA1 407
#define IDI_BATTCHA2 408
#define IDI_BATTCHA3 409
#define IDI_BATTCHA4 410
#define IDI_BATTCAP_ERR 412
#define IDI_HOTPLUG_ERR 420
#define IDI_HOTPLUG_OK 421
#define IDR_SYSTRAY 11001

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -26,6 +26,10 @@ IDI_BATTCHA4 ICON "resources/battery/charging4.ico"
IDI_BATTCAP_ERR ICON "resources/battery/error.ico"
IDI_HOTPLUG_ERR ICON "resources/hotplug/0.ico"
IDI_HOTPLUG_OK ICON "resources/hotplug/1.ico"
IDR_SYSTRAY REGISTRY "resources/rgs/systray.rgs"
#include <reactos/manifest_dll.rc>