https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7fbc5f42302be64db4d33…
commit 7fbc5f42302be64db4d3383060e3c14bcc1dfac6
Author: Shriraj Sawant <sr.official(a)hotmail.com>
AuthorDate: Mon Oct 16 17:11:10 2017 +0300
[STOBJECT] Implement the hotplug and the power icons in the system tray
---
dll/shellext/stobject/CMakeLists.txt | 4 +
dll/shellext/stobject/csystray.cpp | 53 ++--
dll/shellext/stobject/csystray.h | 3 +-
dll/shellext/stobject/hotplug.cpp | 315 ++++++++++++++++-----
dll/shellext/stobject/lang/cs-CZ.rc | 4 +-
dll/shellext/stobject/lang/de-DE.rc | 4 +-
dll/shellext/stobject/lang/en-US.rc | 4 +-
dll/shellext/stobject/lang/es-ES.rc | 4 +-
dll/shellext/stobject/lang/fr-FR.rc | 4 +-
dll/shellext/stobject/lang/it-IT.rc | 4 +-
dll/shellext/stobject/lang/pl-PL.rc | 4 +-
dll/shellext/stobject/lang/ro-RO.rc | 4 +-
dll/shellext/stobject/lang/ru-RU.rc | 4 +-
dll/shellext/stobject/lang/zh-CN.rc | 4 +-
dll/shellext/stobject/lang/zh-TW.rc | 4 +-
dll/shellext/stobject/power.cpp | 301 ++++++++++++++++----
dll/shellext/stobject/precomp.h | 3 -
dll/shellext/stobject/resource.h | 16 ++
dll/shellext/stobject/resources/battery/0.ico | Bin 0 -> 9062 bytes
dll/shellext/stobject/resources/battery/1.ico | Bin 0 -> 9062 bytes
dll/shellext/stobject/resources/battery/2.ico | Bin 0 -> 9062 bytes
dll/shellext/stobject/resources/battery/3.ico | Bin 0 -> 9062 bytes
dll/shellext/stobject/resources/battery/4.ico | Bin 0 -> 9062 bytes
dll/shellext/stobject/resources/battery/5.ico | Bin 0 -> 9062 bytes
.../stobject/resources/battery/charging0.ico | Bin 0 -> 2550 bytes
.../stobject/resources/battery/charging1.ico | Bin 0 -> 2550 bytes
.../stobject/resources/battery/charging2.ico | Bin 0 -> 2550 bytes
.../stobject/resources/battery/charging3.ico | Bin 0 -> 2550 bytes
.../stobject/resources/battery/charging4.ico | Bin 0 -> 2550 bytes
dll/shellext/stobject/resources/battery/error.ico | Bin 0 -> 9062 bytes
dll/shellext/stobject/resources/hotplug/0.ico | Bin 0 -> 2550 bytes
dll/shellext/stobject/resources/hotplug/1.ico | Bin 0 -> 2550 bytes
dll/shellext/stobject/stobject.rc | 19 ++
dll/shellext/stobject/volume.cpp | 29 +-
34 files changed, 592 insertions(+), 195 deletions(-)
diff --git a/dll/shellext/stobject/CMakeLists.txt b/dll/shellext/stobject/CMakeLists.txt
index 2fa34e6144..341fe672ae 100644
--- a/dll/shellext/stobject/CMakeLists.txt
+++ b/dll/shellext/stobject/CMakeLists.txt
@@ -12,6 +12,9 @@ include_directories(
${REACTOS_SOURCE_DIR}/sdk/lib/atl
${REACTOS_SOURCE_DIR})
+add_definitions(
+ -D_ATL_NO_EXCEPTIONS)
+
spec2def(stobject.dll stobject.spec)
file(GLOB_RECURSE stobject_rc_deps resources/*.*)
@@ -30,6 +33,7 @@ set_module_type(stobject win32dll UNICODE)
target_link_libraries(stobject uuid wine atlnew)
add_importlibs(stobject
+ setupapi
advapi32
winmm
ole32
diff --git a/dll/shellext/stobject/csystray.cpp b/dll/shellext/stobject/csystray.cpp
index 8551fbcf23..e4a2afe403 100644
--- a/dll/shellext/stobject/csystray.cpp
+++ b/dll/shellext/stobject/csystray.cpp
@@ -4,6 +4,7 @@
* FILE: dll/shellext/stobject/csystray.cpp
* PURPOSE: Systray shell service object implementation
* PROGRAMMERS: David Quintana <gigaherz(a)gmail.com>
+* Shriraj Sawant a.k.a SR13 <sr.official(a)hotmail.com>
*/
#include "precomp.h"
@@ -97,7 +98,27 @@ HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM
lParam, LR
return S_FALSE;
}
-HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip)
+/*++
+* @name NotifyIcon
+*
+* Basically a Shell_NotifyIcon wrapper.
+* Based on the parameters provided, it changes the current state of the notification
icon.
+*
+* @param code
+* Determines whether to add, delete or modify the notification icon (represented
by uId).
+* @param uId
+* Represents the particular notification icon.
+* @param hIcon
+* A handle to an icon for the notification object.
+* @param szTip
+* A string for the tooltip of the notification.
+* @param dwstate
+* Determines whether to show or hide the notification icon.
+*
+* @return The error code.
+*
+*--*/
+HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip, DWORD
dwstate)
{
NOTIFYICONDATA nim = { 0 };
@@ -108,8 +129,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)
@@ -219,30 +240,8 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM
return TRUE;
case WM_TIMER:
- switch (wParam)
- {
- case 1:
- UpdateIcons();
- return TRUE;
-
- case POWER_TIMER_ID:
- Power_OnTimer(hWnd);
- break;
-
- case VOLUME_TIMER_ID:
- Volume_OnTimer(hWnd);
- break;
-
- case HOTPLUG_TIMER_ID:
- Hotplug_OnTimer(hWnd);
- break;
- }
- break;
-
- case WM_DEVICECHANGE:
- ERR("WM_DEVICECHANGE\n");
- break;
-
+ UpdateIcons();
+ return TRUE;
case WM_DESTROY:
KillTimer(1);
ShutdownIcons();
diff --git a/dll/shellext/stobject/csystray.h b/dll/shellext/stobject/csystray.h
index 04f7c1e292..b95cd65577 100644
--- a/dll/shellext/stobject/csystray.h
+++ b/dll/shellext/stobject/csystray.h
@@ -5,6 +5,7 @@
* PURPOSE: Systray shell service object
* PROGRAMMERS: Robert Naumann
* David Quintana <gigaherz(a)gmail.com>
+ * Shriraj Sawant a.k.a SR13 <sr.official(a)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; }
diff --git a/dll/shellext/stobject/hotplug.cpp b/dll/shellext/stobject/hotplug.cpp
index fbc22ea078..4b17a1baf2 100644
--- a/dll/shellext/stobject/hotplug.cpp
+++ b/dll/shellext/stobject/hotplug.cpp
@@ -2,38 +2,152 @@
* PROJECT: ReactOS system libraries
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/shellext/stobject/hotplug.cpp
- * PURPOSE: Hotplug notification icon handler
- * PROGRAMMERS: Eric Kohl <eric.kohl(a)reactos.org>
- * David Quintana <gigaherz(a)gmail.com>
+ * PURPOSE: Removable devices notification icon handler
+ * PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official(a)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 LPCWSTR g_strTooltip = L"Safely Remove Hardware and Eject Media";
+static WCHAR g_strMenuSel[DISPLAY_NAME_LEN];
static BOOL g_IsRunning = FALSE;
-
-
-HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray)
+static BOOL g_IsRemoving = FALSE;
+
+/*++
+* @name EnumHotpluggedDevices
+*
+* Enumerates the connected safely removable devices.
+*
+* @param devList
+* List of device instances, representing the currently attached devices.
+*
+* @return The error code.
+*
+*--*/
+HRESULT EnumHotpluggedDevices(CSimpleArray<DEVINST> &devList)
{
- WCHAR strTooltip[128];
+ 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);
+
+ // Enumerate all the attached devices.
+ 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;
+
+ // Filter and make list of only the appropriate safely removable devices.
+ if ( (dwCapabilities & CM_DEVCAP_REMOVABLE) &&
+ !(dwCapabilities & CM_DEVCAP_DOCKDEVICE) &&
+ !(dwCapabilities & CM_DEVCAP_SURPRISEREMOVALOK) &&
+ ((dwCapabilities & CM_DEVCAP_EJECTSUPPORTED) || (ulStatus &
DN_DISABLEABLE)) &&
+ !ulPnum)
+ {
+ devList.Add(did.DevInst);
+ }
+ }
+ SetupDiDestroyDeviceInfoList(hdev);
- TRACE("Hotplug_Init\n");
+ if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError())
+ {
+ return E_UNEXPECTED;
+ }
- g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_EXTRACT));
+ return S_OK;
+}
- LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_1, strTooltip, _countof(strTooltip));
+/*++
+* @name NotifyBalloon
+*
+* Pops the balloon notification of the given notification icon.
+*
+* @param pSysTray
+* Provides interface for acquiring CSysTray information as required.
+* @param szTitle
+* Title for the balloon notification.
+* @param szInfo
+* Main content for the balloon notification.
+* @param uId
+* Represents the particular notification icon.
+*
+* @return The error code.
+*
+*--*/
+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(10000); /* As per windows, the balloon notification remains visible for atleast
10 sec.
+ This timer maintains the same condition.
+ Also it is required so that the icon doesn't hide instantly
after last device is removed,
+ as that will prevent popping of notification.
+ */
+ StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), L"");
+ StringCchCopy(nim.szInfo, _countof(nim.szInfo), L"");
+ ret = Shell_NotifyIcon(NIM_MODIFY, &nim);
+ g_IsRemoving = FALSE; /* This flag is used to prevent instant icon hiding after last
device is removed.
+ The above timer maintains the required state for the same.
+ */
+ return ret ? S_OK : E_FAIL;
+}
+HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray)
+{
+ TRACE("Hotplug_Init\n");
+ 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,
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");
- return S_OK;
+
+ 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);
}
HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray)
@@ -45,79 +159,112 @@ 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"rundll32.exe",
L"shell32.dll,Control_RunDLL hotplug.dll", 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)
+static void _ShowContextMenu(CSysTray * pSysTray)
{
- WCHAR szBuffer[128];
- DWORD id, msgPos;
- HMENU hPopup;
-
- LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_2, szBuffer, _countof(szBuffer));
+ HMENU hPopup = CreatePopupMenu();
+ ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
- hPopup = CreatePopupMenu();
- AppendMenuW(hPopup, MF_STRING, 1, szBuffer);
+ for (INT index = 0; index < g_devList.GetSize(); index++)
+ {
+ WCHAR dispName[DISPLAY_NAME_LEN], menuName[DISPLAY_NAME_LEN + 10];
+ 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");
- msgPos = GetMessagePos();
+ swprintf(menuName, L"Eject %wS", dispName);
+ AppendMenuW(hPopup, MF_STRING, index+1, menuName);
+ }
SetForegroundWindow(pSysTray->GetHWnd());
- id = TrackPopupMenuEx(hPopup,
- TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN |
TPM_BOTTOMALIGN,
- GET_X_LPARAM(msgPos),
- GET_Y_LPARAM(msgPos),
- pSysTray->GetHWnd(),
- NULL);
+ DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
+ POINT pt;
+ GetCursorPos(&pt);
- DestroyMenu(hPopup);
+ DWORD id = TrackPopupMenuEx(hPopup, flags,
+ pt.x, pt.y,
+ pSysTray->GetHWnd(), NULL);
+
+ if (id > 0)
+ {
+ 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)
+ {
+ 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
+ {
+ //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.
+ */
+ }
+ }
- if (id == 1)
- RunHotplug();
+ DestroyMenu(hPopup);
}
-static
-VOID
-ShowHotplugPopupMenu(
- HWND hWnd)
+static void _ShowContextMenuR(CSysTray * pSysTray)
{
-#if 0
- DWORD id, msgPos;
-
+ CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2);
HMENU hPopup = CreatePopupMenu();
+ AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu);
- // FIXME
- AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen);
-
- msgPos = GetMessagePos();
-
- SetForegroundWindow(hWnd);
- id = TrackPopupMenuEx(hPopup,
- TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN |
TPM_BOTTOMALIGN,
- GET_X_LPARAM(msgPos),
- GET_Y_LPARAM(msgPos),
- hWnd,
- NULL);
+ SetForegroundWindow(pSysTray->GetHWnd());
+ DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
+ POINT pt;
+ GetCursorPos(&pt);
- DestroyMenu(hPopup);
+ DWORD id = TrackPopupMenuEx(hPopup, flags,
+ pt.x, pt.y,
+ pSysTray->GetHWnd(), NULL);
- if (id != 0)
+ if (id == IDS_HOTPLUG_REMOVE_2)
{
- // FIXME
+ _RunHotplug(pSysTray);
}
-#endif
+
+ DestroyMenu(hPopup);
}
-HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WPARAM
wParam, LPARAM lParam, LRESULT &lResult)
+HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM
wParam, LPARAM lParam, LRESULT &lResult)
{
+ HRESULT hr = E_FAIL;
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 == 2)
+ if (wParam == 1)
{
if (lParam == FALSE)
return Hotplug_Init(pSysTray);
@@ -128,7 +275,7 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray,
UINT uMsg, WP
case WM_USER + 221:
TRACE("Hotplug_Message: WM_USER+221\n");
- if (wParam == 2)
+ if (wParam == 1)
{
lResult = (LRESULT)g_IsRunning;
return S_OK;
@@ -141,22 +288,21 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray,
UINT uMsg, WP
switch (lParam)
{
case WM_LBUTTONDOWN:
- SetTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID, 500, NULL);
break;
case WM_LBUTTONUP:
+ _ShowContextMenu(pSysTray);
break;
case WM_LBUTTONDBLCLK:
- KillTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID);
- RunHotplug();
+ _RunHotplug(pSysTray);
break;
case WM_RBUTTONDOWN:
break;
case WM_RBUTTONUP:
- ShowContextMenu(pSysTray);
+ _ShowContextMenuR(pSysTray);
break;
case WM_RBUTTONDBLCLK:
@@ -167,6 +313,41 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray,
UINT uMsg, WP
}
return S_OK;
+ case WM_DEVICECHANGE:
+ switch (wParam)
+ {
+ case DBT_DEVNODES_CHANGED:
+ hr = EnumHotpluggedDevices(g_devList);
+ if (FAILED(hr))
+ return hr;
+
+ 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:
+ if (!UnregisterDeviceNotification(hDeviceNotify))
+ {
+ return S_FALSE;
+ }
+ return S_OK;*/
+
default:
TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n");
return S_FALSE;
@@ -174,11 +355,3 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray,
UINT uMsg, WP
return S_FALSE;
}
-
-VOID
-Hotplug_OnTimer(HWND hWnd)
-{
- TRACE("Hotplug_OnTimer\n!");
- KillTimer(hWnd, HOTPLUG_TIMER_ID);
- ShowHotplugPopupMenu(hWnd);
-}
diff --git a/dll/shellext/stobject/lang/cs-CZ.rc b/dll/shellext/stobject/lang/cs-CZ.rc
index 84fe3d4fb1..57ec1bca55 100644
--- a/dll/shellext/stobject/lang/cs-CZ.rc
+++ b/dll/shellext/stobject/lang/cs-CZ.rc
@@ -18,8 +18,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Upravit možnosti napájení"
IDS_PWR_METER "&Otevřít ukazatel spotřeby"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "zbývá %1!u!%%"
- IDS_PWR_CHARGING " (nabíjení)"
+ IDS_PWR_PERCENT_REMAINING "zbývá %.2f%%"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Zbývá neznámo"
IDS_PWR_AC "On AC power"
IDS_PWR_HOURS_REMAINING "zbývá %1!u!:%2!02u! hodin (%3!u!%%)"
diff --git a/dll/shellext/stobject/lang/de-DE.rc b/dll/shellext/stobject/lang/de-DE.rc
index 1563baf172..cdb3aa2d48 100644
--- a/dll/shellext/stobject/lang/de-DE.rc
+++ b/dll/shellext/stobject/lang/de-DE.rc
@@ -18,8 +18,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Energieverwaltungseigenschaften
einstellen"
IDS_PWR_METER "Batterieanzeige ö&ffnen"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "%1!u!%% verbleibend"
- IDS_PWR_CHARGING " (wird aufgeladen)"
+ IDS_PWR_PERCENT_REMAINING "%.2f%% verbleibend"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Unbekannt verbleibend"
IDS_PWR_AC "Mit Wechselstrom"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! Stunden (%3!u!%%) verbleibend"
diff --git a/dll/shellext/stobject/lang/en-US.rc b/dll/shellext/stobject/lang/en-US.rc
index e10c25c3cc..ea1f17ffcd 100644
--- a/dll/shellext/stobject/lang/en-US.rc
+++ b/dll/shellext/stobject/lang/en-US.rc
@@ -18,8 +18,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Adjust Power Properties"
IDS_PWR_METER "&Open Power Meter"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining"
- IDS_PWR_CHARGING " (charging)"
+ IDS_PWR_PERCENT_REMAINING "%.2f%% remaining"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
IDS_PWR_AC "On AC power"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining"
diff --git a/dll/shellext/stobject/lang/es-ES.rc b/dll/shellext/stobject/lang/es-ES.rc
index c7a3d0d6b2..ac008f2dd9 100644
--- a/dll/shellext/stobject/lang/es-ES.rc
+++ b/dll/shellext/stobject/lang/es-ES.rc
@@ -19,8 +19,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Ajustar propiedades de energía"
IDS_PWR_METER "Abrir &medidor de energía"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "Queda un %1!u!%%"
- IDS_PWR_CHARGING " (cargando)"
+ IDS_PWR_PERCENT_REMAINING "Queda un %.2f%%"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Estado de batería desconocido"
IDS_PWR_AC "En corriente alterna"
IDS_PWR_HOURS_REMAINING "Quedan %1!u!:%2!02u! horas (%3!u!%%)"
diff --git a/dll/shellext/stobject/lang/fr-FR.rc b/dll/shellext/stobject/lang/fr-FR.rc
index 273cb83b89..de393af36f 100644
--- a/dll/shellext/stobject/lang/fr-FR.rc
+++ b/dll/shellext/stobject/lang/fr-FR.rc
@@ -18,8 +18,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Adjust Power Properties"
IDS_PWR_METER "&Open Power Meter"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining"
- IDS_PWR_CHARGING " (charging)"
+ IDS_PWR_PERCENT_REMAINING "%.2f%% remaining"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
IDS_PWR_AC "On AC power"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining"
diff --git a/dll/shellext/stobject/lang/it-IT.rc b/dll/shellext/stobject/lang/it-IT.rc
index a4d715427c..628466edbe 100644
--- a/dll/shellext/stobject/lang/it-IT.rc
+++ b/dll/shellext/stobject/lang/it-IT.rc
@@ -18,8 +18,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Modifica proprietà alimentazione"
IDS_PWR_METER "&Apri misuratore alimentazione"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "%1!u!%% rimanenti"
- IDS_PWR_CHARGING " (in carica)"
+ IDS_PWR_PERCENT_REMAINING "%.2f%% rimanenti"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Autonomia sconosciuta"
IDS_PWR_AC "Alimentazione da rete AC"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! ore (%3!u!%%) rimanenti"
diff --git a/dll/shellext/stobject/lang/pl-PL.rc b/dll/shellext/stobject/lang/pl-PL.rc
index 0a2889edc4..def3249946 100644
--- a/dll/shellext/stobject/lang/pl-PL.rc
+++ b/dll/shellext/stobject/lang/pl-PL.rc
@@ -18,8 +18,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Opcje zasilania"
IDS_PWR_METER "&Otwórz miernik baterii"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "Pozostało %1!u!%%"
- IDS_PWR_CHARGING " (ładowanie)"
+ IDS_PWR_PERCENT_REMAINING "Pozostało %.2f%%"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Stan naładowania nieznany"
IDS_PWR_AC "Podłączony do zasilacza"
IDS_PWR_HOURS_REMAINING "Pozostało %1!u!:%2!02u! godzin (%3!u!%%)"
diff --git a/dll/shellext/stobject/lang/ro-RO.rc b/dll/shellext/stobject/lang/ro-RO.rc
index 0de2e8de7c..bb19bd1d74 100644
--- a/dll/shellext/stobject/lang/ro-RO.rc
+++ b/dll/shellext/stobject/lang/ro-RO.rc
@@ -19,8 +19,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Ajustare proprietăți de consum energie"
IDS_PWR_METER "&Deschide Contor de energie"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "Au mai rămas %1!u!%%"
- IDS_PWR_CHARGING " (în încărcare)"
+ IDS_PWR_PERCENT_REMAINING "Au mai rămas %.2f%%"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Nu este disponibil cât a mai rămas"
IDS_PWR_AC "În rețea de CA"
IDS_PWR_HOURS_REMAINING "Au mai rămas %1!u!:%2!02u! ore (%3!u!%%)"
diff --git a/dll/shellext/stobject/lang/ru-RU.rc b/dll/shellext/stobject/lang/ru-RU.rc
index 572f1613fd..af307d3024 100644
--- a/dll/shellext/stobject/lang/ru-RU.rc
+++ b/dll/shellext/stobject/lang/ru-RU.rc
@@ -20,8 +20,8 @@ BEGIN
IDS_PWR_PROPERTIES "&Настройка параметров электропитания"
IDS_PWR_METER "&Открыть показатели питания"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "%1!u!%% осталось"
- IDS_PWR_CHARGING " (зарядка)"
+ IDS_PWR_PERCENT_REMAINING "%.2f%% осталось"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "Неизвестно"
IDS_PWR_AC "От сети переменного тока"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! часов (%3!u!%%) осталось"
diff --git a/dll/shellext/stobject/lang/zh-CN.rc b/dll/shellext/stobject/lang/zh-CN.rc
index 6ba1f37f4b..1d402493d0 100644
--- a/dll/shellext/stobject/lang/zh-CN.rc
+++ b/dll/shellext/stobject/lang/zh-CN.rc
@@ -20,8 +20,8 @@ BEGIN
IDS_PWR_PROPERTIES "调整电源属性(&A)"
IDS_PWR_METER "开放式电源表(&O)"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "剩余 %1!u!%%"
- IDS_PWR_CHARGING " (充电中)"
+ IDS_PWR_PERCENT_REMAINING "剩余 %.2f%%"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "未知剩余"
IDS_PWR_AC "交流电源"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小时 剩余 (%3!u!%%) "
diff --git a/dll/shellext/stobject/lang/zh-TW.rc b/dll/shellext/stobject/lang/zh-TW.rc
index 35ae8c4a6f..3d9a5265b8 100644
--- a/dll/shellext/stobject/lang/zh-TW.rc
+++ b/dll/shellext/stobject/lang/zh-TW.rc
@@ -20,8 +20,8 @@ BEGIN
IDS_PWR_PROPERTIES "調整電源屬性(&A)"
IDS_PWR_METER "開放式電源表(&O)"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
- IDS_PWR_PERCENT_REMAINING "剩餘 %1!u!%%"
- IDS_PWR_CHARGING " (充電中)"
+ IDS_PWR_PERCENT_REMAINING "剩餘 %.2f%%"
+ IDS_PWR_CHARGING "%.2f%% and charging"
IDS_PWR_UNKNOWN_REMAINING "未知剩餘"
IDS_PWR_AC "交流電源"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小時 剩餘 (%3!u!%%) "
diff --git a/dll/shellext/stobject/power.cpp b/dll/shellext/stobject/power.cpp
index 24b5feb416..5853b2bdbf 100644
--- a/dll/shellext/stobject/power.cpp
+++ b/dll/shellext/stobject/power.cpp
@@ -4,14 +4,30 @@
* FILE: dll/shellext/stobject/power.cpp
* PURPOSE: Power notification icon handler
* PROGRAMMERS: Eric Kohl <eric.kohl(a)reactos.org>
+ Shriraj Sawant a.k.a SR13 <sr.official(a)hotmail.com>
* David Quintana <gigaherz(a)gmail.com>
*/
+#include <Windows.h>
+#include <SetupAPI.h>
+#include <devguid.h>
+#include <BatClass.h>
+
#include "precomp.h"
#include "powrprof.h"
+#include <mmsystem.h>
+#include <mmddk.h>
+#include <atlstr.h>
+
+#define GBS_HASBATTERY 0x1
+#define GBS_ONBATTERY 0x2
+
WINE_DEFAULT_DEBUG_CHANNEL(stobject);
+int br_icons[5] = { IDI_BATTCAP0, IDI_BATTCAP1, IDI_BATTCAP2, IDI_BATTCAP3, IDI_BATTCAP4
}; // battery mode icons.
+int bc_icons[5] = { IDI_BATTCHA0, IDI_BATTCHA1, IDI_BATTCHA2, IDI_BATTCHA3, IDI_BATTCHA4
}; // charging mode icons.
+
typedef struct _PWRSCHEMECONTEXT
{
HMENU hPopup;
@@ -19,71 +35,261 @@ typedef struct _PWRSCHEMECONTEXT
UINT uiLast;
} PWRSCHEMECONTEXT, *PPWRSCHEMECONTEXT;
+CString g_strTooltip;
+static float g_batCap = 0;
static HICON g_hIconBattery = NULL;
static BOOL g_IsRunning = FALSE;
+/*++
+* @name GetBatteryState
+*
+* Enumerates the available battery devices and provides the remaining capacity.
+*
+* @param cap
+* If no error occurs, then this will contain average remaining capacity.
+* @param dwResult
+* Helps in making battery type checks.
+* {
+* Returned value includes GBS_HASBATTERY if the system has a non-UPS battery,
+* and GBS_ONBATTERY if the system is running on a battery.
+* dwResult & GBS_ONBATTERY means we have not yet found AC power.
+* dwResult & GBS_HASBATTERY means we have found a non-UPS battery.
+* }
+*
+* @return The error code.
+*
+*--*/
+static HRESULT GetBatteryState(float& cap, DWORD& dwResult)
+{
+ cap = 0;
+ dwResult = GBS_ONBATTERY;
-HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray)
+ HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
+ if (INVALID_HANDLE_VALUE == hdev)
+ return E_HANDLE;
+
+ // Limit search to 100 batteries max
+ for (int idev = 0, count = 0; idev < 100; idev++)
+ {
+ SP_DEVICE_INTERFACE_DATA did = { 0 };
+ did.cbSize = sizeof(did);
+
+ if (SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVCLASS_BATTERY, idev,
&did))
+ {
+ DWORD cbRequired = 0;
+
+ SetupDiGetDeviceInterfaceDetail(hdev, &did, 0, 0, &cbRequired, 0);
+ if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
+ {
+ PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, cbRequired);
+ if (pdidd)
+ {
+ pdidd->cbSize = sizeof(*pdidd);
+ if (SetupDiGetDeviceInterfaceDetail(hdev, &did, pdidd,
cbRequired, &cbRequired, 0))
+ {
+ // Enumerated a battery. Ask it for information.
+ HANDLE hBattery = CreateFile(pdidd->DevicePath, GENERIC_READ |
GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (INVALID_HANDLE_VALUE != hBattery)
+ {
+ // Ask the battery for its tag.
+ BATTERY_QUERY_INFORMATION bqi = { 0 };
+
+ DWORD dwWait = 0;
+ DWORD dwOut;
+
+ if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG,
&dwWait, sizeof(dwWait), &bqi.BatteryTag,
+ sizeof(bqi.BatteryTag), &dwOut, NULL) &&
bqi.BatteryTag)
+ {
+ // With the tag, you can query the battery info.
+ BATTERY_INFORMATION bi = { 0 };
+ bqi.InformationLevel = BatteryInformation;
+
+ if (DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi,
+ sizeof(bi), &dwOut, NULL))
+ {
+ // Only non-UPS system batteries count
+ if (bi.Capabilities & BATTERY_SYSTEM_BATTERY)
+ {
+ if (!(bi.Capabilities &
BATTERY_IS_SHORT_TERM))
+ dwResult |= GBS_HASBATTERY;
+
+ // Query the battery status.
+ BATTERY_WAIT_STATUS bws = { 0 };
+ bws.BatteryTag = bqi.BatteryTag;
+
+ BATTERY_STATUS bs;
+ if (DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws),
+ &bs, sizeof(bs), &dwOut, NULL))
+ {
+ if (bs.PowerState &
BATTERY_POWER_ON_LINE)
+ dwResult &= ~GBS_ONBATTERY;
+
+ // Take average of total capacity of
batteries detected!
+ cap = cap*(count)+(float)bs.Capacity /
bi.FullChargedCapacity * 100;
+ cap /= count + 1;
+ count++;
+ }
+ }
+ }
+ }
+ CloseHandle(hBattery);
+ }
+ }
+ LocalFree(pdidd);
+ }
+ }
+ }
+ else if (ERROR_NO_MORE_ITEMS == GetLastError())
+ {
+ break; // Enumeration failed - perhaps we're out of items
+ }
+ }
+ SetupDiDestroyDeviceInfoList(hdev);
+
+ // Final cleanup: If we didn't find a battery, then presume that we
+ // are on AC power.
+
+ if (!(dwResult & GBS_HASBATTERY))
+ dwResult &= ~GBS_ONBATTERY;
+
+ return S_OK;
+}
+
+/*++
+* @name Quantize
+*
+* This function quantizes the mentioned quantity to nearest level.
+*
+* @param p
+* Should be a quantity in percentage.
+* @param lvl
+* Quantization level (this excludes base level 0, which will always be present),
default is 10.
+*
+* @return Nearest quantized level, can be directly used as array index based on context.
+*
+*--*/
+static UINT Quantize(float p, UINT lvl = 10)
{
- WCHAR strTooltip[128];
+ int i = 0;
+ float f, q = (float)100 / lvl, d = q / 2;
+ for (f = 0; f < p; f += q, i++);
+
+ if ((f - d) <= p)
+ return i;
+ else
+ return i - 1;
+/*
+ @remarks This function uses centred/symmetric logic for quantization.
+ For the case of lvl = 4, You will get following integer levels if given (p) value falls
in between the range partitions:
+ 0 <= p < 12.5 : returns 0; (corresponding to 0% centre)
+ 12.5 <= p < 37.5 : returns 1; (corresponding to 25% centre)
+ 37.5 <= p < 62.5 : returns 2; (corresponding to 50% centre)
+ 62.5 <= p < 87.5 : returns 3; (corresponding to 75% centre)
+ 87.5 <= p <= 100 : returns 4; (corresponding to 100% centre)
+*/
+}
- TRACE("Power_Init\n");
+/*++
+* @name DynamicLoadIcon
+*
+* Returns the respective icon as per the current battery capacity.
+* It also does the work of setting global parameters of battery capacity and tooltips.
+*
+* @param hinst
+* A handle to a instance of the module.
+*
+* @return The handle to respective battery icon.
+*
+*--*/
+static HICON DynamicLoadIcon(HINSTANCE hinst)
+{
+ HICON hBatIcon;
+ float cap = 0;
+ DWORD dw = 0;
+ UINT index = -1;
+ HRESULT hr = GetBatteryState(cap, dw);
+
+ if (!FAILED(hr) && (dw & GBS_HASBATTERY))
+ {
+ index = Quantize(cap, 4);
+ g_batCap = cap;
+ }
+ else
+ {
+ g_batCap = 0;
+ hBatIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_BATTCAP_ERR));
+ g_strTooltip.LoadStringW(IDS_PWR_UNKNOWN_REMAINING);
+ return hBatIcon;
+ }
- g_hIconBattery = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BATTERY));
+ if (dw & GBS_ONBATTERY)
+ {
+ hBatIcon = LoadIcon(hinst, MAKEINTRESOURCE(br_icons[index]));
+ g_strTooltip.Format(IDS_PWR_PERCENT_REMAINING, cap);
+ }
+ else
+ {
+ hBatIcon = LoadIcon(hinst, MAKEINTRESOURCE(bc_icons[index]));
+ g_strTooltip.Format(IDS_PWR_CHARGING, cap);
+ }
- LoadStringW(g_hInstance, IDS_PWR_AC, strTooltip, _countof(strTooltip));
+ return hBatIcon;
+}
+HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray)
+{
+ TRACE("Power_Init\n");
+ g_hIconBattery = DynamicLoadIcon(g_hInstance);
g_IsRunning = TRUE;
- return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_POWER, g_hIconBattery, strTooltip);
+ return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_POWER, g_hIconBattery,
g_strTooltip);
}
HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray)
{
TRACE("Power_Update\n");
- return S_OK;
+ g_hIconBattery = DynamicLoadIcon(g_hInstance);
+
+ return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_POWER, g_hIconBattery,
g_strTooltip);
}
HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray)
{
TRACE("Power_Shutdown\n");
-
g_IsRunning = FALSE;
return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_POWER, NULL, NULL);
}
-static void RunPower()
+static void _RunPower()
{
- ShellExecuteW(NULL, NULL, L"rundll32.exe",
L"shell32.dll,Control_RunDLL powercfg.cpl", NULL, SW_SHOWNORMAL);
+ ShellExecuteW(NULL, NULL, L"powercfg.cpl", NULL, NULL, SW_SHOWNORMAL);
}
-static void ShowContextMenu(CSysTray * pSysTray)
+static void _ShowContextMenu(CSysTray * pSysTray)
{
- WCHAR szBuffer[128];
- DWORD id, msgPos;
- HMENU hPopup;
-
- LoadStringW(g_hInstance, IDS_PWR_PROPERTIES, szBuffer, _countof(szBuffer));
-
- hPopup = CreatePopupMenu();
- AppendMenuW(hPopup, MF_STRING, IDS_PWR_PROPERTIES, szBuffer);
- SetMenuDefaultItem(hPopup, IDS_PWR_PROPERTIES, FALSE);
-
- msgPos = GetMessagePos();
+ CString strOpen((LPCSTR)IDS_PWR_PROPERTIES);
+ HMENU hPopup = CreatePopupMenu();
+ AppendMenuW(hPopup, MF_STRING, IDS_PWR_PROPERTIES, strOpen);
SetForegroundWindow(pSysTray->GetHWnd());
- id = TrackPopupMenuEx(hPopup,
- TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN |
TPM_BOTTOMALIGN,
- GET_X_LPARAM(msgPos),
- GET_Y_LPARAM(msgPos),
- pSysTray->GetHWnd(),
- NULL);
+ DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
+ POINT pt;
+ GetCursorPos(&pt);
- DestroyMenu(hPopup);
+ DWORD id = TrackPopupMenuEx(hPopup, flags,
+ pt.x, pt.y,
+ pSysTray->GetHWnd(), NULL);
- if (id == IDS_PWR_PROPERTIES)
- RunPower();
+ switch (id)
+ {
+ case IDS_PWR_PROPERTIES:
+ _RunPower();
+ break;
+ }
+ DestroyMenu(hPopup);
}
static
@@ -114,12 +320,12 @@ PowerSchemesEnumProc(
static
VOID
ShowPowerSchemesPopupMenu(
- HWND hWnd)
+ CSysTray *pSysTray)
{
PWRSCHEMECONTEXT PowerSchemeContext = {NULL, 0, 0};
UINT uiActiveScheme;
- DWORD id, msgPos;
-
+ DWORD id;
+ POINT pt;
PowerSchemeContext.hPopup = CreatePopupMenu();
EnumPwrSchemes(PowerSchemesEnumProc, (LPARAM)&PowerSchemeContext);
@@ -132,14 +338,14 @@ ShowPowerSchemesPopupMenu(
MF_BYCOMMAND);
}
- msgPos = GetMessagePos();
-
- SetForegroundWindow(hWnd);
+ SetForegroundWindow(pSysTray->GetHWnd());
+ GetCursorPos(&pt);
+
id = TrackPopupMenuEx(PowerSchemeContext.hPopup,
TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN |
TPM_BOTTOMALIGN,
- GET_X_LPARAM(msgPos),
- GET_Y_LPARAM(msgPos),
- hWnd,
+ pt.x,
+ pt.y,
+ pSysTray->GetHWnd(),
NULL);
DestroyMenu(PowerSchemeContext.hPopup);
@@ -180,22 +386,21 @@ HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray,
UINT uMsg, WPA
switch (lParam)
{
case WM_LBUTTONDOWN:
- SetTimer(pSysTray->GetHWnd(), POWER_TIMER_ID, 500, NULL);
break;
case WM_LBUTTONUP:
+ ShowPowerSchemesPopupMenu(pSysTray);
break;
case WM_LBUTTONDBLCLK:
- KillTimer(pSysTray->GetHWnd(), POWER_TIMER_ID);
- RunPower();
+ _RunPower();
break;
case WM_RBUTTONDOWN:
break;
case WM_RBUTTONUP:
- ShowContextMenu(pSysTray);
+ _ShowContextMenu(pSysTray);
break;
case WM_RBUTTONDBLCLK:
@@ -213,11 +418,3 @@ HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray,
UINT uMsg, WPA
return S_FALSE;
}
-
-VOID
-Power_OnTimer(HWND hWnd)
-{
- TRACE("Power_OnTimer\n!");
- KillTimer(hWnd, POWER_TIMER_ID);
- ShowPowerSchemesPopupMenu(hWnd);
-}
diff --git a/dll/shellext/stobject/precomp.h b/dll/shellext/stobject/precomp.h
index fd2ea78836..64824ba825 100644
--- a/dll/shellext/stobject/precomp.h
+++ b/dll/shellext/stobject/precomp.h
@@ -69,19 +69,16 @@ extern HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray *
pSysTray);
extern HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg,
WPARAM wParam, LPARAM lParam, LRESULT &lResult);
-extern VOID Volume_OnTimer(HWND hWnd);
extern HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg,
WPARAM wParam, LPARAM lParam, LRESULT &lResult);
-extern VOID Hotplug_OnTimer(HWND hWnd);
extern HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg,
WPARAM wParam, LPARAM lParam, LRESULT &lResult);
-extern VOID Power_OnTimer(HWND hWnd);
#define POWER_TIMER_ID 2
#define VOLUME_TIMER_ID 3
diff --git a/dll/shellext/stobject/resource.h b/dll/shellext/stobject/resource.h
index 2637a12aea..a7466f77d3 100644
--- a/dll/shellext/stobject/resource.h
+++ b/dll/shellext/stobject/resource.h
@@ -39,4 +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_HOTPLUG_ERR 420
+#define IDI_HOTPLUG_OK 421
+
#define IDR_SYSTRAY 11001
diff --git a/dll/shellext/stobject/resources/battery/0.ico
b/dll/shellext/stobject/resources/battery/0.ico
new file mode 100644
index 0000000000..1610499aa3
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/0.ico differ
diff --git a/dll/shellext/stobject/resources/battery/1.ico
b/dll/shellext/stobject/resources/battery/1.ico
new file mode 100644
index 0000000000..9c2f526f9e
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/1.ico differ
diff --git a/dll/shellext/stobject/resources/battery/2.ico
b/dll/shellext/stobject/resources/battery/2.ico
new file mode 100644
index 0000000000..f1dc98aa7f
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/2.ico differ
diff --git a/dll/shellext/stobject/resources/battery/3.ico
b/dll/shellext/stobject/resources/battery/3.ico
new file mode 100644
index 0000000000..59fabc2ef3
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/3.ico differ
diff --git a/dll/shellext/stobject/resources/battery/4.ico
b/dll/shellext/stobject/resources/battery/4.ico
new file mode 100644
index 0000000000..edc24a071e
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/4.ico differ
diff --git a/dll/shellext/stobject/resources/battery/5.ico
b/dll/shellext/stobject/resources/battery/5.ico
new file mode 100644
index 0000000000..cd4e3b8ee7
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/5.ico differ
diff --git a/dll/shellext/stobject/resources/battery/charging0.ico
b/dll/shellext/stobject/resources/battery/charging0.ico
new file mode 100644
index 0000000000..7504162423
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging0.ico differ
diff --git a/dll/shellext/stobject/resources/battery/charging1.ico
b/dll/shellext/stobject/resources/battery/charging1.ico
new file mode 100644
index 0000000000..3a6210c19a
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging1.ico differ
diff --git a/dll/shellext/stobject/resources/battery/charging2.ico
b/dll/shellext/stobject/resources/battery/charging2.ico
new file mode 100644
index 0000000000..7c1c919a35
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging2.ico differ
diff --git a/dll/shellext/stobject/resources/battery/charging3.ico
b/dll/shellext/stobject/resources/battery/charging3.ico
new file mode 100644
index 0000000000..fb92ab6213
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging3.ico differ
diff --git a/dll/shellext/stobject/resources/battery/charging4.ico
b/dll/shellext/stobject/resources/battery/charging4.ico
new file mode 100644
index 0000000000..bd1f495c9a
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging4.ico differ
diff --git a/dll/shellext/stobject/resources/battery/error.ico
b/dll/shellext/stobject/resources/battery/error.ico
new file mode 100644
index 0000000000..6afba7759d
Binary files /dev/null and b/dll/shellext/stobject/resources/battery/error.ico differ
diff --git a/dll/shellext/stobject/resources/hotplug/0.ico
b/dll/shellext/stobject/resources/hotplug/0.ico
new file mode 100644
index 0000000000..83025a942d
Binary files /dev/null and b/dll/shellext/stobject/resources/hotplug/0.ico differ
diff --git a/dll/shellext/stobject/resources/hotplug/1.ico
b/dll/shellext/stobject/resources/hotplug/1.ico
new file mode 100644
index 0000000000..f615f0ebd3
Binary files /dev/null and b/dll/shellext/stobject/resources/hotplug/1.ico differ
diff --git a/dll/shellext/stobject/stobject.rc b/dll/shellext/stobject/stobject.rc
index f7844dead4..4d7e6da69f 100644
--- a/dll/shellext/stobject/stobject.rc
+++ b/dll/shellext/stobject/stobject.rc
@@ -11,6 +11,25 @@ IDI_EXTRACT ICON "resources/2.ico"
IDI_VOLUME ICON "resources/3.ico"
IDI_VOLMUTE ICON "resources/4.ico"
+IDI_BATTCAP0 ICON "resources/battery/0.ico"
+IDI_BATTCAP1 ICON "resources/battery/1.ico"
+IDI_BATTCAP2 ICON "resources/battery/2.ico"
+IDI_BATTCAP3 ICON "resources/battery/3.ico"
+IDI_BATTCAP4 ICON "resources/battery/4.ico"
+IDI_BATTCAP5 ICON "resources/battery/5.ico"
+
+IDI_BATTCHA0 ICON "resources/battery/charging0.ico"
+IDI_BATTCHA1 ICON "resources/battery/charging1.ico"
+IDI_BATTCHA2 ICON "resources/battery/charging2.ico"
+IDI_BATTCHA3 ICON "resources/battery/charging3.ico"
+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>
diff --git a/dll/shellext/stobject/volume.cpp b/dll/shellext/stobject/volume.cpp
index f82e6e0eee..b7cb3ff049 100644
--- a/dll/shellext/stobject/volume.cpp
+++ b/dll/shellext/stobject/volume.cpp
@@ -113,7 +113,7 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
return S_OK;
}
-HRESULT Volume_IsMute(VOID)
+HRESULT Volume_IsMute()
{
#if 0
MIXERCONTROLDETAILS mixerControlDetails;
@@ -217,10 +217,10 @@ HRESULT Volume_OnDeviceChange(_In_ CSysTray * pSysTray, WPARAM
wParam, LPARAM lP
return Volume_FindMixerControl(pSysTray);
}
-static void _RunVolume(BOOL bSmall)
+static void _RunVolume()
{
// FIXME: ensure we are loading the right one
- ShellExecuteW(NULL, NULL, L"sndvol32.exe", bSmall ? L"/t" : NULL,
NULL, SW_SHOWNORMAL);
+ ShellExecuteW(NULL, NULL, L"sndvol32.exe", NULL, NULL, SW_SHOWNORMAL);
}
static void _RunMMCpl()
@@ -238,14 +238,14 @@ static void _ShowContextMenu(CSysTray * pSysTray)
HMENU hPopup = CreatePopupMenu();
AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen);
AppendMenuW(hPopup, MF_STRING, IDS_VOL_ADJUST, strAdjust);
- SetMenuDefaultItem(hPopup, IDS_VOL_OPEN, FALSE);
DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
- DWORD msgPos = GetMessagePos();
-
+ POINT pt;
SetForegroundWindow(pSysTray->GetHWnd());
+ GetCursorPos(&pt);
+
DWORD id = TrackPopupMenuEx(hPopup, flags,
- GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos),
+ pt.x, pt.y,
pSysTray->GetHWnd(), NULL);
DestroyMenu(hPopup);
@@ -253,7 +253,7 @@ static void _ShowContextMenu(CSysTray * pSysTray)
switch (id)
{
case IDS_VOL_OPEN:
- _RunVolume(FALSE);
+ _RunVolume();
break;
case IDS_VOL_ADJUST:
_RunMMCpl();
@@ -296,15 +296,14 @@ HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray,
UINT uMsg, WP
switch (lParam)
{
case WM_LBUTTONDOWN:
- SetTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID, 500, NULL);
break;
case WM_LBUTTONUP:
+ TRACE("TODO: display volume slider\n");
break;
case WM_LBUTTONDBLCLK:
- KillTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID);
- _RunVolume(FALSE);
+ _RunVolume();
break;
case WM_RBUTTONDOWN:
@@ -329,11 +328,3 @@ HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray,
UINT uMsg, WP
return S_FALSE;
}
-
-VOID
-Volume_OnTimer(HWND hWnd)
-{
- TRACE("Volume_OnTimer\n!");
- KillTimer(hWnd, VOLUME_TIMER_ID);
- _RunVolume(TRUE);
-}