1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "mpm_winnt.h"
20 #include "apr_strings.h"
22 #include "apr_portable.h"
23 #include "ap_regkey.h"
25 static char *display_name = NULL;
26 static HANDLE stderr_thread = NULL;
27 static HANDLE stderr_ready;
29 static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
31 HANDLE hPipeRead = (HANDLE) hPipe;
34 char *errmsg = errbuf;
35 const char *errarg[9];
41 apr_pool_create_ex(&p, NULL, NULL, NULL);
43 errarg[0] = "The Apache service named";
44 errarg[1] = display_name;
45 errarg[2] = "reported the following error:\r\n>>>";
53 /* What are we going to do in here, bail on the user? not. */
54 if ((rv = ap_regkey_open(®key, AP_REGKEY_LOCAL_MACHINE,
55 "SYSTEM\\CurrentControlSet\\Services\\"
56 "EventLog\\Application\\Apache Service",
57 APR_READ | APR_WRITE | APR_CREATE, p))
60 DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
61 EVENTLOG_INFORMATION_TYPE;
63 /* The stock message file */
64 ap_regkey_value_set(regkey, "EventMessageFile",
65 "%SystemRoot%\\System32\\netmsg.dll",
68 ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData,
69 sizeof(dwData), REG_DWORD, p);
70 ap_regkey_close(regkey);
73 hEventSource = RegisterEventSourceW(NULL, L"Apache Service");
75 SetEvent(stderr_ready);
77 while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
79 if ((errmsg > errbuf) || !apr_isspace(*errmsg))
82 if ((*(errmsg - 1) == '\n')
83 || (errmsg >= errbuf + sizeof(errbuf) - 1))
85 while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) {
90 /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
91 * The event code in netmsg.dll is 3299
93 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
94 3299, NULL, 9, 0, errarg, NULL);
100 if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
101 apr_snprintf(errbuf, sizeof(errbuf),
102 "Win32 error %d reading stderr pipe stream\r\n",
105 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
106 3299, NULL, 9, 0, errarg, NULL);
109 CloseHandle(hPipeRead);
110 DeregisterEventSource(hEventSource);
111 CloseHandle(stderr_thread);
112 stderr_thread = NULL;
118 void mpm_nt_eventlog_stderr_flush(void)
120 HANDLE cleanup_thread = stderr_thread;
122 if (cleanup_thread) {
123 HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
126 WaitForSingleObject(cleanup_thread, 30000);
127 CloseHandle(cleanup_thread);
132 void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
134 SECURITY_ATTRIBUTES sa;
135 HANDLE hProc = GetCurrentProcess();
136 HANDLE hPipeRead = NULL;
137 HANDLE hPipeWrite = NULL;
140 apr_file_t *eventlog_file;
141 apr_file_t *stderr_file;
143 display_name = argv0;
145 /* Create a pipe to send stderr messages to the system error log.
147 * _dup2() duplicates the write handle inheritable for us.
149 sa.nLength = sizeof(sa);
150 sa.lpSecurityDescriptor = NULL;
151 sa.bInheritHandle = FALSE;
152 CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0);
153 ap_assert(hPipeRead && hPipeWrite);
155 stderr_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
156 stderr_thread = CreateThread(NULL, 0, service_stderr_thread,
157 (LPVOID) hPipeRead, 0, &threadid);
158 ap_assert(stderr_ready && stderr_thread);
160 WaitForSingleObject(stderr_ready, INFINITE);
162 if ((apr_file_open_stderr(&stderr_file, p)
164 && (apr_os_file_put(&eventlog_file, &hPipeWrite, APR_WRITE, p)
166 apr_file_dup2(stderr_file, eventlog_file, p);
168 /* The code above _will_ corrupt the StdHandle...
169 * and we must do so anyways. We set this up only
170 * after we initialized the posix stderr API.
172 ap_open_stderr_log(p);