| /* ==================================================================== |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2000-2002 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Apache" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * Portions of this software are based upon public domain software |
| * originally written at the National Center for Supercomputing Applications, |
| * University of Illinois, Urbana-Champaign. |
| */ |
| |
| #define CORE_PRIVATE |
| |
| #include "httpd.h" |
| #include "http_log.h" |
| #include "mpm_winnt.h" |
| #include "apr_strings.h" |
| #include "apr_lib.h" |
| |
| #include "apr_dbg_win32_handles.h" |
| |
| |
| static 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; |
| HKEY hk; |
| |
| 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 (!RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services" |
| "\\EventLog\\Application\\Apache Service", &hk)) |
| { |
| /* The stock message file */ |
| char *netmsgkey = "%SystemRoot%\\System32\\netmsg.dll"; |
| DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | |
| EVENTLOG_INFORMATION_TYPE; |
| |
| RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ, |
| (LPBYTE) netmsgkey, strlen(netmsgkey) + 1); |
| |
| RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD, |
| (LPBYTE) &dwData, sizeof(dwData)); |
| RegCloseKey(hk); |
| } |
| |
| hEventSource = RegisterEventSource(NULL, "Apache Service"); |
| |
| SetEvent(stderr_ready); |
| |
| while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1)) |
| { |
| if ((errmsg > errbuf) || !isspace(*errmsg)) |
| { |
| ++errmsg; |
| if ((*(errmsg - 1) == '\n') |
| || (errmsg >= errbuf + sizeof(errbuf) - 1)) |
| { |
| while ((errmsg > errbuf) && 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 %d 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; |
| 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(char *argv0, apr_pool_t *p) |
| { |
| SECURITY_ATTRIBUTES sa; |
| HANDLE hProc = GetCurrentProcess(); |
| HANDLE hPipeRead = NULL; |
| HANDLE hPipeWrite = NULL; |
| HANDLE hDup = NULL; |
| DWORD threadid; |
| int fd; |
| |
| 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, 0, service_stderr_thread, |
| (LPVOID) hPipeRead, 0, &threadid); |
| ap_assert(stderr_ready && stderr_thread); |
| |
| WaitForSingleObject(stderr_ready, INFINITE); |
| |
| /* Flush stderr and unset its buffer, then commit and replace stderr. |
| * This is typically a noop for Win2K/XP since services with NULL std |
| * handles [but valid FILE *'s, oddly enough], but is required |
| * for NT 4.0 and to use this code outside of services. |
| */ |
| fflush(stderr); |
| setvbuf(stderr, NULL, _IONBF, 0); |
| _commit(2 /* stderr */); |
| fd = _open_osfhandle((long) hPipeWrite, |
| _O_WRONLY | _O_BINARY); |
| _dup2(fd, 2); |
| _close(fd); |
| _setmode(2, _O_BINARY); |
| |
| /* hPipeWrite was _close()'ed above, and _dup2()'ed |
| * to fd 2 creating a new, inherited Win32 handle. |
| * Recover that real handle from fd 2. |
| */ |
| hPipeWrite = (HANDLE)_get_osfhandle(2); |
| |
| SetStdHandle(STD_ERROR_HANDLE, hPipeWrite); |
| |
| /* 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); |
| } |