diff options
author | William A. Rowe Jr <wrowe@apache.org> | 2000-05-19 07:01:53 +0200 |
---|---|---|
committer | William A. Rowe Jr <wrowe@apache.org> | 2000-05-19 07:01:53 +0200 |
commit | 40b92feb96188523a2f3e893f85cffd6b5b6801b (patch) | |
tree | d6de4307b4ab0ac6123bac64398e720710e25ca7 /server/mpm/winnt/service.c | |
parent | ap_wait_or_timeout() can't be static since it is called from (diff) | |
download | apache2-40b92feb96188523a2f3e893f85cffd6b5b6801b.tar.xz apache2-40b92feb96188523a2f3e893f85cffd6b5b6801b.zip |
Fixes to allow Apache to run as a Win95 service... highlights
main_win32.h : Moved delarations to a header, by request
ap_listen.h : References types declared in http_config.h
http_main.h : Add the Win32 flavor entry point declaration
apr.hw : Cleanup the redundancy department of redundancy
win32/proc.c : Double null termination was required here
Everything else should be obvious and isolated to Win32.
Build files will be committed seperately.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@85253 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/mpm/winnt/service.c')
-rw-r--r-- | server/mpm/winnt/service.c | 194 |
1 files changed, 139 insertions, 55 deletions
diff --git a/server/mpm/winnt/service.c b/server/mpm/winnt/service.c index e60b8a0169..412f25d046 100644 --- a/server/mpm/winnt/service.c +++ b/server/mpm/winnt/service.c @@ -58,21 +58,20 @@ #ifdef WIN32 -#include "os.h" -#include <stdlib.h> -#include <direct.h> - #define CORE_PRIVATE + +#include "main_win32.h" #include "httpd.h" #include "http_conf_globals.h" #include "http_log.h" -#include "http_main.h" #include "service.h" #include "registry.h" #include "ap_mpm.h" +#include "..\..\modules\mpm\winnt\winnt.h" typedef void (CALLBACK *ap_completion_t)(); API_VAR_IMPORT ap_completion_t ap_mpm_init_complete; +API_VAR_IMPORT char *ap_server_argv0; static struct { @@ -85,6 +84,8 @@ static struct SERVICE_STATUS ssStatus; FILE *logFile; char *service_dir; + HANDLE threadService; + HANDLE threadMonitor; } globdat; static void WINAPI service_main_fn(DWORD, LPTSTR *); @@ -93,54 +94,137 @@ static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint); static int ap_start_service(SC_HANDLE); static int ap_stop_service(SC_HANDLE); -static void CALLBACK report_service95_running() +static LRESULT CALLBACK MonitorWin9xWndProc(HWND hWnd, UINT msg, + WPARAM wParam, LPARAM lParam) { - FreeConsole(); +/* This is the WndProc procedure for our invisible window. + * When the user shuts down the system, this window is sent + * a signal WM_ENDSESSION. We clean up by signaling Apache + * to shut down, and idle until Apache's primary thread quits. + */ + if ((msg == WM_ENDSESSION) && (lParam != ENDSESSION_LOGOFF)) + { + ap_start_shutdown(); + if (wParam) + WaitForSingleObject(globdat.threadService, 30000); + return 0; + } + return (DefWindowProc(hWnd, msg, wParam, lParam)); +} + +static DWORD WINAPI MonitorWin9xEvents(LPVOID initEvent) +{ +/* When running on Windows 9x, the ConsoleCtrlHandler is _NOT_ + * called when the system is shutdown. So create an invisible + * window to watch for the WM_ENDSESSION message, and watch for + * the WM_CLOSE message to shut the window down. + */ + WNDCLASS wc; + HWND hwndMain; + + wc.style = CS_GLOBALCLASS; + wc.lpfnWndProc = MonitorWin9xWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = NULL; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = "ApacheWin9xService"; + + if (RegisterClass(&wc)) + { + /* Create an invisible window */ + hwndMain = CreateWindow("ApacheWin9xService", "Apache", + WS_OVERLAPPEDWINDOW & ~WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, NULL, NULL); + if (hwndMain) + { + MSG msg; + /* If we succeed, eliminate the console window. + * Signal the parent we are all set up, and + * watch the message queue while the window lives. + */ + FreeConsole(); + SetEvent((HANDLE) initEvent); + while (GetMessage(&msg, NULL, 0, 0)) + { + if (msg.message == WM_CLOSE) + DestroyWindow(hwndMain); + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + globdat.threadMonitor = 0; + return(0); + } + } + /* We failed or are soon to die... + * we won't need this much longer + */ + SetEvent((HANDLE) initEvent); + globdat.threadMonitor = 0; + return(0); +} - /* We do this only once, ever */ - ap_mpm_init_complete = NULL; +static void CALLBACK report_service9x_running() +{ } -int service95_main(int (*main_fn)(int, char **), int argc, char **argv ) +int service9x_main(int (*main_fn)(int, char **), int argc, char **argv ) { - HINSTANCE hkernel; DWORD (WINAPI *RegisterServiceProcess)(DWORD, DWORD); + HINSTANCE hkernel; + DWORD threadId; + + globdat.threadService = GetCurrentThread(); /* Obtain a handle to the kernel library */ hkernel = LoadLibrary("KERNEL32.DLL"); - if (!hkernel) - return -1; - - /* Find the RegisterServiceProcess function */ - RegisterServiceProcess = (DWORD (WINAPI *)(DWORD, DWORD)) - GetProcAddress(hkernel, "RegisterServiceProcess"); - if (RegisterServiceProcess == NULL) - return -1; - - /* Register this process as a service */ - if (!RegisterServiceProcess((DWORD)NULL, 1)) - return -1; - - /* Eliminate the console for the remainer of the service session */ - ap_mpm_init_complete = report_service95_running; + if (hkernel) { + /* Find the RegisterServiceProcess function */ + RegisterServiceProcess = (DWORD (WINAPI *)(DWORD, DWORD)) + GetProcAddress(hkernel, "RegisterServiceProcess"); + if (RegisterServiceProcess) { + if (RegisterServiceProcess((DWORD)NULL, 1)) { + HANDLE installed = CreateEvent(NULL, FALSE, FALSE, NULL); + globdat.threadMonitor = CreateThread(NULL, 0, + MonitorWin9xEvents, + (LPVOID) installed, + 0, &threadId); + WaitForSingleObject(installed, 30000); + CloseHandle(installed); + } + } + } /* Run the service */ globdat.exit_status = main_fn(argc, argv); + /* Still have a thread & window to clean up, so signal now */ + if (globdat.threadMonitor) + { + PostThreadMessage(threadId, WM_CLOSE, 0, 0); + WaitForSingleObject(globdat.threadMonitor, 30000); + } + /* When the service quits, remove it from the system service table */ - RegisterServiceProcess((DWORD)NULL, 0); + if (RegisterServiceProcess) + RegisterServiceProcess((DWORD)NULL, 0); /* Free the kernel library */ - // Worthless, methinks, since it won't be reclaimed - // FreeLibrary(hkernel); + if (hkernel) + FreeLibrary(hkernel); - /* We have to quit right here to avoid an invalid page fault */ - // But, this is worth experimenting with! return (globdat.exit_status); } -int service_main(int (*main_fn)(int, char **), int argc, char **argv ) +int servicent_main(int (*main_fn)(int, char **), int argc, char **argv ) { SERVICE_TABLE_ENTRY dispatchTable[] = { @@ -166,24 +250,12 @@ int service_main(int (*main_fn)(int, char **), int argc, char **argv ) } } -void service_cd() -{ - /* change to the drive with the executable */ - char buf[300]; - GetModuleFileName(NULL, buf, 300); - buf[2] = 0; - chdir(buf); -} - -static void CALLBACK report_service_started() +static void CALLBACK report_servicent_started() { ReportStatusToSCMgr( SERVICE_RUNNING, // service state NO_ERROR, // exit code 0); // wait hint - - /* This is only reported once, ever! */ - ap_mpm_init_complete = NULL; } void __stdcall service_main_fn(DWORD argc, LPTSTR *argv) @@ -218,9 +290,7 @@ void __stdcall service_main_fn(DWORD argc, LPTSTR *argv) NO_ERROR, // exit code 3000); // wait hint - ap_mpm_init_complete = report_service_started; - - service_cd(); + ap_mpm_init_complete = report_servicent_started; /* Fetch server_conf from the registry * Rebuild argv and argc adding the -d server_root and -f server_conf then @@ -274,7 +344,6 @@ VOID WINAPI service_ctrl(DWORD dwCtrlCode) { int state; - state = globdat.ssStatus.dwCurrentState; switch(dwCtrlCode) { @@ -342,7 +411,7 @@ int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint) return(1); } -void InstallService(char *display_name, char *conf) +void InstallServiceNT(char *display_name, char *conf) { SC_HANDLE schService; SC_HANDLE schSCManager; @@ -415,7 +484,7 @@ void InstallService(char *display_name, char *conf) } -void RemoveService(char *display_name) +void RemoveServiceNT(char *display_name) { SC_HANDLE schService; SC_HANDLE schSCManager; @@ -473,16 +542,27 @@ BOOL isProcessService() { } /* Determine is service_name is a valid service + * Simplify by testing the registry rather than the SCM + * as this will work on both WinNT and Win9x. */ -BOOL isValidService(char *display_name) { - SC_HANDLE schSCM, schSVC; +BOOL isValidService(ap_pool_t *p, char *display_name) { char service_name[256]; - int Err; + char *service_conf; /* Remove spaces from display name to create service name */ ap_collapse_spaces(service_name, display_name); + if(ap_registry_get_service_conf(p, &service_conf, service_name)) { + return TRUE; + } + + return FALSE; + +#if 0 + SC_HANDLE schSCM, schSVC; + int Err; + if (!(schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) { ap_log_error(APLOG_MARK, APLOG_ERR, GetLastError(), NULL, "OpenSCManager failed"); @@ -501,8 +581,12 @@ BOOL isValidService(char *display_name) { "OpenService failed"); return FALSE; +#endif } +/* Although the Win9x service enhancement added -k startservice, + * it is never processed here, so we still ignore that param. + */ int send_signal_to_service(char *display_name, char *sig) { SC_HANDLE schService; SC_HANDLE schSCManager; @@ -607,6 +691,6 @@ int ap_start_service(SC_HANDLE schService) { return TRUE; return FALSE; } - + #endif /* WIN32 */ |