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.
21 #include "mpm_winnt.h"
22 #include "apr_strings.h"
24 #include "apr_portable.h"
25 #include "ap_regkey.h"
27 static char *display_name = NULL;
28 static HANDLE stderr_thread = NULL;
29 static HANDLE stderr_ready;
31 static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
33 HANDLE hPipeRead = (HANDLE) hPipe;
36 char *errmsg = errbuf;
37 const char *errarg[9];
43 apr_pool_sub_make(&p, NULL, NULL);
45 errarg[0] = "The Apache service named";
46 errarg[1] = display_name;
47 errarg[2] = "reported the following error:\r\n>>>";
55 /* What are we going to do in here, bail on the user? not. */
56 if ((rv = ap_regkey_open(®key, AP_REGKEY_LOCAL_MACHINE,
57 "SYSTEM\\CurrentControlSet\\Services\\"
58 "EventLog\\Application\\Apache Service",
59 APR_READ | APR_WRITE | APR_CREATE, p))
62 DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
63 EVENTLOG_INFORMATION_TYPE;
65 /* The stock message file */
66 ap_regkey_value_set(regkey, "EventMessageFile",
67 "%SystemRoot%\\System32\\netmsg.dll",
70 ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData,
71 sizeof(dwData), REG_DWORD, p);
72 ap_regkey_close(regkey);
75 hEventSource = RegisterEventSourceW(NULL, L"Apache Service");
77 SetEvent(stderr_ready);
79 while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
81 if ((errmsg > errbuf) || !apr_isspace(*errmsg))
84 if ((*(errmsg - 1) == '\n')
85 || (errmsg >= errbuf + sizeof(errbuf) - 1))
87 while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) {
92 /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
93 * The event code in netmsg.dll is 3299
95 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
96 3299, NULL, 9, 0, errarg, NULL);
102 if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
103 apr_snprintf(errbuf, sizeof(errbuf),
104 "Win32 error %d reading stderr pipe stream\r\n",
107 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
108 3299, NULL, 9, 0, errarg, NULL);
111 CloseHandle(hPipeRead);
112 DeregisterEventSource(hEventSource);
113 CloseHandle(stderr_thread);
114 stderr_thread = NULL;
120 void mpm_nt_eventlog_stderr_flush(void)
122 HANDLE cleanup_thread = stderr_thread;
124 if (cleanup_thread) {
125 HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
128 WaitForSingleObject(cleanup_thread, 30000);
129 CloseHandle(cleanup_thread);
134 void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
136 SECURITY_ATTRIBUTES sa;
137 HANDLE hProc = GetCurrentProcess();
138 HANDLE hPipeRead = NULL;
139 HANDLE hPipeWrite = NULL;
142 apr_file_t *eventlog_file;
143 apr_file_t *stderr_file;
145 display_name = argv0;
147 /* Create a pipe to send stderr messages to the system error log.
149 * _dup2() duplicates the write handle inheritable for us.
151 sa.nLength = sizeof(sa);
152 sa.lpSecurityDescriptor = NULL;
153 sa.bInheritHandle = FALSE;
154 CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0);
155 ap_assert(hPipeRead && hPipeWrite);
157 stderr_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
158 stderr_thread = CreateThread(NULL, 0, service_stderr_thread,
159 (LPVOID) hPipeRead, 0, &threadid);
160 ap_assert(stderr_ready && stderr_thread);
162 WaitForSingleObject(stderr_ready, INFINITE);
164 if ((apr_file_open_stderr(&stderr_file, p)
166 && (apr_os_file_put(&eventlog_file, &hPipeWrite, APR_WRITE, p)
168 apr_file_dup2(stderr_file, eventlog_file, p);
170 /* The code above _will_ corrupt the StdHandle...
171 * and we must do so anyways. We set this up only
172 * after we initialized the posix stderr API.
174 ap_open_stderr_log(p);