4 This file is patterned after the VNC Win32 code by ATT
7 Bacula® - The Network Backup Solution
9 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
11 The main author of Bacula is Kern Sibbald, with contributions from
12 many others, a complete list can be found in the file AUTHORS.
13 This program is Free Software; you can redistribute it and/or
14 modify it under the terms of version two of the GNU General Public
15 License as published by the Free Software Foundation plus additions
16 that are listed in the file LICENSE.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 Bacula® is a registered trademark of John Walker.
29 The licensor of Bacula is the Free Software Foundation Europe
30 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
31 Switzerland, email:ftf@fsfeurope.org.
39 #include "winbacula.h"
41 #include "winservice.h"
46 #define _WIN32_IE 0x0501
48 #define _WIN32_WINNT 0x0501
51 extern int BaculaMain(int argc, char *argv[]);
52 extern void terminate_stored(int sig);
54 extern BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
55 extern void d_msg(const char *, int, int, const char *, ...);
58 HINSTANCE hAppInstance;
59 const char *szAppName = "Bacula-sd";
61 bool opt_debug = false;
63 /* Imported variables */
64 extern DWORD g_servicethread;
66 #define MAX_COMMAND_ARGS 100
67 static char *command_args[MAX_COMMAND_ARGS] = {"bacula-sd", NULL};
68 static int num_command_args = 1;
69 static pid_t main_pid;
70 static pthread_t main_tid;
73 * WinMain parses the command line and either calls the main App
74 * routine or, under NT, the main service routine.
76 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
77 PSTR CmdLine, int iCmdShow)
79 char *szCmdLine = CmdLine;
80 char *wordPtr, *tempPtr;
83 /* Save the application instance and main thread id */
84 hAppInstance = hInstance;
85 mainthreadId = GetCurrentThreadId();
88 main_tid = pthread_self();
90 INITCOMMONCONTROLSEX initCC = {
91 sizeof(INITCOMMONCONTROLSEX),
95 InitCommonControlsEx(&initCC);
98 * Funny things happen with the command line if the
99 * execution comes from c:/Program Files/bacula/bacula.exe
100 * We get a command line like: Files/bacula/bacula.exe" options
101 * I.e. someone stops scanning command line on a space, not
102 * realizing that the filename is quoted!!!!!!!!!!
103 * So if first character is not a double quote and
104 * the last character before first space is a double
105 * quote, we throw away the junk.
109 while (*wordPtr && *wordPtr != ' ')
111 if (wordPtr > szCmdLine) /* backup to char before space */
113 /* if first character is not a quote and last is, junk it */
114 if (*szCmdLine != '"' && *wordPtr == '"') {
115 szCmdLine = wordPtr + 1;
118 /* Build Unix style argc *argv[] */
120 /* Don't NULL command_args[0] !!! */
121 for (i=1;i<MAX_COMMAND_ARGS;i++)
122 command_args[i] = NULL;
124 char *pszArgs = bstrdup(szCmdLine);
127 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
129 if (*wordPtr == '\"') {
132 } else if (*wordPtr == '/') {
133 /* Skip Windows options */
134 while (*wordPtr && (*wordPtr != ' ' && *wordPtr != '\t'))
136 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
140 while (*wordPtr && num_command_args < MAX_COMMAND_ARGS) {
143 while (*tempPtr && *tempPtr != '\"')
147 while (*tempPtr && *tempPtr != ' ')
152 command_args[num_command_args++] = wordPtr;
154 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
156 if (*wordPtr == '\"') {
164 * Now process Windows command line options
166 for (i = 0; i < (int)strlen(szCmdLine); i++) {
167 if (szCmdLine[i] <= ' ') {
171 if (szCmdLine[i] != '/') {
175 /* Now check for command-line arguments */
177 /* /debug install quietly -- no prompts */
178 if (strnicmp(&szCmdLine[i], BaculaOptDebug, sizeof(BaculaOptDebug) - 1) == 0) {
180 i += sizeof(BaculaOptDebug) - 1;
184 /* /service start service */
185 if (strnicmp(&szCmdLine[i], BaculaRunService, sizeof(BaculaRunService) - 1) == 0) {
186 /* Run Bacula as a service */
187 return bacService::BaculaServiceMain();
189 /* /run (this is the default if no command line arguments) */
190 if (strnicmp(&szCmdLine[i], BaculaRunAsUserApp, sizeof(BaculaRunAsUserApp) - 1) == 0) {
191 /* Bacula is being run as a user-level program */
192 return BaculaAppMain();
195 if (strnicmp(&szCmdLine[i], BaculaInstallService, sizeof(BaculaInstallService) - 1) == 0) {
196 /* Install Bacula as a service */
197 return bacService::InstallService(&szCmdLine[i + sizeof(BaculaInstallService) - 1]);
200 if (strnicmp(&szCmdLine[i], BaculaRemoveService, sizeof(BaculaRemoveService) - 1) == 0) {
201 /* Remove the Bacula service */
202 return bacService::RemoveService();
206 if (strnicmp(&szCmdLine[i], BaculaShowAbout, sizeof(BaculaShowAbout) - 1) == 0) {
207 /* Show Bacula's about box */
208 return bacService::ShowAboutBox();
212 if (strnicmp(&szCmdLine[i], BaculaShowStatus, sizeof(BaculaShowStatus) - 1) == 0) {
213 /* Show Bacula's status box */
214 return bacService::ShowStatus();
218 if (strnicmp(&szCmdLine[i], BaculaKillRunningCopy, sizeof(BaculaKillRunningCopy) - 1) == 0) {
219 /* Kill running copy of Bacula */
220 return bacService::KillRunningCopy();
224 if (strnicmp(&szCmdLine[i], BaculaShowHelp, sizeof(BaculaShowHelp) - 1) == 0) {
225 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK|MB_ICONINFORMATION);
229 MessageBox(NULL, szCmdLine, _("Bad Command Line Options"), MB_OK);
231 /* Show the usage dialog */
232 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK | MB_ICONINFORMATION);
236 return BaculaAppMain();
241 * Called as a thread from BaculaAppMain()
242 * Here we handle the Windows messages
244 //DWORD WINAPI Main_Msg_Loop(LPVOID lpwThreadParam)
245 void *Main_Msg_Loop(LPVOID lpwThreadParam)
247 DWORD old_servicethread = g_servicethread;
250 pthread_detach(pthread_self());
252 /* Since we are the only thread with a message loop
253 * mark ourselves as the service thread so that
254 * we can receive all the window events.
256 g_servicethread = GetCurrentThreadId();
258 /* Create tray icon & menu if we're running as an app */
259 bacMenu *menu = new bacMenu();
261 // log_error_message("Could not create sys tray menu");
265 /* Now enter the Windows message handling loop until told to quit! */
267 while (GetMessage(&msg, NULL, 0,0) ) {
268 TranslateMessage(&msg);
269 DispatchMessage(&msg);
276 if (old_servicethread != 0) { /* started as NT service */
277 /* Mark that we're no longer running */
280 /* Tell the service manager that we've stopped. */
281 ReportStatus(SERVICE_STOPPED, g_error, 0);
283 /* Tell main program to go away */
286 /* Should not get here */
287 pthread_kill(main_tid, SIGTERM); /* ask main thread to terminate */
289 kill(main_pid, SIGTERM); /* ask main thread to terminate */
295 * This is the main routine for Bacula when running as an application
296 * (under Windows 95 or Windows NT)
297 * Under NT, Bacula can also run as a service. The BaculaServerMain routine,
298 * defined in the bacService header, is used instead when running as a service.
302 /* DWORD dwThreadID; */
304 DWORD dwCharsWritten;
310 /* If no arguments were given then just run */
311 if (p_AttachConsole == NULL || !p_AttachConsole(ATTACH_PARENT_PROCESS)) {
316 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), "\r\n", 2, &dwCharsWritten, NULL);
318 /* Set this process to be the last application to be shut down. */
319 if (p_SetProcessShutdownParameters) {
320 p_SetProcessShutdownParameters(0x100, 0);
323 HWND hservwnd = FindWindow(MENU_CLASS_NAME, NULL);
324 if (hservwnd != NULL) {
325 /* We don't allow multiple instances! */
326 MessageBox(NULL, _("Another instance of Bacula is already running"), szAppName, MB_OK);
330 /* Create a thread to handle the Windows messages */
331 pthread_create(&tid, NULL, Main_Msg_Loop, (void *)0);
333 /* Call the "real" Bacula */
334 BaculaMain(num_command_args, command_args);