]> git.sur5r.net Git - bacula/bacula/commitdiff
Add some missed files.
authorRobert Nelson <robertn@the-nelsons.org>
Thu, 27 Jul 2006 02:50:26 +0000 (02:50 +0000)
committerRobert Nelson <robertn@the-nelsons.org>
Thu, 27 Jul 2006 02:50:26 +0000 (02:50 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3183 91ce42f0-d328-0410-95d8-f526ca767f89

22 files changed:
bacula/src/win32/stored/baculasd/bacula.bmp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/bacula.ico [new file with mode: 0644]
bacula/src/win32/stored/baculasd/bacula.rc [new file with mode: 0644]
bacula/src/win32/stored/baculasd/error.ico [new file with mode: 0644]
bacula/src/win32/stored/baculasd/idle.ico [new file with mode: 0644]
bacula/src/win32/stored/baculasd/running.ico [new file with mode: 0644]
bacula/src/win32/stored/baculasd/saving.ico [new file with mode: 0644]
bacula/src/win32/stored/baculasd/warn.ico [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winabout.cpp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winabout.h [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winbacula.h [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winevents.cpp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winevents.h [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winmain.cpp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winres.h [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winres.rc [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winservice.cpp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winservice.h [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winstat.cpp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/winstat.h [new file with mode: 0644]
bacula/src/win32/stored/baculasd/wintray.cpp [new file with mode: 0644]
bacula/src/win32/stored/baculasd/wintray.h [new file with mode: 0644]

diff --git a/bacula/src/win32/stored/baculasd/bacula.bmp b/bacula/src/win32/stored/baculasd/bacula.bmp
new file mode 100644 (file)
index 0000000..a31eb16
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/bacula.bmp differ
diff --git a/bacula/src/win32/stored/baculasd/bacula.ico b/bacula/src/win32/stored/baculasd/bacula.ico
new file mode 100644 (file)
index 0000000..f6d50bf
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/bacula.ico differ
diff --git a/bacula/src/win32/stored/baculasd/bacula.rc b/bacula/src/win32/stored/baculasd/bacula.rc
new file mode 100644 (file)
index 0000000..5849beb
--- /dev/null
@@ -0,0 +1 @@
+1 ICON  "apcupsd.ico"
diff --git a/bacula/src/win32/stored/baculasd/error.ico b/bacula/src/win32/stored/baculasd/error.ico
new file mode 100644 (file)
index 0000000..a8f85f1
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/error.ico differ
diff --git a/bacula/src/win32/stored/baculasd/idle.ico b/bacula/src/win32/stored/baculasd/idle.ico
new file mode 100644 (file)
index 0000000..ce5315f
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/idle.ico differ
diff --git a/bacula/src/win32/stored/baculasd/running.ico b/bacula/src/win32/stored/baculasd/running.ico
new file mode 100644 (file)
index 0000000..32dc42c
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/running.ico differ
diff --git a/bacula/src/win32/stored/baculasd/saving.ico b/bacula/src/win32/stored/baculasd/saving.ico
new file mode 100644 (file)
index 0000000..f6d50bf
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/saving.ico differ
diff --git a/bacula/src/win32/stored/baculasd/warn.ico b/bacula/src/win32/stored/baculasd/warn.ico
new file mode 100644 (file)
index 0000000..26e1d39
Binary files /dev/null and b/bacula/src/win32/stored/baculasd/warn.ico differ
diff --git a/bacula/src/win32/stored/baculasd/winabout.cpp b/bacula/src/win32/stored/baculasd/winabout.cpp
new file mode 100644 (file)
index 0000000..5fbccae
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+   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;
+}
diff --git a/bacula/src/win32/stored/baculasd/winabout.h b/bacula/src/win32/stored/baculasd/winabout.h
new file mode 100644 (file)
index 0000000..46a6e94
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+   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
diff --git a/bacula/src/win32/stored/baculasd/winbacula.h b/bacula/src/win32/stored/baculasd/winbacula.h
new file mode 100644 (file)
index 0000000..993b1ee
--- /dev/null
@@ -0,0 +1,71 @@
+//  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__)
diff --git a/bacula/src/win32/stored/baculasd/winevents.cpp b/bacula/src/win32/stored/baculasd/winevents.cpp
new file mode 100644 (file)
index 0000000..50edd0a
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+   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;
+}
diff --git a/bacula/src/win32/stored/baculasd/winevents.h b/bacula/src/win32/stored/baculasd/winevents.h
new file mode 100644 (file)
index 0000000..a28d66e
--- /dev/null
@@ -0,0 +1,44 @@
+/* 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
diff --git a/bacula/src/win32/stored/baculasd/winmain.cpp b/bacula/src/win32/stored/baculasd/winmain.cpp
new file mode 100644 (file)
index 0000000..e673db3
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+   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);
+}
diff --git a/bacula/src/win32/stored/baculasd/winres.h b/bacula/src/win32/stored/baculasd/winres.h
new file mode 100644 (file)
index 0000000..66a84c1
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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
+
+
diff --git a/bacula/src/win32/stored/baculasd/winres.rc b/bacula/src/win32/stored/baculasd/winres.rc
new file mode 100644 (file)
index 0000000..f01564e
--- /dev/null
@@ -0,0 +1,181 @@
+#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
diff --git a/bacula/src/win32/stored/baculasd/winservice.cpp b/bacula/src/win32/stored/baculasd/winservice.cpp
new file mode 100644 (file)
index 0000000..cde43b6
--- /dev/null
@@ -0,0 +1,753 @@
+//  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); 
+}
diff --git a/bacula/src/win32/stored/baculasd/winservice.h b/bacula/src/win32/stored/baculasd/winservice.h
new file mode 100644 (file)
index 0000000..2195b58
--- /dev/null
@@ -0,0 +1,125 @@
+//  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
diff --git a/bacula/src/win32/stored/baculasd/winstat.cpp b/bacula/src/win32/stored/baculasd/winstat.cpp
new file mode 100644 (file)
index 0000000..45e3c41
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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;
+}
diff --git a/bacula/src/win32/stored/baculasd/winstat.h b/bacula/src/win32/stored/baculasd/winstat.h
new file mode 100644 (file)
index 0000000..3486a00
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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
diff --git a/bacula/src/win32/stored/baculasd/wintray.cpp b/bacula/src/win32/stored/baculasd/wintray.cpp
new file mode 100644 (file)
index 0000000..db2c593
--- /dev/null
@@ -0,0 +1,357 @@
+//  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);
+}
diff --git a/bacula/src/win32/stored/baculasd/wintray.h b/bacula/src/win32/stored/baculasd/wintray.h
new file mode 100644 (file)
index 0000000..e2f7181
--- /dev/null
@@ -0,0 +1,93 @@
+//  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