mirror of
https://github.com/apache/httpd.git
synced 2025-08-10 02:56:11 +00:00
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
This commit is contained in:
@ -56,6 +56,7 @@
|
||||
#define AP_LISTEN_H
|
||||
|
||||
#include "apr_network_io.h"
|
||||
#include "http_config.h"
|
||||
|
||||
typedef struct ap_listen_rec ap_listen_rec;
|
||||
struct ap_listen_rec {
|
||||
|
@ -71,6 +71,10 @@ extern ap_array_header_t *ap_server_pre_read_config;
|
||||
extern ap_array_header_t *ap_server_post_read_config;
|
||||
extern ap_array_header_t *ap_server_config_defines;
|
||||
|
||||
#ifdef WIN32
|
||||
API_EXPORT(int) apache_main(int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
80
os/win32/main_win32.h
Normal file
80
os/win32/main_win32.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2000 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* nor may "Apache" appear in their name, without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* Portions of this software are based upon public domain software
|
||||
* originally written at the National Center for Supercomputing Applications,
|
||||
* University of Illinois, Urbana-Champaign.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Declarations for users of the functions defined in registry.c
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#ifndef NOGDI
|
||||
#define NOGDI
|
||||
#endif
|
||||
#ifndef NONLS
|
||||
#define NONLS
|
||||
#endif
|
||||
#ifndef NOMCX
|
||||
#define NOMCX
|
||||
#endif
|
||||
#ifndef NOIME
|
||||
#define NOIME
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <mswsock.h>
|
@ -68,11 +68,9 @@
|
||||
#include "ap_config.h"
|
||||
#include "ap_listen.h"
|
||||
#include "mpm_default.h"
|
||||
//#include "service.h"
|
||||
#include "iol_socket.h"
|
||||
#include "winnt.h"
|
||||
|
||||
|
||||
/*
|
||||
* Definitions of WINNT MPM specific config globals
|
||||
*/
|
||||
@ -105,9 +103,8 @@ int ap_daemons_to_start=0;
|
||||
static event *exit_event;
|
||||
HANDLE maintenance_event;
|
||||
ap_lock_t *start_mutex;
|
||||
int my_pid;
|
||||
int parent_pid;
|
||||
typedef void (CALLBACK *ap_completion_t)();
|
||||
DWORD my_pid;
|
||||
DWORD parent_pid;
|
||||
API_VAR_EXPORT ap_completion_t ap_mpm_init_complete = NULL;
|
||||
|
||||
static ap_status_t socket_cleanup(void *sock)
|
||||
@ -299,15 +296,19 @@ static void signal_parent(int type)
|
||||
}
|
||||
CloseHandle(e);
|
||||
}
|
||||
|
||||
static int volatile is_graceful = 0;
|
||||
|
||||
API_EXPORT(int) ap_graceful_stop_signalled(void)
|
||||
{
|
||||
return is_graceful;
|
||||
}
|
||||
void ap_start_shutdown(void)
|
||||
|
||||
API_EXPORT(void) ap_start_shutdown(void)
|
||||
{
|
||||
signal_parent(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the signal names, in the global variables signal_name_prefix,
|
||||
* signal_restart_name and signal_shutdown_name.
|
||||
@ -354,6 +355,7 @@ static void sock_disable_nagle(int s)
|
||||
* Routines to deal with managing the list of listening sockets.
|
||||
*/
|
||||
static ap_listen_rec *head_listener;
|
||||
|
||||
static ap_inline ap_listen_rec *find_ready_listener(fd_set * main_fds)
|
||||
{
|
||||
ap_listen_rec *lr;
|
||||
@ -371,6 +373,7 @@ static ap_inline ap_listen_rec *find_ready_listener(fd_set * main_fds)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int setup_listeners(server_rec *s)
|
||||
{
|
||||
ap_listen_rec *lr;
|
||||
@ -1390,7 +1393,10 @@ static int create_process(ap_pool_t *p, HANDLE *handles, HANDLE *events, int *pr
|
||||
int rv;
|
||||
char buf[1024];
|
||||
char *pCommand;
|
||||
char *pEnvVar;
|
||||
char *pEnvBlock;
|
||||
int i;
|
||||
int iEnvBlockLen;
|
||||
STARTUPINFO si; /* Filled in prior to call to CreateProcess */
|
||||
PROCESS_INFORMATION pi; /* filled in on call to CreateProces */
|
||||
|
||||
@ -1425,6 +1431,32 @@ static int create_process(ap_pool_t *p, HANDLE *handles, HANDLE *events, int *pr
|
||||
pCommand = ap_pstrcat(p, pCommand, " \"", server_conf->process->argv[i], "\"", NULL);
|
||||
}
|
||||
|
||||
/* Build the environment, since Win9x disrespects the active env */
|
||||
// SetEnvironmentVariable("AP_PARENT_PID",ap_psprintf(p,"%l",parent_pid));
|
||||
pEnvVar = ap_psprintf(p, "AP_PARENT_PID=%i", parent_pid);
|
||||
/*
|
||||
* Win32's CreateProcess call requires that the environment
|
||||
* be passed in an environment block, a null terminated block of
|
||||
* null terminated strings.
|
||||
*/
|
||||
i = 0;
|
||||
iEnvBlockLen = 1;
|
||||
while (_environ[i]) {
|
||||
iEnvBlockLen += strlen(_environ[i]) + 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
pEnvBlock = (char *)ap_pcalloc(p, iEnvBlockLen + strlen(pEnvVar) + 1);
|
||||
strcpy(pEnvBlock, pEnvVar);
|
||||
pEnvVar = strchr(pEnvBlock, '\0') + 1;
|
||||
|
||||
i = 0;
|
||||
while (_environ[i]) {
|
||||
strcpy(pEnvVar, _environ[i]);
|
||||
pEnvVar = strchr(pEnvVar, '\0') + 1;
|
||||
i++;
|
||||
}
|
||||
pEnvVar = '\0';
|
||||
/* Create a pipe to send socket info to the child */
|
||||
if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT, GetLastError(), server_conf,
|
||||
@ -1432,8 +1464,6 @@ static int create_process(ap_pool_t *p, HANDLE *handles, HANDLE *events, int *pr
|
||||
return -1;
|
||||
}
|
||||
|
||||
SetEnvironmentVariable("AP_PARENT_PID",ap_psprintf(p,"%d",parent_pid));
|
||||
|
||||
/* Give the read end of the pipe (hPipeRead) to the child as stdin. The
|
||||
* parent will write the socket data to the child on this pipe.
|
||||
*/
|
||||
@ -1447,7 +1477,7 @@ static int create_process(ap_pool_t *p, HANDLE *handles, HANDLE *events, int *pr
|
||||
if (!CreateProcess(NULL, pCommand, NULL, NULL,
|
||||
TRUE, /* Inherit handles */
|
||||
CREATE_SUSPENDED, /* Creation flags */
|
||||
NULL, /* Environment block */
|
||||
pEnvBlock, /* Environment block */
|
||||
NULL,
|
||||
&si, &pi)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT, GetLastError(), server_conf,
|
||||
@ -1694,12 +1724,12 @@ static void winnt_pre_config(ap_pool_t *pconf, ap_pool_t *plog, ap_pool_t *ptemp
|
||||
pid = getenv("AP_PARENT_PID");
|
||||
if (pid) {
|
||||
/* This is the child */
|
||||
parent_pid = atoi(pid);
|
||||
my_pid = getpid();
|
||||
parent_pid = (DWORD) atol(pid);
|
||||
my_pid = GetCurrentProcessId();
|
||||
}
|
||||
else {
|
||||
/* This is the parent */
|
||||
parent_pid = my_pid = getpid();
|
||||
parent_pid = my_pid = GetCurrentProcessId();
|
||||
}
|
||||
|
||||
ap_listen_pre_config();
|
||||
@ -1806,7 +1836,7 @@ API_EXPORT(int) ap_mpm_run(ap_pool_t *_pconf, ap_pool_t *plog, server_rec *s )
|
||||
if (pidfile != NULL && unlink(pidfile) == 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,APR_SUCCESS,
|
||||
server_conf, "removed PID file %s (pid=%ld)",
|
||||
pidfile, (long)getpid());
|
||||
pidfile, GetCurrentProcessId());
|
||||
}
|
||||
ap_destroy_lock(start_mutex);
|
||||
|
||||
|
@ -59,11 +59,17 @@
|
||||
#ifndef APACHE_MPM_WINNT_H
|
||||
#define APACHE_MPM_WINNT_H
|
||||
|
||||
#include "ap_listen.h"
|
||||
|
||||
extern int ap_threads_per_child;
|
||||
extern int ap_max_requests_per_child;
|
||||
extern int ap_extended_status;
|
||||
extern void clean_child_exit(int);
|
||||
|
||||
typedef void (CALLBACK *ap_completion_t)();
|
||||
API_VAR_IMPORT ap_completion_t ap_mpm_init_complete;
|
||||
|
||||
API_EXPORT(void) ap_start_shutdown(void);
|
||||
|
||||
typedef struct CompContext {
|
||||
OVERLAPPED Overlapped;
|
||||
|
@ -101,6 +101,7 @@
|
||||
#define SERVICEKEYPRE "System\\CurrentControlSet\\Services\\"
|
||||
#define SERVICEKEYPOST "\\Parameters"
|
||||
|
||||
#define SERVICELAUNCH9X "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices\\"
|
||||
/*
|
||||
* The Windows API registry key functions don't set the last error
|
||||
* value (the windows equivalent of errno). So we need to set it
|
||||
@ -253,19 +254,6 @@ static int ap_registry_get_key_int(ap_pool_t *p, char *key, char *name, char *pB
|
||||
* dir will contain an empty string), or -1 if there was
|
||||
* an error getting the key.
|
||||
*/
|
||||
#if 0
|
||||
int ap_registry_get_server_root(ap_pool_t *p, char *dir, int size)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = ap_registry_get_key_int(p, REGKEY, "ServerRoot", dir, size, NULL);
|
||||
if (rv < 0) {
|
||||
dir[0] = '\0';
|
||||
}
|
||||
|
||||
return (rv < -1) ? -1 : 0;
|
||||
}
|
||||
#else
|
||||
int ap_registry_get_server_root(ap_pool_t *p, char **buf)
|
||||
{
|
||||
int rv;
|
||||
@ -277,7 +265,7 @@ int ap_registry_get_server_root(ap_pool_t *p, char **buf)
|
||||
|
||||
return (rv < -1) ? -1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *ap_get_service_key(char *display_name)
|
||||
{
|
||||
size_t keylen = strlen(display_name);
|
||||
@ -290,21 +278,7 @@ char *ap_get_service_key(char *display_name)
|
||||
|
||||
return(key);
|
||||
}
|
||||
#if 0
|
||||
int ap_registry_get_service_conf(ap_pool_t *p, char *dir, int size, char *display_name)
|
||||
{
|
||||
int rv;
|
||||
char *key = ap_get_service_key(display_name);
|
||||
|
||||
rv = ap_registry_get_key_int(p, key, "ConfPath", dir, size, NULL);
|
||||
if (rv < 0) {
|
||||
dir[0] = '\0';
|
||||
}
|
||||
|
||||
free(key);
|
||||
return (rv < -1) ? -1 : 0;
|
||||
}
|
||||
#else
|
||||
int ap_registry_get_service_conf(ap_pool_t *p, char **buf, char *service_name)
|
||||
{
|
||||
int rv;
|
||||
@ -318,7 +292,6 @@ int ap_registry_get_service_conf(ap_pool_t *p, char **buf, char *service_name)
|
||||
free(key);
|
||||
return (rv < -1) ? -1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
* The rest of this file deals with storing keys or values in the registry
|
||||
@ -552,4 +525,3 @@ int ap_registry_set_server_root(char *dir)
|
||||
|
||||
return rv < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
/* We do this only once, ever */
|
||||
ap_mpm_init_complete = NULL;
|
||||
/* 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));
|
||||
}
|
||||
|
||||
int service95_main(int (*main_fn)(int, char **), int argc, char **argv )
|
||||
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);
|
||||
}
|
||||
|
||||
static void CALLBACK report_service9x_running()
|
||||
{
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
|
Reference in New Issue
Block a user