Windows: log SMB or RDR in use at startup
[openafs.git] / src / WINNT / afsd / afsd_eventlog.c
index 6bb7078..03357f7 100644 (file)
@@ -1,12 +1,16 @@
 ////////////////////////////////////////////////////////////////////
 //
 //
-//             E V E N T   L O G G I N G   F U N C T I O N S 
+//             E V E N T   L O G G I N G   F U N C T I O N S
 //
 //
 ////////////////////////////////////////////////////////////////////
 
 
+#include <afsconfig.h>
+#include <afs/param.h>
+#include <roken.h>
+
 #include <windows.h>
 #include <stdarg.h>
 #include <string.h>
@@ -14,6 +18,8 @@
 #include <WINNT/afsreg.h>
 #include "afsd.h"
 #include "afsd_eventlog.h"
+#define AFS_VERSION_STRINGS
+#include "afs_component_version_number.h"
 
 static BOOL    GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize);
 static BOOL    AddEventSource(void);
@@ -21,14 +27,14 @@ static BOOL AddEventSource(void);
 static BOOL
 GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize)
 {
-    HKEY       hKey = NULL; 
+    HKEY       hKey = NULL;
     DWORD      dwData = 0;
     BOOL       bRet = TRUE;
 
     do {
        // Open key
        if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_SUBKEY, 0, KEY_QUERY_VALUE, &hKey ) )
-       {               
+       {
            bRet = FALSE;
            break;
        }
@@ -42,20 +48,20 @@ GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize)
                              NULL,                     // type buffer
                              (LPBYTE) lpPathBuf,       // data buffer
                              &dwData))         // size of data buffer
-       {       
+       {
            bRet = FALSE;
            break;
        }
-               
+
        *pdwPathBufSize = dwData;
 
     } while (0);
-                               
+
     if (hKey != NULL)
-       RegCloseKey(hKey); 
+       RegCloseKey(hKey);
 
     return bRet;
-} 
+}
 
 //
 // Ensure name for message file is in proper location in Registry.
@@ -63,101 +69,82 @@ GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize)
 static BOOL
 AddEventSource()
 {
-    HKEY       hKey = NULL, hLogKey; 
-    UCHAR      szBuf[MAX_PATH]; 
-    DWORD      dwData, dwDisposition; 
-    BOOL       bRet = TRUE;
+    HKEY       hKey = NULL, hLogKey;
+    UCHAR      szBuf[MAX_PATH] = "afsd_service.exe";
+    DWORD      dwData, dwDisposition;
+    static BOOL        bRet = TRUE;
+    static BOOL bOnce = TRUE;
 
-    do {
-       if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
-                          KEY_QUERY_VALUE, &hLogKey ) )
-       {                       
-           // nope - create it         
-           if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
-                                NULL, REG_OPTION_NON_VOLATILE,
-                                KEY_ALL_ACCESS, NULL, &hLogKey,
-                                &dwDisposition)) 
-           {   
-               bRet = FALSE;
-               break;
-           }
-       }
+    if (!bOnce)
+        return bRet;
 
-       // Let's see if key already exists as a subkey under the 
-       // Application key in the EventLog registry key.  If not,
-       // create it.
-       if ( RegOpenKeyEx( hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
-                          KEY_QUERY_VALUE, &hKey ) )
-       {                       
-           // nope - create it         
-           if ( RegCreateKeyEx(hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
-                                NULL, REG_OPTION_NON_VOLATILE,
-                                KEY_ALL_ACCESS, NULL, &hKey,
-                                &dwDisposition)) 
-           {   
-               bRet = FALSE;
-               break;
-           }
-
-           // Set the name of the message file
-           // Get "ImagePath" from TransarcAFSDaemon service
-           memset(szBuf, '\0', MAX_PATH);
-           dwData = MAX_PATH;
-           GetServicePath(szBuf, &dwData);
-
-           // Add the name to the EventMessageFile subkey. 
-           if ( RegSetValueEx( hKey,                   // subkey handle 
-                               AFSREG_APPLOG_MSGFILE_VALUE,    // value name 
-                               0,                      // must be zero 
-                               REG_EXPAND_SZ,          // value type 
-                               (LPBYTE) szBuf,         // pointer to value data 
-                               (DWORD)strlen(szBuf) + 1))      // length of value data
-           {   
-               bRet = FALSE;
-               break;
-           }
-
-           // Set the supported event types in the TypesSupported subkey. 
-           dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
-               EVENTLOG_INFORMATION_TYPE; 
-
-           if ( RegSetValueEx( hKey,                   // subkey handle 
-                               AFSREG_APPLOG_MSGTYPE_VALUE,    // value name 
-                               0,                      // must be zero 
-                               REG_DWORD,              // value type 
-                               (LPBYTE) &dwData,       // pointer to value data 
-                               sizeof(DWORD)))         // length of value data
-           {   
-               bRet = FALSE;
-               break;
-           }
-       }
-       else
-       {
-           // key was opened - read it
-           memset(szBuf, '\0', MAX_PATH);
-           dwData = MAX_PATH;
-           if ( RegQueryValueEx( hKey,                 // handle to key
-                                 AFSREG_APPLOG_MSGFILE_VALUE,  // value name
-                                 NULL,                 // reserved
-                                 NULL,                 // type buffer
-                                 (LPBYTE) szBuf,               // data buffer
-                                 &dwData))             // size of data buffer
-           {   
-               bRet = FALSE;
-               break;
-           }
-       }
-    } while (0);
-                               
+    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
+                       KEY_SET_VALUE, &hLogKey ) )
+    {
+        // nope - create it
+        if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_APPLOG_SUBKEY, 0,
+                             NULL, REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS, NULL, &hLogKey,
+                             &dwDisposition))
+        {
+            bRet = FALSE;
+            goto done;
+        }
+    }
+
+    // Let's see if key already exists as a subkey under the
+    // Application key in the EventLog registry key.  If not,
+    // create it.
+    if ( RegOpenKeyEx( hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
+                       KEY_SET_VALUE, &hKey ) )
+    {
+        // nope - create it
+        if ( RegCreateKeyEx(hLogKey, AFSREG_CLT_APPLOG_SUBKEY, 0,
+                             NULL, REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS, NULL, &hKey,
+                             &dwDisposition))
+        {
+            bRet = FALSE;
+            goto done;
+        }
+    }
+
+    // Add the name to the EventMessageFile subkey.
+    if ( RegSetValueEx( hKey,                  // subkey handle
+                        AFSREG_APPLOG_MSGFILE_VALUE,   // value name
+                        0,                     // must be zero
+                        REG_SZ,                        // value type
+                        (LPBYTE) szBuf,                // pointer to value data
+                        (DWORD)strlen(szBuf) + 1))     // length of value data
+    {
+        bRet = FALSE;
+        goto done;
+    }
+
+    // Set the supported event types in the TypesSupported subkey.
+    dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
+        EVENTLOG_INFORMATION_TYPE;
+
+    if ( RegSetValueEx( hKey,                  // subkey handle
+                        AFSREG_APPLOG_MSGTYPE_VALUE,   // value name
+                        0,                     // must be zero
+                        REG_DWORD,             // value type
+                        (LPBYTE) &dwData,      // pointer to value data
+                        sizeof(DWORD)))                // length of value data
+    {
+        bRet = FALSE;
+       goto done;
+    }
+
+  done:
     if (hKey != NULL)
-       RegCloseKey(hKey); 
+       RegCloseKey(hKey);
 
     if (hLogKey != NULL)
-       RegCloseKey(hLogKey); 
+       RegCloseKey(hLogKey);
 
     return bRet;
-}      
+}
 
 // Log an event with a formatted system message as the (only) substitution
 // string, from the given message ID.
@@ -176,17 +163,26 @@ LogEventMessage(WORD wEventType, DWORD dwEventID, DWORD dwMessageID)
 // Use the ReportEvent API to write an entry to the system event log.
 //
 #define MAXARGS 8
-#define STRLEN  64
+#define STRLEN  128
+
 VOID
 LogEvent(WORD wEventType, DWORD dwEventID, ...)
 {
     va_list    listArgs;
     HANDLE     hEventSource;
+    HANDLE      hMutex = NULL;
     LPTSTR     lpArgs[MAXARGS];
     CHAR       lpStrings[MAXARGS][STRLEN];
+    static CHAR lpLastStrings[MAXARGS][STRLEN];
     WORD       wNumArgs = 0;
-    WORD       wNumStrings = 0;
-       DWORD   code;
+    static WORD wLastNumArgs = MAXARGS;
+    static time_t lastMessageTime = 0;
+    static WORD wLastEventType = 0;
+    static DWORD dwLastEventID = 0;
+    time_t      now;
+    DWORD       code;
+    BOOL        bLogMessage = TRUE;
+    WORD        i = 0, j;
 
     // Ensure that our event source is properly initialized.
     if (!AddEventSource())
@@ -207,23 +203,45 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...)
     case MSG_FLUSH_UNEXPECTED_EVENT:
     case MSG_UNHANDLED_EXCEPTION:
     case MSG_SMB_ZERO_TRANSACTION_COUNT:
-    case MSG_SERVICE_START_PENDING:
     case MSG_SERVICE_INCORRECT_VERSIONS:
-    case MSG_SERVICE_RUNNING:
     case MSG_SERVICE_STOPPING:
+    case MSG_SERVICE_STOPPED:
     case MSG_SERVICE_ERROR_STOP:
+    case MSG_CRYPT_OFF:
+    case MSG_CRYPT_ON:
        break;
+    case MSG_SERVICE_START_PENDING:
+        wNumArgs = 1;
+        lpArgs[0] = AFSVersion;
+        break;
+    case MSG_SERVICE_RUNNING:
+        wNumArgs = 1;
+        if (smb_Enabled && RDR_Initialized)
+            lpArgs[0] = "SMB and RDR interfaces";
+        else if (smb_Enabled)
+            lpArgs[0] = "SMB interface";
+        else if (RDR_Initialized)
+            lpArgs[0] = "RDR interface";
+        else
+            lpArgs[0] = "No active interface";
+        break;
     case MSG_FLUSH_BAD_SHARE_NAME:
     case MSG_FLUSH_OPEN_ENUM_ERROR:
     case MSG_FLUSH_ENUM_ERROR:
     case MSG_FLUSH_FAILED:
     case MSG_RX_HARD_DEAD_TIME_EXCEEDED:
     case MSG_SERVICE_ERROR_STOP_WITH_MSG:
+    case MSG_SMB_SEND_PACKET_FAILURE:
+    case MSG_UNEXPECTED_SMB_SESSION_CLOSE:
+    case MSG_RX_MSGSIZE_EXCEEDED:
+    case MSG_RX_BUSY_CALL_CHANNEL:
        wNumArgs = 1;
        lpArgs[0] = va_arg(listArgs, LPTSTR);
        break;
     case MSG_TIME_FLUSH_PER_VOLUME:
     case MSG_TIME_FLUSH_TOTAL:
+    case MSG_SMB_MAX_MPX_COUNT:
+    case MSG_SMB_MAX_BUFFER_SIZE:
        wNumArgs = 2;
        lpArgs[0] = va_arg(listArgs, LPTSTR);
        lpArgs[1] = va_arg(listArgs, LPTSTR);
@@ -234,6 +252,17 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...)
     case MSG_SERVER_REPORTS_VSALVAGE:
     case MSG_SERVER_REPORTS_VNOSERVICE:
     case MSG_SERVER_REPORTS_VIO:
+    case MSG_SERVER_REPORTS_VBUSY:
+    case MSG_SERVER_REPORTS_VRESTARTING:
+       wNumArgs = 3;
+       lpArgs[0] = va_arg(listArgs, LPTSTR);
+       StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,afs_int32));
+       lpArgs[1] = lpStrings[1];
+       lpArgs[2] = va_arg(listArgs, LPTSTR);
+        break;
+    case MSG_ALL_SERVERS_BUSY:
+    case MSG_ALL_SERVERS_OFFLINE:
+    case MSG_ALL_SERVERS_DOWN:
        wNumArgs = 2;
        lpArgs[0] = va_arg(listArgs, LPTSTR);
        StringCbPrintf(lpStrings[1],STRLEN,"%d",va_arg(listArgs,afs_int32));
@@ -302,26 +331,83 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...)
        lpArgs[1] = lpStrings[1];
        lpArgs[2] = va_arg(listArgs,LPTSTR);
        break;
+    case MSG_DIRTY_BUFFER_AT_SHUTDOWN:
+       wNumArgs = 6;
+       lpArgs[0] = va_arg(listArgs, LPTSTR);
+        lpArgs[1] = va_arg(listArgs, LPTSTR);
+       StringCbPrintf(lpStrings[2],STRLEN,"%u",va_arg(listArgs,int));
+       StringCbPrintf(lpStrings[3],STRLEN,"%u",va_arg(listArgs,int));
+       StringCbPrintf(lpStrings[4],STRLEN,"%I64u",va_arg(listArgs,afs_int64));
+       StringCbPrintf(lpStrings[5],STRLEN,"%I64u",va_arg(listArgs,afs_int64));
+       lpArgs[2] = lpStrings[2];
+       lpArgs[3] = lpStrings[3];
+       lpArgs[4] = lpStrings[4];
+       lpArgs[5] = lpStrings[5];
+       break;
     }
     va_end(listArgs);
 
     // Make sure we were not given too many args.
     if (wNumArgs >= MAXARGS)
-       return;
+        goto done;
+
+    hMutex = CreateMutex( NULL, TRUE, "AFSD Event Log Mutex");
+    if (hMutex == NULL)
+        goto done;
+
+    if (GetLastError() == ERROR_ALREADY_EXISTS) {
+        code = WaitForSingleObject( hMutex, 500);
+        if (code != WAIT_OBJECT_0)
+            goto done;
+    }
+
+    /*
+     * We rate limit consecutive duplicate messages to one every
+     * five seconds.
+     */
+    now = time(NULL);
+    if (now < lastMessageTime + 5 &&
+        wEventType == wLastEventType &&
+        dwEventID == dwLastEventID &&
+        wNumArgs == wLastNumArgs) {
+        for (i=0; i<wNumArgs; i++) {
+            if ( strncmp(lpArgs[i], lpLastStrings[i], STRLEN))
+                break;
+        }
+        if (i == wNumArgs)
+            bLogMessage = FALSE;
+    }
+
+    if ( bLogMessage) {
+        wLastNumArgs = wNumArgs;
+        wLastEventType = wEventType;
+        dwLastEventID = dwEventID;
+        lastMessageTime = now;
+
+        for ( j = (i == wNumArgs ? 0 : i) ; i < wNumArgs; i++) {
+            StringCbCopyEx( lpLastStrings[i], STRLEN, lpArgs[i], NULL, NULL, STRSAFE_NULL_ON_FAILURE);
+        }
+    }
+
+    ReleaseMutex(hMutex);
 
     // Log the event.
-    code = ReportEvent(hEventSource,           // handle of event source
-                wEventType,            // event type
-                0,                     // event category
-                dwEventID,             // event ID
-                NULL,                  // current user's SID
-                wNumArgs,              // strings in lpszArgs
-                0,                     // no bytes of raw data
-                wNumArgs ? lpArgs : NULL,              // array of error strings
-                NULL);                 // no raw data
+    if ( bLogMessage)
+        code = ReportEvent(hEventSource,               // handle of event source
+                           wEventType,         // event type
+                           0,                  // event category
+                           dwEventID,          // event ID
+                           NULL,                       // current user's SID
+                           wNumArgs,           // strings in lpszArgs
+                           0,                  // no bytes of raw data
+                           wNumArgs ? lpArgs : NULL,// array of error strings
+                           NULL);                      // no raw data
 
+  done:
+    if (hMutex)
+        CloseHandle(hMutex);
 
     DeregisterEventSource(hEventSource);
-}      
+}