From 1279af120c1a876e975892c12deba1ff255e9936 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 10 May 2005 04:34:03 +0000 Subject: [PATCH] windows-minidump-20050509 Enable support for Minidump generation and crash reporting --- src/WINNT/afsd/afsd.h | 2 + src/WINNT/afsd/afsd_init.c | 116 +++++++++++++++++++++++++++++++++++++++--- src/WINNT/afsd/afsd_init.h | 4 ++ src/WINNT/afsd/afsd_service.c | 14 +++-- src/WINNT/afsd/cm_conn.c | 25 +++++++-- src/WINNT/afsd/fs.c | 76 +++++++++++++++++++++++---- 6 files changed, 214 insertions(+), 23 deletions(-) diff --git a/src/WINNT/afsd/afsd.h b/src/WINNT/afsd/afsd.h index 7f9291c..112b202 100644 --- a/src/WINNT/afsd/afsd.h +++ b/src/WINNT/afsd/afsd.h @@ -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 */ diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index 94d68e8..3d7e37a 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #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"); diff --git a/src/WINNT/afsd/afsd_init.h b/src/WINNT/afsd/afsd_init.h index 123bd38..6465341 100644 --- a/src/WINNT/afsd/afsd_init.h +++ b/src/WINNT/afsd/afsd_init.h @@ -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[]; + + diff --git a/src/WINNT/afsd/afsd_service.c b/src/WINNT/afsd/afsd_service.c index a539363..ad334c1 100644 --- a/src/WINNT/afsd/afsd_service.c +++ b/src/WINNT/afsd/afsd_service.c @@ -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 { diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 2a4080d..e4f4533 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -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) diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index ffdbe1f..eb7bff8 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -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 -- 1.9.4