/* $Id$ * Debugging tracer of IRPs and Cc* (Cache Manager) calls for W32 * Copyright (C) 2003 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #define CACHE_SIZE 0x200 #define G_N_ELEMENTS(arr) (sizeof(arr)/sizeof((arr)[0])) NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath); #ifdef ALLOC_PRAGMA #pragma alloc_text (INIT, DriverEntry) #endif /* Ke*Mutex() would be reentrant but it looked too unclear for me. * Never ExAcquireFastMutex() two FAST_MUTEX once or one FAST_MUTEX twice. * Use Ex*ResourceLite instead of Ex*FastMutex() as it would set IRQL to DPC * and we cannot pass the execution to Cc*() in DPC. * Ex*FastMutex() problem: IRP_MJ_SHUTDOWN: Assertion failure. */ static ERESOURCE lock_resource; static int lock_resource_count; static PETHREAD lock_resource_CurrentThread; static void lock_init(void) { if (ExInitializeResourceLite(&lock_resource)) KeBugCheck(0); lock_resource_count=0; lock_resource_CurrentThread=NULL; } static void lock(void) { if (lock_resource_CurrentThread==PsGetCurrentThread()) { if (lock_resource_count<=0) KeBugCheck(0); lock_resource_count++; return; } KeEnterCriticalRegion(); if (!ExAcquireResourceExclusiveLite(&lock_resource,TRUE)) KeBugCheck(0); KeLeaveCriticalRegion(); if (lock_resource_CurrentThread) KeBugCheck(0); if (lock_resource_count) KeBugCheck(0); lock_resource_CurrentThread=PsGetCurrentThread(); lock_resource_count++; } /* We need to _fully_ release the lock if we are passing the control to * callback functions. Single unlock() would free us from our current 'enter:' * lock but another lock() from Cc*() function which called us would be held. * FIXME: Enable of file compression still hangs in CcFlushCache(). */ static void lock_full(int n) { if (n<=0) KeBugCheck(0); if (lock_resource_CurrentThread==PsGetCurrentThread()) KeBugCheck(0); KeEnterCriticalRegion(); if (!ExAcquireResourceExclusiveLite(&lock_resource,TRUE)) KeBugCheck(0); KeLeaveCriticalRegion(); if (lock_resource_CurrentThread) KeBugCheck(0); if (lock_resource_count) KeBugCheck(0); lock_resource_CurrentThread=PsGetCurrentThread(); lock_resource_count+=n; } static void unlock(void) { if (lock_resource_CurrentThread!=PsGetCurrentThread()) KeBugCheck(0); if (lock_resource_count<=0) KeBugCheck(0); if (--lock_resource_count) return; lock_resource_CurrentThread=NULL; KeEnterCriticalRegion(); ExReleaseResourceLite(&lock_resource); KeLeaveCriticalRegion(); } static int unlock_full(void) { int r; if (lock_resource_CurrentThread!=PsGetCurrentThread()) KeBugCheck(0); if (lock_resource_count<=0) KeBugCheck(0); r=lock_resource_count; lock_resource_count=0; lock_resource_CurrentThread=NULL; KeEnterCriticalRegion(); ExReleaseResourceLite(&lock_resource); KeLeaveCriticalRegion(); return r; } #define DBGPREFIX "TraceFS(0x%08lX/0x%08lX): " #define DBGARG PsGetCurrentProcess(),PsGetCurrentThread() static int dbgindent=0; /* DBGSINGLEENTER*() / DBGSINGLELEAVE*() are protected by lock()/unlock() * to serialize the Cc*() function calls as otherwise the debug dumps * chronology may not match the real core execution chronology inside. */ /* lock() will protect dbg_unicode_string() static buffer. */ #define DBGSINGLE6(fmt,arg1,arg2,arg3,arg4,arg5,arg6) \ do { lock(); DbgPrint("%*s" DBGPREFIX fmt "\n",dbgindent,"",DBGARG,arg1,arg2,arg3,arg4,arg5,arg6); unlock(); } while (0) #define DBGSINGLE5(fmt,arg1,arg2,arg3,arg4,arg5) DBGSINGLE6(fmt,arg1,arg2,arg3,arg4,arg5,0) #define DBGSINGLE4(fmt,arg1,arg2,arg3,arg4) DBGSINGLE5(fmt,arg1,arg2,arg3,arg4,0) #define DBGSINGLE3(fmt,arg1,arg2,arg3) DBGSINGLE4(fmt,arg1,arg2,arg3,0) #define DBGSINGLE2(fmt,arg1,arg2) DBGSINGLE3(fmt,arg1,arg2,0) #define DBGSINGLE1(fmt,arg1) DBGSINGLE2(fmt,arg1,0) #define DBGSINGLE0(fmt) DBGSINGLE1(fmt,0) #define DBGSINGLEENTER6(fmt,arg1,arg2,arg3,arg4,arg5,arg6) \ do { lock(); DBGSINGLE6("enter: " fmt,arg1,arg2,arg3,arg4,arg5,arg6); dbgindent++; } while (0) #define DBGSINGLEENTER5(fmt,arg1,arg2,arg3,arg4,arg5) DBGSINGLEENTER6(fmt,arg1,arg2,arg3,arg4,arg5,0) #define DBGSINGLEENTER4(fmt,arg1,arg2,arg3,arg4) DBGSINGLEENTER5(fmt,arg1,arg2,arg3,arg4,0) #define DBGSINGLEENTER3(fmt,arg1,arg2,arg3) DBGSINGLEENTER4(fmt,arg1,arg2,arg3,0) #define DBGSINGLEENTER2(fmt,arg1,arg2) DBGSINGLEENTER3(fmt,arg1,arg2,0) #define DBGSINGLEENTER1(fmt,arg1) DBGSINGLEENTER2(fmt,arg1,0) #define DBGSINGLEENTER0(fmt) DBGSINGLEENTER1(fmt,0) #define DBGSINGLELEAVE3(fmt,arg1,arg2,arg3) \ do { dbgindent--; DBGSINGLE3("leave: " fmt,arg1,arg2,arg3); unlock(); } while (0) #define DBGSINGLELEAVE2(fmt,arg1,arg2) DBGSINGLELEAVE3(fmt,arg1,arg2,0) #define DBGSINGLELEAVE1(fmt,arg1) DBGSINGLELEAVE2(fmt,arg1,0) #define DBGSINGLELEAVE0(fmt) DBGSINGLELEAVE1(fmt,0) /* We cannot use DbgPrint("%wZ",...) as it must have IRQL PASSIVE_LEVEL which * is not satisfied. */ static const char *dbg_unicode_string(UNICODE_STRING *unicode_string) { static char buf[0x100]; char *d; PWSTR s; if (!unicode_string || !unicode_string->Buffer) return "NULL"; d=buf; *d++='\''; for (s=unicode_string->Buffer;sBuffer+(unicode_string->Length/2);s++) { if (d>=buf+sizeof(buf)-4) break; *d++=(char)*s; } *d++='\''; *d=0; return buf; } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS r; DEVICE_OBJECT *device_object; lock_init(); DBGSINGLEENTER1("DriverEntry: RegistryPath=%s",dbg_unicode_string(RegistryPath)); DBGSINGLE1("DriverEntry: %s","$Id$"); r=IoCreateDevice( DriverObject, /* DriverObject */ 0, /* DeviceExtensionSize */ NULL, /* DeviceName; optional */ FILE_DEVICE_UNKNOWN, /* DeviceType */ 0, /* DeviceCharacteristics */ FALSE, /* Exclusive */ &device_object); /* DeviceObject */ DBGSINGLELEAVE1("DriverEntry: r=0x%lX",(long)r); return r; } static const char *const dump_irp_mj_FILE_SYSTEM_CONTROL_MinorFunction_names[]={ "IRP_MN_USER_FS_REQUEST", "IRP_MN_MOUNT_VOLUME", "IRP_MN_VERIFY_VOLUME", "IRP_MN_LOAD_FILE_SYSTEM", "IRP_MN_KERNEL_CALL", }; /* Compatibility with DDK; the structures match. */ #define FileSystemControl DeviceIoControl #define FsControlCode IoControlCode #ifndef FSCTL_REQUEST_BATCH_OPLOCK #define FSCTL_REQUEST_BATCH_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_LOCK_VOLUME #define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_UNLOCK_VOLUME #define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_DISMOUNT_VOLUME #define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_MARK_VOLUME_DIRTY #define FSCTL_MARK_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM,12,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_SET_COMPRESSION #define FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM,16,METHOD_BUFFERED,FILE_READ_DATA|FILE_WRITE_DATA) #endif #ifndef FSCTL_INVALIDATE_VOLUMES #define FSCTL_INVALIDATE_VOLUMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM,21,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_IS_VOLUME_DIRTY #define FSCTL_IS_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM,30,METHOD_BUFFERED,FILE_ANY_ACCESS) #endif #ifndef FSCTL_FILE_PREFETCH #define FSCTL_FILE_PREFETCH CTL_CODE(FILE_DEVICE_FILE_SYSTEM,72,METHOD_BUFFERED,FILE_SPECIAL_ACCESS) #endif static struct SectionObjectPointer { FILE_OBJECT *FileObject; PVOID SharedCacheMap; } SectionObjectPointer_cache[CACHE_SIZE]; static int SectionObjectPointer_cache_used=0; static struct SectionObjectPointer *SectionObjectPointer_set(FILE_OBJECT *FileObject) { struct SectionObjectPointer *sopp; PVOID SharedCacheMap; if (!FileObject->SectionObjectPointer) return NULL; if (!(SharedCacheMap=FileObject->SectionObjectPointer->SharedCacheMap)) return NULL; for (sopp=SectionObjectPointer_cache;soppFileObject==FileObject || sopp->SharedCacheMap==SharedCacheMap) break; } if (sopp>=SectionObjectPointer_cache+G_N_ELEMENTS(SectionObjectPointer_cache)) return NULL; if (sopp==SectionObjectPointer_cache+SectionObjectPointer_cache_used) SectionObjectPointer_cache_used++; sopp->FileObject=FileObject; sopp->SharedCacheMap=SharedCacheMap; return sopp; } static FILE_OBJECT *SectionObjectPointer_find(SECTION_OBJECT_POINTERS *SectionObjectPointer) { struct SectionObjectPointer *sopp; PVOID SharedCacheMap; if (!SectionObjectPointer) return NULL; if (!(SharedCacheMap=SectionObjectPointer->SharedCacheMap)) return NULL; for (sopp=SectionObjectPointer_cache;soppSharedCacheMap==SharedCacheMap) return sopp->FileObject; } return NULL; } static void dump_FileObject(FILE_OBJECT *FileObject) { if (!FileObject) { DBGSINGLE0("FileObject=NULL"); return; } DBGSINGLE5("FileObject=0x%lX: FileName=%s,Flags=0x%lX,SectionObjectPointer=0x%lX,->SharedCacheMap=0x%lX", (long)FileObject, dbg_unicode_string(&FileObject->FileName),FileObject->Flags, (long)FileObject->SectionObjectPointer, (!FileObject->SectionObjectPointer ? -1 : (long)FileObject->SectionObjectPointer->SharedCacheMap)); SectionObjectPointer_set(FileObject); } static FILE_OBJECT *dump_irp_mj(struct _DEVICE_OBJECT *DeviceObject,struct _IRP *Irp) { IO_STACK_LOCATION *IoStackLocation; FILE_OBJECT *FileObject; if (!Irp) { DBGSINGLE0("Irp==NULL"); return NULL; } IoStackLocation=IoGetCurrentIrpStackLocation(Irp); if (!IoStackLocation) { DBGSINGLE0("IoStackLocation==NULL"); return NULL; } FileObject=IoStackLocation->FileObject; dump_FileObject(FileObject); switch (IoStackLocation->MajorFunction) { case IRP_MJ_READ: DBGSINGLE2("READ: ByteOffset=0x%lX,Length=0x%lX", (long)IoStackLocation->Parameters.Read.ByteOffset.QuadPart, IoStackLocation->Parameters.Read.Length); break; case IRP_MJ_WRITE: DBGSINGLE2("WRITE: ByteOffset=0x%lX,Length=0x%lX", (long)IoStackLocation->Parameters.Write.ByteOffset.QuadPart, IoStackLocation->Parameters.Write.Length); break; case IRP_MJ_FILE_SYSTEM_CONTROL: DBGSINGLE2("FILE_SYSTEM_CONTROL: MinorFunction=%s (%0x%X)", ((1 && IoStackLocation->MinorFunction>=0 && IoStackLocation->MinorFunctionMinorFunction] : "???"), IoStackLocation->MinorFunction); switch (IoStackLocation->MinorFunction) { case IRP_MN_USER_FS_REQUEST: { const char *FsControlCode_name; switch (IoStackLocation->Parameters.FileSystemControl.FsControlCode) { case FSCTL_REQUEST_BATCH_OPLOCK: FsControlCode_name="FSCTL_REQUEST_BATCH_OPLOCK"; break; case FSCTL_LOCK_VOLUME: FsControlCode_name="FSCTL_LOCK_VOLUME"; break; case FSCTL_UNLOCK_VOLUME: FsControlCode_name="FSCTL_UNLOCK_VOLUME"; break; case FSCTL_DISMOUNT_VOLUME: FsControlCode_name="FSCTL_DISMOUNT_VOLUME"; break; case FSCTL_MARK_VOLUME_DIRTY: FsControlCode_name="FSCTL_MARK_VOLUME_DIRTY"; break; case FSCTL_SET_COMPRESSION: FsControlCode_name="FSCTL_SET_COMPRESSION"; break; case FSCTL_INVALIDATE_VOLUMES: FsControlCode_name="FSCTL_INVALIDATE_VOLUMES"; break; case FSCTL_IS_VOLUME_DIRTY: FsControlCode_name="FSCTL_IS_VOLUME_DIRTY"; break; case FSCTL_FILE_PREFETCH: FsControlCode_name="FSCTL_FILE_PREFETCH"; break; default: FsControlCode_name="???"; break; } DBGSINGLE2("USER_FS_REQUEST: FsControlCode=%s (0x%X)",FsControlCode_name, IoStackLocation->Parameters.FileSystemControl.FsControlCode); } break; } } return FileObject; } #define TRACEFS_MAJORS \ TRACEFS_MAJOR(IRP_MJ_CREATE) \ TRACEFS_MAJOR(IRP_MJ_CREATE_NAMED_PIPE) \ TRACEFS_MAJOR(IRP_MJ_CLOSE) \ TRACEFS_MAJOR(IRP_MJ_READ) \ TRACEFS_MAJOR(IRP_MJ_WRITE) \ TRACEFS_MAJOR(IRP_MJ_QUERY_INFORMATION) \ TRACEFS_MAJOR(IRP_MJ_SET_INFORMATION) \ TRACEFS_MAJOR(IRP_MJ_QUERY_EA) \ TRACEFS_MAJOR(IRP_MJ_SET_EA) \ TRACEFS_MAJOR(IRP_MJ_FLUSH_BUFFERS) \ TRACEFS_MAJOR(IRP_MJ_QUERY_VOLUME_INFORMATION) \ TRACEFS_MAJOR(IRP_MJ_SET_VOLUME_INFORMATION) \ TRACEFS_MAJOR(IRP_MJ_DIRECTORY_CONTROL) \ TRACEFS_MAJOR(IRP_MJ_FILE_SYSTEM_CONTROL) \ TRACEFS_MAJOR(IRP_MJ_DEVICE_CONTROL) \ TRACEFS_MAJOR(IRP_MJ_INTERNAL_DEVICE_CONTROL) \ TRACEFS_MAJOR(IRP_MJ_SHUTDOWN) \ TRACEFS_MAJOR(IRP_MJ_LOCK_CONTROL) \ TRACEFS_MAJOR(IRP_MJ_CLEANUP) \ TRACEFS_MAJOR(IRP_MJ_CREATE_MAILSLOT) \ TRACEFS_MAJOR(IRP_MJ_QUERY_SECURITY) \ TRACEFS_MAJOR(IRP_MJ_SET_SECURITY) \ TRACEFS_MAJOR(IRP_MJ_POWER) \ TRACEFS_MAJOR(IRP_MJ_SYSTEM_CONTROL) \ TRACEFS_MAJOR(IRP_MJ_DEVICE_CHANGE) \ TRACEFS_MAJOR(IRP_MJ_QUERY_QUOTA) \ TRACEFS_MAJOR(IRP_MJ_SET_QUOTA) \ TRACEFS_MAJOR(IRP_MJ_PNP) #define TRACEFS_MAJOR(irp_mj_name) \ static NTSTATUS (*tracefs_major_##irp_mj_name##_orig)(IN struct _DEVICE_OBJECT *DeviceObject,IN struct _IRP *Irp); \ static NTSTATUS tracefs_major_##irp_mj_name(IN struct _DEVICE_OBJECT *DeviceObject,IN struct _IRP *Irp) \ { \ NTSTATUS r; \ int locked; \ FILE_OBJECT *FileObject; \ \ DBGSINGLEENTER0( #irp_mj_name ); \ FileObject=dump_irp_mj(DeviceObject,Irp); \ /* Prevent deadlock during display of File Explorer directory listing. \ * Needed at least for IRP_MJ_DIRECTORY_CONTROL and IRP_MJ_CLOSE. \ */ \ locked=unlock_full(); \ r=(*tracefs_major_##irp_mj_name##_orig)(DeviceObject,Irp); \ lock_full(locked); \ /* Dump_irp_mj() would crash here even now IRP_MJ_READ; \ * Invalid FileObject address gets detected. \ */ \ dump_FileObject(FileObject); \ DBGSINGLELEAVE1( #irp_mj_name ": r=0x%lX",(long)r); \ return r; \ } TRACEFS_MAJORS #undef TRACEFS_MAJOR VOID IoRegisterFileSystem(IN OUT PDEVICE_OBJECT DeviceObject); VOID ToRegisterFileSystem(IN OUT PDEVICE_OBJECT DeviceObject) { DBGSINGLEENTER0("IoRegisterFileSystem"); #define TRACEFS_MAJOR(irp_mj_name) do { \ tracefs_major_##irp_mj_name##_orig=DeviceObject->DriverObject->MajorFunction[irp_mj_name]; \ DeviceObject->DriverObject->MajorFunction[irp_mj_name]=tracefs_major_##irp_mj_name; \ } while (0); TRACEFS_MAJORS #undef TRACEFS_MAJOR IoRegisterFileSystem(DeviceObject); DBGSINGLELEAVE0("IoRegisterFileSystem"); } static char PsCreateSystemThread_bogusthread; NTSTATUS TsCreateSystemThread( OUT PHANDLE ThreadHandle, IN ULONG DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext ) { DBGSINGLEENTER1("PsCreateSystemThread: StartRoutine=0x%lX",(long)StartRoutine); if (ThreadHandle) *ThreadHandle=(HANDLE)&PsCreateSystemThread_bogusthread; DBGSINGLELEAVE0("PsCreateSystemThread"); return STATUS_SUCCESS; } NTSTATUS NTAPI TwClose( IN HANDLE Handle ) { DBGSINGLEENTER0("ZwClose"); if (Handle==(HANDLE)&PsCreateSystemThread_bogusthread) { DBGSINGLELEAVE0("ZwClose: bogusthread catched"); return STATUS_SUCCESS; } DBGSINGLELEAVE0("ZwClose: passed"); return ZwClose(Handle); } BOOLEAN CcCanIWrite ( IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN BOOLEAN Retrying ); BOOLEAN TcCanIWrite ( IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN BOOLEAN Retrying ) { BOOLEAN r; DBGSINGLEENTER4("CcCanIWrite: FileObject=0x%lX,BytesToWrite=0x%lX,Wait=%d,Retrying=%d", (long)FileObject,BytesToWrite,Wait,Retrying); dump_FileObject(FileObject); r=CcCanIWrite ( FileObject, BytesToWrite, Wait, Retrying ); DBGSINGLELEAVE1("CcCanIWrite: r=%d",r); return r; } BOOLEAN CcCopyRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus ); BOOLEAN TcCopyRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus ) { BOOLEAN r; DBGSINGLEENTER5("CcCopyRead: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Wait=%d,Buffer=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Wait,(long)Buffer); dump_FileObject(FileObject); r=CcCopyRead ( FileObject, FileOffset, Length, Wait, Buffer, IoStatus ); DBGSINGLELEAVE3("CcCopyRead: r=%d,IoStatus->Status=0x%lX,IoStatus->Information=0x%lX", r,(!IoStatus ? -1 : (long)IoStatus->Status),(!IoStatus ? -1 : (long)IoStatus->Information)); return r; } BOOLEAN CcCopyWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer ); BOOLEAN TcCopyWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer ) { BOOLEAN r; DBGSINGLEENTER5("CcCopyWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Wait=%d,Buffer=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Wait,(long)Buffer); dump_FileObject(FileObject); r=CcCopyWrite ( FileObject, FileOffset, Length, Wait, Buffer ); DBGSINGLELEAVE1("CcCopyWrite: r=%d",r); return r; } typedef VOID (*PCC_POST_DEFERRED_WRITE) ( IN PVOID Context1, IN PVOID Context2 ); VOID CcDeferWrite ( IN PFILE_OBJECT FileObject, IN PCC_POST_DEFERRED_WRITE PostRoutine, IN PVOID Context1, IN PVOID Context2, IN ULONG BytesToWrite, IN BOOLEAN Retrying ); TcDeferWrite ( IN PFILE_OBJECT FileObject, IN PCC_POST_DEFERRED_WRITE PostRoutine, IN PVOID Context1, IN PVOID Context2, IN ULONG BytesToWrite, IN BOOLEAN Retrying ) { DBGSINGLEENTER6("CcDeferWrite: FileObject=0x%lX,PostRoutine=0x%lX,Context1=0x%lX,Context2=0x%lX," "BytesToWrite=0x%lX,Retrying=%d", (long)FileObject,(long)PostRoutine,(long)Context1,(long)Context2, BytesToWrite,Retrying); dump_FileObject(FileObject); CcDeferWrite ( FileObject, PostRoutine, Context1, Context2, BytesToWrite, Retrying ); DBGSINGLELEAVE0("CcDeferWrite"); } VOID CcFastCopyRead ( IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN ULONG PageCount, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus ); VOID TcFastCopyRead ( IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN ULONG PageCount, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus ) { DBGSINGLEENTER5("CcFastCopyRead: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,PageCount=0x%lX,Buffer=0x%lX", (long)FileObject,FileOffset,Length,PageCount,(long)Buffer); dump_FileObject(FileObject); CcFastCopyRead ( FileObject, FileOffset, Length, PageCount, Buffer, IoStatus ); DBGSINGLELEAVE2("CcFastCopyRead: IoStatus->Status=0x%lX,IoStatus->Information=0x%lX", (!IoStatus ? -1 : (long)IoStatus->Status),(!IoStatus ? -1 : (long)IoStatus->Information)); } VOID CcFastCopyWrite ( IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN PVOID Buffer ); VOID TcFastCopyWrite ( IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN PVOID Buffer ) { DBGSINGLEENTER4("CcFastCopyWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Buffer=0x%lX", (long)FileObject,FileOffset,Length,(long)Buffer); dump_FileObject(FileObject); CcFastCopyWrite ( FileObject, FileOffset, Length, Buffer ); DBGSINGLELEAVE0("CcFastCopyWrite"); } VOID CcFlushCache ( IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, OUT PIO_STATUS_BLOCK IoStatus OPTIONAL ); VOID TcFlushCache ( IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, OUT PIO_STATUS_BLOCK IoStatus OPTIONAL ) { DBGSINGLEENTER4("CcFlushCache: SectionObjectPointer=0x%lX,->SharedCacheMap=0x%lX,FileOffset=0x%lX,Length=0x%lX", (long)SectionObjectPointer, (!SectionObjectPointer ? -1 : (long)SectionObjectPointer->SharedCacheMap), (!FileOffset ? -1 : (long)FileOffset->QuadPart),Length); dump_FileObject(SectionObjectPointer_find(SectionObjectPointer)); CcFlushCache ( SectionObjectPointer, FileOffset, Length, IoStatus ); dump_FileObject(SectionObjectPointer_find(SectionObjectPointer)); DBGSINGLELEAVE2("CcFlushCache: IoStatus->Status=0x%lX,IoStatus->Information=0x%lX", (!IoStatus ? -1 : (long)IoStatus->Status),(!IoStatus ? -1 : (long)IoStatus->Information)); } typedef VOID (*PDIRTY_PAGE_ROUTINE) ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN PLARGE_INTEGER OldestLsn, IN PLARGE_INTEGER NewestLsn, IN PVOID Context1, IN PVOID Context2 ); static PDIRTY_PAGE_ROUTINE TcGetDirtyPages_DirtyPageRoutine_orig; static BOOLEAN TcGetDirtyPages_DirtyPageRoutine_used=FALSE; static VOID TcGetDirtyPages_DirtyPageRoutine(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length, IN PLARGE_INTEGER OldestLsn,IN PLARGE_INTEGER NewestLsn,IN PVOID Context1,IN PVOID Context2) { DBGSINGLEENTER5("DirtyPageRoutine: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX," "OldestLsn=0x%lX,NewestLsn=0x%lX,Context1,Context2", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length, (!OldestLsn ? -1 : (long)OldestLsn->QuadPart),(!NewestLsn ? -1 : (long)NewestLsn->QuadPart)); dump_FileObject(FileObject); (*TcGetDirtyPages_DirtyPageRoutine_orig)(FileObject,FileOffset,Length,OldestLsn,NewestLsn,Context1,Context2); DBGSINGLELEAVE0("DirtyPageRoutine"); } LARGE_INTEGER CcGetDirtyPages ( IN PVOID LogHandle, IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine, IN PVOID Context1, IN PVOID Context2 ); LARGE_INTEGER TcGetDirtyPages ( IN PVOID LogHandle, IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine, IN PVOID Context1, IN PVOID Context2 ) { LARGE_INTEGER r; DBGSINGLEENTER4("CcGetDirtyPages: LogHandle=0x%lX,DirtyPageRoutine=0x%lX,Context1=0x%lX,Context2=0x%lX", (long)LogHandle,(long)DirtyPageRoutine,(long)Context1,(long)Context2); if (TcGetDirtyPages_DirtyPageRoutine_used) DBGSINGLE0("CcGetDirtyPages: ERROR: TcGetDirtyPages_DirtyPageRoutine_used"); else { TcGetDirtyPages_DirtyPageRoutine_used=TRUE; TcGetDirtyPages_DirtyPageRoutine_orig=DirtyPageRoutine; DirtyPageRoutine=TcGetDirtyPages_DirtyPageRoutine; } r=CcGetDirtyPages ( LogHandle, DirtyPageRoutine, Context1, Context2 ); if (DirtyPageRoutine==TcGetDirtyPages_DirtyPageRoutine) TcGetDirtyPages_DirtyPageRoutine_used=FALSE; DBGSINGLELEAVE1("CcGetDirtyPages: r=0x%lX",(long)r.QuadPart); return r; } typedef BOOLEAN (*PACQUIRE_FOR_LAZY_WRITE)(IN PVOID Context,IN BOOLEAN Wait); typedef VOID (*PRELEASE_FROM_LAZY_WRITE)(IN PVOID Context); typedef BOOLEAN (*PACQUIRE_FOR_READ_AHEAD)(IN PVOID Context,IN BOOLEAN Wait); typedef VOID (*PRELEASE_FROM_READ_AHEAD)(IN PVOID Context); typedef struct _CACHE_MANAGER_CALLBACKS { PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite; PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite; PACQUIRE_FOR_READ_AHEAD AcquireForReadAhead; PRELEASE_FROM_READ_AHEAD ReleaseFromReadAhead; } CACHE_MANAGER_CALLBACKS,*PCACHE_MANAGER_CALLBACKS; static struct Callbacks { FILE_OBJECT *FileObject; CACHE_MANAGER_CALLBACKS Callbacks; PVOID LazyWriteContext; } Callbacks_cache[CACHE_SIZE]; static int Callbacks_cache_used=0; static struct Callbacks *Callbacks_set(FILE_OBJECT *FileObject,CACHE_MANAGER_CALLBACKS *Callbacks,PVOID LazyWriteContext) { struct Callbacks *callbacksp; for (callbacksp=Callbacks_cache;callbackspFileObject==FileObject) break; } if (callbacksp>=Callbacks_cache+G_N_ELEMENTS(Callbacks_cache)) return NULL; if (callbacksp==Callbacks_cache+Callbacks_cache_used) Callbacks_cache_used++; callbacksp->FileObject=FileObject; callbacksp->Callbacks=*Callbacks; callbacksp->LazyWriteContext=LazyWriteContext; return callbacksp; } static BOOLEAN TcInitializeCacheMap_AcquireForLazyWrite(IN PVOID Context,IN BOOLEAN Wait) { struct Callbacks *callbacksp=Context; BOOLEAN r; int locked; DBGSINGLEENTER3("AcquireForLazyWrite: FileObject=0x%lX,Context=0x%lX,Wait=%d", (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext,Wait); dump_FileObject(callbacksp->FileObject); /* Prevent deadlock during File Explorer copy to our destination. */ locked=unlock_full(); r=(*callbacksp->Callbacks.AcquireForLazyWrite)(callbacksp->LazyWriteContext,Wait); lock_full(locked); DBGSINGLELEAVE1("AcquireForLazyWrite: r=%d",r); return r; } static VOID TcInitializeCacheMap_ReleaseFromLazyWrite(IN PVOID Context) { struct Callbacks *callbacksp=Context; int locked; DBGSINGLEENTER2("ReleaseFromLazyWrite: FileObject=0x%lX,Context=0x%lX", (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext); dump_FileObject(callbacksp->FileObject); /* Prevent deadlock during File Explorer copy to our destination. */ locked=unlock_full(); (*callbacksp->Callbacks.ReleaseFromLazyWrite)(callbacksp->LazyWriteContext); lock_full(locked); DBGSINGLELEAVE0("ReleaseFromLazyWrite"); } static BOOLEAN TcInitializeCacheMap_AcquireForReadAhead(IN PVOID Context,IN BOOLEAN Wait) { struct Callbacks *callbacksp=Context; BOOLEAN r; int locked; DBGSINGLEENTER3("AcquireForReadAhead: FileObject=0x%lX,Context=0x%lX,Wait=%d", (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext,Wait); dump_FileObject(callbacksp->FileObject); /* Prevent deadlock during File Explorer copy to our destination. */ locked=unlock_full(); r=(*callbacksp->Callbacks.AcquireForReadAhead)(callbacksp->LazyWriteContext,Wait); lock_full(locked); DBGSINGLELEAVE1("AcquireForReadAhead: r=%d",r); return r; } static VOID TcInitializeCacheMap_ReleaseFromReadAhead(IN PVOID Context) { struct Callbacks *callbacksp=Context; int locked; DBGSINGLEENTER2("ReleaseFromReadAhead: FileObject=0x%lX,Context=0x%lX", (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext); dump_FileObject(callbacksp->FileObject); /* Prevent deadlock during File Explorer copy to our destination. */ locked=unlock_full(); (*callbacksp->Callbacks.ReleaseFromReadAhead)(callbacksp->LazyWriteContext); lock_full(locked); DBGSINGLELEAVE0("ReleaseFromReadAhead"); } static CACHE_MANAGER_CALLBACKS TcInitializeCacheMap_Callbacks={ TcInitializeCacheMap_AcquireForLazyWrite, TcInitializeCacheMap_ReleaseFromLazyWrite, TcInitializeCacheMap_AcquireForReadAhead, TcInitializeCacheMap_ReleaseFromReadAhead, }; typedef struct _CC_FILE_SIZES { LARGE_INTEGER AllocationSize; LARGE_INTEGER FileSize; LARGE_INTEGER ValidDataLength; } CC_FILE_SIZES,*PCC_FILE_SIZES; VOID CcInitializeCacheMap ( IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext ); VOID TcInitializeCacheMap ( IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext ) { struct Callbacks *callbacksp; DBGSINGLEENTER5("CcInitializeCacheMap: FileObject=0x%lX," "FileSizes,->AllocationSize=0x%lX,->FileSize=0x%lX,->ValidDataLength=0x%lX," "PinAccess=%d,Callbacks,LazyWriteContext", (long)FileObject, (!FileSizes ? -1 : (long)FileSizes->AllocationSize.QuadPart), (!FileSizes ? -1 : (long)FileSizes->FileSize.QuadPart), (!FileSizes ? -1 : (long)FileSizes->ValidDataLength.QuadPart), PinAccess); dump_FileObject(FileObject); if ((callbacksp=Callbacks_set(FileObject,Callbacks,LazyWriteContext))) { Callbacks=&TcInitializeCacheMap_Callbacks; LazyWriteContext=callbacksp; if (Callbacks->AcquireForLazyWrite !=TcInitializeCacheMap_AcquireForLazyWrite) DBGSINGLE1("CcInitializeCacheMap: ERROR: AcquireForLazyWrite =0x%lX",Callbacks->AcquireForLazyWrite); if (Callbacks->ReleaseFromLazyWrite!=TcInitializeCacheMap_ReleaseFromLazyWrite) DBGSINGLE1("CcInitializeCacheMap: ERROR: ReleaseFromLazyWrite=0x%lX",Callbacks->ReleaseFromLazyWrite); if (Callbacks->AcquireForReadAhead !=TcInitializeCacheMap_AcquireForReadAhead) DBGSINGLE1("CcInitializeCacheMap: ERROR: AcquireForReadAhead =0x%lX",Callbacks->AcquireForReadAhead); if (Callbacks->ReleaseFromReadAhead!=TcInitializeCacheMap_ReleaseFromReadAhead) DBGSINGLE1("CcInitializeCacheMap: ERROR: ReleaseFromReadAhead=0x%lX",Callbacks->ReleaseFromReadAhead); } CcInitializeCacheMap ( FileObject, FileSizes, PinAccess, Callbacks, LazyWriteContext ); dump_FileObject(FileObject); DBGSINGLELEAVE0("CcInitializeCacheMap"); } BOOLEAN CcMapData ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer ); BOOLEAN TcMapData ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer ) { BOOLEAN r; DBGSINGLEENTER4("CcMapData: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags); dump_FileObject(FileObject); r=CcMapData ( FileObject, FileOffset, Length, Flags, Bcb, Buffer ); DBGSINGLELEAVE3("CcMapData: r=%d,Bcb=0x%lX,Buffer=0x%lX", r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer)); return r; } VOID CcMdlRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus ); VOID TcMdlRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus ) { DBGSINGLEENTER3("CcMdlRead: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length); dump_FileObject(FileObject); CcMdlRead ( FileObject, FileOffset, Length, MdlChain, IoStatus ); DBGSINGLELEAVE3("CcMdlRead: MdlChain=0x%lX,IoStatus->Status=0x%lX,IoStatus->Information=0x%lX", (!MdlChain ? -1 : (long)*MdlChain), (!IoStatus ? -1 : (long)IoStatus->Status),(!IoStatus ? -1 : (long)IoStatus->Information)); } VOID CcMdlReadComplete ( IN PFILE_OBJECT FileObject, IN PMDL MdlChain ); VOID TcMdlReadComplete ( IN PFILE_OBJECT FileObject, IN PMDL MdlChain ) { DBGSINGLEENTER2("CcMdlReadComplete: FileObject=0x%lX,MdlChain=0x%lX", (long)FileObject,(long)MdlChain); dump_FileObject(FileObject); CcMdlReadComplete ( FileObject, MdlChain ); DBGSINGLELEAVE0("CcMdlReadComplete"); } VOID CcMdlWriteAbort ( IN PFILE_OBJECT FileObject, IN PMDL MdlChain ); VOID TcMdlWriteAbort ( IN PFILE_OBJECT FileObject, IN PMDL MdlChain ) { DBGSINGLEENTER2("CcMdlWriteAbort: FileObject=0x%lX,MdlChain=0x%lX", (long)FileObject,(long)MdlChain); dump_FileObject(FileObject); CcMdlWriteAbort ( FileObject, MdlChain ); DBGSINGLELEAVE0("CcMdlWriteAbort"); } VOID CcMdlWriteComplete ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain ); VOID TcMdlWriteComplete ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain ) { DBGSINGLEENTER3("CcMdlWriteComplete: FileObject=0x%lX,FileOffset=0x%lX,MdlChain=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),(long)MdlChain); dump_FileObject(FileObject); CcMdlWriteComplete ( FileObject, FileOffset, MdlChain ); DBGSINGLELEAVE0("CcMdlWriteComplete"); } BOOLEAN CcPinMappedData ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, IN OUT PVOID *Bcb ); BOOLEAN TcPinMappedData ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, IN OUT PVOID *Bcb ) { BOOLEAN r; DBGSINGLEENTER4("CcPinMappedData: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags); dump_FileObject(FileObject); r=CcPinMappedData ( FileObject, FileOffset, Length, Flags, Bcb ); DBGSINGLELEAVE2("CcPinMappedData: r=%d,Bcb=0x%lX", r,(!Bcb ? -1 : (long)*Bcb)); return r; } BOOLEAN CcPinRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer ); BOOLEAN TcPinRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer ) { BOOLEAN r; DBGSINGLEENTER4("CcPinRead: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags); dump_FileObject(FileObject); r=CcPinRead ( FileObject, FileOffset, Length, Flags, Bcb, Buffer ); DBGSINGLELEAVE3("CcPinRead: r=%d,Bcb=0x%lX,Buffer=0x%lX", r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer)); return r; } VOID CcPrepareMdlWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus ); VOID TcPrepareMdlWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus ) { DBGSINGLEENTER3("CcPrepareMdlWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length); dump_FileObject(FileObject); CcPrepareMdlWrite ( FileObject, FileOffset, Length, MdlChain, IoStatus ); DBGSINGLELEAVE3("CcPrepareMdlWrite: MdlChain=0x%lX,IoStatus->Status=0x%lX,IoStatus->Information=0x%lX", (!MdlChain ? -1 : (long)*MdlChain), (!IoStatus ? -1 : (long)IoStatus->Status),(!IoStatus ? -1 : (long)IoStatus->Information)); } BOOLEAN CcPreparePinWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Zero, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer ); BOOLEAN TcPreparePinWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Zero, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer ) { BOOLEAN r; DBGSINGLEENTER5("CcPreparePinWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Zero=%d,Flags=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Zero,Flags); dump_FileObject(FileObject); r=CcPreparePinWrite ( FileObject, FileOffset, Length, Zero, Flags, Bcb, Buffer ); DBGSINGLELEAVE3("CcPreparePinWrite: r=%d,Bcb=0x%lX,Buffer=0x%lX", r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer)); return r; } BOOLEAN CcPurgeCacheSection ( IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps ); BOOLEAN TcPurgeCacheSection ( IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps ) { BOOLEAN r; DBGSINGLEENTER5("CcPurgeCacheSection: SectionObjectPointer=0x%lX,->SharedCacheMap=0x%lX,FileOffset=0x%lX,Length=0x%lX," "UninitializeCacheMaps=%d", (long)SectionObjectPointer, (!SectionObjectPointer ? -1 : (long)SectionObjectPointer->SharedCacheMap), (!FileOffset ? -1 : (long)FileOffset->QuadPart),Length, UninitializeCacheMaps); dump_FileObject(SectionObjectPointer_find(SectionObjectPointer)); r=CcPurgeCacheSection ( SectionObjectPointer, FileOffset, Length, UninitializeCacheMaps ); dump_FileObject(SectionObjectPointer_find(SectionObjectPointer)); DBGSINGLELEAVE1("CcPurgeCacheSection: r=%d",r); return r; } PVOID CcRemapBcb ( IN PVOID Bcb ); PVOID TcRemapBcb ( IN PVOID Bcb ) { PVOID r; DBGSINGLEENTER1("CcRemapBcb: Bcb=0x%lX",(long)Bcb); r=CcRemapBcb ( Bcb ); DBGSINGLELEAVE1("CcRemapBcb: r=0x%lX",(long)r); return r; } VOID CcSetAdditionalCacheAttributes ( IN PFILE_OBJECT FileObject, IN BOOLEAN DisableReadAhead, IN BOOLEAN DisableWriteBehind ); VOID TcSetAdditionalCacheAttributes ( IN PFILE_OBJECT FileObject, IN BOOLEAN DisableReadAhead, IN BOOLEAN DisableWriteBehind ) { DBGSINGLEENTER3("CcSetAdditionalCacheAttributes: FileObject=0x%lX,DisableReadAhead=%d,DisableWriteBehind=%d", (long)FileObject,DisableReadAhead,DisableWriteBehind); dump_FileObject(FileObject); CcSetAdditionalCacheAttributes ( FileObject, DisableReadAhead, DisableWriteBehind ); DBGSINGLELEAVE0("CcSetAdditionalCacheAttributes"); } VOID CcSetBcbOwnerPointer ( IN PVOID Bcb, IN PVOID OwnerPointer ); VOID TcSetBcbOwnerPointer ( IN PVOID Bcb, IN PVOID OwnerPointer ) { DBGSINGLEENTER2("CcSetBcbOwnerPointer: Bcb=0x%lX,OwnerPointer=0x%lX", (long)Bcb,(long)OwnerPointer); CcSetBcbOwnerPointer ( Bcb, OwnerPointer ); DBGSINGLELEAVE0("CcSetBcbOwnerPointer"); } VOID CcSetDirtyPinnedData ( IN PVOID BcbVoid, IN PLARGE_INTEGER Lsn OPTIONAL ); VOID TcSetDirtyPinnedData ( IN PVOID BcbVoid, IN PLARGE_INTEGER Lsn OPTIONAL ) { DBGSINGLEENTER2("CcSetDirtyPinnedData: BcbVoid=0x%lX,Lsn=0x%lX", (long)BcbVoid,(!Lsn ? -1 : (long)Lsn->QuadPart)); CcSetDirtyPinnedData ( BcbVoid, Lsn ); DBGSINGLELEAVE0("CcSetDirtyPinnedData"); } VOID CcSetFileSizes ( IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes ); VOID TcSetFileSizes ( IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes ) { DBGSINGLEENTER4("CcSetFileSizes: FileObject=0x%lX," "FileSizes,->AllocationSize=0x%lX,->FileSize=0x%lX,->ValidDataLength=0x%lX", (long)FileObject, (!FileSizes ? -1 : (long)FileSizes->AllocationSize.QuadPart), (!FileSizes ? -1 : (long)FileSizes->FileSize.QuadPart), (!FileSizes ? -1 : (long)FileSizes->ValidDataLength.QuadPart)); dump_FileObject(FileObject); CcSetFileSizes ( FileObject, FileSizes ); DBGSINGLELEAVE0("CcSetFileSizes"); } typedef VOID (*PFLUSH_TO_LSN)(IN PVOID LogHandle,IN LARGE_INTEGER Lsn); static struct LogHandle { PVOID LogHandle; PFLUSH_TO_LSN FlushToLsnRoutine; } LogHandle_cache[CACHE_SIZE]; static int LogHandle_cache_used=0; static BOOLEAN LogHandle_set(PVOID LogHandle,PFLUSH_TO_LSN FlushToLsnRoutine) { struct LogHandle *loghandlep; for (loghandlep=LogHandle_cache;loghandlepLogHandle==LogHandle) break; } if (loghandlep>=LogHandle_cache+G_N_ELEMENTS(LogHandle_cache)) return FALSE; if (loghandlep==LogHandle_cache+LogHandle_cache_used) LogHandle_cache_used++; loghandlep->LogHandle=LogHandle; loghandlep->FlushToLsnRoutine=FlushToLsnRoutine; return TRUE; } static PFLUSH_TO_LSN LogHandle_find(PVOID LogHandle) { struct LogHandle *loghandlep; for (loghandlep=LogHandle_cache;loghandlepLogHandle==LogHandle) return loghandlep->FlushToLsnRoutine; } return NULL; } static VOID TcSetLogHandleForFile_FlushToLsnRoutine(IN PVOID LogHandle,IN LARGE_INTEGER Lsn) { PFLUSH_TO_LSN FlushToLsnRoutine; int locked; DBGSINGLEENTER2("FlushToLsnRoutine: LogHandle=0x%lX,Lsn=0x%lX", (long)LogHandle,(long)Lsn.QuadPart); /* Prevent deadlock during display of File Explorer directory listing. */ locked=unlock_full(); if ((FlushToLsnRoutine=LogHandle_find(LogHandle))) (*FlushToLsnRoutine)(LogHandle,Lsn); lock_full(locked); DBGSINGLELEAVE0("FlushToLsnRoutine"); } VOID CcSetLogHandleForFile ( IN PFILE_OBJECT FileObject, IN PVOID LogHandle, IN PFLUSH_TO_LSN FlushToLsnRoutine ); VOID TcSetLogHandleForFile ( IN PFILE_OBJECT FileObject, IN PVOID LogHandle, IN PFLUSH_TO_LSN FlushToLsnRoutine ) { DBGSINGLEENTER3("CcSetLogHandleForFile: FileObject=0x%lX,LogHandle=0x%lX,FlushToLsnRoutine=0x%lX", (long)FileObject,(long)LogHandle,(long)FlushToLsnRoutine); dump_FileObject(FileObject); if (LogHandle_set(LogHandle,FlushToLsnRoutine)) FlushToLsnRoutine=TcSetLogHandleForFile_FlushToLsnRoutine; CcSetLogHandleForFile ( FileObject, LogHandle, FlushToLsnRoutine ); DBGSINGLELEAVE0("CcSetLogHandleForFile"); } VOID CcSetReadAheadGranularity ( IN PFILE_OBJECT FileObject, IN ULONG Granularity ); VOID TcSetReadAheadGranularity ( IN PFILE_OBJECT FileObject, IN ULONG Granularity ) { DBGSINGLEENTER2("CcSetReadAheadGranularity: FileObject=0x%lX,Granularity=0x%lX", (long)FileObject,Granularity); dump_FileObject(FileObject); CcSetReadAheadGranularity ( FileObject, Granularity ); DBGSINGLELEAVE0("CcSetReadAheadGranularity"); } typedef struct _CACHE_UNINITIALIZE_EVENT { struct _CACHE_UNINITIALIZE_EVENT *Next; KEVENT Event; } CACHE_UNINITIALIZE_EVENT,*PCACHE_UNINITIALIZE_EVENT; BOOLEAN CcUninitializeCacheMap ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER TruncateSize OPTIONAL, IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL ); BOOLEAN TcUninitializeCacheMap ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER TruncateSize OPTIONAL, IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL ) { BOOLEAN r; DBGSINGLEENTER3("CcUninitializeCacheMap: FileObject=0x%lX,TruncateSize=0x%lX,UninitializeCompleteEvent=0x%lX", (long)FileObject,(!TruncateSize ? -1 : (long)TruncateSize->QuadPart),(long)UninitializeCompleteEvent); dump_FileObject(FileObject); r=CcUninitializeCacheMap ( FileObject, TruncateSize, UninitializeCompleteEvent ); dump_FileObject(FileObject); DBGSINGLELEAVE1("CcUninitializeCacheMap: r=%d",r); return r; } VOID CcUnpinData ( IN PVOID Bcb ); VOID TcUnpinData ( IN PVOID Bcb ) { DBGSINGLEENTER1("CcUnpinData: Bcb=0x%lX",(long)Bcb); CcUnpinData ( Bcb ); DBGSINGLELEAVE0("CcUnpinData"); } VOID CcUnpinDataForThread ( IN PVOID Bcb, IN ERESOURCE_THREAD ResourceThreadId ); VOID TcUnpinDataForThread ( IN PVOID Bcb, IN ERESOURCE_THREAD ResourceThreadId ) { DBGSINGLEENTER2("CcUnpinDataForThread: Bcb=0x%lX,ResourceThreadId=0x%lX", (long)Bcb,(long)ResourceThreadId); CcUnpinDataForThread ( Bcb, ResourceThreadId ); DBGSINGLELEAVE0("CcUnpinDataForThread"); } NTSTATUS CcWaitForCurrentLazyWriterActivity ( VOID ); NTSTATUS TcWaitForCurrentLazyWriterActivity ( VOID ) { NTSTATUS r; DBGSINGLEENTER0("CcWaitForCurrentLazyWriterActivity"); r=CcWaitForCurrentLazyWriterActivity ( ); DBGSINGLELEAVE1("CcWaitForCurrentLazyWriterActivity: r=0x%lX",r); return r; } BOOLEAN CcZeroData ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait ); BOOLEAN TcZeroData ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait ) { BOOLEAN r; DBGSINGLEENTER4("CcZeroData: FileObject=0x%lX,StartOffset=0x%lX,EndOffset=0x%lX,Wait=%d", (long)FileObject, (!StartOffset ? -1 : (long)StartOffset->QuadPart), (!EndOffset ? -1 : (long)EndOffset->QuadPart), Wait); dump_FileObject(FileObject); r=CcZeroData ( FileObject, StartOffset, EndOffset, Wait ); DBGSINGLELEAVE1("CcZeroData: r=%d",r); return r; }