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 */
#include <locale.h>
#include <mbctype.h>
#include <winsock2.h>
+#include <ErrorRep.h>
#include <osi.h>
#include "afsd.h"
void
afsi_start()
{
- char wd[100];
+ char wd[256];
char t[100], u[100], *p, *path;
int zilch;
int code;
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,
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,
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");
#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);
extern char cm_HostName[];
extern char cm_NetbiosName[];
+
+
}
}
}
+ break;
+ case SERVICE_CONTROL_CUSTOM_DUMP:
+ {
+ afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
+ GenerateMiniDump(NULL);
+ dwRet = NO_ERROR;
+ }
+ break;
} /* end switch(ctrlCode) */
return dwRet;
}
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
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);
}
}
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
{
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);
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)
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();
{
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);
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
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)
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