00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define CORE_PRIVATE
00023 #define _WINUSER_
00024
00025 #include "httpd.h"
00026 #include "http_log.h"
00027 #include "mpm_winnt.h"
00028 #include "apr_strings.h"
00029 #include "apr_lib.h"
00030 #include "ap_regkey.h"
00031
00032 #ifdef NOUSER
00033 #undef NOUSER
00034 #endif
00035 #undef _WINUSER_
00036 #include <winuser.h>
00037
00038 static char *mpm_service_name = NULL;
00039 static char *mpm_display_name = NULL;
00040
00041 static struct
00042 {
00043 HANDLE mpm_thread;
00044 HANDLE service_thread;
00045 DWORD service_thread_id;
00046 HANDLE service_init;
00047 HANDLE service_term;
00048 SERVICE_STATUS ssStatus;
00049 SERVICE_STATUS_HANDLE hServiceStatus;
00050 } globdat;
00051
00052 static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint);
00053
00054
00055 #define PRODREGKEY "SOFTWARE\\" AP_SERVER_BASEVENDOR "\\" \
00056 AP_SERVER_BASEPRODUCT "\\" AP_SERVER_BASEREVISION
00057
00058
00059
00060
00061
00062
00063
00064
00065 apr_status_t ap_registry_get_server_root(apr_pool_t *p, char **buf)
00066 {
00067 apr_status_t rv;
00068 ap_regkey_t *key;
00069
00070 if ((rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, PRODREGKEY,
00071 APR_READ, p)) == APR_SUCCESS) {
00072 rv = ap_regkey_value_get(buf, key, "ServerRoot", p);
00073 ap_regkey_close(key);
00074 if (rv == APR_SUCCESS)
00075 return rv;
00076 }
00077
00078 if ((rv = ap_regkey_open(&key, AP_REGKEY_CURRENT_USER, PRODREGKEY,
00079 APR_READ, p)) == APR_SUCCESS) {
00080 rv = ap_regkey_value_get(buf, key, "ServerRoot", p);
00081 ap_regkey_close(key);
00082 if (rv == APR_SUCCESS)
00083 return rv;
00084 }
00085
00086 *buf = NULL;
00087 return rv;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 AP_DECLARE_DATA int real_exit_code = 1;
00118
00119 void hold_console_open_on_error(void)
00120 {
00121 HANDLE hConIn;
00122 HANDLE hConErr;
00123 DWORD result;
00124 time_t start;
00125 time_t remains;
00126 char *msg = "Note the errors or messages above, "
00127 "and press the <ESC> key to exit. ";
00128 CONSOLE_SCREEN_BUFFER_INFO coninfo;
00129 INPUT_RECORD in;
00130 char count[16];
00131
00132 if (!real_exit_code)
00133 return;
00134 hConIn = GetStdHandle(STD_INPUT_HANDLE);
00135 hConErr = GetStdHandle(STD_ERROR_HANDLE);
00136 if ((hConIn == INVALID_HANDLE_VALUE) || (hConErr == INVALID_HANDLE_VALUE))
00137 return;
00138 if (!WriteConsole(hConErr, msg, strlen(msg), &result, NULL) || !result)
00139 return;
00140 if (!GetConsoleScreenBufferInfo(hConErr, &coninfo))
00141 return;
00142 if (!SetConsoleMode(hConIn, ENABLE_MOUSE_INPUT | 0x80))
00143 return;
00144
00145 start = time(NULL);
00146 do
00147 {
00148 while (PeekConsoleInput(hConIn, &in, 1, &result) && result)
00149 {
00150 if (!ReadConsoleInput(hConIn, &in, 1, &result) || !result)
00151 return;
00152 if ((in.EventType == KEY_EVENT) && in.Event.KeyEvent.bKeyDown
00153 && (in.Event.KeyEvent.uChar.AsciiChar == 27))
00154 return;
00155 if (in.EventType == MOUSE_EVENT
00156 && (in.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
00157 return;
00158 }
00159 remains = ((start + 30) - time(NULL));
00160 sprintf (count, "%d...", remains);
00161 if (!SetConsoleCursorPosition(hConErr, coninfo.dwCursorPosition))
00162 return;
00163 if (!WriteConsole(hConErr, count, strlen(count), &result, NULL)
00164 || !result)
00165 return;
00166 }
00167 while ((remains > 0) && WaitForSingleObject(hConIn, 1000) != WAIT_FAILED);
00168 }
00169
00170 static BOOL die_on_logoff = FALSE;
00171
00172 static LRESULT CALLBACK monitor_service_9x_proc(HWND hWnd, UINT msg,
00173 WPARAM wParam, LPARAM lParam)
00174 {
00175
00176
00177
00178
00179
00180 if ((msg == WM_ENDSESSION)
00181 && (die_on_logoff || (lParam != ENDSESSION_LOGOFF)))
00182 {
00183 ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
00184 if (wParam)
00185
00186 WaitForSingleObject(globdat.mpm_thread, 30000);
00187 return 0;
00188 }
00189 return (DefWindowProc(hWnd, msg, wParam, lParam));
00190 }
00191
00192 static DWORD WINAPI monitor_service_9x_thread(void *service_name)
00193 {
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 WNDCLASS wc;
00204 HWND hwndMain;
00205 MSG msg;
00206
00207 wc.style = CS_GLOBALCLASS;
00208 wc.lpfnWndProc = monitor_service_9x_proc;
00209 wc.cbClsExtra = 0;
00210 wc.cbWndExtra = 0;
00211 wc.hInstance = NULL;
00212 wc.hIcon = NULL;
00213 wc.hCursor = NULL;
00214 wc.hbrBackground = NULL;
00215 wc.lpszMenuName = NULL;
00216 if (service_name)
00217 wc.lpszClassName = "ApacheWin95ServiceMonitor";
00218 else
00219 wc.lpszClassName = "ApacheWin95SystemMonitor";
00220
00221 die_on_logoff = service_name ? FALSE : TRUE;
00222
00223 if (!RegisterClass(&wc))
00224 {
00225 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
00226 NULL, "Could not register window class for WatchWindow");
00227 globdat.service_thread_id = 0;
00228 return 0;
00229 }
00230
00231
00232 hwndMain = CreateWindow(wc.lpszClassName,
00233 service_name ? (char *) service_name : "Apache",
00234 WS_OVERLAPPEDWINDOW & ~WS_VISIBLE,
00235 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
00236 CW_USEDEFAULT, NULL, NULL, NULL, NULL);
00237
00238 if (!hwndMain)
00239 {
00240 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
00241 NULL, "Could not create WatchWindow");
00242 globdat.service_thread_id = 0;
00243 return 0;
00244 }
00245
00246
00247
00248
00249
00250 FreeConsole();
00251 SetEvent(globdat.service_init);
00252
00253 while (GetMessage(&msg, NULL, 0, 0))
00254 {
00255 if (msg.message == WM_CLOSE)
00256 DestroyWindow(hwndMain);
00257 else {
00258 TranslateMessage(&msg);
00259 DispatchMessage(&msg);
00260 }
00261 }
00262 globdat.service_thread_id = 0;
00263 return 0;
00264 }
00265
00266
00267 static BOOL CALLBACK console_control_handler(DWORD ctrl_type)
00268 {
00269 switch (ctrl_type)
00270 {
00271 case CTRL_BREAK_EVENT:
00272 fprintf(stderr, "Apache server restarting...\n");
00273 ap_signal_parent(SIGNAL_PARENT_RESTART);
00274 return TRUE;
00275 case CTRL_C_EVENT:
00276 fprintf(stderr, "Apache server interrupted...\n");
00277
00278
00279
00280
00281 ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
00282 return TRUE;
00283
00284 case CTRL_CLOSE_EVENT:
00285 case CTRL_LOGOFF_EVENT:
00286 case CTRL_SHUTDOWN_EVENT:
00287
00288
00289
00290
00291
00292
00293 fprintf(stderr, "Apache server shutdown initiated...\n");
00294 ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
00295 Sleep(30000);
00296 return TRUE;
00297 }
00298
00299
00300 return FALSE;
00301 }
00302
00303
00304 static void stop_console_handler(void)
00305 {
00306 SetConsoleCtrlHandler(console_control_handler, FALSE);
00307 }
00308
00309
00310 void mpm_start_console_handler(void)
00311 {
00312 SetConsoleCtrlHandler(console_control_handler, TRUE);
00313 atexit(stop_console_handler);
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 static BOOL CALLBACK child_control_handler(DWORD ctrl_type)
00323 {
00324 switch (ctrl_type)
00325 {
00326 case CTRL_C_EVENT:
00327 case CTRL_BREAK_EVENT:
00328
00329
00330
00331
00332 return TRUE;
00333
00334 case CTRL_CLOSE_EVENT:
00335 case CTRL_LOGOFF_EVENT:
00336 case CTRL_SHUTDOWN_EVENT:
00337
00338
00339
00340
00341 Sleep(30000);
00342 return TRUE;
00343 }
00344
00345
00346 return FALSE;
00347 }
00348
00349
00350 static void stop_child_console_handler(void)
00351 {
00352 SetConsoleCtrlHandler(child_control_handler, FALSE);
00353 }
00354
00355
00356 void mpm_start_child_console_handler(void)
00357 {
00358 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
00359 FreeConsole();
00360 }
00361 else
00362 {
00363 SetConsoleCtrlHandler(child_control_handler, TRUE);
00364 atexit(stop_child_console_handler);
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373 static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint)
00374 {
00375 static int checkPoint = 1;
00376 int rv = APR_SUCCESS;
00377
00378 if (globdat.hServiceStatus)
00379 {
00380 if (currentState == SERVICE_RUNNING) {
00381 globdat.ssStatus.dwWaitHint = 0;
00382 globdat.ssStatus.dwCheckPoint = 0;
00383 globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
00384 }
00385 else if (currentState == SERVICE_STOPPED) {
00386 globdat.ssStatus.dwWaitHint = 0;
00387 globdat.ssStatus.dwCheckPoint = 0;
00388 if (!exitCode && globdat.ssStatus.dwCurrentState
00389 != SERVICE_STOP_PENDING) {
00390
00391 exitCode = 1;
00392 }
00393 if (exitCode) {
00394 globdat.ssStatus.dwWin32ExitCode =ERROR_SERVICE_SPECIFIC_ERROR;
00395 globdat.ssStatus.dwServiceSpecificExitCode = exitCode;
00396 }
00397 }
00398 else {
00399 globdat.ssStatus.dwCheckPoint = ++checkPoint;
00400 globdat.ssStatus.dwControlsAccepted = 0;
00401 if(waitHint)
00402 globdat.ssStatus.dwWaitHint = waitHint;
00403 }
00404
00405 globdat.ssStatus.dwCurrentState = currentState;
00406
00407 rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus);
00408 }
00409 return(rv);
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 extern apr_pool_t *pconf;
00421
00422
00423
00424
00425
00426 static void set_service_description(void)
00427 {
00428 const char *full_description;
00429 SC_HANDLE schSCManager;
00430 BOOL ret = 0;
00431
00432
00433
00434 if (!mpm_service_name)
00435 return;
00436
00437
00438
00439 full_description = ap_get_server_version();
00440
00441 if ((osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00442 && (osver.dwMajorVersion > 4)
00443 && (ChangeServiceConfig2)
00444 && (schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)))
00445 {
00446 SC_HANDLE schService = OpenService(schSCManager, mpm_service_name,
00447 SERVICE_CHANGE_CONFIG);
00448 if (schService) {
00449
00450
00451
00452
00453 if (ChangeServiceConfig2(schService,
00454 1 ,
00455 (LPVOID) &full_description)) {
00456 full_description = NULL;
00457 }
00458 CloseServiceHandle(schService);
00459 }
00460 CloseServiceHandle(schSCManager);
00461 }
00462
00463 if (full_description)
00464 {
00465 char szPath[MAX_PATH];
00466 ap_regkey_t *svckey;
00467 apr_status_t rv;
00468
00469
00470 apr_snprintf(szPath, sizeof(szPath),
00471 "SYSTEM\\CurrentControlSet\\Services\\%s",
00472 mpm_service_name);
00473 rv = ap_regkey_open(&svckey, AP_REGKEY_LOCAL_MACHINE, szPath,
00474 APR_READ | APR_WRITE, pconf);
00475 if (rv != APR_SUCCESS) {
00476 return;
00477 }
00478
00479 ap_regkey_value_set(svckey, "Description", full_description, 0, pconf);
00480 ap_regkey_close(svckey);
00481 }
00482 }
00483
00484
00485
00486 static VOID WINAPI service_nt_ctrl(DWORD dwCtrlCode)
00487 {
00488 if (dwCtrlCode == SERVICE_CONTROL_STOP)
00489 {
00490 ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
00491 ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 30000);
00492 return;
00493 }
00494 if (dwCtrlCode == SERVICE_APACHE_RESTART)
00495 {
00496 ap_signal_parent(SIGNAL_PARENT_RESTART);
00497 ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000);
00498 return;
00499 }
00500
00501 ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 0);
00502 }
00503
00504
00505
00506
00507
00508
00509 extern apr_array_header_t *mpm_new_argv;
00510
00511
00512 static void __stdcall service_nt_main_fn(DWORD argc, LPTSTR *argv)
00513 {
00514 const char *ignored;
00515
00516
00517 mpm_service_set_name(mpm_new_argv->pool, &ignored, argv[0]);
00518
00519 memset(&globdat.ssStatus, 0, sizeof(globdat.ssStatus));
00520 globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
00521 globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
00522 globdat.ssStatus.dwCheckPoint = 1;
00523
00524
00525 if (!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0], service_nt_ctrl)))
00526 {
00527 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
00528 NULL, "Failure registering service handler");
00529 return;
00530 }
00531
00532
00533 ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000);
00534
00535
00536
00537
00538
00539 if (argc > 1)
00540 {
00541 char **cmb_data;
00542
00543 mpm_new_argv->nalloc = mpm_new_argv->nelts + argc - 1;
00544 cmb_data = malloc(mpm_new_argv->nalloc * sizeof(const char *));
00545
00546
00547 memcpy (cmb_data, mpm_new_argv->elts,
00548 mpm_new_argv->elt_size * mpm_new_argv->nelts);
00549
00550
00551 memcpy (cmb_data + mpm_new_argv->nelts, argv + 1,
00552 mpm_new_argv->elt_size * (argc - 1));
00553
00554
00555 mpm_new_argv->elts = (char *)cmb_data;
00556 mpm_new_argv->nelts = mpm_new_argv->nalloc;
00557 }
00558
00559
00560
00561
00562 SetEvent(globdat.service_init);
00563
00564 WaitForSingleObject(globdat.service_term, INFINITE);
00565 }
00566
00567
00568 DWORD WINAPI service_nt_dispatch_thread(LPVOID nada)
00569 {
00570 apr_status_t rv = APR_SUCCESS;
00571
00572 SERVICE_TABLE_ENTRY dispatchTable[] =
00573 {
00574 { "", service_nt_main_fn },
00575 { NULL, NULL }
00576 };
00577
00578
00579 if (!StartServiceCtrlDispatcher(dispatchTable))
00580 {
00581
00582 rv = apr_get_os_error();
00583 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00584 "Error starting service control dispatcher");
00585 }
00586
00587 return (rv);
00588 }
00589
00590
00591 apr_status_t mpm_service_set_name(apr_pool_t *p, const char **display_name,
00592 const char *set_name)
00593 {
00594 char key_name[MAX_PATH];
00595 ap_regkey_t *key;
00596 apr_status_t rv;
00597
00598
00599
00600
00601
00602 mpm_service_name = apr_palloc(p, strlen(set_name) + 1);
00603 apr_collapse_spaces((char*) mpm_service_name, set_name);
00604 apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
00605 rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name, APR_READ, pconf);
00606 if (rv == APR_SUCCESS) {
00607 rv = ap_regkey_value_get(&mpm_display_name, key, "DisplayName", pconf);
00608 ap_regkey_close(key);
00609 }
00610 if (rv != APR_SUCCESS) {
00611
00612 mpm_display_name = apr_pstrdup(p, set_name);
00613 }
00614 *display_name = mpm_display_name;
00615 return rv;
00616 }
00617
00618
00619 apr_status_t mpm_merge_service_args(apr_pool_t *p,
00620 apr_array_header_t *args,
00621 int fixed_args)
00622 {
00623 apr_array_header_t *svc_args = NULL;
00624 char conf_key[MAX_PATH];
00625 char **cmb_data;
00626 apr_status_t rv;
00627 ap_regkey_t *key;
00628
00629 apr_snprintf(conf_key, sizeof(conf_key), SERVICEPARAMS, mpm_service_name);
00630 rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, conf_key, APR_READ, p);
00631 if (rv == APR_SUCCESS) {
00632 rv = ap_regkey_value_array_get(&svc_args, key, "ConfigArgs", p);
00633 ap_regkey_close(key);
00634 }
00635 if (rv != APR_SUCCESS) {
00636 if (rv == ERROR_FILE_NOT_FOUND) {
00637 ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
00638 "No ConfigArgs registered for %s, perhaps "
00639 "this service is not installed?",
00640 mpm_service_name);
00641 return APR_SUCCESS;
00642 }
00643 else
00644 return (rv);
00645 }
00646
00647 if (!svc_args || svc_args->nelts == 0) {
00648 return (APR_SUCCESS);
00649 }
00650
00651
00652
00653
00654
00655
00656 args->nalloc = args->nelts + svc_args->nelts;
00657 cmb_data = malloc(args->nalloc * sizeof(const char *));
00658
00659
00660 memcpy(cmb_data, args->elts, args->elt_size * fixed_args);
00661
00662
00663 memcpy(cmb_data + fixed_args, svc_args->elts,
00664 svc_args->elt_size * svc_args->nelts);
00665
00666
00667 memcpy(cmb_data + fixed_args + svc_args->nelts,
00668 (const char **)args->elts + fixed_args,
00669 args->elt_size * (args->nelts - fixed_args));
00670
00671 args->elts = (char *)cmb_data;
00672 args->nelts = args->nalloc;
00673
00674 return APR_SUCCESS;
00675 }
00676
00677
00678 void service_stopped(void)
00679 {
00680
00681 if (globdat.service_thread)
00682 {
00683 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00684 {
00685
00686 mpm_nt_eventlog_stderr_flush();
00687
00688
00689 ReleaseMutex(globdat.service_term);
00690
00691 ReportStatusToSCMgr(SERVICE_STOPPED,
00692 NO_ERROR,
00693 0);
00694 }
00695 else
00696 {
00697 RegisterServiceProcess(0, 0);
00698 PostThreadMessage(globdat.service_thread_id, WM_CLOSE, 0, 0);
00699 }
00700
00701 WaitForSingleObject(globdat.service_thread, 5000);
00702 CloseHandle(globdat.service_thread);
00703 }
00704 }
00705
00706
00707 apr_status_t mpm_service_to_start(const char **display_name, apr_pool_t *p)
00708 {
00709 HANDLE hProc = GetCurrentProcess();
00710 HANDLE hThread = GetCurrentThread();
00711 HANDLE waitfor[2];
00712
00713
00714 real_exit_code = 0;
00715
00716
00717
00718
00719 if (!DuplicateHandle(hProc, hThread, hProc, &(globdat.mpm_thread),
00720 0, FALSE, DUPLICATE_SAME_ACCESS)) {
00721 return APR_ENOTHREAD;
00722 }
00723
00724 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00725 {
00726 globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
00727 globdat.service_term = CreateMutex(NULL, TRUE, NULL);
00728 if (!globdat.service_init || !globdat.service_term) {
00729 return APR_EGENERAL;
00730 }
00731
00732 globdat.service_thread = CreateThread(NULL, 0, service_nt_dispatch_thread,
00733 NULL, 0, &globdat.service_thread_id);
00734 }
00735 else
00736 {
00737 if (!RegisterServiceProcess(0, 1))
00738 return GetLastError();
00739
00740 globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
00741 if (!globdat.service_init) {
00742 return APR_EGENERAL;
00743 }
00744
00745 globdat.service_thread = CreateThread(NULL, 0, monitor_service_9x_thread,
00746 (LPVOID) mpm_service_name, 0,
00747 &globdat.service_thread_id);
00748 }
00749
00750 if (!globdat.service_thread) {
00751 return APR_ENOTHREAD;
00752 }
00753
00754 waitfor[0] = globdat.service_init;
00755 waitfor[1] = globdat.service_thread;
00756
00757
00758 if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
00759 return APR_ENOTHREAD;
00760 }
00761
00762 atexit(service_stopped);
00763 *display_name = mpm_display_name;
00764 return APR_SUCCESS;
00765 }
00766
00767
00768 apr_status_t mpm_service_started(void)
00769 {
00770 set_service_description();
00771 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00772 {
00773 ReportStatusToSCMgr(SERVICE_RUNNING,
00774 NO_ERROR,
00775 0);
00776 }
00777 return APR_SUCCESS;
00778 }
00779
00780
00781 void mpm_service_stopping(void)
00782 {
00783 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00784 ReportStatusToSCMgr(SERVICE_STOP_PENDING,
00785 NO_ERROR,
00786 30000);
00787 }
00788
00789
00790 apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc,
00791 const char * const * argv, int reconfig)
00792 {
00793 char key_name[MAX_PATH];
00794 char exe_path[MAX_PATH];
00795 char *launch_cmd;
00796 ap_regkey_t *key;
00797 apr_status_t rv;
00798
00799 fprintf(stderr,reconfig ? "Reconfiguring the %s service\n"
00800 : "Installing the %s service\n", mpm_display_name);
00801
00802
00803 if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
00804 {
00805 apr_status_t rv = apr_get_os_error();
00806 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00807 "GetModuleFileName failed");
00808 return rv;
00809 }
00810
00811 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00812 {
00813 SC_HANDLE schService;
00814 SC_HANDLE schSCManager;
00815
00816 schSCManager = OpenSCManager(NULL, NULL,
00817 SC_MANAGER_CREATE_SERVICE);
00818 if (!schSCManager) {
00819 rv = apr_get_os_error();
00820 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00821 "Failed to open the WinNT service manager");
00822 return (rv);
00823 }
00824
00825 launch_cmd = apr_psprintf(ptemp, "\"%s\" -k runservice", exe_path);
00826
00827 if (reconfig) {
00828
00829 schService = OpenService(schSCManager, mpm_service_name,
00830 SERVICE_CHANGE_CONFIG);
00831 if (!schService) {
00832 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
00833 apr_get_os_error(), NULL,
00834 "OpenService failed");
00835 }
00836
00837 else if (!ChangeServiceConfig(schService,
00838 SERVICE_WIN32_OWN_PROCESS,
00839 SERVICE_AUTO_START,
00840 SERVICE_ERROR_NORMAL,
00841 launch_cmd, NULL, NULL,
00842 "Tcpip\0Afd\0", NULL, NULL,
00843 mpm_display_name)) {
00844 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
00845 apr_get_os_error(), NULL,
00846 "ChangeServiceConfig failed");
00847
00848 CloseServiceHandle(schService);
00849 schService = NULL;
00850 }
00851 }
00852 else {
00853
00854
00855
00856
00857
00858
00859
00860 schService = CreateService(schSCManager,
00861 mpm_service_name,
00862 mpm_display_name,
00863 SERVICE_ALL_ACCESS,
00864 SERVICE_WIN32_OWN_PROCESS,
00865 SERVICE_AUTO_START,
00866 SERVICE_ERROR_NORMAL,
00867 launch_cmd,
00868 NULL,
00869 NULL,
00870 "Tcpip\0Afd\0",
00871 NULL,
00872 NULL);
00873
00874 if (!schService)
00875 {
00876 rv = apr_get_os_error();
00877 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00878 "Failed to create WinNT Service Profile");
00879 CloseServiceHandle(schSCManager);
00880 return (rv);
00881 }
00882 }
00883
00884 CloseServiceHandle(schService);
00885 CloseServiceHandle(schSCManager);
00886 }
00887 else
00888 {
00889
00890 launch_cmd = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice",
00891 exe_path, mpm_service_name);
00892 rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, SERVICECONFIG9X,
00893 APR_READ | APR_WRITE | APR_CREATE, pconf);
00894 if (rv == APR_SUCCESS) {
00895 rv = ap_regkey_value_set(key, mpm_service_name,
00896 launch_cmd, 0, pconf);
00897 ap_regkey_close(key);
00898 }
00899 if (rv != APR_SUCCESS) {
00900 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00901 "%s: Failed to add the RunServices registry entry.",
00902 mpm_display_name);
00903 return (rv);
00904 }
00905
00906 apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
00907 rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name,
00908 APR_READ | APR_WRITE | APR_CREATE, pconf);
00909 if (rv != APR_SUCCESS) {
00910 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00911 "%s: Failed to create the registry service key.",
00912 mpm_display_name);
00913 return (rv);
00914 }
00915 rv = ap_regkey_value_set(key, "ImagePath", launch_cmd, 0, pconf);
00916 if (rv != APR_SUCCESS) {
00917 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00918 "%s: Failed to store ImagePath in the registry.",
00919 mpm_display_name);
00920 ap_regkey_close(key);
00921 return (rv);
00922 }
00923 rv = ap_regkey_value_set(key, "DisplayName",
00924 mpm_display_name, 0, pconf);
00925 ap_regkey_close(key);
00926 if (rv != APR_SUCCESS) {
00927 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00928 "%s: Failed to store DisplayName in the registry.",
00929 mpm_display_name);
00930 return (rv);
00931 }
00932 }
00933
00934 set_service_description();
00935
00936
00937
00938 apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, mpm_service_name);
00939 rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name,
00940 APR_READ | APR_WRITE | APR_CREATE, pconf);
00941 if (rv == APR_SUCCESS) {
00942 rv = ap_regkey_value_array_set(key, "ConfigArgs", argc, argv, pconf);
00943 ap_regkey_close(key);
00944 }
00945 if (rv != APR_SUCCESS) {
00946 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00947 "%s: Failed to store the ConfigArgs in the registry.",
00948 mpm_display_name);
00949 return (rv);
00950 }
00951 fprintf(stderr,"The %s service is successfully installed.\n", mpm_display_name);
00952 return APR_SUCCESS;
00953 }
00954
00955
00956 apr_status_t mpm_service_uninstall(void)
00957 {
00958 char key_name[MAX_PATH];
00959 apr_status_t rv;
00960
00961 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
00962 {
00963 SC_HANDLE schService;
00964 SC_HANDLE schSCManager;
00965
00966 fprintf(stderr,"Removing the %s service\n", mpm_display_name);
00967
00968 schSCManager = OpenSCManager(NULL, NULL,
00969 SC_MANAGER_CONNECT);
00970 if (!schSCManager) {
00971 rv = apr_get_os_error();
00972 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00973 "Failed to open the WinNT service manager.");
00974 return (rv);
00975 }
00976
00977
00978 schService = OpenService(schSCManager, mpm_service_name, DELETE);
00979
00980 if (!schService) {
00981 rv = apr_get_os_error();
00982 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
00983 "%s: OpenService failed", mpm_display_name);
00984 return (rv);
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 if (DeleteService(schService) == 0) {
00998 rv = apr_get_os_error();
00999 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
01000 "%s: Failed to delete the service.", mpm_display_name);
01001 return (rv);
01002 }
01003
01004 CloseServiceHandle(schService);
01005 CloseServiceHandle(schSCManager);
01006 }
01007 else
01008 {
01009 apr_status_t rv2, rv3;
01010 ap_regkey_t *key;
01011 fprintf(stderr,"Removing the %s service\n", mpm_display_name);
01012
01013
01014
01015 rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, SERVICECONFIG9X,
01016 APR_READ | APR_WRITE | APR_CREATE, pconf);
01017 if (rv == APR_SUCCESS) {
01018 rv = ap_regkey_value_remove(key, mpm_service_name, pconf);
01019 ap_regkey_close(key);
01020 }
01021 if (rv != APR_SUCCESS) {
01022 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
01023 "%s: Failed to remove the RunServices registry "
01024 "entry.", mpm_display_name);
01025 }
01026
01027
01028 apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, mpm_service_name);
01029 rv2 = ap_regkey_remove(AP_REGKEY_LOCAL_MACHINE, key_name, pconf);
01030 apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
01031 rv3 = ap_regkey_remove(AP_REGKEY_LOCAL_MACHINE, key_name, pconf);
01032 rv2 = (rv2 != APR_SUCCESS) ? rv2 : rv3;
01033 if (rv2 != APR_SUCCESS) {
01034 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv2, NULL,
01035 "%s: Failed to remove the service config from the "
01036 "registry.", mpm_display_name);
01037 }
01038 rv = (rv != APR_SUCCESS) ? rv : rv2;
01039 if (rv != APR_SUCCESS)
01040 return rv;
01041 }
01042 fprintf(stderr,"The %s service has been removed successfully.\n", mpm_display_name);
01043 return APR_SUCCESS;
01044 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 static int signal_service_transition(SC_HANDLE schService, DWORD signal, DWORD pending, DWORD complete)
01055 {
01056 if (signal && !ControlService(schService, signal, &globdat.ssStatus))
01057 return FALSE;
01058
01059 do {
01060 Sleep(1000);
01061 if (!QueryServiceStatus(schService, &globdat.ssStatus))
01062 return FALSE;
01063 } while (globdat.ssStatus.dwCurrentState == pending);
01064
01065 return (globdat.ssStatus.dwCurrentState == complete);
01066 }
01067
01068
01069 apr_status_t mpm_service_start(apr_pool_t *ptemp, int argc,
01070 const char * const * argv)
01071 {
01072 apr_status_t rv;
01073
01074 fprintf(stderr,"Starting the %s service\n", mpm_display_name);
01075
01076 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
01077 {
01078 char **start_argv;
01079 SC_HANDLE schService;
01080 SC_HANDLE schSCManager;
01081
01082 schSCManager = OpenSCManager(NULL, NULL,
01083 SC_MANAGER_CONNECT);
01084 if (!schSCManager) {
01085 rv = apr_get_os_error();
01086 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
01087 "Failed to open the WinNT service manager");
01088 return (rv);
01089 }
01090
01091
01092 schService = OpenService(schSCManager, mpm_service_name,
01093 SERVICE_START | SERVICE_QUERY_STATUS);
01094 if (!schService) {
01095 rv = apr_get_os_error();
01096 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
01097 "%s: Failed to open the service.", mpm_display_name);
01098 CloseServiceHandle(schSCManager);
01099 return (rv);
01100 }
01101
01102 if (QueryServiceStatus(schService, &globdat.ssStatus)
01103 && (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING)) {
01104 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL,
01105 "Service %s is already started!", mpm_display_name);
01106 CloseServiceHandle(schService);
01107 CloseServiceHandle(schSCManager);
01108 return 0;
01109 }
01110
01111 start_argv = malloc((argc + 1) * sizeof(const char **));
01112 memcpy(start_argv, argv, argc * sizeof(const char **));
01113 start_argv[argc] = NULL;
01114
01115 rv = APR_EINIT;
01116
01117 if (StartService(schService, argc, start_argv)
01118 && signal_service_transition(schService, 0,
01119 SERVICE_START_PENDING,
01120 SERVICE_RUNNING))
01121 rv = APR_SUCCESS;
01122
01123 if (rv != APR_SUCCESS)
01124 rv = apr_get_os_error();
01125
01126 CloseServiceHandle(schService);
01127 CloseServiceHandle(schSCManager);
01128 }
01129 else
01130 {
01131 STARTUPINFO si;
01132 PROCESS_INFORMATION pi;
01133 char exe_path[MAX_PATH];
01134 char exe_cmd[MAX_PATH * 4];
01135 char *next_arg;
01136 int i;
01137
01138
01139
01140
01141 if (FindWindow("ApacheWin95ServiceMonitor", mpm_service_name)) {
01142 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL,
01143 "Service %s is already started!", mpm_display_name);
01144 return 0;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153
01154 if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
01155 {
01156 apr_status_t rv = apr_get_os_error();
01157 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
01158 "GetModuleFileName failed");
01159 return rv;
01160 }
01161
01162 apr_snprintf(exe_cmd, sizeof(exe_cmd),
01163 "\"%s\" -n %s -k runservice",
01164 exe_path, mpm_service_name);
01165 next_arg = strchr(exe_cmd, '\0');
01166 for (i = 0; i < argc; ++i) {
01167 apr_snprintf(next_arg, sizeof(exe_cmd) - (next_arg - exe_cmd),
01168 " \"%s\"", argv[i]);
01169 next_arg = strchr(exe_cmd, '\0');
01170 }
01171
01172 memset(&si, 0, sizeof(si));
01173 memset(&pi, 0, sizeof(pi));
01174 si.cb = sizeof(si);
01175 si.dwFlags = STARTF_USESHOWWINDOW;
01176 si.wShowWindow = SW_HIDE;
01177
01178 rv = APR_EINIT;
01179 if (CreateProcess(NULL, exe_cmd, NULL, NULL, FALSE,
01180 DETACHED_PROCESS,
01181 NULL, NULL, &si, &pi))
01182 {
01183 DWORD code;
01184 while (GetExitCodeProcess(pi.hProcess, &code) == STILL_ACTIVE) {
01185 if (FindWindow("ApacheWin95ServiceMonitor", mpm_service_name)) {
01186 rv = APR_SUCCESS;
01187 break;
01188 }
01189 Sleep (1000);
01190 }
01191 }
01192
01193 if (rv != APR_SUCCESS)
01194 rv = apr_get_os_error();
01195
01196 CloseHandle(pi.hProcess);
01197 CloseHandle(pi.hThread);
01198 }
01199
01200 if (rv == APR_SUCCESS)
01201 fprintf(stderr,"The %s service is running.\n", mpm_display_name);
01202 else
01203 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
01204 "%s: Failed to start the service process.",
01205 mpm_display_name);
01206
01207 return rv;
01208 }
01209
01210
01211
01212
01213 void mpm_signal_service(apr_pool_t *ptemp, int signal)
01214 {
01215 int success = FALSE;
01216
01217 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
01218 {
01219 SC_HANDLE schService;
01220 SC_HANDLE schSCManager;
01221
01222 schSCManager = OpenSCManager(NULL, NULL,
01223 SC_MANAGER_CONNECT);
01224
01225 if (!schSCManager) {
01226 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,
01227 "Failed to open the NT Service Manager");
01228 return;
01229 }
01230
01231
01232 schService = OpenService(schSCManager, mpm_service_name,
01233 SERVICE_INTERROGATE | SERVICE_QUERY_STATUS |
01234 SERVICE_USER_DEFINED_CONTROL |
01235 SERVICE_START | SERVICE_STOP);
01236
01237 if (schService == NULL) {
01238
01239 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,
01240 "Failed to open the %s Service", mpm_display_name);
01241 CloseServiceHandle(schSCManager);
01242 return;
01243 }
01244
01245 if (!QueryServiceStatus(schService, &globdat.ssStatus)) {
01246 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,
01247 "Query of Service %s failed", mpm_display_name);
01248 CloseServiceHandle(schService);
01249 CloseServiceHandle(schSCManager);
01250 return;
01251 }
01252
01253 if (!signal && (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)) {
01254 fprintf(stderr,"The %s service is not started.\n", mpm_display_name);
01255 CloseServiceHandle(schService);
01256 CloseServiceHandle(schSCManager);
01257 return;
01258 }
01259
01260 fprintf(stderr,"The %s service is %s.\n", mpm_display_name,
01261 signal ? "restarting" : "stopping");
01262
01263 if (!signal)
01264 success = signal_service_transition(schService,
01265 SERVICE_CONTROL_STOP,
01266 SERVICE_STOP_PENDING,
01267 SERVICE_STOPPED);
01268 else if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) {
01269 mpm_service_start(ptemp, 0, NULL);
01270 CloseServiceHandle(schService);
01271 CloseServiceHandle(schSCManager);
01272 return;
01273 }
01274 else
01275 success = signal_service_transition(schService,
01276 SERVICE_APACHE_RESTART,
01277 SERVICE_START_PENDING,
01278 SERVICE_RUNNING);
01279
01280 CloseServiceHandle(schService);
01281 CloseServiceHandle(schSCManager);
01282 }
01283 else
01284 {
01285 DWORD service_pid;
01286 HANDLE hwnd;
01287 char prefix[20];
01288
01289
01290
01291 hwnd = FindWindow("ApacheWin95ServiceMonitor", mpm_service_name);
01292 if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid))
01293 globdat.ssStatus.dwCurrentState = SERVICE_RUNNING;
01294 else
01295 {
01296 globdat.ssStatus.dwCurrentState = SERVICE_STOPPED;
01297 if (!signal) {
01298 fprintf(stderr,"The %s service is not started.\n", mpm_display_name);
01299 return;
01300 }
01301 }
01302
01303 fprintf(stderr,"The %s service is %s.\n", mpm_display_name,
01304 signal ? "restarting" : "stopping");
01305
01306 apr_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid);
01307 setup_signal_names(prefix);
01308
01309 if (!signal)
01310 {
01311 int ticks = 60;
01312 ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
01313 while (--ticks)
01314 {
01315 if (!IsWindow(hwnd)) {
01316 success = TRUE;
01317 break;
01318 }
01319 Sleep(1000);
01320 }
01321 }
01322 else
01323 {
01324
01325
01326
01327
01328
01329 if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) {
01330 mpm_service_start(ptemp, 0, NULL);
01331 return;
01332 }
01333 else {
01334 success = TRUE;
01335 ap_signal_parent(SIGNAL_PARENT_RESTART);
01336 }
01337 }
01338 }
01339
01340 if (success)
01341 fprintf(stderr,"The %s service has %s.\n", mpm_display_name,
01342 signal ? "restarted" : "stopped");
01343 else
01344 fprintf(stderr,"Failed to %s the %s service.\n",
01345 signal ? "restart" : "stop", mpm_display_name);
01346 }