📄 jk_nt_service.c
字号:
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/***************************************************************************
* Description: NT System service for Jakarta/Tomcat *
* Author: Gal Shachor <shachor@il.ibm.com> *
* Dave Oxley <Dave@JungleMoss.com> *
* Version: $Revision: 300540 $ *
***************************************************************************/
#include "jk_global.h"
#include "jk_util.h"
#include "jk_ajp13.h"
#include "jk_connect.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#define AJP12_TAG ("ajp12")
#define AJP13_TAG ("ajp13")
#define BASE_REGISTRY_LOCATION ("SYSTEM\\CurrentControlSet\\Services\\")
#define IMAGE_NAME ("ImagePath")
#define PARAMS_LOCATION ("Parameters")
#define PRP_LOCATION ("PropertyFile")
// internal variables
static SERVICE_STATUS ssStatus; // current status of the service
static SERVICE_STATUS_HANDLE sshStatusHandle;
static DWORD dwErr = 0;
static char szErr[1024] = "";
static HANDLE hServerStopEvent = NULL;
static int shutdown_port;
static char *shutdown_protocol = AJP12_TAG;
static char *shutdown_secret = NULL;
static char *shutdown_cmd=NULL;
typedef enum ActionEnum
{ acNoAction = 0,
acInstall = 1,
acRemove = 2,
acStartTC = 3,
acStopTC = 4
} ActionEnum;
struct jk_tomcat_startup_data {
char *cmd_line; /* Start command line */
char *stdout_file;
char *stderr_file;
char *extra_path;
char *tomcat_home;
char *java_bin;
char *shutdown_protocol;
/* for cmd */
char *stop_cmd;
/* For ajp13/ajp12/catalina */
int shutdown_port;
char *shutdown_secret;
/* Optional/not needed */
char *classpath;
char *tomcat_class;
char *server_file;
};
typedef struct jk_tomcat_startup_data jk_tomcat_startup_data_t;
// internal function prototypes
static void WINAPI service_ctrl(DWORD dwCtrlCode);
static void WINAPI service_main(DWORD dwArgc,
char **lpszArgv);
static void install_service(char *name,
char *dname,
char *user,
char *password,
char *deps,
BOOL bAutomatic,
char *rel_prp_file);
static void remove_service(char *name);
static void start_service(char *name,
char *machine);
static void stop_service(char *name,
char *machine);
static char *GetLastErrorText(char *lpszBuf, DWORD dwSize);
static void AddToMessageLog(char *lpszMsg);
static BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint);
static void start_jk_service(char *name);
static void stop_jk_service(void);
static int set_registry_values(SC_HANDLE schService, char *name,
char *prp_file);
static int create_registry_key(const char *tag,
HKEY *key);
static int set_registry_config_parameter(HKEY hkey,
const char *tag,
char *value);
static int get_registry_config_parameter(HKEY hkey,
const char *tag,
char *b, DWORD sz);
static int start_tomcat(const char *name,
HANDLE *hTomcat);
static void stop_tomcat(char *name,
int port,
const char *protocol,
char *secret,
HANDLE hTomcat);
static int read_startup_data(jk_map_t *init_map,
jk_tomcat_startup_data_t *data,
jk_pool_t *p);
static int exec_cmd(const char *name, HANDLE *hTomcat, char *cmdLine);
static void usage_message(const char *name)
{
printf("%s - Usage:\n\n", name);
printf("To install the service:\n");
printf("%s -i <service name> {optional params} <config properties file>\n", name);
printf(" Optional parameters\n");
printf(" -u <user name> - In the form DomainName\\UserName (.\\UserName for local)\n");
printf(" -n <service display name> - In quotes if contains non-lphanumeric chars\n");
printf(" -p <user password>\n");
printf(" -a - Set startup type to automatic\n");
printf(" -d <service dependency> - Can be entered multiple times\n\n");
printf("To remove the service:\n");
printf("%s -r <service name>\n\n", name);
printf("To start the service:\n");
printf("%s -s <service name> {optional params}\n", name);
printf(" Optional parameters\n");
printf(" -m <machine>\n\n");
printf("To stop the service:\n");
printf("%s -t <service name> {optional params}\n", name);
printf(" Optional parameters\n");
printf(" -m <machine>\n");
}
void main(int argc, char **argv)
{
WORD wVersionRequested;
WSADATA wsaData;
int i;
int err;
int count;
int iAction = acNoAction;
char *pServiceDisplayName = NULL;
char *pServiceName = NULL;
char *pUserName = NULL;
char *pPassword = NULL;
char *pMachine = NULL;
BOOL bAutomatic = FALSE;
char strDependancy[256] = "";
memset(strDependancy, 0, 255);
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if(0 != err) {
fprintf(stderr, "Error connecting to winsock");
return;
}
if(LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1) {
fprintf(stderr,
"Error winsock version is %d %d \n",
LOBYTE( wsaData.wVersion ),HIBYTE( wsaData.wVersion ));
WSACleanup();
return;
}
fprintf(stderr, "Asked (and given) winsock %d.%d \n",
LOBYTE(wsaData.wVersion),
HIBYTE(wsaData.wVersion));
__try {
if(argc > 2) {
count=0;
for (i=1;i<argc;i++) {
if ((*argv[i] == '-') || (*argv[i] == '/')) {
char *cmd = argv[i];
cmd++;
if(0 == stricmp("i", cmd)) {
iAction = acInstall;
pServiceName = argv[i+1];
} else if(0 == stricmp("r", cmd)) {
iAction = acRemove;
pServiceName = argv[i+1];
} else if(0 == stricmp("s", cmd)) {
iAction = acStartTC;
pServiceName = argv[i+1];
} else if(0 == stricmp("t", cmd)) {
iAction = acStopTC;
pServiceName = argv[i+1];
} else if(0 == stricmp("u", cmd)) {
pUserName = argv[i+1];
} else if(0 == stricmp("p", cmd)) {
pPassword = argv[i+1];
} else if(0 == stricmp("m", cmd)) {
pMachine = argv[i+1];
} else if(0 == stricmp("a", cmd)) {
bAutomatic = TRUE;
} else if(0 == stricmp("n", cmd)) {
pServiceDisplayName = argv[i+1];
} else if(0 == stricmp("d", cmd)) {
memcpy(strDependancy+count, argv[i+1], strlen(argv[i+1]));
count+= strlen(argv[i+1])+1;
}
}
}
switch (iAction) {
case acInstall:
if (pServiceDisplayName == NULL) {
pServiceDisplayName = pServiceName;
}
install_service(pServiceName, pServiceDisplayName, pUserName,
pPassword, strDependancy, bAutomatic, argv[i-1]);
return;
case acRemove:
remove_service(pServiceName);
return;
case acStartTC:
start_service(pServiceName, pMachine);
return;
case acStopTC:
stop_service(pServiceName, pMachine);
return;
}
} else if(2 == argc) {
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ argv[1], (LPSERVICE_MAIN_FUNCTION)service_main },
{ NULL, NULL }
};
if(!StartServiceCtrlDispatcher(dispatchTable)) {
AddToMessageLog("StartServiceCtrlDispatcher failed.");
}
return;
}
usage_message(argv[0]);
exit(-1);
} __finally {
WSACleanup();
}
}
void WINAPI service_main(DWORD dwArgc, char **lpszArgv)
{
// register our service control handler:
//
//
sshStatusHandle = RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
if(sshStatusHandle) {
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;
// report the status to the service control manager.
//
if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) { // wait hint
start_jk_service(lpszArgv[0]);
}
}
// try to report the stopped status to the service control manager.
//
if(sshStatusHandle) {
ReportStatusToSCMgr(SERVICE_STOPPED,
dwErr,
0);
}
}
void WINAPI service_ctrl(DWORD dwCtrlCode)
{
/*
* Handle the requested control code.
*/
switch(dwCtrlCode)
{
/*
* Stop the service.
*/
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
stop_jk_service();
break;
/*
* Update the service status.
*/
case SERVICE_CONTROL_INTERROGATE:
break;
/*
* Invalid control code, nothing to do.
*/
default:
break;
}
ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
BOOL fResult = TRUE;
if(dwCurrentState == SERVICE_START_PENDING) {
ssStatus.dwControlsAccepted = 0;
} else {
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
}
ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
ssStatus.dwWaitHint = dwWaitHint;
if((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED)) {
ssStatus.dwCheckPoint = 0;
} else {
ssStatus.dwCheckPoint = dwCheckPoint++;
}
if(!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) {
AddToMessageLog(TEXT("SetServiceStatus"));
}
return fResult;
}
typedef WINADVAPI BOOL (WINAPI * pfnChangeServiceConfig2_t)
(SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo);
void install_service(char *name,
char *dname,
char *user,
char *password,
char *deps,
BOOL bAutomatic,
char *rel_prp_file)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
char szExecPath[2048];
char szPropPath[2048];
char szTrueName[256];
char *dummy;
char *src, *dst;
dst = szTrueName;
for (src = name; *src; ++src) {
if (dst >= szTrueName + sizeof(szTrueName) - 1) {
break;
}
if (!isspace(*src) && *src != '/' && *src != '\\') {
*(dst++) = *src;
}
}
*dst = '\0';
if (0 == stricmp("", deps))
deps = NULL;
/* XXX strcat( deps, "Tcpip\0Afd\0" ); */
if(!GetFullPathName(rel_prp_file, sizeof(szPropPath) - 1, szPropPath, &dummy)) {
printf("Unable to install %s - %s\n",
name,
GetLastErrorText(szErr, sizeof(szErr)));
return;
}
if(!jk_file_exists(szPropPath)) {
printf("Unable to install %s - File [%s] does not exists\n",
name,
szPropPath);
return;
}
szExecPath[0] = '\"';
if(GetModuleFileName( NULL, szExecPath + 1, sizeof(szExecPath) - 2) == 0) {
/* Was: if(GetModuleFileName( NULL, szExecPath, sizeof(szExecPath) - 1) == 0) { */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -