From 8bef9c148c43b9ad22b1c9706691c9c8d8ebb102 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Mon, 28 Jul 2014 13:18:57 +0000 Subject: [PATCH] [HIVESFT.INF] * Shell service object DLLs expect the ShellServiceObjectDelayLoad key to exist. [SYSSETUP.INF] * Mark stobject.dll to be registered during setup. [STOBJECT] * Implement icon handling. * Implement rudimentary volume icon handler. * Allow the volume icon to show the mute status of the primary audio device. svn path=/branches/shell-experiments/; revision=63750 --- boot/bootdata/hivesft.inf | 1 + dll/win32/stobject/CMakeLists.txt | 11 +- dll/win32/stobject/precomp.h | 74 ++++++++- dll/win32/stobject/resource.h | 10 +- dll/win32/stobject/stobject.cpp | 240 +++++++++++++++++++++++++----- dll/win32/stobject/stobject.rc | 8 +- media/inf/syssetup.inf | 1 + 7 files changed, 292 insertions(+), 53 deletions(-) diff --git a/boot/bootdata/hivesft.inf b/boot/bootdata/hivesft.inf index 29e76d07a0a..3e1fa3638f2 100644 --- a/boot/bootdata/hivesft.inf +++ b/boot/bootdata/hivesft.inf @@ -108,6 +108,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Setup",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Setup","DriverCachePath",0x00020002,"%SystemRoot%\Driver Cache" HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDlls",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions",,0x00000012 +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad",,0x00000012 ; FIXME - usetup doesn't handle extra paths HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce","",0x00000000,"cmd /c md ""%programfiles%\Internet Explorer\"" && move %windir%\iexplore.exe ""%programfiles%\Internet Explorer\"" && ""%programfiles%\Internet Explorer\iexplore.exe"" /RegServer" diff --git a/dll/win32/stobject/CMakeLists.txt b/dll/win32/stobject/CMakeLists.txt index 5b0f24b0734..773cbddf81e 100644 --- a/dll/win32/stobject/CMakeLists.txt +++ b/dll/win32/stobject/CMakeLists.txt @@ -17,6 +17,7 @@ spec2def(stobject.dll stobject.spec) add_library(stobject SHARED stobject.cpp stobject.rc + volume.cpp ${CMAKE_CURRENT_BINARY_DIR}/stobject.def) set_module_type(stobject win32dll UNICODE) @@ -24,12 +25,14 @@ target_link_libraries(stobject uuid wine atlnew) add_importlibs(stobject advapi32 - ole32 - gdi32 - user32 - comctl32 + winmm + ole32 shlwapi + shell32 + comctl32 msvcrt + gdi32 + user32 kernel32 ntdll) diff --git a/dll/win32/stobject/precomp.h b/dll/win32/stobject/precomp.h index 3f14fd1eb0e..c42e8d5bc81 100644 --- a/dll/win32/stobject/precomp.h +++ b/dll/win32/stobject/precomp.h @@ -25,13 +25,85 @@ #include #include #include +#include + +#include #include #include +#include "resource.h" + extern const GUID CLSID_SysTray; -#include "resource.h" +extern HINSTANCE g_hInstance; + +#define ID_ICON_VOLUME 0x4CB + +/* --------------- CSysTray callbacks ------------------------------ */ + +typedef CWinTraits < + WS_POPUP | WS_DLGFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_PALETTEWINDOW +> CMessageWndClass; + +class CSysTray : + public CComCoClass, + public CComObjectRootEx, + public CWindowImpl, + public IOleCommandTarget +{ + // TODO: keep icon handlers here + + HWND hwndSysTray; + + static DWORD WINAPI s_SysTrayThreadProc(PVOID param); + HRESULT SysTrayMessageLoop(); + HRESULT SysTrayThreadProc(); + HRESULT CreateSysTrayThread(); + HRESULT DestroySysTrayWindow(); + + HRESULT InitIcons(); + HRESULT ShutdownIcons(); + HRESULT UpdateIcons(); + HRESULT ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + +public: + HRESULT NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip); + + HWND GetHWnd() { return m_hWnd; } + +protected: + BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID = 0); + +public: + CSysTray(); + virtual ~CSysTray(); + + // *** IOleCommandTarget methods *** + virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText); + virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); + + DECLARE_WND_CLASS_EX(_T("SystemTray_Main"), CS_GLOBALCLASS, COLOR_3DFACE) + + DECLARE_REGISTRY_RESOURCEID(IDR_SYSTRAY) + DECLARE_NOT_AGGREGATABLE(CSysTray) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CSysTray) + COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + END_COM_MAP() + +}; + +/* --------------- Icon callbacks ------------------------------ */ + +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); + +/* --------------- Utils ------------------------------ */ static __inline ULONG Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...) diff --git a/dll/win32/stobject/resource.h b/dll/win32/stobject/resource.h index 242929678c7..ffd657b1cf0 100644 --- a/dll/win32/stobject/resource.h +++ b/dll/win32/stobject/resource.h @@ -1,8 +1,8 @@ #pragma once -#define IDI_ICON1 200 -#define IDI_ICON2 210 -#define IDI_ICON3 230 -#define IDI_ICON4 231 +#define IDI_BATTERY 200 +#define IDI_EXTRACT 210 +#define IDI_VOLUME 230 +#define IDI_VOLMUTE 231 -#define IDR_SYSTRAY 11001 +#define IDR_SYSTRAY 11001 diff --git a/dll/win32/stobject/stobject.cpp b/dll/win32/stobject/stobject.cpp index 5453652e6e3..69e122a1182 100644 --- a/dll/win32/stobject/stobject.cpp +++ b/dll/win32/stobject/stobject.cpp @@ -1,76 +1,238 @@ /* * PROJECT: ReactOS system libraries * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll\win32\stobject\stobject.c + * FILE: dll\win32\stobject\stobject.cpp * PURPOSE: Systray shell service object - * PROGRAMMERS: Copyright 2014 Robert Naumann + * PROGRAMMERS: Robert Naumann + David Quintana */ #include "precomp.h" #include +#include WINE_DEFAULT_DEBUG_CHANNEL(stobject); const GUID CLSID_SysTray = { 0x35CEC8A3, 0x2BE6, 0x11D2, { 0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53 } }; -class CShellTrayModule : public CComModule +HINSTANCE g_hInstance; + +typedef HRESULT(STDMETHODCALLTYPE * PFNSTINIT) (_In_ CSysTray * pSysTray); +typedef HRESULT(STDMETHODCALLTYPE * PFNSTSHUTDOWN) (_In_ CSysTray * pSysTray); +typedef HRESULT(STDMETHODCALLTYPE * PFNSTUPDATE) (_In_ CSysTray * pSysTray); +typedef HRESULT(STDMETHODCALLTYPE * PFNSTMESSAGE) (_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam); + +struct SysTrayIconHandlers_t { -public: + PFNSTINIT pfnInit; + PFNSTSHUTDOWN pfnShutdown; + PFNSTUPDATE pfnUpdate; + PFNSTMESSAGE pfnMessage; +}; + +SysTrayIconHandlers_t g_IconHandlers [] = { + { Volume_Init, Volume_Shutdown, Volume_Update, Volume_Message } }; +const int g_NumIcons = _countof(g_IconHandlers); -class CSysTray : - public CComCoClass, - public CComObjectRootEx, - public IOleCommandTarget +HRESULT CSysTray::InitIcons() { - // TODO: keep icon handlers here + for (int i = 0; i < g_NumIcons; i++) + { + HRESULT hr = g_IconHandlers[i].pfnInit(this); + if (FAILED(hr)) + return hr; + } -public: - CSysTray() {} - virtual ~CSysTray() {} + return S_OK; +} - // *** IOleCommandTarget methods *** - virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) +HRESULT CSysTray::ShutdownIcons() +{ + for (int i = 0; i < g_NumIcons; i++) { - UNIMPLEMENTED; - return S_OK; + HRESULT hr = g_IconHandlers[i].pfnShutdown(this); + if (FAILED(hr)) + return hr; } - virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) + return S_OK; +} + +HRESULT CSysTray::UpdateIcons() +{ + for (int i = 0; i < g_NumIcons; i++) { - if (!IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject)) - return E_FAIL; + HRESULT hr = g_IconHandlers[i].pfnUpdate(this); + if (FAILED(hr)) + return hr; + } - switch (nCmdID) - { - case OLECMDID_NEW: // init - DbgPrint("CSysTray Init TODO: Initialize tray icon handlers.\n"); - break; - case OLECMDID_SAVE: // shutdown - DbgPrint("CSysTray Shutdown TODO: Shutdown.\n"); + return S_OK; +} + +HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + for (int i = 0; i < g_NumIcons; i++) + { + HRESULT hr = g_IconHandlers[i].pfnMessage(this, uMsg, wParam, lParam); + if (FAILED(hr)) + return hr; + + if (hr != S_FALSE) + return hr; + } + + return S_OK; +} + +HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip) +{ + NOTIFYICONDATA nim; + nim.cbSize = sizeof(NOTIFYICONDATA); + nim.uFlags = NIF_ICON | NIF_STATE | NIF_TIP; + nim.hIcon = hIcon; + nim.uID = uId; + nim.uCallbackMessage = uId; + nim.dwState = 0; + nim.dwStateMask = 0; + nim.hWnd = m_hWnd; + nim.uVersion = NOTIFYICON_VERSION; + if (szTip) + StringCchCopy(nim.szTip, _countof(nim.szTip), szTip); + else + nim.szTip[0] = 0; + BOOL ret = Shell_NotifyIcon(code, &nim); + return ret ? S_OK : E_FAIL; +} + +DWORD WINAPI CSysTray::s_SysTrayThreadProc(PVOID param) +{ + CSysTray * st = (CSysTray*) param; + return st->SysTrayThreadProc(); +} + +HRESULT CSysTray::SysTrayMessageLoop() +{ + BOOL ret; + MSG msg; + + while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) + { + if (ret < 0) break; - } - return S_OK; + + TranslateMessage(&msg); + DispatchMessage(&msg); } - DECLARE_REGISTRY_RESOURCEID(IDR_SYSTRAY) - DECLARE_NOT_AGGREGATABLE(CSysTray) - DECLARE_PROTECT_FINAL_CONSTRUCT() + return S_OK; +} - BEGIN_COM_MAP(CSysTray) - COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) - END_COM_MAP() -}; +HRESULT CSysTray::SysTrayThreadProc() +{ + WCHAR strFileName[MAX_PATH]; + GetModuleFileNameW(g_hInstance, strFileName, MAX_PATH); + HMODULE hLib = LoadLibraryW(strFileName); + + CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED); + + Create(NULL); + HRESULT ret = SysTrayMessageLoop(); + + CoUninitialize(); + + FreeLibraryAndExitThread(hLib, ret); +} + +HRESULT CSysTray::CreateSysTrayThread() +{ + DbgPrint("CSysTray Init TODO: Initialize tray icon handlers.\n"); + + HANDLE hThread = CreateThread(NULL, 0, s_SysTrayThreadProc, this, 0, NULL); + + CloseHandle(hThread); + + return S_OK; +} + +HRESULT CSysTray::DestroySysTrayWindow() +{ + DestroyWindow(); + hwndSysTray = NULL; + return S_OK; +} + +CSysTray::CSysTray() {} +CSysTray::~CSysTray() {} + +// *** IOleCommandTarget methods *** +HRESULT STDMETHODCALLTYPE CSysTray::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) +{ + UNIMPLEMENTED; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CSysTray::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + if (!IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject)) + return E_FAIL; + + switch (nCmdID) + { + case OLECMDID_NEW: // init + return CreateSysTrayThread(); + case OLECMDID_SAVE: // shutdown + return DestroySysTrayWindow(); + } + return S_OK; +} + +BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID) +{ + HRESULT hr; + + if (hWnd != m_hWnd) + return FALSE; + + switch (uMsg) + { + case WM_CREATE: + InitIcons(); + SetTimer(1, 2000, NULL); + return TRUE; + case WM_TIMER: + UpdateIcons(); + return TRUE; + case WM_DESTROY: + ShutdownIcons(); + return TRUE; + } + + DbgPrint("SysTray message received %u (%08p %08p)\n", uMsg, wParam, lParam); + + hr = ProcessIconMessage(uMsg, wParam, lParam); + if (FAILED(hr)) + return FALSE; + + if (hr == S_FALSE) + return FALSE; + + return TRUE; +} BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_SysTray, CSysTray) END_OBJECT_MAP() +class CShellTrayModule : public CComModule +{ +}; + CShellTrayModule gModule; -HINSTANCE g_hInstance; HRESULT RegisterShellServiceObject(REFGUID guidClass, LPCWSTR lpName, BOOL bRegister) { @@ -157,9 +319,9 @@ DllUnregisterServer(void) STDAPI DllGetClassObject( - REFCLSID rclsid, - REFIID riid, - LPVOID *ppv) +REFCLSID rclsid, +REFIID riid, +LPVOID *ppv) { return gModule.DllGetClassObject(rclsid, riid, ppv); } diff --git a/dll/win32/stobject/stobject.rc b/dll/win32/stobject/stobject.rc index e47b00063dd..a05f7bea226 100644 --- a/dll/win32/stobject/stobject.rc +++ b/dll/win32/stobject/stobject.rc @@ -6,10 +6,10 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -IDI_ICON1 ICON "resources/1.ico" -IDI_ICON2 ICON "resources/2.ico" -IDI_ICON3 ICON "resources/3.ico" -IDI_ICON4 ICON "resources/4.ico" +IDI_BATTERY ICON "resources/1.ico" +IDI_EXTRACT ICON "resources/2.ico" +IDI_VOLUME ICON "resources/3.ico" +IDI_VOLMUTE ICON "resources/4.ico" IDR_SYSTRAY REGISTRY "resources/rgs/systray.rgs" diff --git a/media/inf/syssetup.inf b/media/inf/syssetup.inf index 06328771038..6bdfa972eb2 100644 --- a/media/inf/syssetup.inf +++ b/media/inf/syssetup.inf @@ -95,6 +95,7 @@ AddReg=Classes 11,,shell32.dll,3 11,,softpub.dll,1 11,,sti.dll,1 +11,,stobject.dll,1 11,,urlmon.dll,3 11,,vbscript.dll,1 11,,windowscodecs.dll,1 -- 2.17.1