2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 /***************************************************************************
19 * Description: NT System service for Tomcat *
20 * Author: Gal Shachor <shachor@il.ibm.com> *
21 * Dave Oxley <Dave@JungleMoss.com> *
22 * Version: $Revision: 756058 $ *
23 ***************************************************************************/
25 #include "jk_global.h"
28 #include "jk_connect.h"
34 #define AJP12_TAG ("ajp12")
35 #define AJP13_TAG ("ajp13")
36 #define BASE_REGISTRY_LOCATION ("SYSTEM\\CurrentControlSet\\Services\\")
37 #define IMAGE_NAME ("ImagePath")
38 #define PARAMS_LOCATION ("Parameters")
39 #define PRP_LOCATION ("PropertyFile")
42 static SERVICE_STATUS ssStatus; // current status of the service
43 static SERVICE_STATUS_HANDLE sshStatusHandle;
44 static DWORD dwErr = 0;
45 static char szErr[1024] = "";
46 static HANDLE hServerStopEvent = NULL;
47 static int shutdown_port;
48 static char *shutdown_protocol = AJP12_TAG;
49 static char *shutdown_secret = NULL;
50 static char *shutdown_cmd=NULL;
52 typedef enum ActionEnum
61 struct jk_tomcat_startup_data {
62 char *cmd_line; /* Start command line */
69 char *shutdown_protocol;
72 /* For ajp13/ajp12/catalina */
74 char *shutdown_secret;
76 /* Optional/not needed */
82 typedef struct jk_tomcat_startup_data jk_tomcat_startup_data_t;
84 // internal function prototypes
85 static void WINAPI service_ctrl(DWORD dwCtrlCode);
86 static void WINAPI service_main(DWORD dwArgc,
88 static void install_service(char *name,
95 static void remove_service(char *name);
96 static void start_service(char *name,
98 static void stop_service(char *name,
100 static char *GetLastErrorText(char *lpszBuf, DWORD dwSize);
101 static void AddToMessageLog(char *lpszMsg);
102 static BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
103 DWORD dwWin32ExitCode,
105 static void start_jk_service(char *name);
106 static void stop_jk_service(void);
107 static int set_registry_values(SC_HANDLE schService, char *name,
109 static int create_registry_key(const char *tag,
111 static int set_registry_config_parameter(HKEY hkey,
114 static int get_registry_config_parameter(HKEY hkey,
117 static int start_tomcat(const char *name,
119 static void stop_tomcat(char *name,
121 const char *protocol,
124 static int read_startup_data(jk_map_t *init_map,
125 jk_tomcat_startup_data_t *data,
127 static int exec_cmd(const char *name, HANDLE *hTomcat, char *cmdLine);
129 static void usage_message(const char *name)
131 printf("%s - Usage:\n\n", name);
132 printf("To install the service:\n");
133 printf("%s -i <service name> {optional params} <config properties file>\n", name);
134 printf(" Optional parameters\n");
135 printf(" -u <user name> - In the form DomainName\\UserName (.\\UserName for local)\n");
136 printf(" -n <service display name> - In quotes if contains non-lphanumeric chars\n");
137 printf(" -p <user password>\n");
138 printf(" -a - Set startup type to automatic\n");
139 printf(" -d <service dependency> - Can be entered multiple times\n\n");
140 printf("To remove the service:\n");
141 printf("%s -r <service name>\n\n", name);
142 printf("To start the service:\n");
143 printf("%s -s <service name> {optional params}\n", name);
144 printf(" Optional parameters\n");
145 printf(" -m <machine>\n\n");
146 printf("To stop the service:\n");
147 printf("%s -t <service name> {optional params}\n", name);
148 printf(" Optional parameters\n");
149 printf(" -m <machine>\n");
152 void main(int argc, char **argv)
154 WORD wVersionRequested;
159 int iAction = acNoAction;
160 char *pServiceDisplayName = NULL;
161 char *pServiceName = NULL;
162 char *pUserName = NULL;
163 char *pPassword = NULL;
164 char *pMachine = NULL;
165 BOOL bAutomatic = FALSE;
166 char strDependancy[256] = "";
168 memset(strDependancy, 0, 255);
170 wVersionRequested = MAKEWORD(1, 1);
171 err = WSAStartup(wVersionRequested, &wsaData);
173 fprintf(stderr, "Error connecting to winsock");
177 if(LOBYTE( wsaData.wVersion ) != 1 ||
178 HIBYTE( wsaData.wVersion ) != 1) {
180 "Error winsock version is %d %d \n",
181 LOBYTE( wsaData.wVersion ),HIBYTE( wsaData.wVersion ));
186 fprintf(stderr, "Asked (and given) winsock %d.%d \n",
187 LOBYTE(wsaData.wVersion),
188 HIBYTE(wsaData.wVersion));
193 for (i=1;i<argc;i++) {
194 if ((*argv[i] == '-') || (*argv[i] == '/')) {
197 if(0 == stricmp("i", cmd)) {
199 pServiceName = argv[i+1];
200 } else if(0 == stricmp("r", cmd)) {
202 pServiceName = argv[i+1];
203 } else if(0 == stricmp("s", cmd)) {
205 pServiceName = argv[i+1];
206 } else if(0 == stricmp("t", cmd)) {
208 pServiceName = argv[i+1];
209 } else if(0 == stricmp("u", cmd)) {
210 pUserName = argv[i+1];
211 } else if(0 == stricmp("p", cmd)) {
212 pPassword = argv[i+1];
213 } else if(0 == stricmp("m", cmd)) {
214 pMachine = argv[i+1];
215 } else if(0 == stricmp("a", cmd)) {
217 } else if(0 == stricmp("n", cmd)) {
218 pServiceDisplayName = argv[i+1];
219 } else if(0 == stricmp("d", cmd)) {
220 memcpy(strDependancy+count, argv[i+1], strlen(argv[i+1]));
221 count+= strlen(argv[i+1])+1;
227 if (pServiceDisplayName == NULL) {
228 pServiceDisplayName = pServiceName;
230 install_service(pServiceName, pServiceDisplayName, pUserName,
231 pPassword, strDependancy, bAutomatic, argv[i-1]);
234 remove_service(pServiceName);
237 start_service(pServiceName, pMachine);
240 stop_service(pServiceName, pMachine);
243 } else if(2 == argc) {
245 SERVICE_TABLE_ENTRY dispatchTable[] =
247 { argv[1], (LPSERVICE_MAIN_FUNCTION)service_main },
251 if(!StartServiceCtrlDispatcher(dispatchTable)) {
252 AddToMessageLog("StartServiceCtrlDispatcher failed.");
257 usage_message(argv[0]);
264 void WINAPI service_main(DWORD dwArgc, char **lpszArgv)
266 // register our service control handler:
269 sshStatusHandle = RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
271 if(sshStatusHandle) {
273 ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
274 ssStatus.dwServiceSpecificExitCode = 0;
276 // report the status to the service control manager.
278 if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
279 NO_ERROR, // exit code
280 3000)) { // wait hint
281 start_jk_service(lpszArgv[0]);
285 // try to report the stopped status to the service control manager.
287 if(sshStatusHandle) {
288 ReportStatusToSCMgr(SERVICE_STOPPED,
295 void WINAPI service_ctrl(DWORD dwCtrlCode)
298 * Handle the requested control code.
305 case SERVICE_CONTROL_SHUTDOWN:
306 case SERVICE_CONTROL_STOP:
307 ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
312 * Update the service status.
314 case SERVICE_CONTROL_INTERROGATE:
318 * Invalid control code, nothing to do.
325 ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
329 BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
330 DWORD dwWin32ExitCode,
333 static DWORD dwCheckPoint = 1;
336 if(dwCurrentState == SERVICE_START_PENDING) {
337 ssStatus.dwControlsAccepted = 0;
339 ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
342 ssStatus.dwCurrentState = dwCurrentState;
343 ssStatus.dwWin32ExitCode = dwWin32ExitCode;
344 ssStatus.dwWaitHint = dwWaitHint;
346 if((dwCurrentState == SERVICE_RUNNING) ||
347 (dwCurrentState == SERVICE_STOPPED)) {
348 ssStatus.dwCheckPoint = 0;
350 ssStatus.dwCheckPoint = dwCheckPoint++;
353 if(!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) {
354 AddToMessageLog(TEXT("SetServiceStatus"));
360 typedef WINADVAPI BOOL (WINAPI * pfnChangeServiceConfig2_t)
361 (SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo);
364 void install_service(char *name,
372 SC_HANDLE schService;
373 SC_HANDLE schSCManager;
374 char szExecPath[2048];
375 char szPropPath[2048];
376 char szTrueName[256];
381 for (src = name; *src; ++src) {
382 if (dst >= szTrueName + sizeof(szTrueName) - 1) {
385 if (!isspace((int)(*src)) && *src != '/' && *src != '\\') {
391 if (0 == stricmp("", deps))
394 /* XXX strcat( deps, "Tcpip\0Afd\0" ); */
396 if(!GetFullPathName(rel_prp_file, sizeof(szPropPath) - 1, szPropPath, &dummy)) {
397 printf("Unable to install %s - %s\n",
399 GetLastErrorText(szErr, sizeof(szErr)));
403 if(!jk_file_exists(szPropPath)) {
404 printf("Unable to install %s - File [%s] does not exists\n",
410 szExecPath[0] = '\"';
411 if(GetModuleFileName( NULL, szExecPath + 1, sizeof(szExecPath) - 2) == 0) {
412 /* Was: if(GetModuleFileName( NULL, szExecPath, sizeof(szExecPath) - 1) == 0) { */
413 printf("Unable to install %s - %s\n",
415 GetLastErrorText(szErr, sizeof(szErr)));
418 strcat(szExecPath, "\" ");
419 strcat(szExecPath, szTrueName);
422 schSCManager = OpenSCManager(NULL, // machine (NULL == local)
423 NULL, // database (NULL == default)
424 SC_MANAGER_ALL_ACCESS); // access required
427 schService = CreateService(schSCManager, // SCManager database
428 szTrueName, // name of service
429 dname, // name to display
430 SERVICE_ALL_ACCESS, // desired access
431 SERVICE_WIN32_OWN_PROCESS, // service type
432 bAutomatic ? SERVICE_AUTO_START : SERVICE_DEMAND_START, // start type
433 SERVICE_ERROR_NORMAL, // error control type
434 szExecPath, // service's binary
435 NULL, // no load ordering group
436 NULL, // no tag identifier
437 deps, // dependencies
439 password); // password
443 printf("The service named %s was created. Now adding registry entries\n", name);
445 if(set_registry_values(schService, szTrueName, szPropPath)) {
446 CloseServiceHandle(schService);
448 printf("CreateService failed setting the private registry - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
449 DeleteService(schService);
450 CloseServiceHandle(schService);
453 printf("CreateService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
456 CloseServiceHandle(schSCManager);
458 printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
462 void remove_service(char *name)
464 SC_HANDLE schService;
465 SC_HANDLE schSCManager;
466 char szNameBuff[256];
467 DWORD lenNameBuff = 256;
468 char *szTrueName = name;
470 schSCManager = OpenSCManager(NULL, // machine (NULL == local)
471 NULL, // database (NULL == default)
472 SC_MANAGER_ALL_ACCESS ); // access required
475 if (GetServiceKeyName(schSCManager, name, szNameBuff, &lenNameBuff)) {
476 szTrueName = szNameBuff;
478 schService = OpenService(schSCManager, szTrueName, SERVICE_ALL_ACCESS);
481 // try to stop the service
482 if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
483 printf("Stopping %s.", name);
486 while(QueryServiceStatus(schService, &ssStatus )) {
487 if(ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
495 if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
496 printf("\n%s stopped.\n", name);
498 printf("\n%s failed to stop.\n", name);
502 // now remove the service
503 if(DeleteService(schService)) {
504 printf("%s removed.\n", name);
506 printf("DeleteService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
509 CloseServiceHandle(schService);
511 printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
514 CloseServiceHandle(schSCManager);
516 printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
520 void start_service(char *name, char *machine)
522 SC_HANDLE schService;
523 SC_HANDLE schSCManager;
525 schSCManager = OpenSCManager(machine, // machine (NULL == local)
526 NULL, // database (NULL == default)
527 SC_MANAGER_ALL_ACCESS); // access required
530 schService = OpenService(schSCManager, name, SERVICE_ALL_ACCESS);
533 // try to start the service
534 if(StartService(schService, 0, NULL)) {
535 printf("Starting %s.", name);
538 while(QueryServiceStatus(schService, &ssStatus )) {
539 if(ssStatus.dwCurrentState == SERVICE_START_PENDING) {
547 if(ssStatus.dwCurrentState == SERVICE_RUNNING) {
548 printf("\n%s started.\n", name);
550 printf("\n%s failed to start.\n", name);
554 printf("StartService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
556 CloseServiceHandle(schService);
558 printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
561 CloseServiceHandle(schSCManager);
563 printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
567 void stop_service(char *name, char *machine)
569 SC_HANDLE schService;
570 SC_HANDLE schSCManager;
572 schSCManager = OpenSCManager(machine, // machine (NULL == local)
573 NULL, // database (NULL == default)
574 SC_MANAGER_ALL_ACCESS); // access required
577 schService = OpenService(schSCManager, name, SERVICE_ALL_ACCESS);
580 // try to stop the service
581 if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
582 printf("Stopping %s.", name);
585 while(QueryServiceStatus(schService, &ssStatus )) {
586 if(ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
594 if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
595 printf("\n%s stopped.\n", name);
597 printf("\n%s failed to stop.\n", name);
601 printf("StopService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
603 CloseServiceHandle(schService);
605 printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
608 CloseServiceHandle(schSCManager);
610 printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
614 static int set_registry_values(SC_HANDLE schService, char *name,
622 char *szDescription = "Tomcat Server";
623 pfnChangeServiceConfig2_t pfnChangeServiceConfig2;
625 if((hAdvApi32 = GetModuleHandle("advapi32.dll"))
626 && ((pfnChangeServiceConfig2 = (pfnChangeServiceConfig2_t)
627 GetProcAddress(hAdvApi32, "ChangeServiceConfig2A")))) {
628 (void) pfnChangeServiceConfig2(schService, // Service Handle
629 1, // SERVICE_CONFIG_DESCRIPTION
636 strcpy(tag, BASE_REGISTRY_LOCATION);
639 if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
642 KEY_WRITE | KEY_READ,
644 rc = get_registry_config_parameter(hk,
651 rc = set_registry_config_parameter(hk,
655 printf("Registry values were added\n");
656 printf("If you have already updated wrapper.properties you may start the %s"
657 "service by executing \"jk_nt_service -s %s\" from the command prompt\n",
665 printf("Error: Failed to update the service command line - %s\n",
666 GetLastErrorText(szErr, sizeof(szErr)));
670 strcpy(tag, BASE_REGISTRY_LOCATION);
673 strcat(tag, PARAMS_LOCATION);
675 rc = create_registry_key(tag, &hk);
678 rc = set_registry_config_parameter(hk, PRP_LOCATION, prp_file);
680 printf("Error: Can not create value [%s] - %s\n",
682 GetLastErrorText(szErr, sizeof(szErr)));
686 printf("Error: Can not create key [%s] - %s\n",
688 GetLastErrorText(szErr, sizeof(szErr)));
693 static void start_jk_service(char *name)
696 * report the status to the service control manager.
698 if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
699 NO_ERROR, // exit code
700 3000)) { // wait hint
703 * create the event object. The control handler function signals
704 * this event when it receives the "stop" control code.
706 hServerStopEvent = CreateEvent(NULL, // no security attributes
707 TRUE, // manual reset event
708 FALSE, // not-signalled
711 if(hServerStopEvent) {
712 if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
713 NO_ERROR, // exit code
714 20000)) { // wait hint
715 HANDLE hTomcat = NULL;
716 char szNameBuff[256];
717 DWORD lenNameBuff = 256;
718 char *szTrueName = name;
719 SC_HANDLE schSCManager;
722 schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS );
724 if (GetServiceKeyName(schSCManager, name, szNameBuff, &lenNameBuff)) {
725 szTrueName = szNameBuff;
727 CloseServiceHandle(schSCManager);
730 rc = start_tomcat(szTrueName, &hTomcat);
732 if(rc && ReportStatusToSCMgr(SERVICE_RUNNING, // service state
733 NO_ERROR, // exit code
735 HANDLE waitfor[] = { hServerStopEvent, hTomcat};
736 DWORD dwIndex = WaitForMultipleObjects(2, waitfor, FALSE, INFINITE);
743 ResetEvent(hServerStopEvent);
744 stop_tomcat(name, shutdown_port, shutdown_protocol,
745 shutdown_secret, hTomcat);
747 case (WAIT_OBJECT_0 + 1):
751 CloseHandle(hServerStopEvent);
752 CloseHandle(hTomcat);
753 exit(0); // exit ungracefully so
754 // Service Control Manager
755 // will attempt a restart.
760 * close the servlet container and exit
762 stop_tomcat(name, shutdown_port, shutdown_protocol,
763 shutdown_secret, hTomcat);
765 CloseHandle(hServerStopEvent);
766 CloseHandle(hTomcat);
772 if(hServerStopEvent) {
773 CloseHandle(hServerStopEvent);
778 static void stop_jk_service(void)
780 if(hServerStopEvent) {
781 SetEvent(hServerStopEvent);
785 static void AddToMessageLog(char *lpszMsg)
789 char * lpszStrings[2];
791 printf("Error: %s\n", lpszMsg);
793 dwErr = GetLastError();
795 hEventSource = RegisterEventSource(NULL, "Tomcat");
797 sprintf(szMsg, "%s error: %d", "Tomcat", dwErr);
798 lpszStrings[0] = szMsg;
799 lpszStrings[1] = lpszMsg;
801 if(hEventSource != NULL) {
802 ReportEvent(hEventSource, // handle of event source
803 EVENTLOG_ERROR_TYPE, // event type
806 NULL, // current user's SID
807 2, // strings in lpszStrings
808 0, // no bytes of raw data
809 lpszStrings, // array of error strings
810 NULL); // no raw data
812 DeregisterEventSource(hEventSource);
818 // FUNCTION: GetLastErrorText
820 // PURPOSE: copies error message text to string
823 // lpszBuf - destination buffer
824 // dwSize - size of buffer
827 // destination buffer
831 char *GetLastErrorText( char *lpszBuf, DWORD dwSize )
834 char *lpszTemp = NULL;
836 dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
844 // supplied buffer is not long enough
845 if(!dwRet || ((long)dwSize < (long)dwRet+14)) {
848 lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character
849 sprintf(lpszBuf, "%s (0x%x)", lpszTemp, GetLastError());
853 LocalFree((HLOCAL) lpszTemp );
859 static void stop_tomcat(char *name,
861 const char *protocol,
865 struct sockaddr_in in;
867 if(strcasecmp(protocol, "cmd") == 0 ) {
868 exec_cmd( name, hTomcat, shutdown_cmd);
870 TerminateProcess(hTomcat, 0);
874 if(jk_resolve("localhost", port, &in, NULL)) {
875 int sd = jk_open_socket(&in, JK_TRUE, 0, 0, NULL);
879 if(strcasecmp(protocol, "catalina") == 0 ) {
884 len=strlen( secret );
886 rc = send(sd, secret, len , 0);
890 } else if(!strcasecmp(protocol, "ajp13")) {
892 jk_msg_buf_t *msg = NULL;
893 jk_pool_atom_t buf[TINY_POOL_SIZE];
895 jk_open_pool(&pool, buf, sizeof(buf));
897 msg = jk_b_new(&pool);
898 jk_b_set_buffer_size(msg, 512);
900 rc = ajp13_marshal_shutdown_into_msgb(msg,
904 /** will work with old clients, as well as new
906 rc = jk_b_append_string(msg, secret);
909 jk_b_end(msg, AJP13_PROTO);
911 if(0 > jk_tcp_socket_sendfull(sd,
919 char b[] = {(char)254, (char)15};
920 rc = send(sd, b, 2, 0);
925 jk_close_socket(sd, NULL);
927 if(WAIT_OBJECT_0 == WaitForSingleObject(hTomcat, 30*1000)) {
934 TerminateProcess(hTomcat, 0);
937 static int exec_cmd(const char *name, HANDLE *hTomcat, char *cmdLine)
942 strcpy(tag, BASE_REGISTRY_LOCATION);
945 strcat(tag, PARAMS_LOCATION);
947 if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
953 if(get_registry_config_parameter(hk,
959 if(jk_map_alloc(&init_map)) {
960 if(jk_map_read_properties(init_map, NULL, prp_file, NULL,
961 JK_MAP_HANDLE_DUPLICATES, NULL)) {
962 jk_tomcat_startup_data_t data;
964 jk_pool_atom_t buf[HUGE_POOL_SIZE];
965 jk_open_pool(&p, buf, sizeof(buf));
967 if(read_startup_data(init_map, &data, &p)) {
968 STARTUPINFO startupInfo;
969 PROCESS_INFORMATION processInformation;
970 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
972 if(data.extra_path) {
973 jk_append_libpath(&p, data.extra_path);
976 memset(&startupInfo, 0, sizeof(startupInfo));
977 startupInfo.cb = sizeof(startupInfo);
978 startupInfo.lpTitle = "Tomcat";
979 startupInfo.dwFlags = STARTF_USESTDHANDLES;
980 startupInfo.hStdInput = NULL;
981 startupInfo.hStdOutput = CreateFile(data.stdout_file,
986 FILE_ATTRIBUTE_NORMAL,
988 SetFilePointer(startupInfo.hStdOutput,
992 startupInfo.hStdError = CreateFile(data.stderr_file,
997 FILE_ATTRIBUTE_NORMAL,
999 SetFilePointer(startupInfo.hStdError,
1004 memset(&processInformation, 0, sizeof(processInformation));
1007 cmdLine=data.cmd_line;
1010 if(CreateProcess(data.java_bin,
1019 &processInformation)){
1021 *hTomcat = processInformation.hProcess;
1022 CloseHandle(processInformation.hThread);
1023 CloseHandle(startupInfo.hStdOutput);
1024 CloseHandle(startupInfo.hStdError);
1026 shutdown_port = data.shutdown_port;
1027 shutdown_secret = data.shutdown_secret;
1028 shutdown_protocol = strdup(data.shutdown_protocol);
1029 shutdown_cmd = strdup(data.stop_cmd);
1033 printf("Error: Can not create new process - %s\n",
1034 GetLastErrorText(szErr, sizeof(szErr)));
1040 jk_map_free(&init_map);
1048 static int start_tomcat(const char *name, HANDLE *hTomcat)
1050 return exec_cmd( name, hTomcat, NULL );
1053 static int create_registry_key(const char *tag,
1056 LONG lrc = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
1060 REG_OPTION_NON_VOLATILE,
1065 if(ERROR_SUCCESS != lrc) {
1072 static int set_registry_config_parameter(HKEY hkey,
1078 lrc = RegSetValueEx(hkey,
1085 if(ERROR_SUCCESS != lrc) {
1094 static int get_registry_config_parameter(HKEY hkey,
1102 lrc = RegQueryValueEx(hkey,
1108 if(ERROR_SUCCESS != lrc) {
1117 static int read_startup_data(jk_map_t *init_map,
1118 jk_tomcat_startup_data_t *data,
1122 data->classpath = NULL;
1123 data->tomcat_home = NULL;
1124 data->stdout_file = NULL;
1125 data->stderr_file = NULL;
1126 data->java_bin = NULL;
1127 data->extra_path = NULL;
1128 data->tomcat_class = NULL;
1129 data->server_file = NULL;
1131 /* All this is wrong - you just need to configure cmd_line */
1132 /* Optional - you may have cmd_line defined */
1133 data->server_file = jk_map_get_string(init_map,
1134 "wrapper.server_xml",
1136 data->classpath = jk_map_get_string(init_map,
1137 "wrapper.class_path",
1139 data->tomcat_home = jk_map_get_string(init_map,
1140 "wrapper.tomcat_home",
1142 data->java_bin = jk_map_get_string(init_map,
1145 data->tomcat_class = jk_map_get_string(init_map,
1146 "wrapper.startup_class",
1147 "org.apache.tomcat.startup.Tomcat");
1149 data->cmd_line = jk_map_get_string(init_map,
1153 data->stop_cmd = jk_map_get_string(init_map,
1157 if(NULL == data->cmd_line &&
1158 ( (NULL == data->tomcat_class) ||
1159 (NULL == data->server_file) ||
1160 (NULL == data->tomcat_home) ||
1161 (NULL == data->java_bin) )) {
1165 if(NULL == data->cmd_line) {
1166 data->cmd_line = (char *)jk_pool_alloc(p, (20 +
1167 strlen(data->java_bin) +
1168 strlen(" -classpath ") +
1169 strlen(data->classpath) +
1170 strlen(data->tomcat_class) +
1172 strlen(data->tomcat_home) +
1173 strlen(" -config ") +
1174 strlen(data->server_file)
1176 if(NULL == data->cmd_line) {
1180 strcpy(data->cmd_line, data->java_bin);
1181 strcat(data->cmd_line, " -classpath ");
1182 strcat(data->cmd_line, data->classpath);
1183 strcat(data->cmd_line, " ");
1184 strcat(data->cmd_line, data->tomcat_class);
1185 strcat(data->cmd_line, " -home ");
1186 strcat(data->cmd_line, data->tomcat_home);
1187 strcat(data->cmd_line, " -config ");
1188 strcat(data->cmd_line, data->server_file);
1191 data->shutdown_port = jk_map_get_int(init_map,
1192 "wrapper.shutdown_port",
1195 data->shutdown_secret = jk_map_get_string(init_map,
1196 "wrapper.shutdown_secret",
1199 data->shutdown_protocol = jk_map_get_string(init_map,
1200 "wrapper.shutdown_protocol",
1203 data->extra_path = jk_map_get_string(init_map,
1207 data->stdout_file = jk_map_get_string(init_map,
1211 if(NULL == data->stdout_file && NULL == data->tomcat_home ) {
1215 if(NULL == data->stdout_file) {
1216 data->stdout_file = jk_pool_alloc(p, strlen(data->tomcat_home) + 2 + strlen("\\stdout.log"));
1217 strcpy(data->stdout_file, data->tomcat_home);
1218 strcat(data->stdout_file, "\\stdout.log");
1221 data->stderr_file = jk_map_get_string(init_map,
1225 if(NULL == data->stderr_file) {
1226 data->stderr_file = jk_pool_alloc(p, strlen(data->tomcat_home) + 2 + strlen("\\stderr.log"));
1227 strcpy(data->stderr_file, data->tomcat_home);
1228 strcat(data->stderr_file, "\\stderr.log");