From a5726c820b915d82772ff765c31037d83572c404 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 13 Jan 2021 16:15:06 -0800 Subject: [PATCH] sys: add trace functionality --- build/VStudio/winfsp_sys.vcxproj | 1 + build/VStudio/winfsp_sys.vcxproj.filters | 3 + src/sys/debug.c | 5 + src/sys/driver.c | 4 + src/sys/driver.h | 34 ++++++ src/sys/trace.c | 142 +++++++++++++++++++++++ 6 files changed, 189 insertions(+) create mode 100644 src/sys/trace.c diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj index 8843ec77..659fb9e7 100644 --- a/build/VStudio/winfsp_sys.vcxproj +++ b/build/VStudio/winfsp_sys.vcxproj @@ -187,6 +187,7 @@ + diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters index 7ee41c66..7c248ca6 100644 --- a/build/VStudio/winfsp_sys.vcxproj.filters +++ b/build/VStudio/winfsp_sys.vcxproj.filters @@ -125,6 +125,9 @@ Source + + Source + diff --git a/src/sys/debug.c b/src/sys/debug.c index 5d51d915..e9f31163 100644 --- a/src/sys/debug.c +++ b/src/sys/debug.c @@ -22,6 +22,10 @@ #include #if DBG + +#undef STATUS_INSUFFICIENT_RESOURCES +#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL) + #define SYM(x) case x: return #x; #define SYMBRC(x) case x: return "[" #x "]"; @@ -330,4 +334,5 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result) NtStatusSym(Result), (LONGLONG)Irp->IoStatus.Information); } + #endif diff --git a/src/sys/driver.c b/src/sys/driver.c index a03c385a..1ec81b31 100644 --- a/src/sys/driver.c +++ b/src/sys/driver.c @@ -38,6 +38,8 @@ NTSTATUS DriverEntry( { FSP_ENTER_DRV(); + FSP_TRACE_INIT(); + /* setup the driver object */ DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose; @@ -157,6 +159,8 @@ exit: FspSiloFinalize(); if (InitDoneGRes) ExDeleteResourceLite(&FspDeviceGlobalResource); + + FSP_TRACE_FINI(); } #pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName") diff --git a/src/sys/driver.h b/src/sys/driver.h index 9ceb7ded..2f0dc0a3 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -147,6 +147,40 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result); #define DEBUGTEST_EX(C, Percent, Deflt) (Deflt) #endif +/* trace */ +#if FSP_TRACE_ENABLED +VOID FspTraceInitialize(VOID); +VOID FspTraceFinalize(VOID); +VOID FspTrace(const char *file, int line, const char *func); +VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Status); +#define FSP_TRACE_INIT() \ + (FspTraceInitialize(), FSP_TRACE()) +#define FSP_TRACE_FINI() \ + (FSP_TRACE(), FspTraceFinalize()) +#define FSP_TRACE() \ + FspTrace( \ + __FILE__, \ + __LINE__, \ + __FUNCTION__) +#define FSP_TRACE_NTSTATUS(Status) \ + FspTraceNtStatus( \ + __FILE__, \ + __LINE__, \ + __FUNCTION__, \ + Status) +#else +#define FSP_TRACE_INIT() \ + ((VOID)0) +#define FSP_TRACE_FINI() \ + ((VOID)0) +#define FSP_TRACE() \ + ((VOID)0) +#define FSP_TRACE_NTSTATUS(Result) \ + ((VOID)0) +#endif +#undef STATUS_INSUFFICIENT_RESOURCES +#define STATUS_INSUFFICIENT_RESOURCES (FSP_TRACE_NTSTATUS(0xC000009AL), (NTSTATUS)0xC000009AL) + /* FSP_ENTER/FSP_LEAVE */ #if DBG #define FSP_DEBUGLOG_(fmt, rfmt, ...) \ diff --git a/src/sys/trace.c b/src/sys/trace.c new file mode 100644 index 00000000..8d7da42a --- /dev/null +++ b/src/sys/trace.c @@ -0,0 +1,142 @@ +/** + * @file sys/trace.c + * + * @copyright 2015-2020 Bill Zissimopoulos + */ +/* + * This file is part of WinFsp. + * + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License version 3 as published by the Free Software + * Foundation. + * + * Licensees holding a valid commercial license may use this software + * in accordance with the commercial license agreement provided in + * conjunction with the software. The terms and conditions of any such + * commercial license agreement shall govern, supersede, and render + * ineffective any application of the GPLv3 license to this software, + * notwithstanding of any reference thereto in the software or + * associated repository. + */ + +#include + +#if FSP_TRACE_ENABLED + +#undef STATUS_INSUFFICIENT_RESOURCES +#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL) + +static struct +{ + HANDLE Handle; + PKEVENT Event; +} FspLowMemoryCondition, FspLowNonPagedPoolCondition, FspLowPagedPoolCondition; + +VOID FspTrace(const char *file, int line, const char *func) +{ + for (const char *p = file; '\0' != *p; p++) + if ('\\' == *p) + file = p + 1; + + ASSERT(DISPATCH_LEVEL >= KeGetCurrentIrql()); + DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_TRACE_LEVEL, + DRIVER_NAME ": %s[%s:%d]\n", func, file, line); +} + +VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Status) +{ + for (const char *p = file; '\0' != *p; p++) + if ('\\' == *p) + file = p + 1; + + ASSERT(DISPATCH_LEVEL >= KeGetCurrentIrql()); + BOOLEAN LowMemoryCondition, LowNonPagedPoolCondition, LowPagedPoolCondition; + switch (Status) + { + case STATUS_INSUFFICIENT_RESOURCES: + LowMemoryCondition = 0 != FspLowMemoryCondition.Event && + !!KeReadStateEvent(FspLowMemoryCondition.Event); + LowNonPagedPoolCondition = 0 != FspLowNonPagedPoolCondition.Event && + !!KeReadStateEvent(FspLowNonPagedPoolCondition.Event); + LowPagedPoolCondition = 0 != FspLowPagedPoolCondition.Event && + !!KeReadStateEvent(FspLowPagedPoolCondition.Event); + DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_TRACE_LEVEL, + DRIVER_NAME ": %s[%s:%d]: STATUS_INSUFFICIENT_RESOURCE (Memory=%c%c%c)\n", + func, file, line, + LowMemoryCondition ? 'M' : '-', + LowNonPagedPoolCondition ? 'N' : '-', + LowPagedPoolCondition ? 'P' : '-'); + break; + default: + DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_TRACE_LEVEL, + DRIVER_NAME ": %s[%s:%d]: Status=%lx\n", + func, file, line, + Status); + break; + } +} + +static PKEVENT FspOpenEvent(PWSTR Name, PHANDLE PHandle) +{ + UNICODE_STRING ObjectName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + PKEVENT Event; + NTSTATUS Result; + + *PHandle = 0; + + RtlInitUnicodeString(&ObjectName, Name); + InitializeObjectAttributes(&ObjectAttributes, + &ObjectName, OBJ_KERNEL_HANDLE, 0, 0); + Result = ZwOpenEvent(&Handle, + EVENT_ALL_ACCESS, &ObjectAttributes); + if (!NT_SUCCESS(Result)) + return 0; + + Result = ObReferenceObjectByHandle(Handle, + 0, *ExEventObjectType, KernelMode, &Event, 0); + if (!NT_SUCCESS(Result)) + { + ZwClose(Handle); + return 0; + } + + *PHandle = Handle; + + return Event; +} + +static VOID FspCloseEvent(PKEVENT Event, HANDLE Handle) +{ + if (0 != Event) + ObDereferenceObject(Event); + + if (0 != Handle) + ZwClose(Handle); +} + +VOID FspTraceInitialize(VOID) +{ +#define OPEN_EVENT(NAME) \ + (Fsp ## NAME.Event = FspOpenEvent(L"\\KernelObjects\\" #NAME, &Fsp ## NAME.Handle)) + + OPEN_EVENT(LowMemoryCondition); + OPEN_EVENT(LowNonPagedPoolCondition); + OPEN_EVENT(LowPagedPoolCondition); + +#undef OPEN_EVENT +} + +VOID FspTraceFinalize(VOID) +{ +#define CLOSE_EVENT(NAME) \ + (FspCloseEvent(Fsp ## NAME.Event, Fsp ## NAME.Handle), Fsp ## NAME.Event = 0, Fsp ## NAME.Handle = 0) + + CLOSE_EVENT(LowMemoryCondition); + CLOSE_EVENT(LowNonPagedPoolCondition); + CLOSE_EVENT(LowPagedPoolCondition); + +#undef CLOSE_EVENT +} +#endif