KeLeaveCriticalRegion();\r
if (lock_resource_CurrentThread)\r
KeBugCheck(0);\r
- if (lock_resource_count!=0)\r
+ if (lock_resource_count)\r
KeBugCheck(0);\r
lock_resource_CurrentThread=PsGetCurrentThread();\r
lock_resource_count++;\r
}\r
\r
+/* We need to _fully_ release the lock if we are passing the control to\r
+ * callback functions. Single unlock() would free us from our current 'enter:'\r
+ * lock but another lock() from Cc*() function which called us would be held.\r
+ */\r
+static void lock_full(int n)\r
+{\r
+ if (n<=0)\r
+ KeBugCheck(0);\r
+ if (lock_resource_CurrentThread==PsGetCurrentThread())\r
+ KeBugCheck(0);\r
+ KeEnterCriticalRegion();\r
+ if (!ExAcquireResourceExclusiveLite(&lock_resource,TRUE))\r
+ KeBugCheck(0);\r
+ KeLeaveCriticalRegion();\r
+ if (lock_resource_CurrentThread)\r
+ KeBugCheck(0);\r
+ if (lock_resource_count)\r
+ KeBugCheck(0);\r
+ lock_resource_CurrentThread=PsGetCurrentThread();\r
+ lock_resource_count+=n;\r
+}\r
+\r
static void unlock(void)\r
{\r
if (lock_resource_CurrentThread!=PsGetCurrentThread())\r
KeLeaveCriticalRegion();\r
}\r
\r
+static int unlock_full(void)\r
+{\r
+int r;\r
+\r
+ if (lock_resource_CurrentThread!=PsGetCurrentThread())\r
+ KeBugCheck(0);\r
+ if (lock_resource_count<=0)\r
+ KeBugCheck(0);\r
+ r=lock_resource_count;\r
+ lock_resource_count=0;\r
+ lock_resource_CurrentThread=NULL;\r
+ KeEnterCriticalRegion();\r
+ ExReleaseResourceLite(&lock_resource);\r
+ KeLeaveCriticalRegion();\r
+ return r;\r
+}\r
+\r
#define DBGPREFIX "TraceFS(0x%08lX/0x%08lX): "\r
#define DBGARG PsGetCurrentProcess(),PsGetCurrentThread()\r
\r
DBGSINGLE0("FileObject=NULL");\r
return;\r
}\r
- DBGSINGLE4("FileObject=0x%lX: FileName=%s,Flags=0x%lX,SectionObjectPointer->SharedCacheMap=0x%lX",\r
+ DBGSINGLE5("FileObject=0x%lX: FileName=%s,Flags=0x%lX,SectionObjectPointer=0x%lX,->SharedCacheMap=0x%lX",\r
(long)FileObject,\r
dbg_unicode_string(&FileObject->FileName),FileObject->Flags,\r
+ (long)FileObject->SectionObjectPointer,\r
(!FileObject->SectionObjectPointer ? -1 : (long)FileObject->SectionObjectPointer->SharedCacheMap));\r
SectionObjectPointer_set(FileObject);\r
}\r
static NTSTATUS tracefs_major_##irp_mj_name(IN struct _DEVICE_OBJECT *DeviceObject,IN struct _IRP *Irp) \\r
{ \\r
NTSTATUS r; \\r
+int locked; \\r
\\r
DBGSINGLEENTER0( #irp_mj_name ); \\r
dump_irp_mj(DeviceObject,Irp); \\r
+ /* Prevent deadlock during display of File Explorer directory listing. \\r
+ * Needed at least for IRP_MJ_DIRECTORY_CONTROL and IRP_MJ_CLOSE. \\r
+ */ \\r
+ locked=unlock_full(); \\r
r=(*tracefs_major_##irp_mj_name##_orig)(DeviceObject,Irp); \\r
+ lock_full(locked); \\r
DBGSINGLELEAVE1( #irp_mj_name ": r=0x%lX",(long)r); \\r
return r; \\r
}\r
{\r
struct Callbacks *callbacksp=Context;\r
BOOLEAN r;\r
+int locked;\r
\r
DBGSINGLEENTER3("AcquireForLazyWrite: FileObject=0x%lX,Context=0x%lX,Wait=%d",\r
(long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext,Wait);\r
dump_FileObject(callbacksp->FileObject);\r
+ /* Prevent deadlock during File Explorer copy to our destination. */\r
+ locked=unlock_full();\r
r=(*callbacksp->Callbacks.AcquireForLazyWrite)(callbacksp->LazyWriteContext,Wait);\r
+ lock_full(locked);\r
DBGSINGLELEAVE1("AcquireForLazyWrite: r=%d",r);\r
return r;\r
}\r
static VOID TcInitializeCacheMap_ReleaseFromLazyWrite(IN PVOID Context)\r
{\r
struct Callbacks *callbacksp=Context;\r
+int locked;\r
\r
DBGSINGLEENTER2("ReleaseFromLazyWrite: FileObject=0x%lX,Context=0x%lX",\r
(long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext);\r
dump_FileObject(callbacksp->FileObject);\r
+ /* Prevent deadlock during File Explorer copy to our destination. */\r
+ locked=unlock_full();\r
(*callbacksp->Callbacks.ReleaseFromLazyWrite)(callbacksp->LazyWriteContext);\r
+ lock_full(locked);\r
DBGSINGLELEAVE0("ReleaseFromLazyWrite");\r
}\r
\r
{\r
struct Callbacks *callbacksp=Context;\r
BOOLEAN r;\r
+int locked;\r
\r
DBGSINGLEENTER3("AcquireForReadAhead: FileObject=0x%lX,Context=0x%lX,Wait=%d",\r
(long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext,Wait);\r
dump_FileObject(callbacksp->FileObject);\r
+ /* Prevent deadlock during File Explorer copy to our destination. */\r
+ locked=unlock_full();\r
r=(*callbacksp->Callbacks.AcquireForReadAhead)(callbacksp->LazyWriteContext,Wait);\r
+ lock_full(locked);\r
DBGSINGLELEAVE1("AcquireForReadAhead: r=%d",r);\r
return r;\r
}\r
static VOID TcInitializeCacheMap_ReleaseFromReadAhead(IN PVOID Context)\r
{\r
struct Callbacks *callbacksp=Context;\r
+int locked;\r
\r
DBGSINGLEENTER2("ReleaseFromReadAhead: FileObject=0x%lX,Context=0x%lX",\r
(long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext);\r
dump_FileObject(callbacksp->FileObject);\r
+ /* Prevent deadlock during File Explorer copy to our destination. */\r
+ locked=unlock_full();\r
(*callbacksp->Callbacks.ReleaseFromReadAhead)(callbacksp->LazyWriteContext);\r
+ lock_full(locked);\r
DBGSINGLELEAVE0("ReleaseFromReadAhead");\r
}\r
\r
static VOID TcSetLogHandleForFile_FlushToLsnRoutine(IN PVOID LogHandle,IN LARGE_INTEGER Lsn)\r
{\r
PFLUSH_TO_LSN FlushToLsnRoutine;\r
+int locked;\r
\r
DBGSINGLEENTER2("FlushToLsnRoutine: LogHandle=0x%lX,Lsn=0x%lX",\r
(long)LogHandle,(long)Lsn.QuadPart);\r
+ /* Prevent deadlock during display of File Explorer directory listing. */\r
+ locked=unlock_full();\r
if ((FlushToLsnRoutine=LogHandle_find(LogHandle)))\r
(*FlushToLsnRoutine)(LogHandle,Lsn);\r
+ lock_full(locked);\r
DBGSINGLELEAVE0("FlushToLsnRoutine");\r
}\r
\r