summaryrefslogtreecommitdiffstats
path: root/rubbos/app/tomcat-connectors-1.2.32-src/native/nt_service/jk_nt_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'rubbos/app/tomcat-connectors-1.2.32-src/native/nt_service/jk_nt_service.c')
-rw-r--r--rubbos/app/tomcat-connectors-1.2.32-src/native/nt_service/jk_nt_service.c1233
1 files changed, 1233 insertions, 0 deletions
diff --git a/rubbos/app/tomcat-connectors-1.2.32-src/native/nt_service/jk_nt_service.c b/rubbos/app/tomcat-connectors-1.2.32-src/native/nt_service/jk_nt_service.c
new file mode 100644
index 00000000..e17621bf
--- /dev/null
+++ b/rubbos/app/tomcat-connectors-1.2.32-src/native/nt_service/jk_nt_service.c
@@ -0,0 +1,1233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 Tomcat *
+ * Author: Gal Shachor <shachor@il.ibm.com> *
+ * Dave Oxley <Dave@JungleMoss.com> *
+ * Version: $Revision: 756058 $ *
+ ***************************************************************************/
+
+#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((int)(*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) { */
+ printf("Unable to install %s - %s\n",
+ name,
+ GetLastErrorText(szErr, sizeof(szErr)));
+ return;
+ }
+ strcat(szExecPath, "\" ");
+ strcat(szExecPath, szTrueName);
+
+
+ schSCManager = OpenSCManager(NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS); // access required
+ if(schSCManager) {
+
+ schService = CreateService(schSCManager, // SCManager database
+ szTrueName, // name of service
+ dname, // name to display
+ SERVICE_ALL_ACCESS, // desired access
+ SERVICE_WIN32_OWN_PROCESS, // service type
+ bAutomatic ? SERVICE_AUTO_START : SERVICE_DEMAND_START, // start type
+ SERVICE_ERROR_NORMAL, // error control type
+ szExecPath, // service's binary
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ deps, // dependencies
+ user, // account
+ password); // password
+
+ if(schService) {
+
+ printf("The service named %s was created. Now adding registry entries\n", name);
+
+ if(set_registry_values(schService, szTrueName, szPropPath)) {
+ CloseServiceHandle(schService);
+ } else {
+ printf("CreateService failed setting the private registry - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ DeleteService(schService);
+ CloseServiceHandle(schService);
+ }
+ } else {
+ printf("CreateService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+
+ CloseServiceHandle(schSCManager);
+ } else {
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+}
+
+void remove_service(char *name)
+{
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+ char szNameBuff[256];
+ DWORD lenNameBuff = 256;
+ char *szTrueName = name;
+
+ schSCManager = OpenSCManager(NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS ); // access required
+
+ if(schSCManager) {
+ if (GetServiceKeyName(schSCManager, name, szNameBuff, &lenNameBuff)) {
+ szTrueName = szNameBuff;
+ }
+ schService = OpenService(schSCManager, szTrueName, SERVICE_ALL_ACCESS);
+
+ if(schService) {
+ // try to stop the service
+ if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
+ printf("Stopping %s.", name);
+ Sleep(1000);
+
+ while(QueryServiceStatus(schService, &ssStatus )) {
+ if(ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
+ printf(".");
+ Sleep(1000);
+ } else {
+ break;
+ }
+ }
+
+ if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
+ printf("\n%s stopped.\n", name);
+ } else {
+ printf("\n%s failed to stop.\n", name);
+ }
+ }
+
+ // now remove the service
+ if(DeleteService(schService)) {
+ printf("%s removed.\n", name);
+ } else {
+ printf("DeleteService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+
+ CloseServiceHandle(schService);
+ } else {
+ printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+
+ CloseServiceHandle(schSCManager);
+ } else {
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+}
+
+void start_service(char *name, char *machine)
+{
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+ schSCManager = OpenSCManager(machine, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS); // access required
+
+ if(schSCManager) {
+ schService = OpenService(schSCManager, name, SERVICE_ALL_ACCESS);
+
+ if(schService) {
+ // try to start the service
+ if(StartService(schService, 0, NULL)) {
+ printf("Starting %s.", name);
+ Sleep(1000);
+
+ while(QueryServiceStatus(schService, &ssStatus )) {
+ if(ssStatus.dwCurrentState == SERVICE_START_PENDING) {
+ printf(".");
+ Sleep(1000);
+ } else {
+ break;
+ }
+ }
+
+ if(ssStatus.dwCurrentState == SERVICE_RUNNING) {
+ printf("\n%s started.\n", name);
+ } else {
+ printf("\n%s failed to start.\n", name);
+ }
+ }
+ else
+ printf("StartService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+
+ CloseServiceHandle(schService);
+ } else {
+ printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+
+ CloseServiceHandle(schSCManager);
+ } else {
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+}
+
+void stop_service(char *name, char *machine)
+{
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+ schSCManager = OpenSCManager(machine, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS); // access required
+
+ if(schSCManager) {
+ schService = OpenService(schSCManager, name, SERVICE_ALL_ACCESS);
+
+ if(schService) {
+ // try to stop the service
+ if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
+ printf("Stopping %s.", name);
+ Sleep(1000);
+
+ while(QueryServiceStatus(schService, &ssStatus )) {
+ if(ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
+ printf(".");
+ Sleep(1000);
+ } else {
+ break;
+ }
+ }
+
+ if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
+ printf("\n%s stopped.\n", name);
+ } else {
+ printf("\n%s failed to stop.\n", name);
+ }
+ }
+ else
+ printf("StopService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+
+ CloseServiceHandle(schService);
+ } else {
+ printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+
+ CloseServiceHandle(schSCManager);
+ } else {
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
+ }
+}
+
+static int set_registry_values(SC_HANDLE schService, char *name,
+ char *prp_file)
+{
+ char tag[1024];
+ HKEY hk;
+ int rc;
+ /* Api based */
+ HANDLE hAdvApi32;
+ char *szDescription = "Tomcat Server";
+ pfnChangeServiceConfig2_t pfnChangeServiceConfig2;
+
+ if((hAdvApi32 = GetModuleHandle("advapi32.dll"))
+ && ((pfnChangeServiceConfig2 = (pfnChangeServiceConfig2_t)
+ GetProcAddress(hAdvApi32, "ChangeServiceConfig2A")))) {
+ (void) pfnChangeServiceConfig2(schService, // Service Handle
+ 1, // SERVICE_CONFIG_DESCRIPTION
+ &szDescription);
+ } else {
+ char value[2024];
+
+ rc = JK_FALSE;
+
+ strcpy(tag, BASE_REGISTRY_LOCATION);
+ strcat(tag, name);
+
+ if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ tag,
+ (DWORD)0,
+ KEY_WRITE | KEY_READ,
+ &hk)) {
+ rc = get_registry_config_parameter(hk,
+ IMAGE_NAME,
+ value,
+ sizeof(value));
+ if(rc) {
+ strcat(value, " ");
+ strcat(value, name);
+ rc = set_registry_config_parameter(hk,
+ IMAGE_NAME,
+ value);
+ if(rc) {
+ printf("Registry values were added\n");
+ printf("If you have already updated wrapper.properties you may start the %s"
+ "service by executing \"jk_nt_service -s %s\" from the command prompt\n",
+ name,
+ name);
+ }
+ }
+ RegCloseKey(hk);
+ }
+ if(!rc) {
+ printf("Error: Failed to update the service command line - %s\n",
+ GetLastErrorText(szErr, sizeof(szErr)));
+ }
+ }
+
+ strcpy(tag, BASE_REGISTRY_LOCATION);
+ strcat(tag, name);
+ strcat(tag, "\\");
+ strcat(tag, PARAMS_LOCATION);
+
+ rc = create_registry_key(tag, &hk);
+
+ if(rc) {
+ rc = set_registry_config_parameter(hk, PRP_LOCATION, prp_file);
+ if(!rc) {
+ printf("Error: Can not create value [%s] - %s\n",
+ PRP_LOCATION,
+ GetLastErrorText(szErr, sizeof(szErr)));
+ }
+ RegCloseKey(hk);
+ } else {
+ printf("Error: Can not create key [%s] - %s\n",
+ tag,
+ GetLastErrorText(szErr, sizeof(szErr)));
+ }
+ return rc;
+}
+
+static void start_jk_service(char *name)
+{
+ /*
+ * report the status to the service control manager.
+ */
+ if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
+ NO_ERROR, // exit code
+ 3000)) { // wait hint
+
+ /*
+ * create the event object. The control handler function signals
+ * this event when it receives the "stop" control code.
+ */
+ hServerStopEvent = CreateEvent(NULL, // no security attributes
+ TRUE, // manual reset event
+ FALSE, // not-signalled
+ NULL); // no name
+
+ if(hServerStopEvent) {
+ if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
+ NO_ERROR, // exit code
+ 20000)) { // wait hint
+ HANDLE hTomcat = NULL;
+ char szNameBuff[256];
+ DWORD lenNameBuff = 256;
+ char *szTrueName = name;
+ SC_HANDLE schSCManager;
+ int rc;
+
+ schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS );
+ if(schSCManager) {
+ if (GetServiceKeyName(schSCManager, name, szNameBuff, &lenNameBuff)) {
+ szTrueName = szNameBuff;
+ }
+ CloseServiceHandle(schSCManager);
+ }
+
+ rc = start_tomcat(szTrueName, &hTomcat);
+
+ if(rc && ReportStatusToSCMgr(SERVICE_RUNNING, // service state
+ NO_ERROR, // exit code
+ 0)) { // wait hint
+ HANDLE waitfor[] = { hServerStopEvent, hTomcat};
+ DWORD dwIndex = WaitForMultipleObjects(2, waitfor, FALSE, INFINITE);
+
+ switch(dwIndex) {
+ case WAIT_OBJECT_0:
+ /*
+ * Stop order arrived
+ */
+ ResetEvent(hServerStopEvent);
+ stop_tomcat(name, shutdown_port, shutdown_protocol,
+ shutdown_secret, hTomcat);
+ break;
+ case (WAIT_OBJECT_0 + 1):
+ /*
+ * Tomcat died !!!
+ */
+ CloseHandle(hServerStopEvent);
+ CloseHandle(hTomcat);
+ exit(0); // exit ungracefully so
+ // Service Control Manager
+ // will attempt a restart.
+ break;
+ default:
+ /*
+ * some error...
+ * close the servlet container and exit
+ */
+ stop_tomcat(name, shutdown_port, shutdown_protocol,
+ shutdown_secret, hTomcat);
+ }
+ CloseHandle(hServerStopEvent);
+ CloseHandle(hTomcat);
+ }
+ }
+ }
+ }
+
+ if(hServerStopEvent) {
+ CloseHandle(hServerStopEvent);
+ }
+}
+
+
+static void stop_jk_service(void)
+{
+ if(hServerStopEvent) {
+ SetEvent(hServerStopEvent);
+ }
+}
+
+static void AddToMessageLog(char *lpszMsg)
+{
+ char szMsg[2048];
+ HANDLE hEventSource;
+ char * lpszStrings[2];
+
+ printf("Error: %s\n", lpszMsg);
+
+ dwErr = GetLastError();
+
+ hEventSource = RegisterEventSource(NULL, "Tomcat");
+
+ sprintf(szMsg, "%s error: %d", "Tomcat", dwErr);
+ lpszStrings[0] = szMsg;
+ lpszStrings[1] = lpszMsg;
+
+ if(hEventSource != NULL) {
+ ReportEvent(hEventSource, // handle of event source
+ EVENTLOG_ERROR_TYPE, // event type
+ 0, // event category
+ 0, // event ID
+ NULL, // current user's SID
+ 2, // strings in lpszStrings
+ 0, // no bytes of raw data
+ lpszStrings, // array of error strings
+ NULL); // no raw data
+
+ DeregisterEventSource(hEventSource);
+ }
+
+}
+
+//
+// FUNCTION: GetLastErrorText
+//
+// PURPOSE: copies error message text to string
+//
+// PARAMETERS:
+// lpszBuf - destination buffer
+// dwSize - size of buffer
+//
+// RETURN VALUE:
+// destination buffer
+//
+// COMMENTS:
+//
+char *GetLastErrorText( char *lpszBuf, DWORD dwSize )
+{
+ DWORD dwRet;
+ char *lpszTemp = NULL;
+
+ dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ NULL,
+ GetLastError(),
+ LANG_NEUTRAL,
+ (char *)&lpszTemp,
+ 0,
+ NULL);
+
+ // supplied buffer is not long enough
+ if(!dwRet || ((long)dwSize < (long)dwRet+14)) {
+ lpszBuf[0] = '\0';
+ } else {
+ lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character
+ sprintf(lpszBuf, "%s (0x%x)", lpszTemp, GetLastError());
+ }
+
+ if(lpszTemp) {
+ LocalFree((HLOCAL) lpszTemp );
+ }
+
+ return lpszBuf;
+}
+
+static void stop_tomcat(char *name,
+ int port,
+ const char *protocol,
+ char *secret,
+ HANDLE hTomcat)
+{
+ struct sockaddr_in in;
+
+ if(strcasecmp(protocol, "cmd") == 0 ) {
+ exec_cmd( name, hTomcat, shutdown_cmd);
+ /* XXX sleep 100 */
+ TerminateProcess(hTomcat, 0);
+ return;
+ }
+
+ if(jk_resolve("localhost", port, &in, NULL)) {
+ int sd = jk_open_socket(&in, JK_TRUE, 0, 0, NULL);
+ if(sd >0) {
+ int rc = JK_FALSE;
+
+ if(strcasecmp(protocol, "catalina") == 0 ) {
+ char len;
+
+ if( secret==NULL )
+ secret="SHUTDOWN";
+ len=strlen( secret );
+
+ rc = send(sd, secret, len , 0);
+ if(len == rc) {
+ rc = JK_TRUE;
+ }
+ } else if(!strcasecmp(protocol, "ajp13")) {
+ jk_pool_t pool;
+ jk_msg_buf_t *msg = NULL;
+ jk_pool_atom_t buf[TINY_POOL_SIZE];
+
+ jk_open_pool(&pool, buf, sizeof(buf));
+
+ msg = jk_b_new(&pool);
+ jk_b_set_buffer_size(msg, 512);
+
+ rc = ajp13_marshal_shutdown_into_msgb(msg,
+ &pool,
+ NULL);
+ if( secret!=NULL ) {
+ /** will work with old clients, as well as new
+ */
+ rc = jk_b_append_string(msg, secret);
+ }
+ if(rc) {
+ jk_b_end(msg, AJP13_PROTO);
+
+ if(0 > jk_tcp_socket_sendfull(sd,
+ msg->buf,
+ msg->len,
+ NULL)) {
+ rc = JK_FALSE;
+ }
+ }
+ } else {
+ char b[] = {(char)254, (char)15};
+ rc = send(sd, b, 2, 0);
+ if(2 == rc) {
+ rc = JK_TRUE;
+ }
+ }
+ jk_close_socket(sd, NULL);
+ if(JK_TRUE == rc) {
+ if(WAIT_OBJECT_0 == WaitForSingleObject(hTomcat, 30*1000)) {
+ return;
+ }
+ }
+ }
+ }
+
+ TerminateProcess(hTomcat, 0);
+}
+
+static int exec_cmd(const char *name, HANDLE *hTomcat, char *cmdLine)
+{
+ char tag[1024];
+ HKEY hk;
+
+ strcpy(tag, BASE_REGISTRY_LOCATION);
+ strcat(tag, name);
+ strcat(tag, "\\");
+ strcat(tag, PARAMS_LOCATION);
+
+ if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ tag,
+ (DWORD)0,
+ KEY_READ,
+ &hk)) {
+ char prp_file[2048];
+ if(get_registry_config_parameter(hk,
+ PRP_LOCATION,
+ prp_file,
+ sizeof(prp_file))) {
+ jk_map_t *init_map;
+
+ if(jk_map_alloc(&init_map)) {
+ if(jk_map_read_properties(init_map, NULL, prp_file, NULL,
+ JK_MAP_HANDLE_DUPLICATES, NULL)) {
+ jk_tomcat_startup_data_t data;
+ jk_pool_t p;
+ jk_pool_atom_t buf[HUGE_POOL_SIZE];
+ jk_open_pool(&p, buf, sizeof(buf));
+
+ if(read_startup_data(init_map, &data, &p)) {
+ STARTUPINFO startupInfo;
+ PROCESS_INFORMATION processInformation;
+ SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+
+ if(data.extra_path) {
+ jk_append_libpath(&p, data.extra_path);
+ }
+
+ memset(&startupInfo, 0, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+ startupInfo.lpTitle = "Tomcat";
+ startupInfo.dwFlags = STARTF_USESTDHANDLES;
+ startupInfo.hStdInput = NULL;
+ startupInfo.hStdOutput = CreateFile(data.stdout_file,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ &sa,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ SetFilePointer(startupInfo.hStdOutput,
+ 0,
+ NULL,
+ FILE_END);
+ startupInfo.hStdError = CreateFile(data.stderr_file,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ &sa,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ SetFilePointer(startupInfo.hStdError,
+ 0,
+ NULL,
+ FILE_END);
+
+ memset(&processInformation, 0, sizeof(processInformation));
+
+ if( cmdLine==NULL )
+ cmdLine=data.cmd_line;
+
+ printf(cmdLine);
+ if(CreateProcess(data.java_bin,
+ cmdLine,
+ NULL,
+ NULL,
+ TRUE,
+ CREATE_NEW_CONSOLE,
+ NULL,
+ data.tomcat_home,
+ &startupInfo,
+ &processInformation)){
+
+ *hTomcat = processInformation.hProcess;
+ CloseHandle(processInformation.hThread);
+ CloseHandle(startupInfo.hStdOutput);
+ CloseHandle(startupInfo.hStdError);
+
+ shutdown_port = data.shutdown_port;
+ shutdown_secret = data.shutdown_secret;
+ shutdown_protocol = strdup(data.shutdown_protocol);
+ shutdown_cmd = strdup(data.stop_cmd);
+
+ return JK_TRUE;
+ } else {
+ printf("Error: Can not create new process - %s\n",
+ GetLastErrorText(szErr, sizeof(szErr)));
+ }
+
+ }
+ }
+ }
+ jk_map_free(&init_map);
+ }
+ RegCloseKey(hk);
+ }
+
+ return JK_FALSE;
+}
+
+static int start_tomcat(const char *name, HANDLE *hTomcat)
+{
+ return exec_cmd( name, hTomcat, NULL );
+}
+
+static int create_registry_key(const char *tag,
+ HKEY *key)
+{
+ LONG lrc = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+ tag,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ key,
+ NULL);
+ if(ERROR_SUCCESS != lrc) {
+ return JK_FALSE;
+ }
+
+ return JK_TRUE;
+}
+
+static int set_registry_config_parameter(HKEY hkey,
+ const char *tag,
+ char *value)
+{
+ LONG lrc;
+
+ lrc = RegSetValueEx(hkey,
+ tag,
+ 0,
+ REG_SZ,
+ value,
+ strlen(value));
+
+ if(ERROR_SUCCESS != lrc) {
+ return JK_FALSE;
+ }
+
+ return JK_TRUE;
+}
+
+
+
+static int get_registry_config_parameter(HKEY hkey,
+ const char *tag,
+ char *b,
+ DWORD sz)
+{
+ DWORD type = 0;
+ LONG lrc;
+
+ lrc = RegQueryValueEx(hkey,
+ tag,
+ (LPDWORD)0,
+ &type,
+ (LPBYTE)b,
+ &sz);
+ if(ERROR_SUCCESS != lrc) {
+ return JK_FALSE;
+ }
+
+ b[sz] = '\0';
+
+ return JK_TRUE;
+}
+
+static int read_startup_data(jk_map_t *init_map,
+ jk_tomcat_startup_data_t *data,
+ jk_pool_t *p)
+{
+
+ data->classpath = NULL;
+ data->tomcat_home = NULL;
+ data->stdout_file = NULL;
+ data->stderr_file = NULL;
+ data->java_bin = NULL;
+ data->extra_path = NULL;
+ data->tomcat_class = NULL;
+ data->server_file = NULL;
+
+ /* All this is wrong - you just need to configure cmd_line */
+ /* Optional - you may have cmd_line defined */
+ data->server_file = jk_map_get_string(init_map,
+ "wrapper.server_xml",
+ NULL);
+ data->classpath = jk_map_get_string(init_map,
+ "wrapper.class_path",
+ NULL);
+ data->tomcat_home = jk_map_get_string(init_map,
+ "wrapper.tomcat_home",
+ NULL);
+ data->java_bin = jk_map_get_string(init_map,
+ "wrapper.javabin",
+ NULL);
+ data->tomcat_class = jk_map_get_string(init_map,
+ "wrapper.startup_class",
+ "org.apache.tomcat.startup.Tomcat");
+
+ data->cmd_line = jk_map_get_string(init_map,
+ "wrapper.cmd_line",
+ NULL);
+
+ data->stop_cmd = jk_map_get_string(init_map,
+ "wrapper.stop_cmd",
+ NULL);
+
+ if(NULL == data->cmd_line &&
+ ( (NULL == data->tomcat_class) ||
+ (NULL == data->server_file) ||
+ (NULL == data->tomcat_home) ||
+ (NULL == data->java_bin) )) {
+ return JK_FALSE;
+ }
+
+ if(NULL == data->cmd_line) {
+ data->cmd_line = (char *)jk_pool_alloc(p, (20 +
+ strlen(data->java_bin) +
+ strlen(" -classpath ") +
+ strlen(data->classpath) +
+ strlen(data->tomcat_class) +
+ strlen(" -home ") +
+ strlen(data->tomcat_home) +
+ strlen(" -config ") +
+ strlen(data->server_file)
+ ) * sizeof(char));
+ if(NULL == data->cmd_line) {
+ return JK_FALSE;
+ }
+
+ strcpy(data->cmd_line, data->java_bin);
+ strcat(data->cmd_line, " -classpath ");
+ strcat(data->cmd_line, data->classpath);
+ strcat(data->cmd_line, " ");
+ strcat(data->cmd_line, data->tomcat_class);
+ strcat(data->cmd_line, " -home ");
+ strcat(data->cmd_line, data->tomcat_home);
+ strcat(data->cmd_line, " -config ");
+ strcat(data->cmd_line, data->server_file);
+ }
+
+ data->shutdown_port = jk_map_get_int(init_map,
+ "wrapper.shutdown_port",
+ 8007);
+
+ data->shutdown_secret = jk_map_get_string(init_map,
+ "wrapper.shutdown_secret",
+ NULL);
+
+ data->shutdown_protocol = jk_map_get_string(init_map,
+ "wrapper.shutdown_protocol",
+ AJP12_TAG);
+
+ data->extra_path = jk_map_get_string(init_map,
+ "wrapper.ld_path",
+ NULL);
+
+ data->stdout_file = jk_map_get_string(init_map,
+ "wrapper.stdout",
+ NULL);
+
+ if(NULL == data->stdout_file && NULL == data->tomcat_home ) {
+ return JK_FALSE;
+ }
+
+ if(NULL == data->stdout_file) {
+ data->stdout_file = jk_pool_alloc(p, strlen(data->tomcat_home) + 2 + strlen("\\stdout.log"));
+ strcpy(data->stdout_file, data->tomcat_home);
+ strcat(data->stdout_file, "\\stdout.log");
+ }
+
+ data->stderr_file = jk_map_get_string(init_map,
+ "wrapper.stderr",
+ NULL);
+
+ if(NULL == data->stderr_file) {
+ data->stderr_file = jk_pool_alloc(p, strlen(data->tomcat_home) + 2 + strlen("\\stderr.log"));
+ strcpy(data->stderr_file, data->tomcat_home);
+ strcat(data->stderr_file, "\\stderr.log");
+ }
+
+ return JK_TRUE;
+}
+