windows-eventlog-20051219
[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             // Set the name of the message file
103             // Get "ImagePath" from TransarcAFSDaemon service
104             memset(szBuf, '\0', MAX_PATH);
105             dwData = MAX_PATH;
106             GetServicePath(szBuf, &dwData);
107
108             // Add the name to the EventMessageFile subkey. 
109             if ( RegSetValueEx( hKey,                   // subkey handle 
110                                 AFSREG_APPLOG_MSGFILE_VALUE,    // value name 
111                                 0,                      // must be zero 
112                                 REG_EXPAND_SZ,          // value type 
113                                 (LPBYTE) szBuf,         // pointer to value data 
114                                 (DWORD)strlen(szBuf) + 1))      // length of value data
115             {   
116                 bRet = FALSE;
117                 break;
118             }
119
120             // Set the supported event types in the TypesSupported subkey. 
121             dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
122                 EVENTLOG_INFORMATION_TYPE; 
123
124             if ( RegSetValueEx( hKey,                   // subkey handle 
125                                 AFSREG_APPLOG_MSGTYPE_VALUE,    // value name 
126                                 0,                      // must be zero 
127                                 REG_DWORD,              // value type 
128                                 (LPBYTE) &dwData,       // pointer to value data 
129                                 sizeof(DWORD)))         // length of value data
130             {   
131                 bRet = FALSE;
132                 break;
133             }
134         }
135         else
136         {
137             // key was opened - read it
138             memset(szBuf, '\0', MAX_PATH);
139             dwData = MAX_PATH;
140             if ( RegQueryValueEx( hKey,                 // handle to key
141                                   AFSREG_APPLOG_MSGFILE_VALUE,  // value name
142                                   NULL,                 // reserved
143                                   NULL,                 // type buffer
144                                   (LPBYTE) szBuf,               // data buffer
145                                   &dwData))             // size of data buffer
146             {   
147                 bRet = FALSE;
148                 break;
149             }
150         }
151     } while (0);
152                                 
153     if (hKey != NULL)
154         RegCloseKey(hKey); 
155
156     if (hLogKey != NULL)
157         RegCloseKey(hLogKey); 
158
159     return bRet;
160 }       
161
162 // Log an event with a formatted system message as the (only) substitution
163 // string, from the given message ID.
164 VOID
165 LogEventMessage(WORD wEventType, DWORD dwEventID, DWORD dwMessageID)
166 {
167     LPTSTR msgBuf;
168
169     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
170                    NULL, dwMessageID, 0, (LPTSTR)&msgBuf, 0, NULL);
171     LogEvent(wEventType, dwEventID, msgBuf, NULL);
172     LocalFree(msgBuf);
173 }
174
175 //
176 // Use the ReportEvent API to write an entry to the system event log.
177 //
178 #define MAXARGS 8
179 #define STRLEN  64
180 VOID
181 LogEvent(WORD wEventType, DWORD dwEventID, ...)
182 {
183     va_list     listArgs;
184     HANDLE      hEventSource;
185     LPTSTR      lpArgs[MAXARGS];
186     CHAR        lpStrings[MAXARGS][STRLEN];
187     WORD        wNumArgs = 0;
188     WORD        wNumStrings = 0;
189         DWORD   code;
190
191     // Ensure that our event source is properly initialized.
192     if (!AddEventSource())
193         return;
194
195     // Get a handle to the event log.
196     hEventSource = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
197     if (hEventSource == NULL)
198         return;
199
200     // Construct the array of substitution strings.
201     va_start(listArgs, dwEventID);
202
203     switch ( dwEventID ) {
204     case MSG_FLUSH_NO_SHARE_NAME:
205     case MSG_FLUSH_NO_MEMORY:
206     case MSG_FLUSH_IMPERSONATE_ERROR:
207     case MSG_FLUSH_UNEXPECTED_EVENT:
208     case MSG_UNHANDLED_EXCEPTION:
209     case MSG_SMB_ZERO_TRANSACTION_COUNT:
210     case MSG_SERVICE_START_PENDING:
211     case MSG_SERVICE_INCORRECT_VERSIONS:
212     case MSG_SERVICE_RUNNING:
213     case MSG_SERVICE_STOPPING:
214     case MSG_SERVICE_ERROR_STOP:
215         break;
216     case MSG_FLUSH_BAD_SHARE_NAME:
217     case MSG_FLUSH_OPEN_ENUM_ERROR:
218     case MSG_FLUSH_ENUM_ERROR:
219     case MSG_FLUSH_FAILED:
220     case MSG_RX_HARD_DEAD_TIME_EXCEEDED:
221     case MSG_SERVICE_ERROR_STOP_WITH_MSG:
222         wNumArgs = 1;
223         lpArgs[0] = va_arg(listArgs, LPTSTR);
224         break;
225     case MSG_TIME_FLUSH_PER_VOLUME:
226     case MSG_TIME_FLUSH_TOTAL:
227         wNumArgs = 2;
228         lpArgs[0] = va_arg(listArgs, LPTSTR);
229         lpArgs[1] = va_arg(listArgs, LPTSTR);
230         break;
231     case MSG_SERVER_REPORTS_VNOVOL:
232     case MSG_SERVER_REPORTS_VMOVED:
233     case MSG_SERVER_REPORTS_VOFFLINE:
234     case MSG_SERVER_REPORTS_VSALVAGE:
235     case MSG_SERVER_REPORTS_VNOSERVICE:
236     case MSG_SERVER_REPORTS_VIO:
237         wNumArgs = 2;
238         lpArgs[0] = va_arg(listArgs, LPTSTR);
239         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,afs_int32));
240         lpArgs[1] = lpStrings[1];
241         break;
242     case MSG_BAD_SMB_PARAM:
243         wNumArgs = 5;
244         lpArgs[0] = va_arg(listArgs, LPTSTR);
245         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
246         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,int));
247         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,int));
248         StringCbPrintf(lpStrings[4],STRLEN,"%d",va_arg(listArgs,WORD));
249         lpArgs[1] = lpStrings[1];
250         lpArgs[2] = lpStrings[2];
251         lpArgs[3] = lpStrings[3];
252         lpArgs[4] = lpStrings[4];
253         break;
254     case MSG_BAD_SMB_PARAM_WITH_OFFSET:
255         wNumArgs = 6;
256         lpArgs[0] = va_arg(listArgs, LPTSTR);
257         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
258         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,int));
259         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,int));
260         StringCbPrintf(lpStrings[4],STRLEN,"%d",va_arg(listArgs,int));
261         StringCbPrintf(lpStrings[5],STRLEN,"%d",va_arg(listArgs,WORD));
262         lpArgs[1] = lpStrings[1];
263         lpArgs[2] = lpStrings[2];
264         lpArgs[3] = lpStrings[3];
265         lpArgs[4] = lpStrings[4];
266         lpArgs[5] = lpStrings[5];
267         break;
268     case MSG_BAD_SMB_TOO_SHORT:
269     case MSG_BAD_SMB_INVALID:
270     case MSG_BAD_SMB_INCOMPLETE:
271         wNumArgs = 1;
272         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,WORD));
273         lpArgs[0] = lpStrings[0];
274         break;
275     case MSG_SMB_SESSION_START:
276         wNumArgs = 1;
277         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,long));
278         lpArgs[0] = lpStrings[0];
279         break;
280     case MSG_BAD_SMB_WRONG_SESSION:
281         wNumArgs = 2;
282         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,DWORD));
283         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,WORD));
284         lpArgs[0] = lpStrings[0];
285         lpArgs[1] = lpStrings[1];
286         break;
287     case MSG_BAD_VCP:
288         wNumArgs = 4;
289         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,UCHAR));
290         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,UCHAR));
291         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,UCHAR));
292         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,UCHAR));
293         lpArgs[0] = lpStrings[0];
294         lpArgs[1] = lpStrings[1];
295         lpArgs[2] = lpStrings[2];
296         lpArgs[3] = lpStrings[3];
297         break;
298     case MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION:
299         wNumArgs = 3;
300         lpArgs[0] = va_arg(listArgs, LPTSTR);
301         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
302         lpArgs[1] = lpStrings[1];
303         lpArgs[2] = va_arg(listArgs,LPTSTR);
304         break;
305     }
306     va_end(listArgs);
307
308     // Make sure we were not given too many args.
309     if (wNumArgs >= MAXARGS)
310         return;
311
312     // Log the event.
313     code = ReportEvent(hEventSource,            // handle of event source
314                  wEventType,            // event type
315                  0,                     // event category
316                  dwEventID,             // event ID
317                  NULL,                  // current user's SID
318                  wNumArgs,              // strings in lpszArgs
319                  0,                     // no bytes of raw data
320                  wNumArgs ? lpArgs : NULL,              // array of error strings
321                  NULL);                 // no raw data
322
323
324     DeregisterEventSource(hEventSource);
325 }       
326
327