--- /dev/null
+1 ICON "apcupsd.ico"
--- /dev/null
+/*
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ This file is patterned after the VNC Win32 code by ATT
+
+ Kern E. Sibbald, 2000
+*/
+
+#include "bacula.h"
+#include "winbacula.h"
+#include "winabout.h"
+#include "winres.h"
+
+bacAbout::bacAbout()
+{
+ visible = false;
+}
+
+bacAbout::~bacAbout() { };
+
+void bacAbout::Show(BOOL show)
+{
+ if (show && !visible) {
+ DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_ABOUT), NULL,
+ (DLGPROC)DialogProc, (LONG)this);
+ }
+}
+
+
+BOOL CALLBACK
+bacAbout::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ /* Get the dialog class pointer from USERDATA */
+ bacAbout *_this;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ /* save the dialog class pointer */
+ SetWindowLong(hwnd, GWL_USERDATA, lParam);
+ _this = (bacAbout *)lParam;
+
+ /* Show the dialog */
+ SetForegroundWindow(hwnd);
+ _this->visible = true;
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ case IDOK:
+ EndDialog(hwnd, TRUE);
+ _this = (bacAbout *)GetWindowLong(hwnd, GWL_USERDATA);
+ _this->visible = false;
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ EndDialog(hwnd, FALSE);
+ _this = (bacAbout *)GetWindowLong(hwnd, GWL_USERDATA);
+ _this->visible = false;
+ return TRUE;
+ }
+ return 0;
+}
--- /dev/null
+/*
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ This file was inspired by the VNC Win32 code by ATT
+
+ Kern E. Sibbald, 2000
+*/
+
+
+/* Object implementing the About dialog for Bacula */
+
+class bacAbout;
+
+#ifndef _WINABOUT_H_
+#define _WINABOUT_H_ 1
+
+/* Define the bacAbout class */
+class bacAbout
+{
+public:
+ bacAbout();
+ ~bacAbout();
+
+ /* The dialog box window proc */
+ static BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ void Show(BOOL show);
+
+ /* Object local storage */
+ bool visible;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+//
+// This file was part of the VNC system.
+//
+// The VNC system is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// If the source code for the VNC system is not available from the place
+// whence you received this file, check http://www.uk.research.att.com/vnc or contact
+// the authors on vnc@uk.research.att.com for information on obtaining it.
+//
+// This file has been adapted to the Win32 version of Bacula
+// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
+// the original author, for providing an excellent template.
+//
+// Copyright (2000) Kern E. Sibbald
+//
+
+
+// Application specific messages
+
+// Message used for system tray notifications
+#define WM_TRAYNOTIFY WM_USER+1
+
+// Messages used for the server object to notify windows of things
+#define WM_SRV_CLIENT_CONNECT WM_USER+2
+#define WM_SRV_CLIENT_AUTHENTICATED WM_USER+3
+#define WM_SRV_CLIENT_DISCONNECT WM_USER+4
+
+// Export the application details
+extern HINSTANCE hAppInstance;
+extern const char *szAppName;
+extern DWORD mainthreadId;
+
+// Main UPS server routine
+extern int BaculaAppMain();
+
+extern void LogErrorMsg(char *msg);
+
+// Standard command-line flag definitions
+const char BaculaRunService[] = "/service";
+const char BaculaRunServiceHelper[] = "/servicehelper";
+const char BaculaRunAsUserApp[] = "/run";
+
+const char BaculaInstallService[] = "/install";
+const char BaculaRemoveService[] = "/remove";
+
+const char BaculaShowAbout[] = "/about";
+const char BaculaShowStatus[] = "/status";
+const char BaculaShowEvents[] = "/events";
+const char BaculaKillRunningCopy[] = "/kill";
+
+const char BaculaShowHelp[] = "/help";
+
+// Usage string
+const char BaculaUsageText[] = "Bacula [/run] [/kill] [/install] [/remove] [/about] [/status] [/events]\n";
+
+void LogErrorMsg(char *msg, char *fname, int lineno);
+#define log_error_message(msg) LogErrorMsg((msg), __FILE__, __LINE__)
--- /dev/null
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ This file is patterned after the VNC Win32 code by ATT
+
+ Copyright (2000) Kern E. Sibbald
+*/
+
+
+/* Code for the Events dialogue */
+
+#include "bacula.h"
+#include "winbacula.h"
+#include "winevents.h"
+#include "winres.h"
+
+extern "C" void FillEventsBox(HWND hwnd, int id_list);
+
+bacEvents::bacEvents()
+{
+ visible = FALSE;
+}
+
+bacEvents::~bacEvents()
+{
+}
+
+/* Show the dialogue box */
+void
+bacEvents::Show(BOOL show)
+{
+ if (show && !visible) {
+ DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_EVENTS), NULL,
+ (DLGPROC)DialogProc, (LONG)this);
+ }
+}
+
+
+BOOL CALLBACK
+bacEvents::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ /* The dialog-box this pointer is in USERDATA */
+ bacEvents *_this = (bacEvents *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ /* Retrieve the Dialog box parameter */
+ SetWindowLong(hwnd, GWL_USERDATA, lParam);
+ _this = (bacEvents *)lParam;
+
+ /* Show the dialog */
+ SetForegroundWindow(hwnd);
+ _this->visible = TRUE;
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ case IDOK:
+ EndDialog(hwnd, TRUE);
+ _this->visible = FALSE;
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ EndDialog(hwnd, FALSE);
+ _this->visible = FALSE;
+ return TRUE;
+ }
+ return 0;
+}
--- /dev/null
+/* Object implementing the Events dialog for Bacula */
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+
+class bacEvents;
+
+#ifndef _win_bacEVENTS
+#define _win_bacEVENTS 1
+
+/* Define the bacEvents class */
+class bacEvents
+{
+public:
+ bacEvents();
+ ~bacEvents();
+
+ /* The dialog box window proc */
+ static BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ void Show(BOOL show);
+
+ /* Object local storage */
+ BOOL visible;
+};
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2000-2005 Kern Sibbald
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ This file is patterned after the VNC Win32 code by ATT
+
+*/
+
+#include <unistd.h>
+#include <ctype.h>
+#include "bacula.h"
+#include "winbacula.h"
+#include "wintray.h"
+#include "winservice.h"
+#include <signal.h>
+#include <pthread.h>
+
+extern int BaculaMain(int argc, char *argv[]);
+extern void terminate_stored(int sig);
+extern DWORD g_error;
+extern BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
+extern void d_msg(const char *, int, int, const char *, ...);
+
+/* Globals */
+HINSTANCE hAppInstance;
+const char *szAppName = "Bacula";
+DWORD mainthreadId;
+
+/* Imported variables */
+extern DWORD g_servicethread;
+
+#define MAX_COMMAND_ARGS 100
+static char *command_args[MAX_COMMAND_ARGS] = {"bacula-sd", NULL};
+static int num_command_args = 1;
+static pid_t main_pid;
+static pthread_t main_tid;
+
+/*
+ * WinMain parses the command line and either calls the main App
+ * routine or, under NT, the main service routine.
+ */
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ PSTR CmdLine, int iCmdShow)
+{
+ char *szCmdLine = CmdLine;
+ char *wordPtr, *tempPtr;
+ int i, quote;
+
+ /* Save the application instance and main thread id */
+ hAppInstance = hInstance;
+ mainthreadId = GetCurrentThreadId();
+
+ main_pid = getpid();
+ main_tid = pthread_self();
+
+ /*
+ * Funny things happen with the command line if the
+ * execution comes from c:/Program Files/bacula/bacula.exe
+ * We get a command line like: Files/bacula/bacula.exe" options
+ * I.e. someone stops scanning command line on a space, not
+ * realizing that the filename is quoted!!!!!!!!!!
+ * So if first character is not a double quote and
+ * the last character before first space is a double
+ * quote, we throw away the junk.
+ */
+
+ wordPtr = szCmdLine;
+ while (*wordPtr && *wordPtr != ' ')
+ wordPtr++;
+ if (wordPtr > szCmdLine) /* backup to char before space */
+ wordPtr--;
+ /* if first character is not a quote and last is, junk it */
+ if (*szCmdLine != '"' && *wordPtr == '"') {
+ szCmdLine = wordPtr + 1;
+ }
+// MessageBox(NULL, szCmdLine, "Cmdline", MB_OK);
+
+ /* Build Unix style argc *argv[] */
+
+ /* Don't NULL command_args[0] !!! */
+ for (i=1;i<MAX_COMMAND_ARGS;i++)
+ command_args[i] = NULL;
+
+ wordPtr = szCmdLine;
+ quote = 0;
+ while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
+ wordPtr++;
+ if (*wordPtr == '\"') {
+ quote = 1;
+ wordPtr++;
+ } else if (*wordPtr == '/') {
+ /* Skip Windows options */
+ while (*wordPtr && (*wordPtr != ' ' && *wordPtr != '\t'))
+ wordPtr++;
+ while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
+ wordPtr++;
+ }
+ if (*wordPtr) {
+ while (*wordPtr && num_command_args < MAX_COMMAND_ARGS) {
+ tempPtr = wordPtr;
+ if (quote) {
+ while (*tempPtr && *tempPtr != '\"')
+ tempPtr++;
+ quote = 0;
+ } else {
+ while (*tempPtr && *tempPtr != ' ')
+ tempPtr++;
+ }
+ if (*tempPtr)
+ *(tempPtr++) = '\0';
+ command_args[num_command_args++] = wordPtr;
+ wordPtr = tempPtr;
+ while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
+ wordPtr++;
+ if (*wordPtr == '\"') {
+ quote = 1;
+ wordPtr++;
+ }
+ }
+ }
+
+ /*
+ * Now process Windows command line options
+ * as defined by ATT
+ *
+ * Make the command-line lowercase and parse it
+ */
+ for (i = 0; i < (int)strlen(szCmdLine); i++) {
+ szCmdLine[i] = tolower(szCmdLine[i]);
+ }
+
+ bool argfound = false;
+ for (i = 0; i < (int)strlen(szCmdLine); i++) {
+ if (szCmdLine[i] <= ' ') {
+ continue;
+ }
+
+ if (szCmdLine[i] == '-') {
+ while (szCmdLine[i] && szCmdLine[i] != ' ') {
+ i++;
+ }
+ continue;
+ }
+
+ argfound = true;
+
+ /* Now check for command-line arguments */
+
+ /* /service helper - probably only needed on win9x */
+ if (strncmp(&szCmdLine[i], BaculaRunServiceHelper, strlen(BaculaRunServiceHelper)) == 0
+ && g_platform_id == VER_PLATFORM_WIN32_NT) {
+ /* exit with result "okay" */
+ return 0;
+ }
+
+ /* /service start service */
+ if (strncmp(&szCmdLine[i], BaculaRunService, strlen(BaculaRunService)) == 0) {
+ /* Run Bacula as a service */
+ return bacService::BaculaServiceMain();
+ }
+ /* /run (this is the default if no command line arguments) */
+ if (strncmp(&szCmdLine[i], BaculaRunAsUserApp, strlen(BaculaRunAsUserApp)) == 0) {
+ /* Bacula is being run as a user-level program */
+ return BaculaAppMain();
+ }
+ /* /install */
+ if (strncmp(&szCmdLine[i], BaculaInstallService, strlen(BaculaInstallService)) == 0) {
+ /* Install Bacula as a service */
+ bacService::InstallService();
+ i += strlen(BaculaInstallService);
+ continue;
+ }
+ /* /remove */
+ if (strncmp(&szCmdLine[i], BaculaRemoveService, strlen(BaculaRemoveService)) == 0) {
+ /* Remove the Bacula service */
+ bacService::RemoveService();
+ i += strlen(BaculaRemoveService);
+ continue;
+ }
+
+ /* /about */
+ if (strncmp(&szCmdLine[i], BaculaShowAbout, strlen(BaculaShowAbout)) == 0) {
+ /* Show Bacula's about box */
+ bacService::ShowAboutBox();
+ i += strlen(BaculaShowAbout);
+ continue;
+ }
+
+ /* /status */
+ if (strncmp(&szCmdLine[i], BaculaShowStatus, strlen(BaculaShowStatus)) == 0) {
+ /* Show Bacula's status box */
+ bacService::ShowStatus();
+ i += strlen(BaculaShowStatus);
+ continue;
+ }
+
+ /* /kill */
+ if (strncmp(&szCmdLine[i], BaculaKillRunningCopy, strlen(BaculaKillRunningCopy)) == 0) {
+ /* Kill running copy of Bacula */
+ bacService::KillRunningCopy();
+ i += strlen(BaculaKillRunningCopy);
+ continue;
+ }
+
+ /* /help */
+ if (strncmp(&szCmdLine[i], BaculaShowHelp, strlen(BaculaShowHelp)) == 0) {
+ MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK|MB_ICONINFORMATION);
+ i += strlen(BaculaShowHelp);
+ continue;
+ }
+
+ MessageBox(NULL, szCmdLine, _("Bad Command Line Options"), MB_OK);
+
+ /* Show the usage dialog */
+ MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK | MB_ICONINFORMATION);
+ break;
+ }
+
+ /* If no arguments were given then just run */
+ if (!argfound) {
+ BaculaAppMain();
+ }
+ return 0;
+}
+
+
+/*
+ * Called as a thread from BaculaAppMain()
+ * Here we handle the Windows messages
+ */
+//DWORD WINAPI Main_Msg_Loop(LPVOID lpwThreadParam)
+void *Main_Msg_Loop(LPVOID lpwThreadParam)
+{
+ DWORD old_servicethread = g_servicethread;
+
+
+ pthread_detach(pthread_self());
+
+ /* Since we are the only thread with a message loop
+ * mark ourselves as the service thread so that
+ * we can receive all the window events.
+ */
+ g_servicethread = GetCurrentThreadId();
+
+ /* Create tray icon & menu if we're running as an app */
+ bacMenu *menu = new bacMenu();
+ if (menu == NULL) {
+// log_error_message("Could not create sys tray menu");
+ PostQuitMessage(0);
+ }
+
+ /* Now enter the Windows message handling loop until told to quit! */
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0,0) ) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ if (menu != NULL) {
+ delete menu;
+ }
+
+ if (old_servicethread != 0) { /* started as NT service */
+ /* Mark that we're no longer running */
+ g_servicethread = 0;
+
+ /* Tell the service manager that we've stopped. */
+ ReportStatus(SERVICE_STOPPED, g_error, 0);
+ }
+ /* Tell main program to go away */
+ terminate_stored(0);
+
+ /* Should not get here */
+ pthread_kill(main_tid, SIGTERM); /* ask main thread to terminate */
+ sleep(1);
+ kill(main_pid, SIGTERM); /* ask main thread to terminate */
+ _exit(0);
+}
+
+
+/*
+ * This is the main routine for Bacula when running as an application
+ * (under Windows 95 or Windows NT)
+ * Under NT, Bacula can also run as a service. The BaculaServerMain routine,
+ * defined in the bacService header, is used instead when running as a service.
+ */
+int BaculaAppMain()
+{
+ /* DWORD dwThreadID; */
+ pthread_t tid;
+
+ InitWinAPIWrapper();
+
+ WSA_Init();
+
+ /* Set this process to be the last application to be shut down. */
+ if (p_SetProcessShutdownParameters) {
+ p_SetProcessShutdownParameters(0x100, 0);
+ }
+
+ HWND hservwnd = FindWindow(MENU_CLASS_NAME, NULL);
+ if (hservwnd != NULL) {
+ /* We don't allow multiple instances! */
+ MessageBox(NULL, _("Another instance of Bacula is already running"), szAppName, MB_OK);
+ _exit(0);
+ }
+
+ /* Create a thread to handle the Windows messages */
+// (void)CreateThread(NULL, 0, Main_Msg_Loop, NULL, 0, &dwThreadID);
+ pthread_create(&tid, NULL, Main_Msg_Loop, (void *)0);
+
+ /* Call the "real" Bacula */
+ BaculaMain(num_command_args, command_args);
+ PostQuitMessage(0);
+ WSACleanup();
+ _exit(0);
+}
--- /dev/null
+/*
+ * Included by bacula.rc
+ */
+
+/* Icon definitions */
+#define IDI_BACULA 100
+#define IDI_IDLE 101
+#define IDI_RUNNING 102
+#define IDI_JOB_ERROR 103
+#define IDI_JOB_WARNING 104
+#define IDR_TRAYMENU 105
+#define IDB_BACULABMP 106
+
+#define IDC_LIST 1000
+#define IDC_NONYET_LABEL 1006
+#define IDC_UPDATE_BORDER 1010
+#define IDC_APCUPSDBMP 1016
+#define IDC_VERSION 1017
+#define IDC_NAME 1018
+#define IDC_EMAIL 1019
+#define IDC_WWW 1022
+#define IDC_COPYRIGHT 1023
+#define IDACCEPT 1030
+#define IDREJECT 1031
+#define IDC_STATIC_TEXT1 1032
+#define IDC_ACCEPT_IP 1033
+#define IDC_STATIC_TEXT 1034
+#define IDC_ACCEPT_TIMEOUT 1035
+#define IDC_TRADEMARK 1036
+
+
+#define ID_PROPERTIES 40001
+#define ID_CLOSE 40002
+#define ID_KILLCLIENTS 40003
+#define ID_ABOUT 40004
+#define ID_STATUS 40005
+#define ID_DEFAULT_PROPERTIES 40006
+#define ID_EVENTS 40007
+
+/* Dialog definitions */
+#define IDD_PROPERTIES 200
+#define IDD_ABOUT 201
+#define IDD_STATUS 202
+#define IDD_EVENTS 203
+
+
--- /dev/null
+#include <winuser.h>
+#include <winver.h>
+#include "winres.h"
+#include "../../../version.h"
+
+/* NB: Internationalization of this file will require some work... */
+#define N_(s) s
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icons
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_BACULA ICON DISCARDABLE "bacula.ico"
+IDI_IDLE ICON DISCARDABLE "idle.ico"
+IDI_RUNNING ICON DISCARDABLE "running.ico"
+IDI_JOB_ERROR ICON DISCARDABLE "error.ico"
+IDI_JOB_WARNING ICON DISCARDABLE "warn.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_TRAYMENU MENU DISCARDABLE
+BEGIN
+ POPUP "tray"
+ BEGIN
+ MENUITEM N_("&Status"), ID_STATUS
+ MENUITEM N_("&Events"), ID_EVENTS
+#ifdef properties_implemented
+ MENUITEM N_("&Properties"), ID_PROPERTIES
+#endif
+ MENUITEM SEPARATOR
+ MENUITEM N_("&About Bacula"), ID_ABOUT
+ MENUITEM SEPARATOR
+ MENUITEM N_("&Close Bacula"), ID_CLOSE
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,1,0,0
+ PRODUCTVERSION 1,1,0,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0 //
+#endif
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E0" // Lang=US English, CharSet=Windows Multiligual
+ BEGIN
+ VALUE "Comments", "by Kern Sibbald\0"
+ VALUE "CompanyName", " \0"
+ VALUE "FileDescription", "Bacula File daemon for Win32\0"
+ VALUE "FileVersion", VERSION "\0"
+ VALUE "InternalName", "Bacula\0"
+ VALUE "LegalCopyright", "Copyright Kern Sibbald, 1999-2006\0"
+ VALUE "LegalTrademarks", "Licensed under GNU GPL 2.0\0"
+ VALUE "OriginalFilename", "filed.exe\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Bacula - Win32 Version\0"
+ VALUE "ProductVersion", VERSION
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252 // US English, Multilingual
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_BACULABMP BITMAP DISCARDABLE "bacula.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDI_BACULA "Bacula"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Properties Dialog
+//
+#ifdef properties_implemented
+
+IDD_PROPERTIES DIALOG DISCARDABLE 0, 0, 221, 204
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Bacula Properties"
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON N_("&Cancel"),IDCANCEL,165,25,51,15
+ DEFPUSHBUTTON N_("&OK"),IDOK,165,5,51,15
+ LTEXT "No Properites yet",IDC_NONYET_LABEL,19,30,56,15,
+ SS_CENTERIMAGE
+END
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// About Dialog
+//
+
+IDD_ABOUT DIALOG DISCARDABLE 0, 0, 250, 145
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Bacula"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,190,120,50,15
+// CONTROL "\3", IDC_BACULABMP,"Static",SS_ICON | SS_CENTERIMAGE |
+// SS_SUNKEN,7,5,73,65
+#ifndef HAVE_MINGW
+ CONTROL IDB_BACULABMP,IDB_BACULABMP,"Static",SS_BITMAP|SS_SUNKEN,7,5,32,32
+#endif
+
+ LTEXT N_(" by Kern Sibbald"),IDC_NAME,134,38,78,10
+ LTEXT N_("For more information, see:"),-1,115,60,100,10
+ LTEXT " www.bacula.org",IDC_WWW,115,70,100,10
+// LTEXT " ",-1,69,81,100,10
+// LTEXT " ",-1,90,70,100,10
+ LTEXT "Copyright (C) 1999-2006, Kern Sibbald",IDC_COPYRIGHT,7,120,175,10
+ LTEXT N_("Licensed under GNU GPL 2.0."),IDC_TRADEMARK,7,130,175,10
+ RTEXT N_("Build Date:"),-1,108,24,42,8
+ RTEXT N_("Bacula Version:"),-1,100,9,50,8
+ LTEXT VERSION,IDC_VERSION,159,10,65,8
+ LTEXT BDATE,-1,159,24,65,10
+
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Status Dialog
+//
+
+IDD_STATUS DIALOG DISCARDABLE 0, 0, 411, 244
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION N_("Bacula Status")
+FONT 8, "Courier New"
+BEGIN
+ DEFPUSHBUTTON "&OK",IDOK,355,5,51,15
+ LISTBOX IDC_LIST, 2, 2, 350, 240, WS_VSCROLL | WS_HSCROLL | WS_BORDER
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Events Dialog
+//
+
+IDD_EVENTS DIALOG DISCARDABLE 0, 0, 411, 204
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION N_("Bacula Events")
+FONT 8, "Courier New"
+BEGIN
+ DEFPUSHBUTTON "&OK",IDOK,355,5,51,15
+ LISTBOX IDC_LIST, 2, 2, 350, 200, WS_VSCROLL | WS_HSCROLL | WS_BORDER
+END
--- /dev/null
+// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+//
+// This file was part of the VNC system.
+//
+// The VNC system is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// If the source code for the VNC system is not available from the place
+// whence you received this file, check http://www.uk.research.att.com/vnc or contact
+// the authors on vnc@uk.research.att.com for information on obtaining it.
+//
+// This file has been adapted to the Win32 version of Bacula
+// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
+// the original author, for providing an excellent template.
+//
+// Copyright (2000-2003) Kern E. Sibbald
+//
+
+
+// winService
+
+// Implementation of service-oriented functionality of Bacula
+// I.e. command line options that contact a running version of
+// Bacula and ask it to do something (show about, show status,
+// show events, ...)
+
+
+#include "bacula.h"
+#include "winbacula.h"
+#include "winservice.h"
+#include "wintray.h"
+
+void set_service_description(SC_HANDLE hSCManager, SC_HANDLE hService,
+ LPSTR lpDesc);
+
+// OS-SPECIFIC ROUTINES
+
+// Create an instance of the bacService class to cause the static fields to be
+// initialised properly
+
+bacService init;
+
+bacService::bacService()
+{
+ OSVERSIONINFO osversioninfo;
+ osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
+
+ // Get the current OS version
+ if (!GetVersionEx(&osversioninfo)) {
+ g_platform_id = 0;
+ } else {
+ g_platform_id = osversioninfo.dwPlatformId;
+ }
+}
+
+
+// IsWin95 - returns a BOOL indicating whether the current OS is Win95
+BOOL
+bacService::IsWin95()
+{
+ return (g_platform_id == VER_PLATFORM_WIN32_WINDOWS);
+}
+
+// IsWinNT - returns a bool indicating whether the current OS is WinNT
+BOOL
+bacService::IsWinNT()
+{
+ return (g_platform_id == VER_PLATFORM_WIN32_NT);
+}
+
+// Internal routine to find the Bacula menu class window and
+// post a message to it!
+
+BOOL
+PostToBacula(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ // Locate the hidden Bacula menu window
+ HWND hservwnd = FindWindow(MENU_CLASS_NAME, NULL);
+ if (hservwnd == NULL) {
+ return FALSE;
+ }
+
+ // Post the message to Bacula
+ PostMessage(hservwnd, message, wParam, lParam);
+ return TRUE;
+}
+
+
+// Static routine to show the Properties dialog for a currently-running
+// copy of Bacula, (usually a servicified version.)
+
+BOOL
+bacService::ShowProperties()
+{
+ return TRUE;
+}
+
+// Static routine to show the Default Properties dialog for a currently-running
+// copy of Bacula, (usually a servicified version.)
+
+BOOL
+bacService::ShowDefaultProperties()
+{
+ return TRUE;
+}
+
+// Static routine to show the About dialog for a currently-running
+// copy of Bacula, (usually a servicified version.)
+
+BOOL
+bacService::ShowAboutBox()
+{
+ // Post to the Bacula menu window
+ if (!PostToBacula(MENU_ABOUTBOX_SHOW, 0, 0)) {
+ MessageBox(NULL, _("No existing instance of Bacula could be contacted"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// Static routine to show the Status dialog for a currently-running
+// copy of Bacula, (usually a servicified version.)
+
+BOOL
+bacService::ShowStatus()
+{
+ // Post to the Bacula menu window
+ if (!PostToBacula(MENU_STATUS_SHOW, 0, 0)) {
+ MessageBox(NULL, _("No existing instance of Bacula could be contacted"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// SERVICE-MODE ROUTINES
+
+// Service-mode defines:
+
+// Executable name
+#define BAC_APPNAME "baculasd"
+
+// Internal service name
+#define BAC_SERVICENAME "Baculasd"
+
+// Displayed service name
+#define BAC_SERVICEDISPLAYNAME "Bacula Storage Server"
+
+// List other required serves
+#define BAC_DEPENDENCIES __TEXT("tcpip\0afd\0+File System\0")
+
+
+// Internal service state
+SERVICE_STATUS g_srvstatus; // current status of the service
+SERVICE_STATUS_HANDLE g_hstatus;
+DWORD g_error = 0;
+DWORD g_servicethread = 0;
+char* g_errortext[256];
+
+
+// Forward defines of internal service functions
+void WINAPI ServiceMain(DWORD argc, char **argv);
+DWORD WINAPI ServiceWorkThread(LPVOID lpwThreadParam);
+void ServiceStop();
+void WINAPI ServiceCtrl(DWORD ctrlcode);
+bool WINAPI CtrlHandler (DWORD ctrltype);
+BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
+
+// ROUTINE TO QUERY WHETHER THIS PROCESS IS RUNNING AS A SERVICE OR NOT
+
+BOOL g_servicemode = FALSE;
+
+BOOL
+bacService::RunningAsService()
+{
+ return g_servicemode;
+}
+
+BOOL
+bacService::KillRunningCopy()
+{
+ while (PostToBacula(WM_CLOSE, 0, 0))
+ { }
+ return TRUE;
+}
+
+// SERVICE MAIN ROUTINE
+int
+bacService::BaculaServiceMain()
+{
+ // Mark that we are a service
+ g_servicemode = TRUE;
+
+ // How to run as a service depends upon the OS being used
+ switch (g_platform_id) {
+
+ // Windows 95/98/Me
+ case VER_PLATFORM_WIN32_WINDOWS:
+ {
+ // Obtain a handle to the kernel library
+ HINSTANCE kerneldll = LoadLibrary("KERNEL32.DLL");
+ if (kerneldll == NULL) {
+ MessageBox(NULL, _("KERNEL32.DLL not found: Bacula service not started"),
+ "Bacula Service", MB_OK);
+ break;
+ }
+
+ // And find the RegisterServiceProcess function
+ DWORD (WINAPI *RegisterService)(DWORD, DWORD);
+ RegisterService = (DWORD (WINAPI *)(DWORD, DWORD))
+ GetProcAddress(kerneldll, "RegisterServiceProcess");
+ if (RegisterService == NULL) {
+ MessageBox(NULL, _("Registry service not found: Bacula service not started"),
+ "Bacula Service", MB_OK);
+ log_error_message(_("Registry service not found"));
+ break;
+ }
+
+ // Register this process with the OS as a service!
+ RegisterService(0, 1);
+
+ // Run the main program as a service
+ BaculaAppMain();
+
+ // Then remove the service from the system service table
+ RegisterService(0, 0);
+
+ // Free the kernel library
+ FreeLibrary(kerneldll);
+ break;
+ }
+
+
+ // Windows NT, Win2K, WinXP
+ case VER_PLATFORM_WIN32_NT:
+ {
+ // Create a service entry table
+ SERVICE_TABLE_ENTRY dispatchTable[] = {
+ {BAC_SERVICENAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
+ {NULL, NULL}
+ };
+
+ // Call the service control dispatcher with our entry table
+ if (!StartServiceCtrlDispatcher(dispatchTable)) {
+ log_error_message(_("StartServiceCtrlDispatcher failed."));
+ }
+ break;
+ } /* end case */
+ } /* end switch */
+ return 0;
+}
+
+// SERVICE MAIN ROUTINE - NT ONLY !!!
+// NT/Win2K/WinXP ONLY !!!
+void WINAPI ServiceMain(DWORD argc, char **argv)
+{
+ DWORD dwThreadID;
+
+ // Register the service control handler
+ g_hstatus = RegisterServiceCtrlHandler(BAC_SERVICENAME, ServiceCtrl);
+
+ if (g_hstatus == 0) {
+ log_error_message(_("RegisterServiceCtlHandler failed"));
+ MessageBox(NULL, _("Contact Register Service Handler failure"),
+ "Bacula service", MB_OK);
+ return;
+ }
+
+ // Set up some standard service state values
+ g_srvstatus.dwServiceType = SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS;
+ g_srvstatus.dwServiceSpecificExitCode = 0;
+
+ // Give this status to the SCM
+ if (!ReportStatus(
+ SERVICE_START_PENDING, // Service state
+ NO_ERROR, // Exit code type
+ 45000)) { // Hint as to how long Bacula should have hung before you assume error
+
+ ReportStatus(SERVICE_STOPPED, g_error, 0);
+ log_error_message(_("ReportStatus STOPPED failed 1"));
+ return;
+ }
+
+ // Now start the service for real
+ (void)CreateThread(NULL, 0, ServiceWorkThread, NULL, 0, &dwThreadID);
+ return;
+}
+
+// SERVICE START ROUTINE - thread that calls BaculaAppMain
+// NT ONLY !!!!
+DWORD WINAPI ServiceWorkThread(LPVOID lpwThreadParam)
+{
+
+ // Save the current thread identifier
+ g_servicethread = GetCurrentThreadId();
+
+ // report the status to the service control manager.
+ //
+ if (!ReportStatus(
+ SERVICE_RUNNING, // service state
+ NO_ERROR, // exit code
+ 0)) { // wait hint
+ MessageBox(NULL, _("Report Service failure"), "Bacula Service", MB_OK);
+ log_error_message("ReportStatus RUNNING failed");
+ return 0;
+ }
+
+ /* Call Bacula main code */
+ BaculaAppMain();
+
+ /* Mark that we're no longer running */
+ g_servicethread = 0;
+
+ /* Tell the service manager that we've stopped */
+ ReportStatus(SERVICE_STOPPED, g_error, 0);
+ return 0;
+}
+
+
+// SERVICE STOP ROUTINE - post a quit message to the relevant thread
+void ServiceStop()
+{
+ // Post a quit message to the main service thread
+ if (g_servicethread != 0) {
+ PostThreadMessage(g_servicethread, WM_QUIT, 0, 0);
+ }
+}
+
+// SERVICE INSTALL ROUTINE
+int
+bacService::InstallService()
+{
+ const int pathlength = 2048;
+ char path[pathlength];
+ char servicecmd[pathlength];
+ int len;
+
+ // Get the filename of this executable
+ if (GetModuleFileName(NULL, path, pathlength-(strlen(BaculaRunService)+2)) == 0) {
+ MessageBox(NULL, _("Unable to install Bacula service"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+ }
+
+ // Append the service-start flag to the end of the path:
+ if ((int)strlen(path) + 20 + (int)strlen(BaculaRunService) < pathlength) {
+ sprintf(servicecmd, "\"%s\" %s -c \"%s", path, BaculaRunService, path);
+ len = strlen(servicecmd) - 1;
+ for ( ; len > 0; len--) {
+ if (servicecmd[len] == '\\') {
+ servicecmd[len+1] = 0;
+ break;
+ }
+ servicecmd[len] = 0;
+ }
+ strcat(servicecmd, "bacula-sd.conf\"");
+
+ } else {
+ log_error_message(_("Service command length too long"));
+ MessageBox(NULL, _("Service command length too long. Service not registered."),
+ szAppName, MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+ }
+
+ // How to add the Bacula service depends upon the OS
+ switch (g_platform_id) {
+
+ // Windows 95/98/Me
+ case VER_PLATFORM_WIN32_WINDOWS:
+ // Locate the RunService registry entry
+ HKEY runservices;
+ if (RegCreateKey(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",
+ &runservices) != ERROR_SUCCESS) {
+ log_error_message(_("Cannot write System Registry"));
+ MessageBox(NULL, _("The System Registry could not be updated - the Bacula service was not installed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ break;
+ }
+
+ // Attempt to add a Bacula key
+ if (RegSetValueEx(runservices, szAppName, 0, REG_SZ, (unsigned char *)servicecmd, strlen(servicecmd)+1) != ERROR_SUCCESS) {
+ RegCloseKey(runservices);
+ log_error_message(_("Cannot add Bacula key to System Registry"));
+ MessageBox(NULL, _("The Bacula service could not be installed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ break;
+ }
+
+ RegCloseKey(runservices);
+
+ // We have successfully installed the service!
+ MessageBox(NULL,
+ _("The Bacula File service was successfully installed.\n"
+ "The service may be started by double clicking on the\n"
+ "Bacula \"Start\" icon and will be automatically\n"
+ "be run the next time this machine is rebooted. "),
+ szAppName,
+ MB_ICONINFORMATION | MB_OK);
+ break;
+
+ // Windows NT, Win2K, WinXP
+ case VER_PLATFORM_WIN32_NT:
+ SC_HANDLE hservice;
+ SC_HANDLE hsrvmanager;
+
+ // Open the default, local Service Control Manager database
+ hsrvmanager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hsrvmanager == NULL) {
+ log_error_message("OpenSCManager failed");
+ MessageBox(NULL,
+ _("The Service Control Manager could not be contacted - the Bacula service was not installed"),
+ szAppName, MB_ICONEXCLAMATION | MB_OK);
+ break;
+ }
+
+ // Create an entry for the Bacula service
+ hservice = CreateService(
+ hsrvmanager, // SCManager database
+ BAC_SERVICENAME, // name of service
+ BAC_SERVICEDISPLAYNAME, // name to display
+ SERVICE_ALL_ACCESS, // desired access
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ // service type
+ SERVICE_AUTO_START, // start type
+ SERVICE_ERROR_NORMAL, // error control type
+ servicecmd, // service's binary
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ BAC_DEPENDENCIES, // dependencies
+ NULL, // LocalSystem account
+ NULL); // no password
+ if (hservice == NULL) {
+ CloseServiceHandle(hsrvmanager);
+ log_error_message("CreateService failed");
+ MessageBox(NULL,
+ _("The Bacula service could not be installed"),
+ szAppName, MB_ICONEXCLAMATION | MB_OK);
+ break;
+ }
+
+ set_service_description(hsrvmanager,hservice,
+_("Provides file backup and restore services. Bacula -- the network backup solution."));
+
+ CloseServiceHandle(hsrvmanager);
+ CloseServiceHandle(hservice);
+
+ // Everything went fine
+ MessageBox(NULL,
+ _("The Bacula File service was successfully installed.\n"
+ "The service may be started from the Control Panel and will\n"
+ "automatically be run the next time this machine is rebooted."),
+ szAppName,
+ MB_ICONINFORMATION | MB_OK);
+ break;
+ default:
+ log_error_message("Unknown Windows System version");
+ MessageBox(NULL,
+ _("Unknown Windows operating system.\n"
+ "Cannot install Bacula service.\n"),
+ szAppName, MB_ICONEXCLAMATION | MB_OK);
+ break;
+ };
+
+ return 0;
+}
+
+
+// SERVICE REMOVE ROUTINE
+int
+bacService::RemoveService()
+{
+ // How to remove the Bacula service depends upon the OS
+ switch (g_platform_id) {
+
+ // Windows 95/98/Me
+ case VER_PLATFORM_WIN32_WINDOWS:
+ // Locate the RunService registry entry
+ HKEY runservices;
+ if (RegOpenKey(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",
+ &runservices) != ERROR_SUCCESS) {
+ MessageBox(NULL,
+ _("Could not find registry entry.\nService probably not registerd - the Bacula service was not removed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ } else {
+ // Attempt to delete the Bacula key
+ if (RegDeleteValue(runservices, szAppName) != ERROR_SUCCESS) {
+ RegCloseKey(runservices);
+ MessageBox(NULL, _("Could not delete Registry key.\nThe Bacula service could not be removed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ }
+
+ RegCloseKey(runservices);
+ break;
+ }
+
+ // Try to kill any running copy of Bacula
+ if (!KillRunningCopy()) {
+ MessageBox(NULL,
+ _("Bacula could not be contacted, probably not running"),
+ szAppName, MB_ICONEXCLAMATION | MB_OK);
+ break;
+ }
+
+ // We have successfully removed the service!
+ MessageBox(NULL, _("The Bacula service has been removed"), szAppName, MB_ICONINFORMATION | MB_OK);
+ break;
+
+ // Windows NT, Win2K, WinXP
+ case VER_PLATFORM_WIN32_NT:
+ SC_HANDLE hservice;
+ SC_HANDLE hsrvmanager;
+
+ // Open the SCM
+ hsrvmanager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+ if (hsrvmanager) {
+ hservice = OpenService(hsrvmanager, BAC_SERVICENAME, SERVICE_ALL_ACCESS);
+ if (hservice != NULL) {
+ SERVICE_STATUS status;
+
+ // Try to stop the Bacula service
+ if (ControlService(hservice, SERVICE_CONTROL_STOP, &status)) {
+ while(QueryServiceStatus(hservice, &status)) {
+ if (status.dwCurrentState == SERVICE_STOP_PENDING) {
+ Sleep(1000);
+ } else {
+ break;
+ }
+ }
+
+ if (status.dwCurrentState != SERVICE_STOPPED) {
+ MessageBox(NULL, _("The Bacula service could not be stopped"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ }
+ }
+
+ // Now remove the service from the SCM
+ if(DeleteService(hservice)) {
+ MessageBox(NULL, _("The Bacula service has been removed"), szAppName, MB_ICONINFORMATION | MB_OK);
+ } else {
+ MessageBox(NULL, _("The Bacula service could not be removed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ }
+
+ CloseServiceHandle(hservice);
+ } else {
+ MessageBox(NULL, _("The Bacula service could not be found"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ }
+
+ CloseServiceHandle(hsrvmanager);
+ } else {
+ MessageBox(NULL, _("The SCM could not be contacted - the Bacula service was not removed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
+ }
+ break;
+ }
+ return 0;
+}
+
+// USEFUL SERVICE SUPPORT ROUTINES
+
+// Service control routine
+void WINAPI ServiceCtrl(DWORD ctrlcode)
+{
+ // What control code have we been sent?
+ switch(ctrlcode) {
+ case SERVICE_CONTROL_STOP:
+ // STOP : The service must stop
+ g_srvstatus.dwCurrentState = SERVICE_STOP_PENDING;
+ ServiceStop();
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ // QUERY : Service control manager just wants to know our state
+ break;
+
+ default:
+ // Control code not recognised
+ break;
+ }
+
+ // Tell the control manager what we're up to.
+ ReportStatus(g_srvstatus.dwCurrentState, NO_ERROR, 0);
+}
+
+// Service manager status reporting
+BOOL ReportStatus(DWORD state,
+ DWORD exitcode,
+ DWORD waithint)
+{
+ static DWORD checkpoint = 1;
+ BOOL result = TRUE;
+
+ // If we're in the start state then we don't want the control manager
+ // sending us control messages because they'll confuse us.
+ if (state == SERVICE_START_PENDING) {
+ g_srvstatus.dwControlsAccepted = 0;
+ } else {
+ g_srvstatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+ }
+
+ // Save the new status we've been given
+ g_srvstatus.dwCurrentState = state;
+ g_srvstatus.dwWin32ExitCode = exitcode;
+ g_srvstatus.dwWaitHint = waithint;
+
+ // Update the checkpoint variable to let the SCM know that we
+ // haven't died if requests take a long time
+ if ((state == SERVICE_RUNNING) || (state == SERVICE_STOPPED)) {
+ g_srvstatus.dwCheckPoint = 0;
+ } else {
+ g_srvstatus.dwCheckPoint = checkpoint++;
+ }
+
+ // Tell the SCM our new status
+ if (!(result = SetServiceStatus(g_hstatus, &g_srvstatus))) {
+ log_error_message(_("SetServiceStatus failed"));
+ }
+
+ return result;
+}
+
+// Error reporting
+void LogErrorMsg(char *message, char *fname, int lineno)
+{
+ char msgbuff[256];
+ HANDLE heventsrc;
+ char * strings[32];
+ LPTSTR msg;
+
+ // Get the error code
+ g_error = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ g_error,
+ 0,
+ (LPTSTR)&msg,
+ 0,
+ NULL);
+
+ // Use event logging to log the error
+ heventsrc = RegisterEventSource(NULL, BAC_SERVICENAME);
+
+ sprintf(msgbuff, _("\n\n%s error: %ld at %s:%d"),
+ BAC_SERVICENAME, g_error, fname, lineno);
+ strings[0] = msgbuff;
+ strings[1] = message;
+ strings[2] = msg;
+
+ if (heventsrc != NULL) {
+ MessageBeep(MB_OK);
+
+ ReportEvent(
+ heventsrc, // handle of event source
+ EVENTLOG_ERROR_TYPE, // event type
+ 0, // event category
+ 0, // event ID
+ NULL, // current user's SID
+ 3, // strings in 'strings'
+ 0, // no bytes of raw data
+ (const char **)strings, // array of error strings
+ NULL); // no raw data
+
+ DeregisterEventSource(heventsrc);
+ }
+ LocalFree(msg);
+}
+typedef BOOL (WINAPI * WinAPI)(SC_HANDLE, DWORD, LPVOID);
+
+void set_service_description(SC_HANDLE hSCManager, SC_HANDLE hService,
+ LPSTR lpDesc)
+{
+ SC_LOCK sclLock;
+ LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf;
+ SERVICE_DESCRIPTION sdBuf;
+ DWORD dwBytesNeeded;
+ WinAPI ChangeServiceDescription;
+
+ HINSTANCE hLib = LoadLibrary("ADVAPI32.DLL");
+ if (!hLib) {
+ return;
+ }
+ ChangeServiceDescription = (WinAPI)GetProcAddress(hLib,
+ "ChangeServiceConfig2A");
+ FreeLibrary(hLib);
+ if (!ChangeServiceDescription) {
+ return;
+ }
+
+ // Need to acquire database lock before reconfiguring.
+ sclLock = LockServiceDatabase(hSCManager);
+
+ // If the database cannot be locked, report the details.
+ if (sclLock == NULL) {
+ // Exit if the database is not locked by another process.
+ if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) {
+ log_error_message("LockServiceDatabase");
+ return;
+ }
+
+ // Allocate a buffer to get details about the lock.
+ lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS)LocalAlloc(
+ LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256);
+ if (lpqslsBuf == NULL) {
+ log_error_message("LocalAlloc");
+ return;
+ }
+
+ // Get and print the lock status information.
+ if (!QueryServiceLockStatus(
+ hSCManager,
+ lpqslsBuf,
+ sizeof(QUERY_SERVICE_LOCK_STATUS)+256,
+ &dwBytesNeeded)) {
+ log_error_message("QueryServiceLockStatus");
+ }
+
+ if (lpqslsBuf->fIsLocked) {
+ printf(_("Locked by: %s, duration: %ld seconds\n"),
+ lpqslsBuf->lpLockOwner,
+ lpqslsBuf->dwLockDuration);
+ } else {
+ printf(_("No longer locked\n"));
+ }
+
+ LocalFree(lpqslsBuf);
+ log_error_message(_("Could not lock database"));
+ return;
+ }
+
+ // The database is locked, so it is safe to make changes.
+
+ sdBuf.lpDescription = lpDesc;
+
+ if (!ChangeServiceDescription(
+ hService, // handle to service
+ SERVICE_CONFIG_DESCRIPTION, // change: description
+ &sdBuf) ) { // value: new description
+ log_error_message("ChangeServiceConfig2");
+ }
+
+ // Release the database lock.
+ UnlockServiceDatabase(sclLock);
+}
--- /dev/null
+// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+//
+// This file was part of the ups system.
+//
+// The ups system is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// If the source code for the ups system is not available from the place
+// whence you received this file, check http://www.uk.research.att.com/vnc or contact
+// the authors on ups@uk.research.att.com for information on obtaining it.
+//
+// This file has been adapted to the Win32 version of Bacula
+// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
+// the original author, for providing an excellent template.
+//
+// Copyright (2000) Kern E. Sibbald
+//
+
+
+// winservice.cpp
+
+// SERVICE-MODE CODE
+
+// This class provides access to service-oriented routines, under both
+// Windows NT and Windows 95. Some routines only operate under one
+// OS, others operate under any OS.
+
+class bacService;
+
+#if (!defined(_win_bacService))
+#define _win_bacService
+
+// The NT-specific code wrapper class
+class bacService
+{
+public:
+ bacService();
+
+ // SERVICE INSTALL & START FUNCTIONS
+
+ // Routine called by WinMain to cause Bacula to be installed
+ // as a service.
+ static int BaculaServiceMain();
+
+ // Routine to install the Apcupsd service on the local machine
+ static int InstallService();
+
+ // Routine to remove the Apcupsd service from the local machine
+ static int RemoveService();
+
+ // SERVICE SUPPORT FUNCTIONS
+
+ // Routine to establish and return the currently logged in user name
+ static BOOL CurrentUser(char *buffer, UINT size);
+
+ // Routine to post a message to the currently running Apcupsd server
+ // to pass it a handle to the current user
+ static BOOL PostUserHelperMessage();
+ // Routine to process a user helper message
+ static BOOL ProcessUserHelperMessage(WPARAM wParam, LPARAM lParam);
+
+ // Routines to establish which OS we're running on
+ static BOOL IsWin95();
+ static BOOL IsWinNT();
+
+ // Routine to establish whether the current instance is running
+ // as a service or not
+ static BOOL RunningAsService();
+
+ // Routine to kill any other running copy of Apcupsd
+ static BOOL KillRunningCopy();
+
+ // Routine to set the current thread into the given desktop
+ static BOOL SelectHDESK(HDESK newdesktop);
+
+ // Routine to set the current thread into the named desktop,
+ // or the input desktop if no name is given
+ static BOOL SelectDesktop(char *name);
+
+ // Routine to establish whether the current thread desktop is the
+ // current user input one
+ static BOOL InputDesktopSelected();
+
+ // Routine to fake a CtrlAltDel to winlogon when required.
+ // *** This is a nasty little hack...
+ static BOOL SimulateCtrlAltDel();
+
+ // Routine to make any currently running version of Apcupsd show its
+ // Properties dialog, to allow the user to make changes to their settings
+ static BOOL ShowProperties();
+
+ // Routine to make any currently running version of Apcupsd show the
+ // Properties dialog for the default settings, so the user can make changes
+ static BOOL ShowDefaultProperties();
+
+ // Routine to make the an already running copy of Apcupsd bring up its
+ // About box so you can check the version!
+ static BOOL ShowAboutBox();
+
+ // Routine to make the an already running copy of Apcupsd bring up its
+ // Status dialog
+ static BOOL ShowStatus();
+
+ // Routine to make the an already running copy of Apcupsd bring up its
+ // Events dialog
+ static BOOL ShowEvents();
+
+ // Routine to make an already running copy of Apcupsd form an outgoing
+ // connection to a new ups client
+ static BOOL PostAddNewClient(unsigned long ipaddress);
+};
+
+#endif
--- /dev/null
+/*
+ * Bacula File daemon Status Dialog box
+ *
+ * Inspired from the VNC code by ATT.
+ *
+ * Copyright (2000) Kern E. Sibbald
+ *
+ */
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "bacula.h"
+#include "winbacula.h"
+#include "winstat.h"
+#include "winres.h"
+
+extern void FillStatusBox(HWND hwnd, int id_list);
+
+bacStatus::bacStatus()
+{
+ visible = FALSE;
+}
+
+bacStatus::~bacStatus()
+{
+}
+
+
+/* Dialog box handling functions */
+void
+bacStatus::Show(BOOL show)
+{
+ if (show && !visible) {
+ DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_STATUS), NULL,
+ (DLGPROC)DialogProc, (LONG)this);
+ }
+}
+
+BOOL CALLBACK
+bacStatus::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ /* Get class pointer from user data */
+ bacStatus *_this = (bacStatus *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ /* Set class pointer in user data */
+ SetWindowLong(hwnd, GWL_USERDATA, lParam);
+ _this = (bacStatus *)lParam;
+
+ /* show the dialog */
+ SetForegroundWindow(hwnd);
+
+ /* Update every 5 seconds */
+ SetTimer(hwnd, 1, 5000, NULL);
+ _this->visible = TRUE;
+ FillStatusBox(hwnd, IDC_LIST);
+ return TRUE;
+
+ case WM_TIMER:
+ FillStatusBox(hwnd, IDC_LIST);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ case IDOK:
+ KillTimer(hwnd, 1);
+ EndDialog(hwnd, TRUE);
+ _this->visible = FALSE;
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ KillTimer(hwnd, 1);
+ EndDialog(hwnd, FALSE);
+ _this->visible = FALSE;
+ return TRUE;
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * Bacula Status Dialog header file
+ *
+ */
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+
+class bacStatus;
+
+#ifndef _WINSTAT_H_
+#define _WINSTAT_H_
+
+class bacStatus
+{
+public:
+ bacStatus();
+ ~bacStatus();
+
+ /* The Windows callback routine */
+ static BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ void Show(BOOL show);
+
+ BOOL visible;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+//
+// This file was part of the vnc system.
+//
+// The vnc system is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// If the source code for the vnc system is not available from the place
+// whence you received this file, check http://www.uk.research.att.com/vnc or contact
+// the authors on vnc@uk.research.att.com for information on obtaining it.
+//
+// This file has been adapted to the Win32 version of Bacula
+// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
+// the original author, for providing an excellent template.
+//
+// Copyright 2000-2004, Kern E. Sibbald
+//
+
+
+
+// Tray
+
+// Implementation of a system tray icon & menu for Bacula
+
+#include "bacula.h"
+#include "winbacula.h"
+#include "winservice.h"
+#include "winres.h"
+
+// Header
+
+#include "wintray.h"
+#include "bacula.h"
+#include "jcr.h"
+
+// Constants
+#ifdef properties_implemented
+const UINT MENU_PROPERTIES_SHOW = RegisterWindowMessage("Bacula.Properties.User.Show");
+const UINT MENU_DEFAULT_PROPERTIES_SHOW = RegisterWindowMessage("Bacula.Properties.Default.Show");
+#endif
+const UINT MENU_ABOUTBOX_SHOW = RegisterWindowMessage("Bacula.AboutBox.Show");
+const UINT MENU_STATUS_SHOW = RegisterWindowMessage("Bacula.Status.Show");
+const UINT MENU_EVENTS_SHOW = RegisterWindowMessage("Bacula.Events.Show");
+const UINT MENU_SERVICEHELPER_MSG = RegisterWindowMessage("Bacula.ServiceHelper.Message");
+const UINT MENU_ADD_CLIENT_MSG = RegisterWindowMessage("Bacula.AddClient.Message");
+const char *MENU_CLASS_NAME = "BaculaSD Tray Icon";
+
+extern void terminate_stored(int sig);
+extern char *bac_status(char *buf, int buf_len);
+extern int bacstat;
+
+// Implementation
+
+bacMenu::bacMenu()
+{
+ // Create a dummy window to handle tray icon messages
+ WNDCLASSEX wndclass;
+
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = bacMenu::WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hAppInstance;
+ wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wndclass.lpszMenuName = (const char *) NULL;
+ wndclass.lpszClassName = MENU_CLASS_NAME;
+ wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+
+ RegisterClassEx(&wndclass);
+
+ m_hwnd = CreateWindow(MENU_CLASS_NAME,
+ MENU_CLASS_NAME,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ 200, 200,
+ NULL,
+ NULL,
+ hAppInstance,
+ NULL);
+ if (m_hwnd == NULL) {
+ PostQuitMessage(0);
+ return;
+ }
+
+ // record which client created this window
+ SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this);
+
+ // Timer to trigger icon updating
+ SetTimer(m_hwnd, 1, 5000, NULL);
+
+ // Load the icons for the tray
+ m_idle_icon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_IDLE));
+ m_running_icon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_RUNNING));
+ m_error_icon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_JOB_ERROR));
+ m_warn_icon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_JOB_WARNING));
+
+ // Load the popup menu
+ m_hmenu = LoadMenu(hAppInstance, MAKEINTRESOURCE(IDR_TRAYMENU));
+
+ // Install the tray icon!
+ AddTrayIcon();
+}
+
+bacMenu::~bacMenu()
+{
+ // Remove the tray icon
+ SendTrayMsg(NIM_DELETE, 0);
+
+ // Destroy the loaded menu
+ if (m_hmenu != NULL)
+ DestroyMenu(m_hmenu);
+}
+
+void
+bacMenu::AddTrayIcon()
+{
+ SendTrayMsg(NIM_ADD, bacstat);
+}
+
+void
+bacMenu::DelTrayIcon()
+{
+ SendTrayMsg(NIM_DELETE, 0);
+}
+
+
+void
+bacMenu::UpdateTrayIcon(int bacstat)
+{
+ (void *)bac_status(NULL, 0);
+ SendTrayMsg(NIM_MODIFY, bacstat);
+}
+
+void
+bacMenu::SendTrayMsg(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 resource string as tip if there is one
+ if (LoadString(hAppInstance, IDI_BACULA, m_nid.szTip, sizeof(m_nid.szTip))) {
+ m_nid.uFlags |= NIF_TIP;
+ }
+
+ // Try to add the Bacula status to the tip string, if possible
+ if (m_nid.uFlags & NIF_TIP) {
+ bac_status(m_nid.szTip, sizeof(m_nid.szTip));
+ }
+
+ // Send the message
+ if (Shell_NotifyIcon(msg, &m_nid)) {
+ EnableMenuItem(m_hmenu, ID_CLOSE, MF_ENABLED);
+ } else {
+ if (!bacService::RunningAsService()) {
+ if (msg == NIM_ADD) {
+ // The tray icon couldn't be created, so use the Properties dialog
+ // as the main program window
+ // removed because it causes quit when not running as a
+ // service in use with BartPe.
+ // PostQuitMessage(0);
+ }
+ }
+ }
+}
+
+// Process window messages
+LRESULT CALLBACK bacMenu::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ // This is a static method, so we don't know which instantiation we're
+ // dealing with. We use Allen Hadden's (ahadden@taratec.com) suggestion
+ // from a newsgroup to get the pseudo-this.
+ bacMenu *_this = (bacMenu *) GetWindowLong(hwnd, GWL_USERDATA);
+
+ switch (iMsg) {
+
+ // Every five seconds, a timer message causes the icon to update
+ case WM_TIMER:
+ // *** HACK for running servicified
+ if (bacService::RunningAsService()) {
+ // Attempt to add the icon if it's not already there
+ _this->AddTrayIcon();
+ }
+
+ // Update the icon
+ _this->UpdateTrayIcon(bacstat);
+ break;
+
+ // STANDARD MESSAGE HANDLING
+ case WM_CREATE:
+ return 0;
+
+ case WM_COMMAND:
+ // User has clicked an item on the tray menu
+ switch (LOWORD(wParam)) {
+ case ID_STATUS:
+ // Show the status dialog
+ _this->m_status.Show(TRUE);
+ _this->UpdateTrayIcon(bacstat);
+ break;
+
+ case ID_EVENTS:
+ // Show the Events dialog
+ _this->m_events.Show(TRUE);
+ _this->UpdateTrayIcon(bacstat);
+ break;
+
+
+ case ID_KILLCLIENTS:
+ // Disconnect all currently connected clients
+ break;
+
+ case ID_ABOUT:
+ // Show the About box
+ _this->m_about.Show(TRUE);
+ break;
+
+ case ID_CLOSE:
+ // User selected Close from the tray menu
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ break;
+
+ }
+ return 0;
+
+ case WM_TRAYNOTIFY:
+ // User has clicked on the tray icon or the menu
+ {
+ // Get the submenu to use as a pop-up menu
+ HMENU submenu = GetSubMenu(_this->m_hmenu, 0);
+
+ // What event are we responding to, RMB click?
+ if (lParam==WM_RBUTTONUP) {
+ if (submenu == NULL) {
+ return 0;
+ }
+
+ // Make the first menu item the default (bold font)
+ SetMenuDefaultItem(submenu, 0, TRUE);
+
+ // Get the current cursor position, to display the menu at
+ POINT mouse;
+ GetCursorPos(&mouse);
+
+ // There's a "bug"
+ // (Microsoft calls it a feature) in Windows 95 that requires calling
+ // SetForegroundWindow. To find out more, search for Q135788 in MSDN.
+ //
+ SetForegroundWindow(_this->m_nid.hWnd);
+
+ // Display the menu at the desired position
+ TrackPopupMenu(submenu,
+ 0, mouse.x, mouse.y, 0,
+ _this->m_nid.hWnd, NULL);
+
+ return 0;
+ }
+
+ // Or was there a LMB double click?
+ if (lParam==WM_LBUTTONDBLCLK) {
+ // double click: execute first menu item
+ SendMessage(_this->m_nid.hWnd,
+ WM_COMMAND,
+ GetMenuItemID(submenu, 0),
+ 0);
+ }
+
+ return 0;
+ }
+
+ case WM_CLOSE:
+ terminate_stored(0);
+ break;
+
+ case WM_DESTROY:
+ // The user wants Bacula to quit cleanly...
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_QUERYENDSESSION:
+ // Are we running as a system service?
+ // Or is the system shutting down (in which case we should check anyway!)
+ if ((!bacService::RunningAsService()) || (lParam == 0)) {
+ // No, so we are about to be killed
+
+ // If there are remote connections then we should verify
+ // that the user is happy about killing them.
+
+ // Finally, post a quit message, just in case
+ PostQuitMessage(0);
+ return TRUE;
+ }
+ return TRUE;
+
+
+ default:
+ if (iMsg == MENU_ABOUTBOX_SHOW) {
+ // External request to show our About dialog
+ PostMessage(hwnd, WM_COMMAND, MAKELONG(ID_ABOUT, 0), 0);
+ return 0;
+ }
+ if (iMsg == MENU_STATUS_SHOW) {
+ // External request to show our status
+ PostMessage(hwnd, WM_COMMAND, MAKELONG(ID_STATUS, 0), 0);
+ return 0;
+ }
+ }
+
+ // Message not recognised
+ return DefWindowProc(hwnd, iMsg, wParam, lParam);
+}
--- /dev/null
+// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+//
+// This file was part of the VNC system.
+//
+// The VNC system is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// If the source code for the VNC system is not available from the place
+// whence you received this file, check http://www.uk.research.att.com/vnc or contact
+// the authors on vnc@uk.research.att.com for information on obtaining it.
+//
+// This file has been adapted to the Win32 version of Bacula
+// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
+// the original author, for providing an excellent template.
+//
+// Copyright (2000) Kern E. Sibbald
+//
+
+
+
+// winMenu
+
+// This class handles creation of a system-tray icon & menu
+
+class bacMenu;
+
+#if (!defined(_win_bacMENU))
+#define _win_bacMENU
+
+#include "winabout.h"
+#include "winstat.h"
+#include "winevents.h"
+
+// Constants
+extern const UINT MENU_ABOUTBOX_SHOW;
+extern const UINT MENU_STATUS_SHOW;
+extern const UINT MENU_EVENTS_SHOW;
+extern const UINT MENU_SERVICEHELPER_MSG;
+extern const UINT MENU_ADD_CLIENT_MSG;
+extern const char *MENU_CLASS_NAME;
+
+// The tray menu class itself
+class bacMenu
+{
+public:
+ bacMenu();
+ ~bacMenu();
+protected:
+ // Tray icon handling
+ void AddTrayIcon();
+ void DelTrayIcon();
+ void UpdateTrayIcon(int battstat);
+ void SendTrayMsg(DWORD msg, int battstat);
+
+ // Message handler for the tray window
+ static LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
+
+ // Fields
+protected:
+
+ // About dialog for this server
+ bacAbout m_about;
+
+ // Status dialog for this server
+ bacStatus m_status;
+
+ bacEvents m_events;
+
+ HWND m_hwnd;
+ HMENU m_hmenu;
+ NOTIFYICONDATA m_nid;
+
+ // The icon handles
+ HICON m_idle_icon;
+ HICON m_running_icon;
+ HICON m_error_icon;
+ HICON m_warn_icon;
+};
+
+
+#endif