📄 service.c
字号:
}
void service_stopped(void)
{
/* Still have a thread & window to clean up, so signal now */
if (globdat.service_thread)
{
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
/* Stop logging to the event log */
mpm_nt_eventlog_stderr_flush();
/* Cause the service_nt_main_fn to complete */
ReleaseMutex(globdat.service_term);
ReportStatusToSCMgr(SERVICE_STOPPED, // service state
NO_ERROR, // exit code
0); // wait hint
}
else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
{
RegisterServiceProcess(0, 0);
PostThreadMessage(globdat.service_thread_id, WM_CLOSE, 0, 0);
}
WaitForSingleObject(globdat.service_thread, 5000);
CloseHandle(globdat.service_thread);
}
}
apr_status_t mpm_service_to_start(const char **display_name, apr_pool_t *p)
{
HANDLE hProc = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
HANDLE waitfor[2];
/* Prevent holding open the (hidden) console */
real_exit_code = 0;
/* GetCurrentThread returns a psuedo-handle, we need
* a real handle for another thread to wait upon.
*/
if (!DuplicateHandle(hProc, hThread, hProc, &(globdat.mpm_thread),
0, FALSE, DUPLICATE_SAME_ACCESS)) {
return APR_ENOTHREAD;
}
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
globdat.service_term = CreateMutex(NULL, TRUE, NULL);
if (!globdat.service_init || !globdat.service_term) {
return APR_EGENERAL;
}
globdat.service_thread = CreateThread(NULL, 0, service_nt_dispatch_thread,
NULL, 0, &globdat.service_thread_id);
}
else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
{
if (!RegisterServiceProcess(0, 1))
return GetLastError();
globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!globdat.service_init) {
return APR_EGENERAL;
}
globdat.service_thread = CreateThread(NULL, 0, monitor_service_9x_thread,
(LPVOID) mpm_service_name, 0,
&globdat.service_thread_id);
}
if (!globdat.service_thread) {
return APR_ENOTHREAD;
}
waitfor[0] = globdat.service_init;
waitfor[1] = globdat.service_thread;
/* Wait for controlling thread init or termination */
if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
return APR_ENOTHREAD;
}
atexit(service_stopped);
*display_name = mpm_display_name;
return APR_SUCCESS;
}
apr_status_t mpm_service_started(void)
{
set_service_description();
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
ReportStatusToSCMgr(SERVICE_RUNNING, // service state
NO_ERROR, // exit code
0); // wait hint
}
return APR_SUCCESS;
}
void mpm_service_stopping(void)
{
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
ReportStatusToSCMgr(SERVICE_STOP_PENDING, // service state
NO_ERROR, // exit code
30000); // wait hint
}
apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc,
const char * const * argv, int reconfig)
{
char key_name[MAX_PATH];
char exe_path[MAX_PATH];
char *launch_cmd;
ap_regkey_t *key;
apr_status_t rv;
fprintf(stderr,reconfig ? "Reconfiguring the %s service\n"
: "Installing the %s service\n", mpm_display_name);
/* ###: utf-ize */
if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
{
apr_status_t rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"GetModuleFileName failed");
return rv;
}
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
SC_MANAGER_CREATE_SERVICE);
if (!schSCManager) {
rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"Failed to open the WinNT service manager");
return (rv);
}
launch_cmd = apr_psprintf(ptemp, "\"%s\" -k runservice", exe_path);
if (reconfig) {
/* ###: utf-ize */
schService = OpenService(schSCManager, mpm_service_name,
SERVICE_CHANGE_CONFIG);
if (!schService) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
apr_get_os_error(), NULL,
"OpenService failed");
}
/* ###: utf-ize */
else if (!ChangeServiceConfig(schService,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
launch_cmd, NULL, NULL,
"Tcpip\0Afd\0", NULL, NULL,
mpm_display_name)) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
apr_get_os_error(), NULL,
"ChangeServiceConfig failed");
/* !schService aborts configuration below */
CloseServiceHandle(schService);
schService = NULL;
}
}
else {
/* RPCSS is the Remote Procedure Call (RPC) Locator required
* for DCOM communication pipes. I am far from convinced we
* should add this to the default service dependencies, but
* be warned that future apache modules or ISAPI dll's may
* depend on it.
*/
/* ###: utf-ize */
schService = CreateService(schSCManager, // SCManager database
mpm_service_name, // name of service
mpm_display_name, // name to display
SERVICE_ALL_ACCESS, // access required
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
launch_cmd, // service's binary
NULL, // no load svc group
NULL, // no tag identifier
"Tcpip\0Afd\0", // dependencies
NULL, // use SYSTEM account
NULL); // no password
if (!schService)
{
rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"Failed to create WinNT Service Profile");
CloseServiceHandle(schSCManager);
return (rv);
}
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
{
/* Store the launch command in the registry */
launch_cmd = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice",
exe_path, mpm_service_name);
rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, SERVICECONFIG9X,
APR_READ | APR_WRITE | APR_CREATE, pconf);
if (rv == APR_SUCCESS) {
rv = ap_regkey_value_set(key, mpm_service_name,
launch_cmd, 0, pconf);
ap_regkey_close(key);
}
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: Failed to add the RunServices registry entry.",
mpm_display_name);
return (rv);
}
apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name,
APR_READ | APR_WRITE | APR_CREATE, pconf);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: Failed to create the registry service key.",
mpm_display_name);
return (rv);
}
rv = ap_regkey_value_set(key, "ImagePath", launch_cmd, 0, pconf);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: Failed to store ImagePath in the registry.",
mpm_display_name);
ap_regkey_close(key);
return (rv);
}
rv = ap_regkey_value_set(key, "DisplayName",
mpm_display_name, 0, pconf);
ap_regkey_close(key);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: Failed to store DisplayName in the registry.",
mpm_display_name);
return (rv);
}
}
set_service_description();
/* For both WinNT & Win9x store the service ConfigArgs in the registry...
*/
apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, mpm_service_name);
rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name,
APR_READ | APR_WRITE | APR_CREATE, pconf);
if (rv == APR_SUCCESS) {
rv = ap_regkey_value_array_set(key, "ConfigArgs", argc, argv, pconf);
ap_regkey_close(key);
}
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: Failed to store the ConfigArgs in the registry.",
mpm_display_name);
return (rv);
}
fprintf(stderr,"The %s service is successfully installed.\n", mpm_display_name);
return APR_SUCCESS;
}
apr_status_t mpm_service_uninstall(void)
{
char key_name[MAX_PATH];
apr_status_t rv;
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
fprintf(stderr,"Removing the %s service\n", mpm_display_name);
schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
SC_MANAGER_CONNECT);
if (!schSCManager) {
rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"Failed to open the WinNT service manager.");
return (rv);
}
/* ###: utf-ize */
schService = OpenService(schSCManager, mpm_service_name, DELETE);
if (!schService) {
rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: OpenService failed", mpm_display_name);
return (rv);
}
/* assure the service is stopped before continuing
*
* This may be out of order... we might not be able to be
* granted all access if the service is running anyway.
*
* And do we want to make it *this easy* for them
* to uninstall their service unintentionally?
*/
// ap_stop_service(schService);
if (DeleteService(schService) == 0) {
rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
"%s: Failed to delete the service.", mpm_display_name);
return (rv);
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
{
apr_status_t rv2, rv3;
ap_regkey_t *key;
fprintf(stderr,"Removing the %s service\n", mpm_display_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -