summaryrefslogtreecommitdiffstats
path: root/server/mpm/winnt/nt_eventlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/mpm/winnt/nt_eventlog.c')
-rw-r--r--server/mpm/winnt/nt_eventlog.c172
1 files changed, 172 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..cd49ee6
--- /dev/null
+++ b/server/mpm/winnt/nt_eventlog.c
@@ -0,0 +1,172 @@
+/* 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);
+ apr_pool_tag(p, "service_stderr_thread");
+
+ 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(&regkey, 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);
+}