1 /* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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 "ap_regkey.h"
26 static char *display_name = NULL;
27 static HANDLE stderr_thread = NULL;
28 static HANDLE stderr_ready;
30 static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
32 HANDLE hPipeRead = (HANDLE) hPipe;
35 char *errmsg = errbuf;
36 const char *errarg[9];
42 apr_pool_create_ex(&p, NULL, NULL, NULL);
44 errarg[0] = "The Apache service named";
45 errarg[1] = display_name;
46 errarg[2] = "reported the following error:\r\n>>>";
54 /* What are we going to do in here, bail on the user? not. */
55 if ((rv = ap_regkey_open(®key, AP_REGKEY_LOCAL_MACHINE,
56 "SYSTEM\\CurrentControlSet\\Services\\"
57 "EventLog\\Application\\Apache Service",
58 APR_READ | APR_WRITE | APR_CREATE, p))
61 DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
62 EVENTLOG_INFORMATION_TYPE;
64 /* The stock message file */
65 ap_regkey_value_set(regkey, "EventMessageFile",
66 "%SystemRoot%\\System32\\netmsg.dll",
69 ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData,
70 sizeof(dwData), REG_DWORD, p);
71 ap_regkey_close(regkey);
74 hEventSource = RegisterEventSourceW(NULL, L"Apache Service");
76 SetEvent(stderr_ready);
78 while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
80 if ((errmsg > errbuf) || !apr_isspace(*errmsg))
83 if ((*(errmsg - 1) == '\n')
84 || (errmsg >= errbuf + sizeof(errbuf) - 1))
86 while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) {
91 /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
92 * The event code in netmsg.dll is 3299
94 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
95 3299, NULL, 9, 0, errarg, NULL);
101 if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
102 apr_snprintf(errbuf, sizeof(errbuf),
103 "Win32 error %d reading stderr pipe stream\r\n",
106 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
107 3299, NULL, 9, 0, errarg, NULL);
110 CloseHandle(hPipeRead);
111 DeregisterEventSource(hEventSource);
112 CloseHandle(stderr_thread);
113 stderr_thread = NULL;
119 void mpm_nt_eventlog_stderr_flush(void)
121 HANDLE cleanup_thread = stderr_thread;
123 if (cleanup_thread) {
124 HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
127 WaitForSingleObject(cleanup_thread, 30000);
128 CloseHandle(cleanup_thread);
133 void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
135 SECURITY_ATTRIBUTES sa;
136 HANDLE hProc = GetCurrentProcess();
137 HANDLE hPipeRead = NULL;
138 HANDLE hPipeWrite = NULL;
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 /* Flush stderr and unset its buffer, then commit and replace stderr.
163 * This is typically a noop for Win2K/XP since services with NULL std
164 * handles [but valid FILE *'s, oddly enough], but is required
165 * for NT 4.0 and to use this code outside of services.
168 setvbuf(stderr, NULL, _IONBF, 0);
169 _commit(2 /* stderr */);
170 fd = _open_osfhandle((long) hPipeWrite,
171 _O_WRONLY | _O_BINARY);
174 _setmode(2, _O_BINARY);
176 /* hPipeWrite was _close()'ed above, and _dup2()'ed
177 * to fd 2 creating a new, inherited Win32 handle.
178 * Recover that real handle from fd 2.
180 hPipeWrite = (HANDLE)_get_osfhandle(2);
182 SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
184 /* The code above _will_ corrupt the StdHandle...
185 * and we must do so anyways. We set this up only
186 * after we initialized the posix stderr API.
188 ap_open_stderr_log(p);