2 Copyright (C) 2000-2006 Kern Sibbald
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 version 2 as amended with additional clauses defined in the
7 file LICENSE in the main source directory.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 the file LICENSE for additional details.
14 This file is patterned after the VNC Win32 code by ATT
25 #include "winbacula.h"
27 #include "winservice.h"
30 #include "../../lib/winapi.h"
33 extern int BaculaMain(int argc, char *argv[]);
34 extern void terminate_filed(int sig);
36 extern BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
37 extern void d_msg(const char *, int, int, const char *, ...);
40 HINSTANCE hAppInstance;
41 const char *szAppName = "Bacula";
44 /* Imported variables */
45 extern DWORD g_servicethread;
46 extern DWORD g_platform_id;
48 #define MAX_COMMAND_ARGS 100
49 static char *command_args[MAX_COMMAND_ARGS] = {"bacula-fd", NULL};
50 static int num_command_args = 1;
51 static pid_t main_pid;
52 static pthread_t main_tid;
55 * WinMain parses the command line and either calls the main App
56 * routine or, under NT, the main service routine.
58 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
59 PSTR CmdLine, int iCmdShow)
61 char *szCmdLine = CmdLine;
62 char *wordPtr, *tempPtr;
66 /* Save the application instance and main thread id */
67 hAppInstance = hInstance;
68 mainthreadId = GetCurrentThreadId();
71 main_tid = pthread_self();
74 * Funny things happen with the command line if the
75 * execution comes from c:/Program Files/bacula/bacula.exe
76 * We get a command line like: Files/bacula/bacula.exe" options
77 * I.e. someone stops scanning command line on a space, not
78 * realizing that the filename is quoted!!!!!!!!!!
79 * So if first character is not a double quote and
80 * the last character before first space is a double
81 * quote, we throw away the junk.
85 while (*wordPtr && *wordPtr != ' ')
87 if (wordPtr > szCmdLine) /* backup to char before space */
89 /* if first character is not a quote and last is, junk it */
90 if (*szCmdLine != '"' && *wordPtr == '"') {
91 szCmdLine = wordPtr + 1;
93 // MessageBox(NULL, szCmdLine, "Cmdline", MB_OK);
95 /* Build Unix style argc *argv[] */
97 /* Don't NULL command_args[0] !!! */
98 for (i=1;i<MAX_COMMAND_ARGS;i++)
99 command_args[i] = NULL;
103 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
105 if (*wordPtr == '\"') {
108 } else if (*wordPtr == '/') {
109 /* Skip Windows options */
110 while (*wordPtr && (*wordPtr != ' ' && *wordPtr != '\t'))
112 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
116 while (*wordPtr && num_command_args < MAX_COMMAND_ARGS) {
119 while (*tempPtr && *tempPtr != '\"')
123 while (*tempPtr && *tempPtr != ' ')
128 command_args[num_command_args++] = wordPtr;
130 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
132 if (*wordPtr == '\"') {
140 * Now process Windows command line options
143 * Make the command-line lowercase and parse it
145 for (i = 0; i < (int)strlen(szCmdLine); i++) {
146 szCmdLine[i] = tolower(szCmdLine[i]);
149 bool argfound = false;
150 for (i = 0; i < (int)strlen(szCmdLine); i++) {
151 if (szCmdLine[i] <= ' ') {
155 if (szCmdLine[i] == '-') {
156 while (szCmdLine[i] && szCmdLine[i] != ' ') {
164 /* Now check for command-line arguments */
166 /* /silent install quietly -- no prompts */
167 if (strncmp(&szCmdLine[i], "/silent", strlen("/silent")) == 0) {
169 i += strlen("/silent");
172 /* /service start service */
173 if (strncmp(&szCmdLine[i], BaculaRunService, strlen(BaculaRunService)) == 0) {
174 /* Run Bacula as a service */
175 return bacService::BaculaServiceMain();
177 /* /run (this is the default if no command line arguments) */
178 if (strncmp(&szCmdLine[i], BaculaRunAsUserApp, strlen(BaculaRunAsUserApp)) == 0) {
179 /* Bacula is being run as a user-level program */
180 return BaculaAppMain();
183 if (strncmp(&szCmdLine[i], BaculaInstallService, strlen(BaculaInstallService)) == 0) {
184 /* Install Bacula as a service */
185 bacService::InstallService(silent);
186 i += strlen(BaculaInstallService);
190 if (strncmp(&szCmdLine[i], BaculaRemoveService, strlen(BaculaRemoveService)) == 0) {
191 /* Remove the Bacula service */
192 bacService::RemoveService(silent);
193 i += strlen(BaculaRemoveService);
198 if (strncmp(&szCmdLine[i], BaculaShowAbout, strlen(BaculaShowAbout)) == 0) {
199 /* Show Bacula's about box */
200 bacService::ShowAboutBox();
201 i += strlen(BaculaShowAbout);
206 if (strncmp(&szCmdLine[i], BaculaShowStatus, strlen(BaculaShowStatus)) == 0) {
207 /* Show Bacula's status box */
208 bacService::ShowStatus();
209 i += strlen(BaculaShowStatus);
214 if (strncmp(&szCmdLine[i], BaculaKillRunningCopy, strlen(BaculaKillRunningCopy)) == 0) {
215 /* Kill running copy of Bacula */
216 bacService::KillRunningCopy();
217 i += strlen(BaculaKillRunningCopy);
222 if (strncmp(&szCmdLine[i], BaculaShowHelp, strlen(BaculaShowHelp)) == 0) {
223 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK|MB_ICONINFORMATION);
224 i += strlen(BaculaShowHelp);
228 MessageBox(NULL, szCmdLine, _("Bad Command Line Options"), MB_OK);
230 /* Show the usage dialog */
231 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK | MB_ICONINFORMATION);
235 /* If no arguments were given then just run */
244 * Called as a thread from BaculaAppMain()
245 * Here we handle the Windows messages
247 //DWORD WINAPI Main_Msg_Loop(LPVOID lpwThreadParam)
248 void *Main_Msg_Loop(LPVOID lpwThreadParam)
250 DWORD old_servicethread = g_servicethread;
253 pthread_detach(pthread_self());
255 /* Since we are the only thread with a message loop
256 * mark ourselves as the service thread so that
257 * we can receive all the window events.
259 g_servicethread = GetCurrentThreadId();
261 /* Create tray icon & menu if we're running as an app */
262 bacMenu *menu = new bacMenu();
264 // log_error_message("Could not create sys tray menu");
269 /* Now enter the Windows message handling loop until told to quit! */
271 while (GetMessage(&msg, NULL, 0,0) ) {
272 TranslateMessage(&msg);
273 DispatchMessage(&msg);
280 if (old_servicethread != 0) { /* started as NT service */
281 /* Mark that we're no longer running */
284 /* Tell the service manager that we've stopped. */
285 ReportStatus(SERVICE_STOPPED, g_error, 0);
287 /* Tell main program to go away */
290 /* Should not get here */
291 pthread_kill(main_tid, SIGTERM); /* ask main thread to terminate */
293 kill(main_pid, SIGTERM); /* ask main thread to terminate */
299 * This is the main routine for Bacula when running as an application
300 * (under Windows 95 or Windows NT)
301 * Under NT, Bacula can also run as a service. The BaculaServerMain routine,
302 * defined in the bacService header, is used instead when running as a service.
306 /* DWORD dwThreadID; */
313 /* Set this process to be the last application to be shut down. */
314 if (p_SetProcessShutdownParameters) {
315 p_SetProcessShutdownParameters(0x100, 0);
318 HWND hservwnd = FindWindow(MENU_CLASS_NAME, NULL);
319 if (hservwnd != NULL) {
320 /* We don't allow multiple instances! */
321 MessageBox(NULL, _("Another instance of Bacula is already running"), szAppName, MB_OK);
326 /* Create a thread to handle the Windows messages */
327 // (void)CreateThread(NULL, 0, Main_Msg_Loop, NULL, 0, &dwThreadID);
328 pthread_create(&tid, NULL, Main_Msg_Loop, (void *)0);
330 /* Call the "real" Bacula */
331 BaculaMain(num_command_args, command_args);