windows-minidump-20050509
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 10 May 2005 04:34:03 +0000 (04:34 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 10 May 2005 04:34:03 +0000 (04:34 +0000)
Enable support for Minidump generation and crash reporting

src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/afsd_init.h
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/fs.c

index 7f9291c..112b202 100644 (file)
@@ -147,4 +147,6 @@ typedef BOOL ( APIENTRY * AfsdDaemonHook )(void);
 typedef BOOL ( APIENTRY * AfsdStoppingHook )(void);
 #define AFSD_STOPPED_HOOK "AfsdStoppedHook"
 typedef BOOL ( APIENTRY * AfsdStoppedHook )(void);
+
+#define SERVICE_CONTROL_CUSTOM_DUMP 128
 #endif /* AFSD_H_ENV */
index 94d68e8..3d7e37a 100644 (file)
@@ -19,6 +19,7 @@
 #include <locale.h>
 #include <mbctype.h>
 #include <winsock2.h>
+#include <ErrorRep.h>
 
 #include <osi.h>
 #include "afsd.h"
@@ -135,7 +136,7 @@ void afsd_initUpperCaseTable()
 void
 afsi_start()
 {
-    char wd[100];
+    char wd[256];
     char t[100], u[100], *p, *path;
     int zilch;
     int code;
@@ -815,13 +816,10 @@ int afsd_InitCM(char **reasonP)
     dummyLen = sizeof(traceOnPanic);
     code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
                             (BYTE *) &traceOnPanic, &dummyLen);
-    if (code == ERROR_SUCCESS)
-        afsi_log("Set to %s on panic",
-                  traceOnPanic ? "trap" : "not trap");
-    else {  
-        traceOnPanic = 0;
-        /* Don't log */
+    if (code != ERROR_SUCCESS)
+        traceOnPanic = 1;              /* log */
     }
+    afsi_log("Set to %s on panic", traceOnPanic ? "trap" : "not trap");
 
     dummyLen = sizeof(reportSessionStartups);
     code = RegQueryValueEx(parmKey, "ReportSessionStartups", NULL, NULL,
@@ -1390,12 +1388,104 @@ static DWORD *afsd_crtDbgBreakCurrent = NULL;
 static DWORD afsd_crtDbgBreaks[256];
 #endif
 
+static EFaultRepRetVal (WINAPI *pReportFault)(LPEXCEPTION_POINTERS pep, DWORD dwMode) = NULL;
+static BOOL (WINAPI *pMiniDumpWriteDump)(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,
+                                  MINIDUMP_TYPE DumpType,
+                                  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+                                  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+                                  PMINIDUMP_CALLBACK_INFORMATION CallbackParam) = NULL;
+
+
+static HANDLE
+OpenDumpFile(void)
+{
+    char wd[256];
+
+    if (getenv("TEMP"))
+    {
+        StringCbCopyA(wd, sizeof(wd), getenv("TEMP"));
+    }
+    else
+    {
+        if (!GetWindowsDirectory(wd, sizeof(wd)))
+            return NULL;
+    }
+    StringCbCatA(wd, sizeof(wd), "\\afsd.dmp");
+    return CreateFile( wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+                            CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
+}
+
+void 
+GenerateMiniDump(PEXCEPTION_POINTERS ep)
+{
+    if (ep == NULL) 
+    {
+        // Generate exception to get proper context in dump
+        __try 
+        {
+            RaiseException(DBG_CONTINUE, 0, 0, NULL);
+        } 
+        __except(GenerateMiniDump(GetExceptionInformation()), EXCEPTION_CONTINUE_EXECUTION) 
+        {
+        }
+    } 
+    else
+    {
+        MINIDUMP_EXCEPTION_INFORMATION eInfo;
+        HANDLE hFile = NULL;
+        HMODULE hDbgHelp = NULL;
+
+        hDbgHelp = LoadLibrary("Dbghelp.dll");
+        if ( hDbgHelp == NULL )
+            return;
+
+        (FARPROC) pMiniDumpWriteDump = GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
+        if ( pMiniDumpWriteDump == NULL ) {
+            FreeLibrary(hDbgHelp);
+            return;
+        }
+
+        hFile = OpenDumpFile();
+
+        if ( hFile ) {
+            HKEY parmKey;
+            DWORD dummyLen;
+            DWORD dwValue;
+            DWORD code;
+            DWORD dwMiniDumpType = MiniDumpNormal;
+
+            code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+                                 0, KEY_QUERY_VALUE, &parmKey);
+            if (code == ERROR_SUCCESS) {
+                dummyLen = sizeof(DWORD);
+                code = RegQueryValueEx(parmKey, "MiniDumpType", NULL, NULL,
+                                        (BYTE *) &dwValue, &dummyLen);
+                if (code == ERROR_SUCCESS)
+                    dwMiniDumpType = dwValue ? 1 : 0;
+                RegCloseKey (parmKey);
+            }
+
+            eInfo.ThreadId = GetCurrentThreadId();
+            eInfo.ExceptionPointers = ep;
+            eInfo.ClientPointers = FALSE;
+
+            pMiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
+                                hFile, dwMiniDumpType, ep ? &eInfo : NULL,
+                                NULL, NULL);
+
+            CloseHandle(hFile);
+        }
+        FreeLibrary(hDbgHelp);
+    }
+}
+
 LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
 {
     CONTEXT context;
 #ifdef _DEBUG  
     BOOL allocRequestBrk = FALSE;
 #endif 
+    HMODULE hLib = NULL;
   
     afsi_log("UnhandledException : code : 0x%x, address: 0x%x\n", 
              ep->ExceptionRecord->ExceptionCode, 
@@ -1414,7 +1504,17 @@ LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
     context = *ep->ContextRecord;
           
     afsd_printStack(GetCurrentThread(), &context);
-          
+
+    GenerateMiniDump(ep);
+
+    hLib = LoadLibrary("Faultrep.dll");
+    if ( hLib ) {
+        (FARPROC) pReportFault = GetProcAddress(hLib, "ReportFault");
+        if ( pReportFault )
+            pReportFault(ep, 0);
+        FreeLibrary(hLib);
+    }
+
     if (ep->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
     {
         afsi_log("\nEXCEPTION_BREAKPOINT - continue execution ...\n");
index 123bd38..6465341 100644 (file)
@@ -12,6 +12,8 @@ void afsi_start();
 #ifndef DJGPP
 int afsd_InitCM(char **reasonP);
 int afsd_InitSMB(char **reasonP, void *aMBfunc);
+
+void GenerateMiniDump(PEXCEPTION_POINTERS ep);
 #else /* DJGPP */
 int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock);
 int afsd_InitSMB(char **reasonP);
@@ -22,3 +24,5 @@ void afsd_SetUnhandledExceptionFilter();
 
 extern char cm_HostName[];
 extern char cm_NetbiosName[];
+
+
index a539363..ad334c1 100644 (file)
@@ -354,6 +354,14 @@ afsd_ServiceControlHandlerEx(
                 }   
             }
         }
+        break;
+    case SERVICE_CONTROL_CUSTOM_DUMP: 
+        {
+            afsi_log("SERVICE_CONTROL_CUSTOM_DUMP"); 
+            GenerateMiniDump(NULL);
+                       dwRet = NO_ERROR;
+        }
+        break;
     }          /* end switch(ctrlCode) */                                                        
     return dwRet;   
 }
@@ -1050,7 +1058,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     ServiceStatus.dwCheckPoint = 1;
     ServiceStatus.dwWaitHint = 30000;
     /* accept Power Events */
-    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
+    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
     SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
 
@@ -1138,7 +1146,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
             ServiceStatus.dwCheckPoint = 2;
             ServiceStatus.dwWaitHint = 20000;
             /* accept Power Events */
-            ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
+            ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
             SetServiceStatus(StatusHandle, &ServiceStatus);
         }
     }
@@ -1241,7 +1249,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         ServiceStatus.dwWaitHint = 0;
 
         /* accept Power events */
-        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
         SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif  
         {
index 2a4080d..e4f4533 100644 (file)
@@ -378,7 +378,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
         if ( timeLeft > 2 )
             retry = 1;
     }
-    else if (errorCode == RXKADEXPIRED) {
+    else if (errorCode == RXKADEXPIRED || 
+             errorCode == RXKADBADTICKET) {
         if (!dead_session) {
             lock_ObtainMutex(&userp->mx);
             ucellp = cm_GetUCell(userp, serverp->cellp);
@@ -393,8 +394,26 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                 retry = 1;
         }
     } else {
-        if (errorCode)
-            osi_Log1(afsd_logp, "cm_Analyze: ignoring error code 0x%x", errorCode);
+        if (errorCode) {
+            char * s = "unknown error";
+            switch ( errorCode ) {
+            case RXKADINCONSISTENCY: s = "RXKADINCONSISTENCY"; break;
+            case RXKADPACKETSHORT  : s = "RXKADPACKETSHORT  "; break;
+            case RXKADLEVELFAIL    : s = "RXKADLEVELFAIL    "; break;
+            case RXKADTICKETLEN    : s = "RXKADTICKETLEN    "; break;
+            case RXKADOUTOFSEQUENCE: s = "RXKADOUTOFSEQUENCE"; break;
+            case RXKADNOAUTH       : s = "RXKADNOAUTH       "; break;
+            case RXKADBADKEY       : s = "RXKADBADKEY       "; break;
+            case RXKADBADTICKET    : s = "RXKADBADTICKET    "; break;
+            case RXKADUNKNOWNKEY   : s = "RXKADUNKNOWNKEY   "; break;
+            case RXKADEXPIRED      : s = "RXKADEXPIRED      "; break;
+            case RXKADSEALEDINCON  : s = "RXKADSEALEDINCON  "; break;
+            case RXKADDATALEN      : s = "RXKADDATALEN      "; break;
+            case RXKADILLEGALLEVEL : s = "RXKADILLEGALLEVEL "; break;
+            }
+            osi_Log2(afsd_logp, "cm_Analyze: ignoring error code 0x%x (%s)", 
+                     errorCode, s);
+        }
     }
 
     if (retry && dead_session)
index ffdbe1f..eb7bff8 100644 (file)
@@ -60,6 +60,7 @@ extern struct cmd_syndesc *cmd_CreateSyntax();
 
 static int MemDumpCmd(struct cmd_syndesc *asp, char *arock);
 static int CSCPolicyCmd(struct cmd_syndesc *asp, char *arock);
+static int MiniDumpCmd(struct cmd_syndesc *asp, char *arock);
 
 extern afs_int32 VL_GetEntryByNameO();
 
@@ -3619,21 +3620,26 @@ MemDumpCmd(struct cmd_syndesc *asp, char *arock)
 {
     long code;
     struct ViceIoctl blob;
-    long inValue;
+    long inValue = 0;
     long outValue;
-  
+
+    if ( !IsAdmin() ) {
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
+        return EACCES;
+    }
+
     if ((asp->parms[0].items && asp->parms[1].items)) {
         fprintf(stderr, "%s trace: must use at most one of '-begin' or '-end'\n", pn);
         return EINVAL;
     }
-  
+
     /* determine if we're turning this tracing on or off */
-    inValue = 0;
     if (asp->parms[0].items)
         inValue = 1;            /* begin */
-    else if (asp->parms[1].items) 
+    else if (asp->parms[1].items)
         inValue = 0;            /* end */
-  
+
+
     blob.in_size = sizeof(long);
     blob.in = (char *) &inValue;
     blob.out_size = sizeof(long);
@@ -3645,10 +3651,55 @@ MemDumpCmd(struct cmd_syndesc *asp, char *arock)
         return code;
     }
 
-    if (outValue) printf("AFS memdump begin.\n");
-    else printf("AFS memdump end.\n");
+    if (outValue) { 
+        printf("AFS memdump created.\n");
+        return 0;
+    } else {
+        printf("AFS memdump failed.\n");
+        return -1;
+    }
+}
 
-    return 0;
+static int
+MiniDumpCmd(struct cmd_syndesc *asp, char *arock)
+{
+    long code;
+    BOOL success = 0;
+    SERVICE_STATUS status;
+    SC_HANDLE hManager = NULL;
+    SC_HANDLE hService = NULL;
+
+    if ( !IsAdmin() ) {
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
+        return EACCES;
+    }
+
+    hManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+    if (!hManager)
+        goto failure;
+
+    hService = OpenService(hManager, "TransarcAFSDaemon", SERVICE_USER_DEFINED_CONTROL);
+    if (!hService)
+        goto failure;
+
+    success = ControlService(hService, SERVICE_CONTROL_CUSTOM_DUMP, &status);
+
+    if (success) {
+        CloseServiceHandle(hService);
+        CloseServiceHandle(hManager);
+
+        printf("AFS minidump generated.\n");
+        return 0;
+    }
+
+  failure: 
+    if (hService)
+        CloseServiceHandle(hService);
+    if (hManager)
+        CloseServiceHandle(hManager);
+
+    printf("AFS minidump failed.\n");
+    return -1;
 }
 
 static int
@@ -3658,6 +3709,11 @@ CSCPolicyCmd(struct cmd_syndesc *asp, char *arock)
     char *share = NULL;
     HKEY hkCSCPolicy;
 
+    if ( !IsAdmin() ) {
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
+        return EACCES;
+    }
+
     for(ti=asp->parms[0].items; ti;ti=ti->next) {
         share = ti->data;
         if (share)
@@ -4352,6 +4408,8 @@ main(int argc, char **argv)
     cmd_AddParm(ts, "-documents", CMD_FLAG, CMD_OPTIONAL, "automatic caching of documents");
     cmd_AddParm(ts, "-disable", CMD_FLAG, CMD_OPTIONAL, "disable caching");
 
+    ts = cmd_CreateSyntax("minidump", MiniDumpCmd, 0, "Generate MiniDump of current service state");
+
     code = cmd_Dispatch(argc, argv);
 
 #ifndef WIN32