--- /dev/null
+/*
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2018 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
+*/
+/*
+ *
+ * Kern Sibbald, August 2007
+ *
+ * This is a generic tray monitor routine, which is used by all three
+ * of the daemons. Each one compiles it with slightly different
+ * #defines.
+ *
+ */
+
+#include "bacula.h"
+#include "jcr.h"
+#include "win32.h"
+
+trayMonitor::trayMonitor()
+{
+
+// m_tbcreated_msg = RegisterWindowMessage("TaskbarCreated");
+
+ /* Create a window to handle tray icon messages */
+ WNDCLASSEX trayclass;
+
+ trayclass.cbSize = sizeof(trayclass);
+ trayclass.style = 0;
+ trayclass.lpfnWndProc = trayMonitor::trayWinProc;
+ trayclass.cbClsExtra = 0;
+ trayclass.cbWndExtra = 0;
+ trayclass.hInstance = appInstance;
+ trayclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ trayclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ trayclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ trayclass.lpszMenuName = NULL;
+ trayclass.lpszClassName = APP_NAME;
+ trayclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+
+ RegisterClassEx(&trayclass);
+
+ m_hwnd = CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
+ NULL, NULL, appInstance, NULL);
+ if (!m_hwnd) {
+ PostQuitMessage(0);
+ return;
+ }
+
+ /* Save our class pointer */
+ SetWindowLong(m_hwnd, GWL_USERDATA, (LPARAM)this);
+
+
+ // Load the icons for the tray
+ m_idle_icon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_IDLE));
+ m_running_icon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_RUNNING));
+ m_error_icon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_JOB_ERROR));
+ m_warn_icon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_JOB_WARNING));
+
+ /* Load the menu */
+ m_hmenu = LoadMenu(appInstance, MAKEINTRESOURCE(IDR_TRAYMENU));
+ m_visible = false;
+ m_installed = false;
+
+ /* Install the icon in the tray */
+ install();
+
+ /* Timer to trigger icon updating */
+ SetTimer(m_hwnd, 1, 5000, NULL);
+}
+
+trayMonitor::~trayMonitor()
+{
+ /* Remove the icon from the tray */
+ sendMessage(NIM_DELETE, 0);
+
+ if (m_hmenu) {
+ DestroyMenu(m_hmenu);
+ m_hmenu = NULL;
+ }
+}
+
+void trayMonitor::install()
+{
+ m_installed = true;
+ sendMessage(NIM_ADD, bacstat);
+}
+
+void trayMonitor::update(int bacstat)
+{
+ if (!m_installed) {
+ install();
+ }
+ (void)bac_status(NULL, 0);
+ sendMessage(NIM_MODIFY, bacstat);
+}
+
+void trayMonitor::sendMessage(DWORD msg, int bacstat)
+{
+ struct s_last_job *job;
+
+ // Create the tray icon message
+ m_nid.hWnd = m_hwnd;
+ m_nid.cbSize = sizeof(m_nid);
+ m_nid.uID = IDI_BACULA; // never changes after construction
+ switch (bacstat) {
+ case 0:
+ m_nid.hIcon = m_idle_icon;
+ break;
+ case JS_Running:
+ m_nid.hIcon = m_running_icon;
+ break;
+ case JS_ErrorTerminated:
+ m_nid.hIcon = m_error_icon;
+ break;
+ default:
+ if (last_jobs->size() > 0) {
+ job = (struct s_last_job *)last_jobs->last();
+ if (job->Errors) {
+ m_nid.hIcon = m_warn_icon;
+ } else {
+ m_nid.hIcon = m_idle_icon;
+ }
+ } else {
+ m_nid.hIcon = m_idle_icon;
+ }
+ break;
+ }
+
+ m_nid.uFlags = NIF_ICON | NIF_MESSAGE;
+ m_nid.uCallbackMessage = WM_TRAYNOTIFY;
+
+
+ /* Use the resource string as tip */
+ if (LoadString(appInstance, IDI_BACULA, m_nid.szTip, sizeof(m_nid.szTip))) {
+ m_nid.uFlags |= NIF_TIP;
+ }
+
+ /* Add the Bacula status to the tip string */
+ if (m_nid.uFlags & NIF_TIP) {
+ bac_status(m_nid.szTip, sizeof(m_nid.szTip));
+ }
+
+ if (Shell_NotifyIcon(msg, &m_nid)) {
+ EnableMenuItem(m_hmenu, ID_CLOSE, MF_ENABLED);
+ }
+}
+
+/*
+ * This is the windows call back for our tray window
+ */
+LRESULT CALLBACK trayMonitor::trayWinProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ HMENU menu;
+ trayMonitor *mon = (trayMonitor *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (iMsg) {
+
+ /* Every five seconds, a timer message causes the icon to update */
+ case WM_TIMER:
+ if (isAService()) {
+ mon->install();
+ }
+ mon->update(bacstat);
+ break;
+
+ case WM_CREATE:
+ return 0;
+
+ case WM_COMMAND:
+ /* User has clicked an item on the tray monitor menu */
+ switch (LOWORD(wParam)) {
+ case ID_STATUS:
+ /* show the dialog box */
+ mon->m_status.show(true);
+ mon->update(bacstat);
+ break;
+
+ case ID_ABOUT:
+ /* Show the About box */
+ mon->m_about.show(true);
+ break;
+
+ /* This is turned off now */
+#ifdef xxx
+ case ID_CLOSE:
+ /* User selected Close from the tray menu */
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ break;
+#endif
+
+ }
+ return 0;
+
+ /* Our special command to check for mouse events */
+ case WM_TRAYNOTIFY:
+ /* Right button click pops up the menu */
+ if (lParam == WM_RBUTTONUP) {
+ POINT mouse;
+ /* Get the menu and pop it up */
+ menu = GetSubMenu(mon->m_hmenu, 0);
+ if (!menu) {
+ return 0;
+ }
+
+ /* The first menu item (Status) is the default */
+ SetMenuDefaultItem(menu, 0, TRUE);
+ GetCursorPos(&mouse);
+ SetForegroundWindow(mon->m_nid.hWnd); /* display the menu */
+
+ /* Open the menu at the mouse position */
+ TrackPopupMenu(menu, 0, mouse.x, mouse.y, 0, mon->m_nid.hWnd, NULL);
+
+ /* Left double click brings up status dialog directly */
+ } else if (lParam == WM_LBUTTONDBLCLK) {
+ mon->m_status.show(true);
+ mon->update(bacstat);
+ }
+ return 0;
+
+ case WM_CLOSE:
+ if (isAService()) {
+ mon->sendMessage(NIM_DELETE, 0);
+ }
+ terminate_app(0);
+ break;
+
+ case WM_DESTROY:
+ /* zap everything */
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_QUERYENDSESSION:
+ if (!isAService() || lParam == 0) {
+ PostQuitMessage(0);
+ return TRUE;
+ }
+ return TRUE;
+
+ default:
+ /* Need to redraw tray icon */
+// if (iMsg == mon->m_tbcreated_msg) {
+// mon->install();
+// }
+ break;
+ }
+
+ return DefWindowProc(hwnd, iMsg, wParam, lParam);
+}