2 This file is patterned after the VNC Win32 code by ATT
5 Bacula® - The Network Backup Solution
7 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
9 The main author of Bacula is Kern Sibbald, with contributions from
10 many others, a complete list can be found in the file AUTHORS.
11 This program is Free Software; you can redistribute it and/or
12 modify it under the terms of version two of the GNU General Public
13 License as published by the Free Software Foundation and included
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 Bacula® is a registered trademark of John Walker.
27 The licensor of Bacula is the Free Software Foundation Europe
28 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
29 Switzerland, email:ftf@fsfeurope.org.
36 #include "winbacula.h"
38 #include "winservice.h"
43 #define _WIN32_IE 0x0401
45 #define _WIN32_WINNT 0x0501
48 extern int BaculaMain(int argc, char *argv[]);
49 extern void terminate_filed(int sig);
51 extern BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
52 extern void d_msg(const char *, int, int, const char *, ...);
53 extern void VSSInit();
56 HINSTANCE hAppInstance;
57 const char *szAppName = "Bacula-fd";
59 bool opt_debug = false;
61 /* Imported variables */
62 extern DWORD g_servicethread;
64 #define MAX_COMMAND_ARGS 100
65 static char *command_args[MAX_COMMAND_ARGS] = {"bacula-fd", NULL};
66 static int num_command_args = 1;
67 static pid_t main_pid;
68 static pthread_t main_tid;
71 * WinMain parses the command line and either calls the main App
72 * routine or, under NT, the main service routine.
74 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
75 PSTR CmdLine, int iCmdShow)
77 char *szCmdLine = CmdLine;
78 char *wordPtr, *tempPtr;
81 /* Save the application instance and main thread id */
82 hAppInstance = hInstance;
83 mainthreadId = GetCurrentThreadId();
86 main_tid = pthread_self();
88 INITCOMMONCONTROLSEX initCC = {
89 sizeof(INITCOMMONCONTROLSEX),
93 InitCommonControlsEx(&initCC);
96 * Funny things happen with the command line if the
97 * execution comes from c:/Program Files/bacula/bacula.exe
98 * We get a command line like: Files/bacula/bacula.exe" options
99 * I.e. someone stops scanning command line on a space, not
100 * realizing that the filename is quoted!!!!!!!!!!
101 * So if first character is not a double quote and
102 * the last character before first space is a double
103 * quote, we throw away the junk.
107 while (*wordPtr && *wordPtr != ' ')
109 if (wordPtr > szCmdLine) /* backup to char before space */
111 /* if first character is not a quote and last is, junk it */
112 if (*szCmdLine != '"' && *wordPtr == '"') {
113 szCmdLine = wordPtr + 1;
116 /* Build Unix style argc *argv[] */
118 /* Don't NULL command_args[0] !!! */
119 for (i=1;i<MAX_COMMAND_ARGS;i++) {
120 command_args[i] = NULL;
123 char *pszArgs = bstrdup(szCmdLine);
126 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
128 if (*wordPtr == '\"') {
131 } else if (*wordPtr == '/') {
132 /* Skip Windows options */
133 while (*wordPtr && (*wordPtr != ' ' && *wordPtr != '\t'))
135 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
139 while (*wordPtr && num_command_args < MAX_COMMAND_ARGS) {
142 while (*tempPtr && *tempPtr != '\"')
146 while (*tempPtr && *tempPtr != ' ')
151 command_args[num_command_args++] = wordPtr;
153 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
155 if (*wordPtr == '\"') {
163 * Now process Windows command line options
165 for (i = 0; i < (int)strlen(szCmdLine); i++) {
166 if (szCmdLine[i] <= ' ') {
170 if (szCmdLine[i] != '/') {
174 /* Now check for command-line arguments */
176 /* /debug - enable debugging facilities such as console message window */
177 if (strnicmp(&szCmdLine[i], BaculaOptDebug, sizeof(BaculaOptDebug) - 1) == 0) {
179 i += sizeof(BaculaOptDebug) - 1;
183 /* /service start service */
184 if (strnicmp(&szCmdLine[i], BaculaRunService, sizeof(BaculaRunService) - 1) == 0) {
185 /* Run Bacula as a service */
186 return bacService::BaculaServiceMain();
188 /* /run (this is the default if no command line arguments) */
189 if (strnicmp(&szCmdLine[i], BaculaRunAsUserApp, sizeof(BaculaRunAsUserApp) - 1) == 0) {
190 /* Bacula is being run as a user-level program */
191 return BaculaAppMain();
194 if (strnicmp(&szCmdLine[i], BaculaInstallService, sizeof(BaculaInstallService) - 1) == 0) {
195 /* Install Bacula as a service */
196 return bacService::InstallService(&szCmdLine[i + sizeof(BaculaInstallService) - 1]);
199 if (strnicmp(&szCmdLine[i], BaculaRemoveService, sizeof(BaculaRemoveService) - 1) == 0) {
200 /* Remove the Bacula service */
201 return bacService::RemoveService();
205 if (strnicmp(&szCmdLine[i], BaculaShowAbout, sizeof(BaculaShowAbout) - 1) == 0) {
206 /* Show Bacula's about box */
207 return bacService::ShowAboutBox();
211 if (strnicmp(&szCmdLine[i], BaculaShowStatus, sizeof(BaculaShowStatus) - 1) == 0) {
212 /* Show Bacula's status box */
213 return bacService::ShowStatus();
217 if (strnicmp(&szCmdLine[i], BaculaKillRunningCopy, sizeof(BaculaKillRunningCopy) - 1) == 0) {
218 /* Kill running copy of Bacula */
219 return bacService::KillRunningCopy();
223 if (strnicmp(&szCmdLine[i], BaculaShowHelp, sizeof(BaculaShowHelp) - 1) == 0) {
224 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK|MB_ICONINFORMATION);
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 return BaculaAppMain();
240 * Called as a thread from BaculaAppMain()
241 * Here we handle the Windows messages
243 //DWORD WINAPI Main_Msg_Loop(LPVOID lpwThreadParam)
244 void *Main_Msg_Loop(LPVOID lpwThreadParam)
246 DWORD old_servicethread = g_servicethread;
248 pthread_detach(pthread_self());
250 /* Since we are the only thread with a message loop
251 * mark ourselves as the service thread so that
252 * we can receive all the window events.
254 g_servicethread = GetCurrentThreadId();
256 /* Create tray icon & menu if we're running as an app */
257 bacMenu *menu = new bacMenu();
259 // log_error_message("Could not create sys tray menu");
263 /* Now enter the Windows message handling loop until told to quit! */
265 while (GetMessage(&msg, NULL, 0,0) ) {
266 TranslateMessage(&msg);
267 DispatchMessage(&msg);
274 if (old_servicethread != 0) { /* started as NT service */
275 /* Mark that we're no longer running */
278 /* Tell the service manager that we've stopped. */
279 ReportStatus(SERVICE_STOPPED, g_error, 0);
281 /* Tell main program to go away */
284 /* Should not get here */
285 pthread_kill(main_tid, SIGTERM); /* ask main thread to terminate */
287 kill(main_pid, SIGTERM); /* ask main thread to terminate */
293 * This is the main routine for Bacula when running as an application
294 * (under Windows 95 or Windows NT)
295 * Under NT, Bacula can also run as a service. The BaculaServerMain routine,
296 * defined in the bacService header, is used instead when running as a service.
300 /* DWORD dwThreadID; */
302 DWORD dwCharsWritten;
306 /* If no arguments were given then just run */
307 if (p_AttachConsole == NULL || !p_AttachConsole(ATTACH_PARENT_PROCESS)) {
312 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);