1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
63 #include "mpm_winnt.h"
64 #include "apr_strings.h"
66 #include "ap_regkey.h"
68 static char *display_name = NULL;
69 static HANDLE stderr_thread = NULL;
70 static HANDLE stderr_ready;
72 static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
74 HANDLE hPipeRead = (HANDLE) hPipe;
77 char *errmsg = errbuf;
78 const char *errarg[9];
84 apr_pool_sub_make(&p, NULL, NULL);
86 errarg[0] = "The Apache service named";
87 errarg[1] = display_name;
88 errarg[2] = "reported the following error:\r\n>>>";
96 /* What are we going to do in here, bail on the user? not. */
97 if ((rv = ap_regkey_open(®key, AP_REGKEY_LOCAL_MACHINE,
98 "SYSTEM\\CurrentControlSet\\Services\\"
99 "EventLog\\Application\\Apache Service",
100 APR_READ | APR_WRITE | APR_CREATE, p))
103 DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
104 EVENTLOG_INFORMATION_TYPE;
106 /* The stock message file */
107 ap_regkey_value_set(regkey, "EventMessageFile",
108 "%SystemRoot%\\System32\\netmsg.dll",
109 AP_REGKEY_EXPAND, p);
111 ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData,
112 sizeof(dwData), REG_DWORD, p);
113 ap_regkey_close(regkey);
116 hEventSource = RegisterEventSourceW(NULL, L"Apache Service");
118 SetEvent(stderr_ready);
120 while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
122 if ((errmsg > errbuf) || !apr_isspace(*errmsg))
125 if ((*(errmsg - 1) == '\n')
126 || (errmsg >= errbuf + sizeof(errbuf) - 1))
128 while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) {
133 /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
134 * The event code in netmsg.dll is 3299
136 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
137 3299, NULL, 9, 0, errarg, NULL);
143 if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
144 apr_snprintf(errbuf, sizeof(errbuf),
145 "Win32 error %d reading stderr pipe stream\r\n",
148 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
149 3299, NULL, 9, 0, errarg, NULL);
152 CloseHandle(hPipeRead);
153 DeregisterEventSource(hEventSource);
154 CloseHandle(stderr_thread);
155 stderr_thread = NULL;
161 void mpm_nt_eventlog_stderr_flush(void)
163 HANDLE cleanup_thread = stderr_thread;
165 if (cleanup_thread) {
166 HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
169 WaitForSingleObject(cleanup_thread, 30000);
170 CloseHandle(cleanup_thread);
175 void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
177 SECURITY_ATTRIBUTES sa;
178 HANDLE hProc = GetCurrentProcess();
179 HANDLE hPipeRead = NULL;
180 HANDLE hPipeWrite = NULL;
185 display_name = argv0;
187 /* Create a pipe to send stderr messages to the system error log.
189 * _dup2() duplicates the write handle inheritable for us.
191 sa.nLength = sizeof(sa);
192 sa.lpSecurityDescriptor = NULL;
193 sa.bInheritHandle = FALSE;
194 CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0);
195 ap_assert(hPipeRead && hPipeWrite);
197 stderr_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
198 stderr_thread = CreateThread(NULL, 0, service_stderr_thread,
199 (LPVOID) hPipeRead, 0, &threadid);
200 ap_assert(stderr_ready && stderr_thread);
202 WaitForSingleObject(stderr_ready, INFINITE);
204 /* Flush stderr and unset its buffer, then commit and replace stderr.
205 * This is typically a noop for Win2K/XP since services with NULL std
206 * handles [but valid FILE *'s, oddly enough], but is required
207 * for NT 4.0 and to use this code outside of services.
210 setvbuf(stderr, NULL, _IONBF, 0);
211 _commit(2 /* stderr */);
212 fd = _open_osfhandle((long) hPipeWrite,
213 _O_WRONLY | _O_BINARY);
216 _setmode(2, _O_BINARY);
218 /* hPipeWrite was _close()'ed above, and _dup2()'ed
219 * to fd 2 creating a new, inherited Win32 handle.
220 * Recover that real handle from fd 2.
222 hPipeWrite = (HANDLE)_get_osfhandle(2);
224 SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
226 /* The code above _will_ corrupt the StdHandle...
227 * and we must do so anyways. We set this up only
228 * after we initialized the posix stderr API.
230 ap_open_stderr_log(p);