2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/shellext/stobject/csystray.cpp
5 * PURPOSE: Systray shell service object implementation
6 * PROGRAMMERS: David Quintana <gigaherz@gmail.com>
7 * Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
12 #include <undocshell.h>
13 #include <shellutils.h>
15 SysTrayIconHandlers_t g_IconHandlers
[] = {
16 { Volume_Init
, Volume_Shutdown
, Volume_Update
, Volume_Message
},
17 { Hotplug_Init
, Hotplug_Shutdown
, Hotplug_Update
, Hotplug_Message
},
18 { Power_Init
, Power_Shutdown
, Power_Update
, Power_Message
}
20 const int g_NumIcons
= _countof(g_IconHandlers
);
22 CSysTray::CSysTray() {}
23 CSysTray::~CSysTray() {}
25 HRESULT
CSysTray::InitNetShell()
27 HRESULT hr
= CoCreateInstance(CLSID_ConnectionTray
, 0, 1u, IID_PPV_ARG(IOleCommandTarget
, &pctNetShell
));
31 return pctNetShell
->Exec(&CGID_ShellServiceObject
,
33 OLECMDEXECOPT_DODEFAULT
, NULL
, NULL
);
36 HRESULT
CSysTray::ShutdownNetShell()
40 HRESULT hr
= pctNetShell
->Exec(&CGID_ShellServiceObject
,
42 OLECMDEXECOPT_DODEFAULT
, NULL
, NULL
);
43 pctNetShell
.Release();
47 HRESULT
CSysTray::InitIcons()
49 TRACE("Initializing Notification icons...\n");
50 for (int i
= 0; i
< g_NumIcons
; i
++)
52 HRESULT hr
= g_IconHandlers
[i
].pfnInit(this);
57 return InitNetShell();
60 HRESULT
CSysTray::ShutdownIcons()
62 TRACE("Shutting down Notification icons...\n");
63 for (int i
= 0; i
< g_NumIcons
; i
++)
65 HRESULT hr
= g_IconHandlers
[i
].pfnShutdown(this);
70 return ShutdownNetShell();
73 HRESULT
CSysTray::UpdateIcons()
75 TRACE("Updating Notification icons...\n");
76 for (int i
= 0; i
< g_NumIcons
; i
++)
78 HRESULT hr
= g_IconHandlers
[i
].pfnUpdate(this);
86 HRESULT
CSysTray::ProcessIconMessage(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
)
88 for (int i
= 0; i
< g_NumIcons
; i
++)
90 HRESULT hr
= g_IconHandlers
[i
].pfnMessage(this, uMsg
, wParam
, lParam
, lResult
);
98 // Not handled by anyone, so return accordingly.
105 * Basically a Shell_NotifyIcon wrapper.
106 * Based on the parameters provided, it changes the current state of the notification icon.
109 * Determines whether to add, delete or modify the notification icon (represented by uId).
111 * Represents the particular notification icon.
113 * A handle to an icon for the notification object.
115 * A string for the tooltip of the notification.
117 * Determines whether to show or hide the notification icon.
119 * @return The error code.
122 HRESULT
CSysTray::NotifyIcon(INT code
, UINT uId
, HICON hIcon
, LPCWSTR szTip
, DWORD dwstate
)
124 NOTIFYICONDATA nim
= { 0 };
126 TRACE("NotifyIcon code=%d, uId=%d, hIcon=%p, szTip=%S\n", code
, uId
, hIcon
, szTip
);
128 nim
.cbSize
= sizeof(nim
);
129 nim
.uFlags
= NIF_MESSAGE
| NIF_ICON
| NIF_STATE
| NIF_TIP
;
132 nim
.uCallbackMessage
= uId
;
133 nim
.dwState
= dwstate
;
134 nim
.dwStateMask
= NIS_HIDDEN
;
136 nim
.uVersion
= NOTIFYICON_VERSION
;
138 StringCchCopy(nim
.szTip
, _countof(nim
.szTip
), szTip
);
141 BOOL ret
= Shell_NotifyIcon(code
, &nim
);
142 return ret
? S_OK
: E_FAIL
;
145 DWORD WINAPI
CSysTray::s_SysTrayThreadProc(PVOID param
)
147 CSysTray
* st
= (CSysTray
*) param
;
148 return st
->SysTrayThreadProc();
151 HRESULT
CSysTray::SysTrayMessageLoop()
156 while ((ret
= GetMessage(&msg
, NULL
, 0, 0)) != 0)
161 TranslateMessage(&msg
);
162 DispatchMessage(&msg
);
168 HRESULT
CSysTray::SysTrayThreadProc()
170 WCHAR strFileName
[MAX_PATH
];
171 GetModuleFileNameW(g_hInstance
, strFileName
, MAX_PATH
);
172 HMODULE hLib
= LoadLibraryW(strFileName
);
174 CoInitializeEx(NULL
, COINIT_DISABLE_OLE1DDE
| COINIT_APARTMENTTHREADED
);
178 HRESULT ret
= SysTrayMessageLoop();
182 FreeLibraryAndExitThread(hLib
, ret
);
185 HRESULT
CSysTray::CreateSysTrayThread()
187 TRACE("CSysTray Init TODO: Initialize tray icon handlers.\n");
189 HANDLE hThread
= CreateThread(NULL
, 0, s_SysTrayThreadProc
, this, 0, NULL
);
191 CloseHandle(hThread
);
196 HRESULT
CSysTray::DestroySysTrayWindow()
203 // *** IOleCommandTarget methods ***
204 HRESULT STDMETHODCALLTYPE
CSysTray::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
210 HRESULT STDMETHODCALLTYPE
CSysTray::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
212 if (!IsEqualGUID(*pguidCmdGroup
, CGID_ShellServiceObject
))
217 case OLECMDID_NEW
: // init
218 return CreateSysTrayThread();
219 case OLECMDID_SAVE
: // shutdown
220 return DestroySysTrayWindow();
225 BOOL
CSysTray::ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD dwMsgMapID
)
240 SetTimer(1, 2000, NULL
);
247 ProcessIconMessage(uMsg
, wParam
, lParam
, lResult
);
256 TRACE("SysTray message received %u (%08p %08p)\n", uMsg
, wParam
, lParam
);
258 hr
= ProcessIconMessage(uMsg
, wParam
, lParam
, lResult
);