upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / server / mpm / winnt / nt_eventlog.c
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
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 "apr_portable.h"
25 #include "ap_regkey.h"
26
27 static char  *display_name  = NULL;
28 static HANDLE stderr_thread = NULL;
29 static HANDLE stderr_ready;
30
31 static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
32 {
33     HANDLE hPipeRead = (HANDLE) hPipe;
34     HANDLE hEventSource;
35     char errbuf[256];
36     char *errmsg = errbuf;
37     const char *errarg[9];
38     DWORD errres;
39     ap_regkey_t *regkey;
40     apr_status_t rv;
41     apr_pool_t *p;
42     
43     apr_pool_sub_make(&p, NULL, NULL);
44
45     errarg[0] = "The Apache service named";
46     errarg[1] = display_name;
47     errarg[2] = "reported the following error:\r\n>>>";
48     errarg[3] = errbuf;
49     errarg[4] = NULL;
50     errarg[5] = NULL;
51     errarg[6] = NULL;
52     errarg[7] = NULL;
53     errarg[8] = NULL;
54
55     /* What are we going to do in here, bail on the user?  not. */
56     if ((rv = ap_regkey_open(&regkey, AP_REGKEY_LOCAL_MACHINE, 
57                              "SYSTEM\\CurrentControlSet\\Services\\"
58                              "EventLog\\Application\\Apache Service",
59                              APR_READ | APR_WRITE | APR_CREATE, p)) 
60             == APR_SUCCESS)
61     {
62         DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
63                        EVENTLOG_INFORMATION_TYPE; 
64  
65         /* The stock message file */
66         ap_regkey_value_set(regkey, "EventMessageFile", 
67                             "%SystemRoot%\\System32\\netmsg.dll", 
68                             AP_REGKEY_EXPAND, p);
69         
70         ap_regkey_value_raw_set(regkey, "TypesSupported", &dwData, 
71                                 sizeof(dwData), REG_DWORD, p);
72         ap_regkey_close(regkey);
73     }
74
75     hEventSource = RegisterEventSourceW(NULL, L"Apache Service");
76
77     SetEvent(stderr_ready);
78
79     while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
80     {
81         if ((errmsg > errbuf) || !apr_isspace(*errmsg))
82         {
83             ++errmsg;
84             if ((*(errmsg - 1) == '\n') 
85                     || (errmsg >= errbuf + sizeof(errbuf) - 1))
86             {
87                 while ((errmsg > errbuf) && apr_isspace(*(errmsg - 1))) {
88                     --errmsg;
89                 }
90                 *errmsg = '\0';
91
92                 /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
93                  * The event code in netmsg.dll is 3299
94                  */
95                 ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, 
96                             3299, NULL, 9, 0, errarg, NULL);
97                 errmsg = errbuf;
98             }
99         }
100     }
101
102     if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
103         apr_snprintf(errbuf, sizeof(errbuf),
104                      "Win32 error %d reading stderr pipe stream\r\n", 
105                      GetLastError());
106
107         ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, 
108                     3299, NULL, 9, 0, errarg, NULL);
109     }
110
111     CloseHandle(hPipeRead);
112     DeregisterEventSource(hEventSource);
113     CloseHandle(stderr_thread);
114     stderr_thread = NULL;
115     apr_pool_destroy(p);
116     return 0;
117 }
118
119
120 void mpm_nt_eventlog_stderr_flush(void)
121 {
122     HANDLE cleanup_thread = stderr_thread;
123
124     if (cleanup_thread) {
125         HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
126         fclose(stderr);
127         CloseHandle(hErr);
128         WaitForSingleObject(cleanup_thread, 30000);
129         CloseHandle(cleanup_thread);
130     }
131 }
132
133
134 void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
135 {
136     SECURITY_ATTRIBUTES sa;
137     HANDLE hProc = GetCurrentProcess();
138     HANDLE hPipeRead = NULL;
139     HANDLE hPipeWrite = NULL;
140     HANDLE hDup = NULL;
141     DWORD  threadid;
142     apr_file_t *eventlog_file;
143     apr_file_t *stderr_file;
144
145     display_name = argv0;
146
147     /* Create a pipe to send stderr messages to the system error log.
148      *
149      * _dup2() duplicates the write handle inheritable for us.
150      */
151     sa.nLength = sizeof(sa);
152     sa.lpSecurityDescriptor = NULL;
153     sa.bInheritHandle = FALSE;
154     CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0); 
155     ap_assert(hPipeRead && hPipeWrite);
156
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);
161
162     WaitForSingleObject(stderr_ready, INFINITE);
163
164     if ((apr_file_open_stderr(&stderr_file, p) 
165              == APR_SUCCESS)
166      && (apr_os_file_put(&eventlog_file, &hPipeWrite, APR_WRITE, p)
167              == APR_SUCCESS))
168         apr_file_dup2(stderr_file, eventlog_file, p);
169
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.
173      */
174     ap_open_stderr_log(p);
175 }