windows-eventlog2-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     if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
72                        KEY_QUERY_VALUE, &hLogKey ) )
73     {                           
74         // nope - create it             
75         if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
76                              NULL, REG_OPTION_NON_VOLATILE,
77                              KEY_ALL_ACCESS, NULL, &hLogKey,
78                              &dwDisposition)) 
79         {       
80             bRet = FALSE;
81             goto done;
82         }
83     }
84
85     // Let's see if key already exists as a subkey under the 
86     // Application key in the EventLog registry key.  If not,
87     // create it.
88     if ( RegOpenKeyEx( hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
89                        KEY_QUERY_VALUE, &hKey ) )
90     {                           
91         // nope - create it             
92         if ( RegCreateKeyEx(hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
93                              NULL, REG_OPTION_NON_VOLATILE,
94                              KEY_ALL_ACCESS, NULL, &hKey,
95                              &dwDisposition)) 
96         {               
97             bRet = FALSE;
98             goto done;
99         }
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         goto done;
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         goto done;
138     }
139             
140   done:
141     if (hKey != NULL)
142         RegCloseKey(hKey); 
143
144     if (hLogKey != NULL)
145         RegCloseKey(hLogKey); 
146
147     return bRet;
148 }       
149
150 // Log an event with a formatted system message as the (only) substitution
151 // string, from the given message ID.
152 VOID
153 LogEventMessage(WORD wEventType, DWORD dwEventID, DWORD dwMessageID)
154 {
155     LPTSTR msgBuf;
156
157     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
158                    NULL, dwMessageID, 0, (LPTSTR)&msgBuf, 0, NULL);
159     LogEvent(wEventType, dwEventID, msgBuf, NULL);
160     LocalFree(msgBuf);
161 }
162
163 //
164 // Use the ReportEvent API to write an entry to the system event log.
165 //
166 #define MAXARGS 8
167 #define STRLEN  64
168 VOID
169 LogEvent(WORD wEventType, DWORD dwEventID, ...)
170 {
171     va_list     listArgs;
172     HANDLE      hEventSource;
173     LPTSTR      lpArgs[MAXARGS];
174     CHAR        lpStrings[MAXARGS][STRLEN];
175     WORD        wNumArgs = 0;
176     WORD        wNumStrings = 0;
177         DWORD   code;
178
179     // Ensure that our event source is properly initialized.
180     if (!AddEventSource())
181         return;
182
183     // Get a handle to the event log.
184     hEventSource = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
185     if (hEventSource == NULL)
186         return;
187
188     // Construct the array of substitution strings.
189     va_start(listArgs, dwEventID);
190
191     switch ( dwEventID ) {
192     case MSG_FLUSH_NO_SHARE_NAME:
193     case MSG_FLUSH_NO_MEMORY:
194     case MSG_FLUSH_IMPERSONATE_ERROR:
195     case MSG_FLUSH_UNEXPECTED_EVENT:
196     case MSG_UNHANDLED_EXCEPTION:
197     case MSG_SMB_ZERO_TRANSACTION_COUNT:
198     case MSG_SERVICE_START_PENDING:
199     case MSG_SERVICE_INCORRECT_VERSIONS:
200     case MSG_SERVICE_RUNNING:
201     case MSG_SERVICE_STOPPING:
202     case MSG_SERVICE_ERROR_STOP:
203     case MSG_CRYPT_OFF:
204     case MSG_CRYPT_ON:
205         break;
206     case MSG_FLUSH_BAD_SHARE_NAME:
207     case MSG_FLUSH_OPEN_ENUM_ERROR:
208     case MSG_FLUSH_ENUM_ERROR:
209     case MSG_FLUSH_FAILED:
210     case MSG_RX_HARD_DEAD_TIME_EXCEEDED:
211     case MSG_SERVICE_ERROR_STOP_WITH_MSG:
212     case MSG_SMB_SEND_PACKET_FAILURE:
213     case MSG_UNEXPECTED_SMB_SESSION_CLOSE:
214         wNumArgs = 1;
215         lpArgs[0] = va_arg(listArgs, LPTSTR);
216         break;
217     case MSG_TIME_FLUSH_PER_VOLUME:
218     case MSG_TIME_FLUSH_TOTAL:
219         wNumArgs = 2;
220         lpArgs[0] = va_arg(listArgs, LPTSTR);
221         lpArgs[1] = va_arg(listArgs, LPTSTR);
222         break;
223     case MSG_SERVER_REPORTS_VNOVOL:
224     case MSG_SERVER_REPORTS_VMOVED:
225     case MSG_SERVER_REPORTS_VOFFLINE:
226     case MSG_SERVER_REPORTS_VSALVAGE:
227     case MSG_SERVER_REPORTS_VNOSERVICE:
228     case MSG_SERVER_REPORTS_VIO:
229         wNumArgs = 2;
230         lpArgs[0] = va_arg(listArgs, LPTSTR);
231         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,afs_int32));
232         lpArgs[1] = lpStrings[1];
233         break;
234     case MSG_BAD_SMB_PARAM:
235         wNumArgs = 5;
236         lpArgs[0] = va_arg(listArgs, LPTSTR);
237         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
238         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,int));
239         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,int));
240         StringCbPrintf(lpStrings[4],STRLEN,"%d",va_arg(listArgs,WORD));
241         lpArgs[1] = lpStrings[1];
242         lpArgs[2] = lpStrings[2];
243         lpArgs[3] = lpStrings[3];
244         lpArgs[4] = lpStrings[4];
245         break;
246     case MSG_BAD_SMB_PARAM_WITH_OFFSET:
247         wNumArgs = 6;
248         lpArgs[0] = va_arg(listArgs, LPTSTR);
249         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
250         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,int));
251         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,int));
252         StringCbPrintf(lpStrings[4],STRLEN,"%d",va_arg(listArgs,int));
253         StringCbPrintf(lpStrings[5],STRLEN,"%d",va_arg(listArgs,WORD));
254         lpArgs[1] = lpStrings[1];
255         lpArgs[2] = lpStrings[2];
256         lpArgs[3] = lpStrings[3];
257         lpArgs[4] = lpStrings[4];
258         lpArgs[5] = lpStrings[5];
259         break;
260     case MSG_BAD_SMB_TOO_SHORT:
261     case MSG_BAD_SMB_INVALID:
262     case MSG_BAD_SMB_INCOMPLETE:
263         wNumArgs = 1;
264         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,WORD));
265         lpArgs[0] = lpStrings[0];
266         break;
267     case MSG_SMB_SESSION_START:
268         wNumArgs = 1;
269         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,long));
270         lpArgs[0] = lpStrings[0];
271         break;
272     case MSG_BAD_SMB_WRONG_SESSION:
273         wNumArgs = 2;
274         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,DWORD));
275         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,WORD));
276         lpArgs[0] = lpStrings[0];
277         lpArgs[1] = lpStrings[1];
278         break;
279     case MSG_BAD_VCP:
280         wNumArgs = 4;
281         StringCbPrintf(lpStrings[0],STRLEN,"%d",va_arg(listArgs,UCHAR));
282         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,UCHAR));
283         StringCbPrintf(lpStrings[2],STRLEN,"%d",va_arg(listArgs,UCHAR));
284         StringCbPrintf(lpStrings[3],STRLEN,"%d",va_arg(listArgs,UCHAR));
285         lpArgs[0] = lpStrings[0];
286         lpArgs[1] = lpStrings[1];
287         lpArgs[2] = lpStrings[2];
288         lpArgs[3] = lpStrings[3];
289         break;
290     case MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION:
291         wNumArgs = 3;
292         lpArgs[0] = va_arg(listArgs, LPTSTR);
293         StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,int));
294         lpArgs[1] = lpStrings[1];
295         lpArgs[2] = va_arg(listArgs,LPTSTR);
296         break;
297     }
298     va_end(listArgs);
299
300     // Make sure we were not given too many args.
301     if (wNumArgs >= MAXARGS)
302         return;
303
304     // Log the event.
305     code = ReportEvent(hEventSource,            // handle of event source
306                  wEventType,            // event type
307                  0,                     // event category
308                  dwEventID,             // event ID
309                  NULL,                  // current user's SID
310                  wNumArgs,              // strings in lpszArgs
311                  0,                     // no bytes of raw data
312                  wNumArgs ? lpArgs : NULL,              // array of error strings
313                  NULL);                 // no raw data
314
315
316     DeregisterEventSource(hEventSource);
317 }       
318
319