diff options
Diffstat (limited to 'server/mpm/winnt/nt_eventlog.c')
-rw-r--r-- | server/mpm/winnt/nt_eventlog.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/server/mpm/winnt/nt_eventlog.c b/server/mpm/winnt/nt_eventlog.c new file mode 100644 index 0000000..e7e80d0 --- /dev/null +++ b/server/mpm/winnt/nt_eventlog.c @@ -0,0 +1,171 @@ +/* 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. + */ + +#include "httpd.h" +#include "http_log.h" +#include "mpm_winnt.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include "apr_portable.h" +#include "ap_regkey.h" + +static const char *display_name = NULL; +static HANDLE stderr_thread = NULL; +static HANDLE stderr_ready; + +static DWORD WINAPI service_stderr_thread(LPVOID hPipe) +{ + HANDLE hPipeRead = (HANDLE) hPipe; + HANDLE hEventSource; + char errbuf[256]; + char *errmsg = errbuf; + const char *errarg[9]; + DWORD errres; + ap_regkey_t *regkey; + apr_status_t rv; + apr_pool_t *p; + + apr_pool_create_ex(&p, NULL, NULL, NULL); + + errarg[0] = "The Apache service named"; + errarg[1] = display_name; + errarg[2] = "reported the following error:\r\n>>>"; + errarg[3] = errbuf; + errarg[4] = NULL; + errarg[5] = NULL; + errarg[6] = NULL; + errarg[7] = NULL; + errarg[8] = NULL; + + /* What are we going to do in here, bail on the user? not. */ + if ((rv = ap_regkey_open(®key, AP_REGKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\" + "EventLog\\Application\\Apache Service", + APR_READ | APR_WRITE | APR_CREATE, p)) + == APR_SUCCESS) + { + DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | + EVENTLOG_INFORMATION_TYPE; + + /* The stock message file */ + ap_regkey_value_set(regkey, "EventMessageFile", + "%SystemRoot%\\System32\\netmsg.dll", + AP_REGKEY_EXPAND, p); + + ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData, + sizeof(dwData), REG_DWORD, p); + ap_regkey_close(regkey); + } + + hEventSource = RegisterEventSourceW(NULL, L"Apache Service"); + + SetEvent(stderr_ready); + + while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1)) + { + if ((errmsg > errbuf) || !apr_isspace(*errmsg)) + { + ++errmsg; + if ((*(errmsg - 1) == '\n') + || (errmsg >= errbuf + sizeof(errbuf) - 1)) + { + while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) { + --errmsg; + } + *errmsg = '\0'; + + /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9' + * The event code in netmsg.dll is 3299 + */ + ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, + 3299, NULL, 9, 0, errarg, NULL); + errmsg = errbuf; + } + } + } + + if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) { + apr_snprintf(errbuf, sizeof(errbuf), + "Win32 error %lu reading stderr pipe stream\r\n", + GetLastError()); + + ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, + 3299, NULL, 9, 0, errarg, NULL); + } + + CloseHandle(hPipeRead); + DeregisterEventSource(hEventSource); + CloseHandle(stderr_thread); + stderr_thread = NULL; + apr_pool_destroy(p); + return 0; +} + + +void mpm_nt_eventlog_stderr_flush(void) +{ + HANDLE cleanup_thread = stderr_thread; + + if (cleanup_thread) { + HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE); + fclose(stderr); + CloseHandle(hErr); + WaitForSingleObject(cleanup_thread, 30000); + CloseHandle(cleanup_thread); + } +} + + +void mpm_nt_eventlog_stderr_open(const char *argv0, apr_pool_t *p) +{ + SECURITY_ATTRIBUTES sa; + HANDLE hPipeRead = NULL; + HANDLE hPipeWrite = NULL; + DWORD threadid; + apr_file_t *eventlog_file; + apr_file_t *stderr_file; + + display_name = argv0; + + /* Create a pipe to send stderr messages to the system error log. + * + * _dup2() duplicates the write handle inheritable for us. + */ + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = FALSE; + CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0); + ap_assert(hPipeRead && hPipeWrite); + + stderr_ready = CreateEvent(NULL, FALSE, FALSE, NULL); + stderr_thread = CreateThread(NULL, 65536, service_stderr_thread, + (LPVOID)hPipeRead, stack_res_flag, &threadid); + ap_assert(stderr_ready && stderr_thread); + + WaitForSingleObject(stderr_ready, INFINITE); + + if ((apr_file_open_stderr(&stderr_file, p) + == APR_SUCCESS) + && (apr_os_file_put(&eventlog_file, &hPipeWrite, APR_WRITE, p) + == APR_SUCCESS)) + apr_file_dup2(stderr_file, eventlog_file, p); + + /* The code above _will_ corrupt the StdHandle... + * and we must do so anyways. We set this up only + * after we initialized the posix stderr API. + */ + ap_open_stderr_log(p); +} |