]> granicus.if.org Git - apache/blob - server/mpm/winnt/nt_eventlog.c
No functional Change: Removing trailing whitespace. This also
[apache] / server / mpm / winnt / nt_eventlog.c
1 /* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #define CORE_PRIVATE
18
19 #include "httpd.h"
20 #include "http_log.h"
21 #include "mpm_winnt.h"
22 #include "apr_strings.h"
23 #include "apr_lib.h"
24 #include "ap_regkey.h"
25
26 static char  *display_name  = NULL;
27 static HANDLE stderr_thread = NULL;
28 static HANDLE stderr_ready;
29
30 static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
31 {
32     HANDLE hPipeRead = (HANDLE) hPipe;
33     HANDLE hEventSource;
34     char errbuf[256];
35     char *errmsg = errbuf;
36     const char *errarg[9];
37     DWORD errres;
38     ap_regkey_t *regkey;
39     apr_status_t rv;
40     apr_pool_t *p;
41
42     apr_pool_create_ex(&p, NULL, NULL, NULL);
43
44     errarg[0] = "The Apache service named";
45     errarg[1] = display_name;
46     errarg[2] = "reported the following error:\r\n>>>";
47     errarg[3] = errbuf;
48     errarg[4] = NULL;
49     errarg[5] = NULL;
50     errarg[6] = NULL;
51     errarg[7] = NULL;
52     errarg[8] = NULL;
53
54     /* What are we going to do in here, bail on the user?  not. */
55     if ((rv = ap_regkey_open(&regkey, AP_REGKEY_LOCAL_MACHINE,
56                              "SYSTEM\\CurrentControlSet\\Services\\"
57                              "EventLog\\Application\\Apache Service",
58                              APR_READ | APR_WRITE | APR_CREATE, p))
59             == APR_SUCCESS)
60     {
61         DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
62                        EVENTLOG_INFORMATION_TYPE;
63
64         /* The stock message file */
65         ap_regkey_value_set(regkey, "EventMessageFile",
66                             "%SystemRoot%\\System32\\netmsg.dll",
67                             AP_REGKEY_EXPAND, p);
68
69         ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData,
70                                 sizeof(dwData), REG_DWORD, p);
71         ap_regkey_close(regkey);
72     }
73
74     hEventSource = RegisterEventSourceW(NULL, L"Apache Service");
75
76     SetEvent(stderr_ready);
77
78     while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
79     {
80         if ((errmsg > errbuf) || !apr_isspace(*errmsg))
81         {
82             ++errmsg;
83             if ((*(errmsg - 1) == '\n')
84                     || (errmsg >= errbuf + sizeof(errbuf) - 1))
85             {
86                 while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) {
87                     --errmsg;
88                 }
89                 *errmsg = '\0';
90
91                 /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
92                  * The event code in netmsg.dll is 3299
93                  */
94                 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
95                             3299, NULL, 9, 0, errarg, NULL);
96                 errmsg = errbuf;
97             }
98         }
99     }
100
101     if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
102         apr_snprintf(errbuf, sizeof(errbuf),
103                      "Win32 error %d reading stderr pipe stream\r\n",
104                      GetLastError());
105
106         ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
107                     3299, NULL, 9, 0, errarg, NULL);
108     }
109
110     CloseHandle(hPipeRead);
111     DeregisterEventSource(hEventSource);
112     CloseHandle(stderr_thread);
113     stderr_thread = NULL;
114     apr_pool_destroy(p);
115     return 0;
116 }
117
118
119 void mpm_nt_eventlog_stderr_flush(void)
120 {
121     HANDLE cleanup_thread = stderr_thread;
122
123     if (cleanup_thread) {
124         HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
125         fclose(stderr);
126         CloseHandle(hErr);
127         WaitForSingleObject(cleanup_thread, 30000);
128         CloseHandle(cleanup_thread);
129     }
130 }
131
132
133 void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
134 {
135     SECURITY_ATTRIBUTES sa;
136     HANDLE hProc = GetCurrentProcess();
137     HANDLE hPipeRead = NULL;
138     HANDLE hPipeWrite = NULL;
139     HANDLE hDup = NULL;
140     DWORD  threadid;
141     int    fd;
142
143     display_name = argv0;
144
145     /* Create a pipe to send stderr messages to the system error log.
146      *
147      * _dup2() duplicates the write handle inheritable for us.
148      */
149     sa.nLength = sizeof(sa);
150     sa.lpSecurityDescriptor = NULL;
151     sa.bInheritHandle = FALSE;
152     CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0);
153     ap_assert(hPipeRead && hPipeWrite);
154
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);
159
160     WaitForSingleObject(stderr_ready, INFINITE);
161
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.
166      */
167     fflush(stderr);
168     setvbuf(stderr, NULL, _IONBF, 0);
169     _commit(2 /* stderr */);
170     fd = _open_osfhandle((long) hPipeWrite,
171                          _O_WRONLY | _O_BINARY);
172     _dup2(fd, 2);
173     _close(fd);
174     _setmode(2, _O_BINARY);
175
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.
179      */
180     hPipeWrite = (HANDLE)_get_osfhandle(2);
181
182     SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
183
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.
187      */
188     ap_open_stderr_log(p);
189 }