windows-eventlog-20080301
[openafs.git] / src / WINNT / afsd / afsd_eventlog.c
1 ////////////////////////////////////////////////////////////////////
2 //
3 //
4 //              E V E N T   L O G G I N G   F U N C T I O N S 
5 //
6 //
7 ////////////////////////////////////////////////////////////////////
8
9
10 #include <windows.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <strsafe.h>
14 #include <WINNT/afsreg.h>
15 #include "afsd.h"
16 #include "afsd_eventlog.h"
17
18 static BOOL     GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize);
19 static BOOL     AddEventSource(void);
20
21 static BOOL
22 GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize)
23 {
24     HKEY        hKey = NULL; 
25     DWORD       dwData = 0;
26     BOOL        bRet = TRUE;
27
28     do {
29         // Open key
30         if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_SUBKEY, 0, KEY_QUERY_VALUE, &hKey ) )
31         {               
32             bRet = FALSE;
33             break;
34         }
35
36         // prepare user's buffer and read into it
37         dwData = *pdwPathBufSize;
38         memset(lpPathBuf, '\0', dwData);
39         if ( RegQueryValueEx( hKey,                     // handle to key
40                               "ImagePath",              // value name
41                               NULL,                     // reserved
42                               NULL,                     // type buffer
43                               (LPBYTE) lpPathBuf,       // data buffer
44                               &dwData))         // size of data buffer
45         {       
46             bRet = FALSE;
47             break;
48         }
49                 
50         *pdwPathBufSize = dwData;
51
52     } while (0);
53                                 
54     if (hKey != NULL)
55         RegCloseKey(hKey); 
56
57     return bRet;
58
59
60 //
61 // Ensure name for message file is in proper location in Registry.
62 //
63 static BOOL
64 AddEventSource()
65 {
66     HKEY        hKey = NULL, hLogKey; 
67     UCHAR       szBuf[MAX_PATH]; 
68     DWORD       dwData, dwDisposition; 
69     BOOL        bRet = TRUE;
70
71     do {
72         if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
73                            KEY_QUERY_VALUE, &hLogKey ) )
74         {                       
75             // nope - create it         
76             if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
77                                  NULL, REG_OPTION_NON_VOLATILE,
78                                  KEY_ALL_ACCESS, NULL, &hLogKey,
79                                  &dwDisposition)) 
80             {   
81                 bRet = FALSE;
82                 break;
83             }
84         }
85
86         // Let's see if key already exists as a subkey under the 
87         // Application key in the EventLog registry key.  If not,
88         // create it.
89         if ( RegOpenKeyEx( hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
90                            KEY_QUERY_VALUE, &hKey ) )
91         {                       
92             // nope - create it         
93             if ( RegCreateKeyEx(hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
94                                  NULL, REG_OPTION_NON_VOLATILE,
95                                  KEY_ALL_ACCESS, NULL, &hKey,
96                                  &dwDisposition)) 
97             {   
98                 bRet = FALSE;
99                 break;
100             }
101
102 #if 0
103             // Set the name of the message file
104             // Get "ImagePath" from TransarcAFSDaemon service
105             memset(szBuf, '\0', MAX_PATH);
106             dwData = MAX_PATH;
107             GetServicePath(szBuf, &dwData);
108 #else
109             // Windows takes the specified name and searchs the PATH environment variable
110             // It never appears to even try the fully qualified name.
111             strcpy(szBuf, "afsd_service.exe");
112 #endif
113             // Add the name to the EventMessageFile subkey. 
114             if ( RegSetValueEx( hKey,                   // subkey handle 
115                                 AFSREG_APPLOG_MSGFILE_VALUE,    // value name 
116                                 0,                      // must be zero 
117                                 REG_SZ,                 // value type 
118                                 (LPBYTE) szBuf,         // pointer to value data 
119                                 (DWORD)strlen(szBuf) + 1))      // length of value data
120             {   
121                 bRet = FALSE;
122                 break;
123             }
124
125             // Set the supported event types in the TypesSupported subkey. 
126             dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
127                 EVENTLOG_INFORMATION_TYPE; 
128
129             if ( RegSetValueEx( hKey,                   // subkey handle 
130                                 AFSREG_APPLOG_MSGTYPE_VALUE,    // value name 
131                                 0,                      // must be zero 
132                                 REG_DWORD,              // value type 
133                                 (LPBYTE) &dwData,       // pointer to value data 
134                                 sizeof(DWORD)))         // length of value data
135             {   
136                 bRet = FALSE;
137                 break;
138             }
139         }
140         else
141         {
142             // key was opened - read it
143             memset(szBuf, '\0', MAX_PATH);
144             dwData = MAX_PATH;
145             if ( RegQueryValueEx( hKey,                 // handle to key
146                                   AFSREG_APPLOG_MSGFILE_VALUE,  // value name
147                                   NULL,                 // reserved
148                                   NULL,                 // type buffer
149                                   (LPBYTE) szBuf,               // data buffer
150                                   &dwData))             // size of data buffer
151             {   
152                 bRet = FALSE;
153                 break;
154             }
155         }
156     } while (0);
157                                 
158     if (hKey != NULL)
159         RegCloseKey(hKey); 
160
161     if (hLogKey != NULL)
162         RegCloseKey(hLogKey); 
163
164     return bRet;
165 }       
166
167 // Log an event with a formatted system message as the (only) substitution
168 // string, from the given message ID.
169 VOID
170 LogEventMessage(WORD wEventType, DWORD dwEventID, DWORD dwMessageID)
171 {
172     LPTSTR msgBuf;
173
174     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
175                    NULL, dwMessageID, 0, (LPTSTR)&msgBuf, 0, NULL);
176     LogEvent(wEventType, dwEventID, msgBuf, NULL);
177     LocalFree(msgBuf);
178 }
179
180 //
181 // Use the ReportEvent API to write an entry to the system event log.
182 //
183 #define MAXARGS 8
184 #define STRLEN  64
185 VOID
186 LogEvent(WORD wEventType, DWORD dwEventID, ...)
187 {
188     va_list     listArgs;
189     HANDLE      hEventSource;
190     LPTSTR      lpArgs[MAXARGS];
191     CHAR        lpStrings[MAXARGS][STRLEN];
192     WORD        wNumArgs = 0;
193     WORD        wNumStrings = 0;
194         DWORD   code;
195
196     // Ensure that our event source is properly initialized.
197     if (!AddEventSource())
198         return;
199
200     // Get a handle to the event log.
201     hEventSource = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
202     if (hEventSource == NULL)
203         return;
204
205     // Construct the array of substitution strings.
206     va_start(listArgs, dwEventID);
207
208     switch ( dwEventID ) {
209     case MSG_FLUSH_NO_SHARE_NAME:
210     case MSG_FLUSH_NO_MEMORY:
211     case MSG_FLUSH_IMPERSONATE_ERROR:
212     case MSG_FLUSH_UNEXPECTED_EVENT:
213     case MSG_UNHANDLED_EXCEPTION:
214     case MSG_SMB_ZERO_TRANSACTION_COUNT:
215     case MSG_SERVICE_START_PENDING:
216     case MSG_SERVICE_INCORRECT_VERSIONS:
217     case MSG_SERVICE_RUNNING:
218     case MSG_SERVICE_STOPPING:
219     case MSG_SERVICE_ERROR_STOP:
220     case MSG_CRYPT_OFF:
221     case MSG_CRYPT_ON:
222         break;
223     case MSG_FLUSH_BAD_SHARE_NAME:
224     case MSG_FLUSH_OPEN_ENUM_ERROR:
225     case MSG_FLUSH_ENUM_ERROR:
226     case MSG_FLUSH_FAILED:
227     case MSG_RX_HARD_DEAD_TIME_EXCEEDED:
228     case MSG_SERVICE_ERROR_STOP_WITH_MSG:
229     case MSG_SMB_SEND_PACKET_FAILURE:
230     case MSG_UNEXPECTED_SMB_SESSION_CLOSE:
231         wNumArgs = 1;
232         lpArgs[0] = va_arg(listArgs, LPTSTR);
233         break;
234     case MSG_TIME_FLUSH_PER_VOLUME:
235     case MSG_TIME_FLUSH_TOTAL:
236         wNumArgs = 2;
237         lpArgs[0] = va_arg(listArgs, LPTSTR);
238         lpArgs[1] = va_arg(listArgs, LPTSTR);
239         break;
240     case MSG_SERVER_REPORTS_VNOVOL:
241     case MSG_SERVER_REPORTS_VMOVED:
242     case MSG_SERVER_REPORTS_VOFFLINE:
243     case MSG_SERVER_REPORTS_VSALVAGE:
244     case MSG_SERVER_REPORTS_VNOSERVICE:
245     case MSG_SERVER_REPORTS_VIO:
246         wNumArgs = 2;
247         lpArgs[0] = va_arg(listArgs, LPTSTR);
248         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,afs_int32));
249         lpArgs[1] = lpStrings[1];
250         break;
251     case MSG_BAD_SMB_PARAM:
252         wNumArgs = 5;
253         lpArgs[0] = va_arg(listArgs, LPTSTR);
254         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
255         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,int));
256         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,int));
257         StringCbPrintf(lpStrings[4],STRLEN,"%d",va_arg(listArgs,WORD));
258         lpArgs[1] = lpStrings[1];
259         lpArgs[2] = lpStrings[2];
260         lpArgs[3] = lpStrings[3];
261         lpArgs[4] = lpStrings[4];
262         break;
263     case MSG_BAD_SMB_PARAM_WITH_OFFSET:
264         wNumArgs = 6;
265         lpArgs[0] = va_arg(listArgs, LPTSTR);
266         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
267         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,int));
268         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,int));
269         StringCbPrintf(lpStrings[4],STRLEN,"%d",va_arg(listArgs,int));
270         StringCbPrintf(lpStrings[5],STRLEN,"%d",va_arg(listArgs,WORD));
271         lpArgs[1] = lpStrings[1];
272         lpArgs[2] = lpStrings[2];
273         lpArgs[3] = lpStrings[3];
274         lpArgs[4] = lpStrings[4];
275         lpArgs[5] = lpStrings[5];
276         break;
277     case MSG_BAD_SMB_TOO_SHORT:
278     case MSG_BAD_SMB_INVALID:
279     case MSG_BAD_SMB_INCOMPLETE:
280         wNumArgs = 1;
281         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,WORD));
282         lpArgs[0] = lpStrings[0];
283         break;
284     case MSG_SMB_SESSION_START:
285         wNumArgs = 1;
286         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,long));
287         lpArgs[0] = lpStrings[0];
288         break;
289     case MSG_BAD_SMB_WRONG_SESSION:
290         wNumArgs = 2;
291         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,DWORD));
292         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,WORD));
293         lpArgs[0] = lpStrings[0];
294         lpArgs[1] = lpStrings[1];
295         break;
296     case MSG_BAD_VCP:
297         wNumArgs = 4;
298         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,UCHAR));
299         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,UCHAR));
300         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,UCHAR));
301         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,UCHAR));
302         lpArgs[0] = lpStrings[0];
303         lpArgs[1] = lpStrings[1];
304         lpArgs[2] = lpStrings[2];
305         lpArgs[3] = lpStrings[3];
306         break;
307     case MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION:
308         wNumArgs = 3;
309         lpArgs[0] = va_arg(listArgs, LPTSTR);
310         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
311         lpArgs[1] = lpStrings[1];
312         lpArgs[2] = va_arg(listArgs,LPTSTR);
313         break;
314     }
315     va_end(listArgs);
316
317     // Make sure we were not given too many args.
318     if (wNumArgs >= MAXARGS)
319         return;
320
321     // Log the event.
322     code = ReportEvent(hEventSource,            // handle of event source
323                  wEventType,            // event type
324                  0,                     // event category
325                  dwEventID,             // event ID
326                  NULL,                  // current user's SID
327                  wNumArgs,              // strings in lpszArgs
328                  0,                     // no bytes of raw data
329                  wNumArgs ? lpArgs : NULL,              // array of error strings
330                  NULL);                 // no raw data
331
332
333     DeregisterEventSource(hEventSource);
334 }       
335
336