add_subdirectory(cdfs)
add_subdirectory(ext2)
-#add_subdirectory(ext2_new)
add_subdirectory(fastfat)
#add_subdirectory(fastfat_new)
add_subdirectory(fs_rec)
add_subdirectory(npfs)
add_subdirectory(ntfs)
add_subdirectory(udfs)
+add_subdirectory(registryfs)
-include_directories(inc)
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers
+ inc)
list(APPEND SOURCE
- src/volinfo.c
+ src/init.c
+ src/ext3/generic.c
+ src/ext3/htree.c
+ src/ext3/indirect.c
+ src/ext3/recover.c
+ src/ext4/ext4_bh.c
+ src/ext4/ext4_extents.c
+ src/ext4/ext4_jbd2.c
+ src/ext4/extents.c
+ src/jbd/recovery.c
+ src/jbd/replay.c
+ src/jbd/revoke.c
+ src/nls/nls_ascii.c
+ src/nls/nls_base.c
+ src/nls/nls_cp437.c
+ src/nls/nls_cp737.c
+ src/nls/nls_cp775.c
+ src/nls/nls_cp850.c
+ src/nls/nls_cp852.c
+ src/nls/nls_cp855.c
+ src/nls/nls_cp857.c
+ src/nls/nls_cp860.c
+ src/nls/nls_cp861.c
+ src/nls/nls_cp862.c
+ src/nls/nls_cp863.c
+ src/nls/nls_cp864.c
+ src/nls/nls_cp865.c
+ src/nls/nls_cp866.c
+ src/nls/nls_cp869.c
+ src/nls/nls_cp874.c
+ src/nls/nls_cp932.c
+ src/nls/nls_cp936.c
+ src/nls/nls_cp949.c
+ src/nls/nls_cp950.c
+ src/nls/nls_cp1250.c
+ src/nls/nls_cp1251.c
+ src/nls/nls_cp1255.c
+ src/nls/nls_euc-jp.c
+ src/nls/nls_iso8859-1.c
+ src/nls/nls_iso8859-2.c
+ src/nls/nls_iso8859-3.c
+ src/nls/nls_iso8859-4.c
+ src/nls/nls_iso8859-5.c
+ src/nls/nls_iso8859-6.c
+ src/nls/nls_iso8859-7.c
+ src/nls/nls_iso8859-9.c
+ src/nls/nls_iso8859-13.c
+ src/nls/nls_iso8859-14.c
+ src/nls/nls_iso8859-15.c
+ src/nls/nls_koi8-r.c
+ src/nls/nls_koi8-ru.c
+ src/nls/nls_koi8-u.c
+ src/nls/nls_utf8.c
+ src/block.c
+ src/cleanup.c
+ src/close.c
+ src/cmcb.c
src/create.c
- src/write.c
- src/metadata.c
+ src/debug.c
+ src/devctl.c
+ src/dirctl.c
+ src/dispatch.c
+ src/except.c
src/fastio.c
- src/dircntrl.c
- src/DiskIO.c
- src/fsctrl.c
- src/devcntrl.c
- src/flush.c
- src/ext2init.c
- src/io.c
- src/close.c
src/fileinfo.c
- src/read.c
- src/cleanup.c
+ src/flush.c
+ src/fsctl.c
+ src/linux.c
+ src/lock.c
+ src/memory.c
src/misc.c
+ src/nls.c
+ src/pnp.c
+ src/rbtree.c
+ src/read.c
src/shutdown.c
- inc/ext2fsd.h)
+ src/volinfo.c
+ src/write.c
+ inc/ext2fs.h)
-add_library(ext2fs SHARED ${SOURCE})
+add_library(ext2fs SHARED ${SOURCE} ext2fs.rc)
-if((NOT MSVC) AND (NOT CMAKE_C_COMPILER_ID STREQUAL "Clang"))
- add_target_compile_flags(ext2fs "-Wno-unused-but-set-variable")
+if(NOT MSVC)
+ add_target_compile_flags(ext2fs "-Wno-pointer-sign -Wno-unused-function")
+ if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ replace_compile_flags("-Werror" " ")
+ add_target_compile_flags(ext2fs "-Wno-unused-but-set-variable -Wno-unused-variable -Wno-missing-braces")
+ endif()
+else()
+ #disable warnings: "unreferenced local variable", "initialized, but not used variable", "benign include"
+ replace_compile_flags("/we\"4189\"" " ")
+ add_target_compile_flags(ext2fs "/wd\"4189\" /wd\"4142\" /wd\"4101\"")
endif()
-target_link_libraries(ext2fs ${PSEH_LIB})
-add_pch(ext2fs inc/ext2fsd.h SOURCE)
+target_link_libraries(ext2fs memcmp ${PSEH_LIB})
+add_definitions(-D__KERNEL__ -D_X86_)
set_module_type(ext2fs kernelmodedriver)
add_importlibs(ext2fs ntoskrnl hal)
+add_pch(ext2fs inc/ext2fs.h SOURCE)
add_cd_file(TARGET ext2fs DESTINATION reactos/system32/drivers NO_CAB FOR all)
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
-// Used by D:\Work\VC\Drivers\ext2FSD\src\ext2.rc
+// Used by ext2fsd.rc
//
// Next default values for new objects
-//
+//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NO_MFC 1
-#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
-/*************************************************************************
-*
-* File: cleanup.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Should contain code to handle the "Cleanup" dispatch entry point.
-* This file serves as a placeholder. Please update this file as part
-* of designing and implementing your FSD.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_CLEANUP
-#define DEBUG_LEVEL (DEBUG_TRACE_CLEANUP)
-
-
-/*************************************************************************
-*
-* Function: Ext2Cleanup()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a cleanup
-* request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: Does not matter!
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Cleanup(
-PDEVICE_OBJECT DeviceObject, // the logical volume device object
-PIRP Irp) // I/O Request Packet
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
-
- DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Cleanup IRP Received...", 0);
-
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
-
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
-
- try
- {
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: cleanup.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
+/* INCLUDES *****************************************************************/
- RC = Ext2CommonCleanup(PtrIrpContext, Irp, TRUE);
+#include "ext2fs.h"
- }
- except( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) )
- {
+/* GLOBALS ***************************************************************/
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
+extern PEXT2_GLOBAL Ext2Global;
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
+/* DEFINITIONS *************************************************************/
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
-}
-
-/*************************************************************************
-*
-* Function: Ext2CommonCleanup()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one'
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: Does not matter!
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonCleanup(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-BOOLEAN FirstAttempt )
+NTSTATUS
+Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
{
-
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- PFILE_OBJECT PtrFileObject = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- PERESOURCE PtrResourceAcquired = NULL;
-
- BOOLEAN CompleteIrp = TRUE;
- BOOLEAN PostRequest = FALSE;
- BOOLEAN AcquiredVCB = FALSE;
- BOOLEAN BlockForResource;
- int i = 1;
-
- try
- {
- // First, get a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
-
- if( !PtrFileObject->FsContext2 )
- {
- // This must be a Cleanup request received
- // as a result of IoCreateStreamFileObject
- // Only such a File object would have a NULL CCB
-
- DebugTrace( DEBUG_TRACE_MISC, " === Cleanup with NULL CCB", 0);
- if( PtrFileObject )
- {
- DebugTrace( DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
- }
- try_return();
- }
-
-
- Ext2GetFCB_CCB_VCB_FromFileObject (
- PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
-
- if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
- //if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
- {
- DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
- }
- else
- {
- DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup Volume", 0);
- }
-
-
- PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
- ASSERT(PtrVCB);
- ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
-
- // (a) Acquiring the VCBResource Exclusively...
- // This is done to synchronise with the close and cleanup routines...
- BlockForResource = !FirstAttempt;
- if( !FirstAttempt )
- {
-
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire VCB Exclusively [Cleanup]", 0);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCB Exclusively [Cleanup]", 0);
- }
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
- }
-
- i = 1;
- while( !AcquiredVCB )
- {
- DebugTraceState("VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- if( ! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
- {
- DebugTrace( DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquisition FAILED [Cleanup]", 0);
- if( BlockForResource && i != 1000 )
- {
- LARGE_INTEGER Delay;
- Delay.QuadPart = -500 * i;
- KeDelayExecutionThread( KernelMode, FALSE, &Delay );
- DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
- }
- else
- {
- if( i == 1000 )
- DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
- PostRequest = TRUE;
- try_return( RC = STATUS_PENDING );
- }
- }
- else
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquired in [Cleanup]", 0);
- AcquiredVCB = TRUE;
- }
- i *= 10;
- }
-
-
- // (b) Acquire the file (FCB) exclusively
- if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
- {
- // This FCB is an FCB indeed. ;)
- // So acquiring it exclusively...
- // This is done to synchronise with read/write routines...
- if( !FirstAttempt )
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire FCB Exclusively [Cleanup]", 0);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCB Exclusively [Cleanup]", 0);
- }
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
- }
-
- i = 1;
- while( !PtrResourceAcquired )
- {
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquisition FAILED [Cleanup]", 0);
- if( BlockForResource && i != 1000 )
- {
- LARGE_INTEGER Delay;
- Delay.QuadPart = -500 * i;
- KeDelayExecutionThread( KernelMode, FALSE, &Delay );
- DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
- }
- else
- {
- if( i == 1000 )
- DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
- PostRequest = TRUE;
- try_return( RC = STATUS_PENDING );
- }
- }
- else
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB acquired [Cleanup]", 0);
- PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource );
- }
- i *= 10;
- }
-
- // (c) Flush file data to disk
- if ( PtrFileObject->PrivateCacheMap != NULL)
- {
- IO_STATUS_BLOCK Status;
- CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status );
- }
-
- // (d) Talk to the FSRTL package (if you use it) about pending oplocks.
- // (e) Notify the FSRTL package (if you use it) for use with pending
- // notification IRPs
- // (f) Unlock byte-range locks (if any were acquired by process)
-
- // (g) Attempting to update time stamp values
- // Errors are ignored...
- // Not considered as critical errors...
-
- /*
- if( PtrFCB->OpenHandleCount == 1 )
- {
- ULONG CreationTime, AccessTime, ModificationTime;
- EXT2_INODE Inode;
-
- CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
- {
- // Update time stamps in the inode...
- Inode.i_ctime = CreationTime;
- Inode.i_atime = AccessTime;
- Inode.i_mtime = ModificationTime;
-
- // Updating the inode...
- Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode );
- }
- }
- */
-
- // (h) Inform the Cache Manager to uninitialize Cache Maps ...
- CcUninitializeCacheMap( PtrFileObject, NULL, NULL );
-
- // (i) Decrementing the Open Handle count...
- if( PtrFCB->OpenHandleCount )
- {
- InterlockedDecrement( &PtrFCB->OpenHandleCount );
- }
- else
- {
- Ext2BreakPoint();
- }
-
- PtrFCB->FCBFlags |= FO_CLEANUP_COMPLETE;
-
- DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Cleanup]", PtrFCB->ReferenceCount );
- DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Cleanup]", PtrFCB->OpenHandleCount );
-
- // (j) Remove share access...
- // Will do that later ;)
-
- // (k) Is this a close on delete file?
- // If so, delete the file...
- if( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE) &&
- !PtrFCB->OpenHandleCount )
- {
- //
- // Have to delete this file...
- //
- Ext2DeleteFile( PtrFCB, PtrIrpContext );
- PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart = 0;
- PtrFCB->INodeNo = 0;
- }
- }
- else
- {
- // This must be a volume close...
- // Just go ahead and complete this IRP...
- PtrVCB->VCBOpenCount--;
- DebugTrace(DEBUG_TRACE_MISC, "VCB Cleanup Requested !!!", 0);
- CompleteIrp = TRUE;
- }
-
- try_return();
-
- try_exit: NOTHING;
-
- }
- finally
- {
- if(PtrResourceAcquired)
- {
- Ext2ReleaseResource(PtrResourceAcquired);
- DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** Resource Released [Cleanup]", 0);
- DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]",
- PtrResourceAcquired->ActiveCount,
- PtrResourceAcquired->NumberOfExclusiveWaiters,
- PtrResourceAcquired->NumberOfSharedWaiters );
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
- }
-
- }
-
- if( AcquiredVCB )
- {
- ASSERT(PtrVCB);
- Ext2ReleaseResource(&(PtrVCB->VCBResource));
- DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** VCB Released [Cleanup]", 0);
- DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- AcquiredVCB = FALSE;
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
- }
-
- }
-
- if( PostRequest )
- {
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
- }
- if( RC != STATUS_PENDING )
- {
- Ext2ReleaseIrpContext( PtrIrpContext );
- // complete the IRP
- IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
- }
- } // end of "finally" processing
-
- return(RC);
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PEXT2_VCB Vcb;
+ PFILE_OBJECT FileObject;
+ PEXT2_FCB Fcb;
+ PEXT2_CCB Ccb;
+ PIRP Irp;
+ PEXT2_MCB Mcb;
+
+
+ BOOLEAN VcbResourceAcquired = FALSE;
+ BOOLEAN FcbResourceAcquired = FALSE;
+ BOOLEAN FcbPagingIoResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext != NULL);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ Irp = IrpContext->Irp;
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ if (!IsVcbInited(Vcb)) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ FileObject = IrpContext->FileObject;
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
+ Fcb->Identifier.Type != EXT2FCB)) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+ Mcb = Fcb->Mcb;
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+
+ if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ VcbResourceAcquired =
+ ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
+ );
+
+ if (Fcb->Identifier.Type == EXT2VCB) {
+
+ if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
+ Vcb->LockFile == FileObject ){
+
+ ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
+ Vcb->LockFile = NULL;
+ Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
+ }
+
+ if (Ccb) {
+ Ext2DerefXcb(&Vcb->OpenHandleCount);
+ Ext2DerefXcb(&Vcb->OpenVolumeCount);
+ }
+
+ IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
+
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
+ if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
+ IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
+ !IsVcbReadOnly(Vcb) ) {
+ Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
+ }
+ _SEH2_LEAVE;
+ }
+
+ if (Ccb == NULL) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if (IsDirectory(Fcb)) {
+ if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
+ SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
+
+ FsRtlNotifyFullChangeDirectory(
+ Vcb->NotifySync,
+ &Vcb->NotifyList,
+ Ccb,
+ NULL,
+ FALSE,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ NULL );
+ }
+
+ FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
+
+ }
+
+ ExReleaseResourceLite(&Vcb->MainResource);
+ VcbResourceAcquired = FALSE;
+
+ FcbResourceAcquired =
+ ExAcquireResourceExclusiveLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
+ );
+
+ ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
+ (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
+
+ Ext2DerefXcb(&Vcb->OpenHandleCount);
+ Ext2DerefXcb(&Fcb->OpenHandleCount);
+
+ if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
+ Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
+ }
+
+ if (IsDirectory(Fcb)) {
+
+ ext3_release_dir(Fcb->Inode, &Ccb->filp);
+
+ } else {
+
+ if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
+ !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
+
+ LARGE_INTEGER SysTime;
+ KeQuerySystemTime(&SysTime);
+
+ Fcb->Inode->i_atime =
+ Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
+ Fcb->Mcb->LastAccessTime =
+ Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
+
+ Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
+
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_LAST_WRITE |
+ FILE_NOTIFY_CHANGE_LAST_ACCESS,
+ FILE_ACTION_MODIFIED );
+ }
+
+ FsRtlCheckOplock( &Fcb->Oplock,
+ Irp,
+ IrpContext,
+ NULL,
+ NULL );
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+
+ if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
+ Fcb->NonCachedOpenCount--;
+ }
+
+ if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
+ SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
+ }
+
+ //
+ // Drop any byte range locks this process may have on the file.
+ //
+
+ FsRtlFastUnlockAll(
+ &Fcb->FileLockAnchor,
+ FileObject,
+ IoGetRequestorProcess(Irp),
+ NULL );
+
+ //
+ // If there are no byte range locks owned by other processes on the
+ // file the fast I/O read/write functions doesn't have to check for
+ // locks so we set IsFastIoPossible to FastIoIsPossible again.
+ //
+ if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
+ if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
+ Ext2GetCurrentProcessName(),
+ "FastIoIsPossible",
+ &Fcb->Mcb->FullName
+ ));
+#endif
+
+ Fcb->Header.IsFastIoPossible = FastIoIsPossible;
+ }
+ }
+
+ if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
+ FCB_ALLOC_IN_SETINFO) ){
+
+ if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
+ if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
+ if (!INODE_HAS_EXTENT(Fcb->Inode)) {
+ #if EXT2_PRE_ALLOCATION_SUPPORT
+ CcZeroData(FileObject, &Fcb->Header.ValidDataLength,
+ &Fcb->Header.AllocationSize, TRUE);
+ #endif
+ }
+ }
+ }
+
+ if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
+
+ LARGE_INTEGER Size;
+
+ ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
+ FcbPagingIoResourceAcquired = TRUE;
+
+ Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
+ (ULONGLONG)Fcb->Mcb->Inode.i_size,
+ (ULONGLONG)BLOCK_SIZE);
+ if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
+
+ Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+ Fcb->Header.AllocationSize = Size;
+ Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
+ if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
+ Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject,
+ (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+ }
+ ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ FcbPagingIoResourceAcquired = FALSE;
+ }
+ }
+ }
+
+ if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
+
+ if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {
+
+ //
+ // Ext2DeleteFile will acquire these lock inside
+ //
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ FcbResourceAcquired = FALSE;
+ }
+
+ //
+ // this file is to be deleted ...
+ //
+ if (Ccb->SymLink) {
+ Mcb = Ccb->SymLink;
+ FileObject->DeletePending = FALSE;
+ }
+
+ Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+
+ if (NT_SUCCESS(Status)) {
+ if (IsMcbDirectory(Mcb)) {
+ Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ FILE_ACTION_REMOVED );
+ } else {
+ Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ FILE_ACTION_REMOVED );
+ }
+ }
+
+ //
+ // re-acquire the main resource lock
+ //
+
+ FcbResourceAcquired =
+ ExAcquireResourceExclusiveLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
+ );
+
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject,
+ (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+ }
+ }
+
+ if (!IsDirectory(Fcb)) {
+
+ if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
+ (Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) &&
+ (Fcb->SectionObject.DataSectionObject != NULL)) {
+
+ if (!IsVcbReadOnly(Vcb)) {
+ CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
+ ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+ }
+
+ if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
+ ExReleaseResourceLite(&(Fcb->PagingIoResource));
+ }
+
+ CcPurgeCacheSection( &Fcb->SectionObject,
+ NULL,
+ 0,
+ FALSE );
+ }
+
+ CcUninitializeCacheMap(FileObject, NULL, NULL);
+ }
+
+ IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
+
+ DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
+ Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
+
+ Status = STATUS_SUCCESS;
+
+ if (FileObject) {
+ SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
+ }
+
+ } _SEH2_FINALLY {
+
+ if (FcbPagingIoResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ }
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+ if (Status == STATUS_PENDING) {
+ Ext2QueueRequest(IrpContext);
+ } else {
+ IrpContext->Irp->IoStatus.Status = Status;
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
}
-/*************************************************************************
-*
-* File: close.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Should contain code to handle the "Close" dispatch entry point.
-* This file serves as a placeholder. Please update this file as part
-* of designing and implementing your FSD.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_CLOSE
-
-#define DEBUG_LEVEL (DEBUG_TRACE_CLOSE)
-
-
-/*************************************************************************
-*
-* Function: Ext2Close()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a close
-* request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: Does not matter!
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Close(
-PDEVICE_OBJECT DeviceObject, // the logical volume device object
-PIRP Irp) // I/O Request Packet
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: close.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+/* DEFINITIONS *************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2QueueCloseRequest)
+#pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
+#endif
+
+NTSTATUS
+Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PEXT2_VCB Vcb = NULL;
+ BOOLEAN VcbResourceAcquired = FALSE;
+ PFILE_OBJECT FileObject;
+ PEXT2_FCB Fcb;
+ BOOLEAN FcbResourceAcquired = FALSE;
+ PEXT2_CCB Ccb;
+ BOOLEAN bDeleteVcb = FALSE;
+ BOOLEAN bBeingClosed = FALSE;
+ BOOLEAN bSkipLeave = FALSE;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext != NULL);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_SUCCESS;
+ Vcb = NULL;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
+ Vcb->OpenHandleCount, Vcb->ReferenceCount));
+
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ VcbResourceAcquired = TRUE;
+
+ bSkipLeave = TRUE;
+ if (IsFlagOn(Vcb->Flags, VCB_BEING_CLOSED)) {
+ bBeingClosed = TRUE;
+ } else {
+ SetLongFlag(Vcb->Flags, VCB_BEING_CLOSED);
+ bBeingClosed = FALSE;
+ }
+
+ if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
+
+ FileObject = NULL;
+ Fcb = IrpContext->Fcb;
+ Ccb = IrpContext->Ccb;
+
+ } else {
+
+ FileObject = IrpContext->FileObject;
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (!Fcb) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+ ASSERT(Fcb != NULL);
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ }
+
+ DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n",
+ bBeingClosed, Vcb, Vcb->ReferenceCount));
+
+ if (Fcb->Identifier.Type == EXT2VCB) {
+
+ if (Ccb) {
+
+ Ext2DerefXcb(&Vcb->ReferenceCount);
+ Ext2FreeCcb(Vcb, Ccb);
+
+ if (FileObject) {
+ FileObject->FsContext2 = Ccb = NULL;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if ( Fcb->Identifier.Type != EXT2FCB ||
+ Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
+ _SEH2_LEAVE;
+ }
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ FcbResourceAcquired = TRUE;
+
+ Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
+
+ if (!Ccb) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
+ (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
+
+ if (IsFlagOn(Fcb->Flags, FCB_STATE_BUSY)) {
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY);
+ DEBUG(DL_WRN, ( "Ext2Close: busy bit set: %wZ\n", &Fcb->Mcb->FullName ));
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
+ Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
+
+ if (Ccb) {
+
+ Ext2FreeCcb(Vcb, Ccb);
+
+ if (FileObject) {
+ FileObject->FsContext2 = Ccb = NULL;
+ }
+ }
+
+ if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) {
+
+ //
+ // Remove Fcb from Vcb->FcbList ...
+ //
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ FcbResourceAcquired = FALSE;
+ }
+
+ Ext2FreeFcb(Fcb);
+
+ if (FileObject) {
+ FileObject->FsContext = Fcb = NULL;
+ }
+ }
+
+ Ext2DerefXcb(&Vcb->ReferenceCount);
+ Status = STATUS_SUCCESS;
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Close IRP Received...", 0);
-
+ } _SEH2_FINALLY {
- FsRtlEnterFileSystem();
+ if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) {
+ /* for Ext2Fsd driver open/close, Vcb is NULL */
+ if ((!bBeingClosed) && (Vcb->ReferenceCount == 0)&&
+ (!IsMounted(Vcb) || IsDispending(Vcb))) {
+ bDeleteVcb = TRUE;
+ }
+ }
- ASSERT(DeviceObject);
- ASSERT(Irp);
+ if (bSkipLeave && !bBeingClosed) {
+ ClearFlag(Vcb->Flags, VCB_BEING_CLOSED);
+ }
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
- try
- {
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
+ if (!IrpContext->ExceptionInProgress) {
- RC = Ext2CommonClose(PtrIrpContext, Irp, TRUE);
+ if (Status == STATUS_PENDING) {
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
+ Ext2QueueCloseRequest(IrpContext);
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
+ } else {
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
+ Ext2CompleteIrpContext(IrpContext, Status);
- FsRtlExitFileSystem();
+ if (bDeleteVcb) {
- return(RC);
+ PVPB Vpb = Vcb->Vpb;
+ DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n",
+ Vcb, Vpb));
+
+ Ext2CheckDismount(IrpContext, Vcb, FALSE);
+ }
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
}
+VOID
+Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
+
+ if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
+ Ext2Sleep(500); /* 0.5 sec*/
+ } else {
+ Ext2Sleep(50); /* 0.05 sec*/
+ }
-/*************************************************************************
-*
-* Function: Ext2CommonClose()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one'
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: Does not matter!
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonClose(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-BOOLEAN FirstAttempt )
+ } else {
+
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
+
+ IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
+ IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
+ }
+
+ ExInitializeWorkItem(
+ &IrpContext->WorkQueueItem,
+ Ext2DeQueueCloseRequest,
+ IrpContext);
+
+ ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
+}
+
+VOID NTAPI
+Ext2DeQueueCloseRequest (IN PVOID Context)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- PFILE_OBJECT PtrFileObject = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- PERESOURCE PtrResourceAcquired = NULL;
- PERESOURCE PtrPagingIoResourceAcquired = NULL;
-
- BOOLEAN CompleteIrp = TRUE;
- BOOLEAN PostRequest = FALSE;
- BOOLEAN AcquiredVCB = FALSE;
- BOOLEAN BlockForResource;
- int i = 1;
-
- try
- {
- // First, get a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
-
- if( !PtrFileObject->FsContext2 )
- {
- // This must be a Cleanup request received
- // as a result of IoCreateStreamFileObject
- // Only such a File object would have a NULL CCB
-
- DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0);
- if( PtrFileObject )
- {
- DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
- }
- try_return();
- }
-
- // Get the FCB and CCB pointers
-
- Ext2GetFCB_CCB_VCB_FromFileObject (
- PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
-
- PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
- ASSERT( PtrVCB );
-
- if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
- //if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
- {
- DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -null-", 0);
- }
-
- // (a) Acquiring the VCBResource Exclusively...
- // This is done to synchronise with the close and cleanup routines...
-// if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) )
-
- BlockForResource = !FirstAttempt;
- if( !FirstAttempt )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0);
- }
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
- }
-
- i = 1;
- while( !AcquiredVCB )
- {
- DebugTraceState( "VCB AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- if(! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquisition FAILED [Close]", 0);
- if( BlockForResource && i != 1000 )
- {
- LARGE_INTEGER Delay;
-
- //KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
-
- Delay.QuadPart = -500 * i;
- KeDelayExecutionThread( KernelMode, FALSE, &Delay );
- DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
- }
- else
- {
- if( i == 1000 )
- DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
- PostRequest = TRUE;
- try_return( RC = STATUS_PENDING );
- }
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired in [Close]", 0);
- AcquiredVCB = TRUE;
- }
- i *= 10;
- }
-
- // (b) Acquire the file (FCB) exclusively
- if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
- {
- // This FCB is an FCB indeed. ;)
- // So acquiring it exclusively...
- // This is done to synchronise with read/write routines...
- if( !FirstAttempt )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively [Close]", 0);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Exclusively [Close]", 0);
- }
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
- }
-
- PtrReqdFCB = &PtrFCB->NTRequiredFCB;
-
- i = 1;
- while( !PtrResourceAcquired )
- {
- DebugTraceState( "FCBMain AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->MainResource), FALSE ) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Close]", 0);
- if( BlockForResource && i != 1000 )
- {
- LARGE_INTEGER Delay;
-
- //KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
-
- Delay.QuadPart = -500 * i;
- KeDelayExecutionThread( KernelMode, FALSE, &Delay );
- DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
- }
- else
- {
- if( i == 1000 )
- DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
- PostRequest = TRUE;
- try_return( RC = STATUS_PENDING );
- }
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [Close]", 0);
- PtrResourceAcquired = & ( PtrReqdFCB->MainResource );
- }
- i *= 10;
- }
-
- i = 1;
- while( !PtrPagingIoResourceAcquired )
- {
- DebugTraceState( "FCBPaging AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
- if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->PagingIoResource), FALSE ) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Close]", 0);
- if( BlockForResource && i != 1000 )
- {
- LARGE_INTEGER Delay;
-
- // KeSetPriorityThread( PsGetCurrentThread(), LOW_REALTIME_PRIORITY );
-
- Delay.QuadPart = -500 * i;
- KeDelayExecutionThread( KernelMode, FALSE, &Delay );
- DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
- }
- else
- {
- if( i == 1000 )
- DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
- PostRequest = TRUE;
- try_return( RC = STATUS_PENDING );
- }
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [Close]", 0);
- PtrPagingIoResourceAcquired = & ( PtrReqdFCB->PagingIoResource );
- }
- i *= 10;
- }
-
- // (c) Delete the CCB structure (free memory)
- RemoveEntryList( &PtrCCB->NextCCB );
- Ext2ReleaseCCB( PtrCCB );
- PtrFileObject->FsContext2 = NULL;
-
- // (d) Decrementing the Reference Count...
- if( PtrFCB->ReferenceCount )
- {
- InterlockedDecrement( &PtrFCB->ReferenceCount );
- }
- else
- {
- Ext2BreakPoint();
- }
- DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Close]", PtrFCB->ReferenceCount );
- DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Close]", PtrFCB->OpenHandleCount );
- if( PtrFCB->ReferenceCount == 0 )
- {
-
- // Attempting to update time stamp values
- // Errors are ignored...
- // Not considered as critical errors...
-
- {
- ULONG CreationTime, AccessTime, ModificationTime;
- EXT2_INODE Inode;
-
- CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
- {
- // Update time stamps in the inode...
- Inode.i_ctime = CreationTime;
- Inode.i_atime = AccessTime;
- Inode.i_mtime = ModificationTime;
-
- // Updating the inode...
- Ext2WriteInode( NULL, PtrVCB, PtrFCB->INodeNo, &Inode );
- }
- }
-
-
- if( PtrFCB->INodeNo == EXT2_ROOT_INO )
- {
- //
- // Root Directory FCB
- // Preserve this
- // FSD has a File Object for this FCB...
- //
- DebugTrace(DEBUG_TRACE_MISC, "^^^^^Root Directory FCB ; leaveing it alone[Close]", 0);
- // Do nothing...
-
- }
- else if( PtrFCB->DcbFcb.Dcb.PtrDirFileObject )
- {
- //
- // If this is a FCB created on the FSD's initiative
- // Leave it alone
- //
- DebugTrace(DEBUG_TRACE_MISC, "^^^^^FCB Created on the FSD's initiative; leaveing it alone[Close]", 0);
- if( !PtrFCB->ClosableFCBs.OnClosableFCBList )
- {
- InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
- &PtrFCB->ClosableFCBs.ClosableFCBList );
- PtrVCB->ClosableFCBs.Count++;
-
- PtrFCB->ClosableFCBs.OnClosableFCBList = TRUE;
- }
-
- if( PtrVCB->ClosableFCBs.Count > EXT2_MAXCLOSABLE_FCBS_UL )
- {
- PtrExt2FCB PtrTempFCB = NULL;
- // Checking if Closable FCBs are too many in number...
- // Shouldn't block the
- // Should do this asynchronously...
- // Maybe later...
- PLIST_ENTRY PtrEntry = NULL;
-
- PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
-
- PtrTempFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
- if( Ext2CloseClosableFCB( PtrTempFCB ) )
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Close]", PtrTempFCB );
- ExFreePool( PtrTempFCB );
- PtrVCB->ClosableFCBs.Count--;
- }
- else
- {
- // Put the FCB back in the list...
- InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
- &PtrTempFCB->ClosableFCBs.ClosableFCBList );
- }
- DebugTrace( DEBUG_TRACE_SPECIAL, "ClosableFCBs Count = %ld [Close]", PtrVCB->ClosableFCBs.Count );
- }
- }
- else
- {
- // Remove this FCB as well...
- DebugTrace(DEBUG_TRACE_MISC, "^^^^^Deleting FCB [Close]", 0);
- RemoveEntryList( &PtrFCB->NextFCB );
-
- if ( PtrPagingIoResourceAcquired )
- {
- Ext2ReleaseResource(PtrPagingIoResourceAcquired);
- DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
- PtrPagingIoResourceAcquired->ActiveCount,
- PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters,
- PtrPagingIoResourceAcquired->NumberOfSharedWaiters );
-
- PtrPagingIoResourceAcquired = NULL;
- }
-
- if ( PtrResourceAcquired )
- {
- Ext2ReleaseResource(PtrResourceAcquired);
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
- DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
- PtrResourceAcquired->ActiveCount,
- PtrResourceAcquired->NumberOfExclusiveWaiters,
- PtrResourceAcquired->NumberOfSharedWaiters );
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
- }
- PtrResourceAcquired = NULL;
- }
-
- Ext2ReleaseFCB( PtrFCB );
- }
-
- }
- CompleteIrp = TRUE;
- }
- else
- {
- // This must be a volume close...
- // What do I do now? ;)
- DebugTrace(DEBUG_TRACE_MISC, "VCB Close Requested !!!", 0);
- CompleteIrp = TRUE;
- }
- try_return();
-
- try_exit: NOTHING;
-
- }
- finally
- {
- if ( PtrPagingIoResourceAcquired )
- {
- Ext2ReleaseResource(PtrPagingIoResourceAcquired);
- DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
- PtrPagingIoResourceAcquired->ActiveCount,
- PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters,
- PtrPagingIoResourceAcquired->NumberOfSharedWaiters );
-
- PtrPagingIoResourceAcquired = NULL;
- }
-
- if ( PtrResourceAcquired )
- {
- Ext2ReleaseResource(PtrResourceAcquired);
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
- DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
- PtrResourceAcquired->ActiveCount,
- PtrResourceAcquired->NumberOfExclusiveWaiters,
- PtrResourceAcquired->NumberOfSharedWaiters );
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
- }
- PtrResourceAcquired = NULL;
- }
-
- if (AcquiredVCB)
- {
- ASSERT(PtrVCB);
- Ext2ReleaseResource(&(PtrVCB->VCBResource));
- DebugTraceState( "VCB AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Close]", 0);
-
- AcquiredVCB = FALSE;
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
- }
-
- }
-
- if( PostRequest )
- {
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
- }
- else if( CompleteIrp && RC != STATUS_PENDING )
- {
- // complete the IRP
- IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
-
- Ext2ReleaseIrpContext( PtrIrpContext );
- }
-
- } // end of "finally" processing
-
- return(RC);
+ PEXT2_IRP_CONTEXT IrpContext;
+
+ IrpContext = (PEXT2_IRP_CONTEXT) Context;
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ _SEH2_TRY {
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+ Ext2Close(IrpContext);
+
+ } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
+
+ Ext2ExceptionHandler(IrpContext);
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
}
-/*************************************************************************
-*
-* File: create.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the "Create"/"Open" dispatch entry point.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_CREATE
-
-#define DEBUG_LEVEL (DEBUG_TRACE_CREATE)
-
-
-/*************************************************************************
-*
-* Function: Ext2Create()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a create/open
-* request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Create(
-PDEVICE_OBJECT DeviceObject, // the logical volume device object
-PIRP Irp) // I/O Request Packet
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext;
- BOOLEAN AreWeTopLevel = FALSE;
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: create.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
- DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Create Control IRP received...", 0);
+/* INCLUDES *****************************************************************/
- FsRtlEnterFileSystem();
-
- // Ext2BreakPoint();
+#include "ext2fs.h"
- ASSERT(DeviceObject);
- ASSERT(Irp);
+/* GLOBALS *****************************************************************/
- // sometimes, we may be called here with the device object representing
- // the file system (instead of the device object created for a logical
- // volume. In this case, there is not much we wish to do (this create
- // typically will happen 'cause some process has to open the FSD device
- // object so as to be able to send an IOCTL to the FSD)
+extern PEXT2_GLOBAL Ext2Global;
- // All of the logical volume device objects we create have a device
- // extension whereas the device object representing the FSD has no
- // device extension. This seems like a good enough method to identify
- // between the two device objects ...
- if (DeviceObject->Size == (unsigned short)(sizeof(DEVICE_OBJECT)))
- {
- // this is an open of the FSD itself
- DebugTrace( DEBUG_TRACE_MISC, " === Open for the FSD itself", 0);
- Irp->IoStatus.Status = RC;
- Irp->IoStatus.Information = FILE_OPENED;
+/* DEFINITIONS *************************************************************/
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return(RC);
- }
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2IsNameValid)
+#pragma alloc_text(PAGE, Ext2FollowLink)
+#pragma alloc_text(PAGE, Ext2IsSpecialSystemFile)
+#pragma alloc_text(PAGE, Ext2LookupFile)
+#pragma alloc_text(PAGE, Ext2ScanDir)
+#pragma alloc_text(PAGE, Ext2CreateFile)
+#pragma alloc_text(PAGE, Ext2CreateVolume)
+#pragma alloc_text(PAGE, Ext2Create)
+#pragma alloc_text(PAGE, Ext2CreateInode)
+#pragma alloc_text(PAGE, Ext2SupersedeOrOverWriteFile)
+#endif
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
- try
- {
+BOOLEAN
+Ext2IsNameValid(PUNICODE_STRING FileName)
+{
+ USHORT i = 0;
+ PUSHORT pName = (PUSHORT) FileName->Buffer;
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
+ if (FileName == NULL) {
+ return FALSE;
+ }
- RC = Ext2CommonCreate(PtrIrpContext, Irp, TRUE );
+ while (i < (FileName->Length / sizeof(WCHAR))) {
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
+ if (pName[i] == 0) {
+ break;
+ }
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
+ if (pName[i] == L'|' || pName[i] == L':' ||
+ pName[i] == L'/' || pName[i] == L'*' ||
+ pName[i] == L'?' || pName[i] == L'\"' ||
+ pName[i] == L'<' || pName[i] == L'>' ) {
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
+ return FALSE;
+ }
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
-
- FsRtlExitFileSystem();
+ i++;
+ }
- return(RC);
+ return TRUE;
}
+NTSTATUS
+Ext2FollowLink (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_MCB Parent,
+ IN PEXT2_MCB Mcb,
+ IN USHORT Linkdep
+)
+{
+ NTSTATUS Status = STATUS_LINK_FAILED;
+
+ UNICODE_STRING UniName;
+ OEM_STRING OemName;
+ BOOLEAN bOemBuffer = FALSE;
+
+ PEXT2_MCB Target = NULL;
+
+ USHORT i;
+
+ _SEH2_TRY {
+
+ RtlZeroMemory(&UniName, sizeof(UNICODE_STRING));
+ RtlZeroMemory(&OemName, sizeof(OEM_STRING));
+
+ /* exit if we jump into a possible symlink forever loop */
+ if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS ||
+ IoGetRemainingStackSize() < 1024) {
+ _SEH2_LEAVE;
+ }
+
+ /* read the symlink target path */
+ if (Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
+
+ OemName.Buffer = (PUCHAR) (&Mcb->Inode.i_block[0]);
+ OemName.Length = (USHORT)Mcb->Inode.i_size;
+ OemName.MaximumLength = OemName.Length + 1;
+
+ } else {
+
+ OemName.Length = (USHORT)Mcb->Inode.i_size;
+ OemName.MaximumLength = OemName.Length + 1;
+ OemName.Buffer = Ext2AllocatePool(PagedPool,
+ OemName.MaximumLength,
+ 'NL2E');
+ if (OemName.Buffer == NULL) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+ bOemBuffer = TRUE;
+ RtlZeroMemory(OemName.Buffer, OemName.MaximumLength);
+
+ Status = Ext2ReadInode(
+ IrpContext,
+ Vcb,
+ Mcb,
+ (ULONGLONG)0,
+ OemName.Buffer,
+ (ULONG)(Mcb->Inode.i_size),
+ FALSE,
+ NULL);
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ /* convert Linux slash to Windows backslash */
+ for (i=0; i < OemName.Length; i++) {
+ if (OemName.Buffer[i] == '/') {
+ OemName.Buffer[i] = '\\';
+ }
+ }
+
+ /* convert oem string to unicode string */
+ UniName.MaximumLength = (USHORT)Ext2OEMToUnicodeSize(Vcb, &OemName);
+ if (UniName.MaximumLength <= 0) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+
+ UniName.MaximumLength += 2;
+ UniName.Buffer = Ext2AllocatePool(PagedPool,
+ UniName.MaximumLength,
+ 'NL2E');
+ if (UniName.Buffer == NULL) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+ RtlZeroMemory(UniName.Buffer, UniName.MaximumLength);
+ Status = Ext2OEMToUnicode(Vcb, &UniName, &OemName);
+ if (!NT_SUCCESS(Status)) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+
+ /* search the real target */
+ Status = Ext2LookupFile(
+ IrpContext,
+ Vcb,
+ &UniName,
+ Parent,
+ &Target,
+ Linkdep
+ );
+ if (Target == NULL) {
+ Status = STATUS_LINK_FAILED;
+ }
+
+ if (Target == NULL /* link target doesn't exist */ ||
+ Target == Mcb /* symlink points to itself */ ||
+ IsMcbSpecialFile(Target) /* target not resolved*/ ||
+ IsFileDeleted(Target) /* target deleted */ ) {
+
+ if (Target) {
+ ASSERT(Target->Refercount > 0);
+ Ext2DerefMcb(Target);
+ }
+ ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+ SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+ Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
+ Mcb->Target = NULL;
+
+ } else if (IsMcbSymLink(Target)) {
+
+ ASSERT(Target->Refercount > 0);
+ ASSERT(Target->Target != NULL);
+ Ext2ReferMcb(Target->Target);
+ Mcb->Target = Target->Target;
+ Ext2DerefMcb(Target);
+ ASSERT(!IsMcbSymLink(Target->Target));
+ SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+ ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+ ASSERT(Mcb->Target->Refercount > 0);
+ Mcb->FileAttr = Target->FileAttr;
+
+ } else {
+
+ Mcb->Target = Target;
+ SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+ ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+ ASSERT(Mcb->Target->Refercount > 0);
+ Mcb->FileAttr = Target->FileAttr;
+ }
+
+ } _SEH2_FINALLY {
+
+ if (bOemBuffer) {
+ Ext2FreePool(OemName.Buffer, 'NL2E');
+ }
+
+ if (UniName.Buffer) {
+ Ext2FreePool(UniName.Buffer, 'NL2E');
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+BOOLEAN
+Ext2IsSpecialSystemFile(
+ IN PUNICODE_STRING FileName,
+ IN BOOLEAN bDirectory
+)
+{
+ PWSTR SpecialFileList[] = {
+ L"pagefile.sys",
+ L"swapfile.sys",
+ L"hiberfil.sys",
+ NULL
+ };
+
+ PWSTR SpecialDirList[] = {
+ L"Recycled",
+ L"RECYCLER",
+ L"$RECYCLE.BIN",
+ NULL
+ };
+
+ PWSTR entryName;
+ ULONG length;
+ int i;
+
+ for (i = 0; TRUE; i++) {
+
+ if (bDirectory) {
+ entryName = SpecialDirList[i];
+ } else {
+ entryName = SpecialFileList[i];
+ }
+
+ if (NULL == entryName) {
+ break;
+ }
+
+ length = wcslen(entryName) * sizeof(WCHAR);
+ if (FileName->Length == length) {
+ if ( 0 == _wcsnicmp( entryName,
+ FileName->Buffer,
+ length / sizeof(WCHAR) )) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
-/*************************************************************************
-*
-* Function: Ext2CommonCreate()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one'
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonCreate(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-BOOLEAN FirstAttempt)
+NTSTATUS
+Ext2LookupFile (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PUNICODE_STRING FullName,
+ IN PEXT2_MCB Parent,
+ OUT PEXT2_MCB * Ext2Mcb,
+ IN USHORT Linkdep
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- PIO_SECURITY_CONTEXT PtrSecurityContext = NULL;
- PFILE_OBJECT PtrNewFileObject = NULL;
- PFILE_OBJECT PtrRelatedFileObject = NULL;
- uint32 AllocationSize = 0; // if we create a new file
- PFILE_FULL_EA_INFORMATION PtrExtAttrBuffer = NULL;
- unsigned long RequestedOptions = 0;
- unsigned long RequestedDisposition = 0;
- uint8 FileAttributes = 0;
- unsigned short ShareAccess = 0;
- unsigned long ExtAttrLength = 0;
- ACCESS_MASK DesiredAccess;
-
- BOOLEAN DeferredProcessing = FALSE;
-
- PtrExt2VCB PtrVCB = NULL;
- BOOLEAN AcquiredVCB = FALSE;
-
- BOOLEAN DirectoryOnlyRequested = FALSE;
- BOOLEAN FileOnlyRequested = FALSE;
- BOOLEAN NoBufferingSpecified = FALSE;
- BOOLEAN WriteThroughRequested = FALSE;
- BOOLEAN DeleteOnCloseSpecified = FALSE;
- BOOLEAN NoExtAttrKnowledge = FALSE;
- BOOLEAN CreateTreeConnection = FALSE;
- BOOLEAN OpenByFileId = FALSE;
-
- BOOLEAN SequentialOnly = FALSE;
- BOOLEAN RandomAccess = FALSE;
-
- // Are we dealing with a page file?
- BOOLEAN PageFileManipulation = FALSE;
-
- // Is this open for a target directory (used in rename operations)?
- BOOLEAN OpenTargetDirectory = FALSE;
-
- // Should we ignore case when attempting to locate the object?
- BOOLEAN IgnoreCaseWhenChecking = FALSE;
-
- PtrExt2CCB PtrRelatedCCB = NULL, PtrNewCCB = NULL;
- PtrExt2FCB PtrRelatedFCB = NULL, PtrNewFCB = NULL;
-
- unsigned long ReturnedInformation = -1;
-
- UNICODE_STRING TargetObjectName;
- UNICODE_STRING RelatedObjectName;
-
- UNICODE_STRING AbsolutePathName;
- UNICODE_STRING RenameLinkTargetFileName;
-
- /* Silence GCC warnings */
- RtlZeroMemory(&RelatedObjectName, sizeof(UNICODE_STRING));
-
-
- ASSERT(PtrIrpContext);
- ASSERT(PtrIrp);
-
- try
- {
-
- AbsolutePathName.Buffer = NULL;
- AbsolutePathName.Length = AbsolutePathName.MaximumLength = 0;
-
- // Getting a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- // Can we block?
- if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK))
- {
- // Asynchronous processing required...
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
- DeferredProcessing = TRUE;
- try_return();
- }
-
- // Obtaining the parameters specified by the user.
- PtrNewFileObject = PtrIoStackLocation->FileObject;
- TargetObjectName = PtrNewFileObject->FileName;
- PtrRelatedFileObject = PtrNewFileObject->RelatedFileObject;
-
- if( PtrNewFileObject->FileName.Length && PtrNewFileObject->FileName.Buffer )
- {
- if( PtrNewFileObject->FileName.Buffer[ PtrNewFileObject->FileName.Length/2 ] != 0 )
- {
- DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrFileObject->FileName not NULL terminated! [Create]", 0 );
- }
- DebugTrace( DEBUG_TRACE_FILE_NAME, " === Create/Open File Name : -%S- [Create]", PtrNewFileObject->FileName.Buffer );
- }
- else
- {
- DebugTrace( DEBUG_TRACE_FILE_NAME, " === Create/Open File Name : -null- [Create]", 0);
- }
-
- // Is this a Relative Create/Open?
- if (PtrRelatedFileObject)
- {
- PtrRelatedCCB = (PtrExt2CCB)(PtrRelatedFileObject->FsContext2);
- ASSERT(PtrRelatedCCB);
- ASSERT(PtrRelatedCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB);
- // each CCB in turn points to a FCB
- PtrRelatedFCB = PtrRelatedCCB->PtrFCB;
- ASSERT(PtrRelatedFCB);
- if( PtrRelatedFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB &&
- PtrRelatedFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB )
- {
- // How the hell can this happen!!!
- Ext2BreakPoint();
- }
-
- AssertFCBorVCB( PtrRelatedFCB );
-
- RelatedObjectName = PtrRelatedFileObject->FileName;
-
- if( PtrRelatedFileObject->FileName.Length && PtrRelatedFileObject->FileName.Buffer )
- {
- DebugTrace( DEBUG_TRACE_FILE_NAME, " === Relative to : -%S-", PtrRelatedFileObject->FileName.Buffer );
- }
- else
- {
- DebugTrace( DEBUG_TRACE_FILE_NAME, " === Relative to : -null-",0);
- }
-
- }
-
-
- AllocationSize = PtrIrp->Overlay.AllocationSize.LowPart;
- // Only 32 bit file sizes supported...
-
- if (PtrIrp->Overlay.AllocationSize.HighPart)
- {
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- // Getting a pointer to the supplied security context
- PtrSecurityContext = PtrIoStackLocation->Parameters.Create.SecurityContext;
-
- // Obtaining the desired access
- DesiredAccess = PtrSecurityContext->DesiredAccess;
-
- // Getting the options supplied by the user...
- RequestedOptions = (PtrIoStackLocation->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS);
- RequestedDisposition = ((PtrIoStackLocation->Parameters.Create.Options >> 24) & 0xFF);
-
- FileAttributes = (uint8)(PtrIoStackLocation->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS);
- ShareAccess = PtrIoStackLocation->Parameters.Create.ShareAccess;
- PtrExtAttrBuffer = PtrIrp->AssociatedIrp.SystemBuffer;
-
- ExtAttrLength = PtrIoStackLocation->Parameters.Create.EaLength;
-
- SequentialOnly = ((RequestedOptions & FILE_SEQUENTIAL_ONLY ) ? TRUE : FALSE);
- RandomAccess = ((RequestedOptions & FILE_RANDOM_ACCESS ) ? TRUE : FALSE);
-
-
- DirectoryOnlyRequested = ((RequestedOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
- FileOnlyRequested = ((RequestedOptions & FILE_NON_DIRECTORY_FILE) ? TRUE : FALSE);
- NoBufferingSpecified = ((RequestedOptions & FILE_NO_INTERMEDIATE_BUFFERING) ? TRUE : FALSE);
- WriteThroughRequested = ((RequestedOptions & FILE_WRITE_THROUGH) ? TRUE : FALSE);
- DeleteOnCloseSpecified = ((RequestedOptions & FILE_DELETE_ON_CLOSE) ? TRUE : FALSE);
- NoExtAttrKnowledge = ((RequestedOptions & FILE_NO_EA_KNOWLEDGE) ? TRUE : FALSE);
- CreateTreeConnection = ((RequestedOptions & FILE_CREATE_TREE_CONNECTION) ? TRUE : FALSE);
- OpenByFileId = ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? TRUE : FALSE);
- PageFileManipulation = ((PtrIoStackLocation->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE);
- OpenTargetDirectory = ((PtrIoStackLocation->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE);
- IgnoreCaseWhenChecking = ((PtrIoStackLocation->Flags & SL_CASE_SENSITIVE) ? TRUE : FALSE);
-
- // Ensure that the operation has been directed to a valid VCB ...
- PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
- ASSERT(PtrVCB);
- ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
-
-
- if( !PtrNewFileObject->Vpb )
- {
- PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
- }
-
- // Acquiring the VCBResource Exclusively...
- // This is done to synchronise with the close and cleanup routines...
-
- DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Create]", 0);
-
- DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Create]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
-
- AcquiredVCB = TRUE;
-
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired in Create", 0);
- if( PtrNewFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Create]", PtrNewFileObject);
- }
-
- // Verify Volume...
- // if (!NT_SUCCESS(RC = Ext2VerifyVolume(PtrVCB)))
- // {
- // try_return();
- // }
-
- // If the volume has been locked, fail the request
-
- if (PtrVCB->VCBFlags & EXT2_VCB_FLAGS_VOLUME_LOCKED)
- {
- DebugTrace(DEBUG_TRACE_MISC, "Volume locked. Failing Create", 0 );
- RC = STATUS_ACCESS_DENIED;
- try_return();
- }
-
-
- if ((PtrNewFileObject->FileName.Length == 0) && ((PtrRelatedFileObject == NULL) ||
- (PtrRelatedFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB)))
- {
- //
- // >>>>>>>>>>>>> Volume Open requested. <<<<<<<<<<<<<
- //
-
- // Performing validity checks...
- if ((OpenTargetDirectory) || (PtrExtAttrBuffer))
- {
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- if (DirectoryOnlyRequested)
- {
- // a volume is not a directory
- RC = STATUS_NOT_A_DIRECTORY;
- try_return();
- }
-
- if ((RequestedDisposition != FILE_OPEN) && (RequestedDisposition != FILE_OPEN_IF))
- {
- // cannot create a new volume, I'm afraid ...
- RC = STATUS_ACCESS_DENIED;
- try_return();
- }
- DebugTrace(DEBUG_TRACE_MISC, "Volume open requested", 0 );
- RC = Ext2OpenVolume(PtrVCB, PtrIrpContext, PtrIrp, ShareAccess, PtrSecurityContext, PtrNewFileObject);
- ReturnedInformation = PtrIrp->IoStatus.Information;
-
- try_return();
- }
-
- if (OpenByFileId)
- {
- DebugTrace(DEBUG_TRACE_MISC, "Open by File Id requested", 0 );
- RC = STATUS_ACCESS_DENIED;
- try_return();
- }
-
- // Relative path name specified...
- if (PtrRelatedFileObject)
- {
-
- if (!(PtrRelatedFCB->FCBFlags & EXT2_FCB_DIRECTORY))
- {
- // we must have a directory as the "related" object
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- // Performing validity checks...
- if ((RelatedObjectName.Length == 0) || (RelatedObjectName.Buffer[0] != L'\\'))
- {
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- if ((TargetObjectName.Length != 0) && (TargetObjectName.Buffer[0] == L'\\'))
- {
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- // Creating an absolute path-name.
- {
- AbsolutePathName.MaximumLength = TargetObjectName.Length + RelatedObjectName.Length + sizeof(WCHAR);
- if (!(AbsolutePathName.Buffer = Ext2AllocatePool(PagedPool, AbsolutePathName.MaximumLength )))
- {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- RtlZeroMemory(AbsolutePathName.Buffer, AbsolutePathName.MaximumLength);
-
- RtlCopyMemory((void *)(AbsolutePathName.Buffer), (void *)(RelatedObjectName.Buffer), RelatedObjectName.Length);
- AbsolutePathName.Length = RelatedObjectName.Length;
- RtlAppendUnicodeToString(&AbsolutePathName, L"\\");
- RtlAppendUnicodeToString(&AbsolutePathName, TargetObjectName.Buffer);
- }
-
- }
- // Absolute Path name specified...
- else
- {
-
-
- // Validity Checks...
- if (TargetObjectName.Buffer[0] != L'\\')
- {
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- {
- AbsolutePathName.MaximumLength = TargetObjectName.Length;
- if (!(AbsolutePathName.Buffer = Ext2AllocatePool(PagedPool, AbsolutePathName.MaximumLength ))) {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- RtlZeroMemory(AbsolutePathName.Buffer, AbsolutePathName.MaximumLength);
-
- RtlCopyMemory((void *)(AbsolutePathName.Buffer), (void *)(TargetObjectName.Buffer), TargetObjectName.Length);
- AbsolutePathName.Length = TargetObjectName.Length;
- }
- }
-
-
- // Parsing the path...
- if (AbsolutePathName.Length == 2)
- {
-
- // this is an open of the root directory, ensure that the caller has not requested a file only
- if (FileOnlyRequested || (RequestedDisposition == FILE_SUPERSEDE) || (RequestedDisposition == FILE_OVERWRITE) ||
- (RequestedDisposition == FILE_OVERWRITE_IF))
- {
- RC = STATUS_FILE_IS_A_DIRECTORY;
- try_return();
- }
-
- RC = Ext2OpenRootDirectory(PtrVCB, PtrIrpContext, PtrIrp, ShareAccess, PtrSecurityContext, PtrNewFileObject);
- DebugTrace(DEBUG_TRACE_MISC, " === Root directory opened", 0 );
- try_return();
- }
-
-
- {
- // Used during parsing the file path...
- UNICODE_STRING RemainingName;
- UNICODE_STRING CurrentName;
- UNICODE_STRING NextRemainingName;
- ULONG CurrInodeNo = 0;
- PtrExt2FCB PtrCurrFCB = NULL;
- PtrExt2FCB PtrNextFCB = NULL;
- PFILE_OBJECT PtrCurrFileObject = NULL;
- ULONG Type = 0;
- LARGE_INTEGER ZeroSize;
- BOOLEAN Found = FALSE;
-
- ZeroSize.QuadPart = 0;
- if ( PtrRelatedFileObject )
- {
- CurrInodeNo = PtrRelatedFCB->INodeNo;
- PtrCurrFCB = PtrRelatedFCB;
- }
- else
- {
- CurrInodeNo = PtrVCB->PtrRootDirectoryFCB->INodeNo;
- PtrCurrFCB = PtrVCB->PtrRootDirectoryFCB;
-
- }
-
- // Ext2ZerooutUnicodeString( &RemainingName );
- Ext2ZerooutUnicodeString( &CurrentName );
- Ext2ZerooutUnicodeString( &NextRemainingName );
-
- RemainingName = TargetObjectName;
-
- while ( !Found && CurrInodeNo )
- {
- FsRtlDissectName ( RemainingName, &CurrentName, &NextRemainingName );
-
- RemainingName = NextRemainingName;
- // CurrInodeNo is the parent inode for the entry I am searching for
- // PtrCurrFCB is the parent's FCB
- // Current Name is its name...
-
-
- PtrNextFCB = Ext2LocateChildFCBInCore ( PtrVCB, &CurrentName, CurrInodeNo );
-
- if( PtrNextFCB )
- {
- CurrInodeNo = PtrNextFCB->INodeNo;
-
- if( NextRemainingName.Length == 0 )
- {
- //
- // Done Parsing...
- // Found the file...
- //
- Found = TRUE;
-
- if( OpenTargetDirectory )
- {
- //
- // This is for a rename/move operation...
- //
- ReturnedInformation = FILE_EXISTS;
-
- // Now replace the file name field with that of the
- // Target file name...
- Ext2CopyUnicodeString(
- &RenameLinkTargetFileName,
- &CurrentName );
- /*
-
- for( i = 0; i < (CurrentName.Length/2); i++ )
- {
- PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
- }
- PtrNewFileObject->FileName.Length = CurrentName.Length;
- */
- // Now open the Parent Directory...
- PtrNextFCB = PtrCurrFCB;
- CurrInodeNo = PtrNextFCB->INodeNo;
- }
-
- //
- // Relating the FCB to the New File Object
- //
- PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
- PtrNewFileObject->PrivateCacheMap = NULL;
- PtrNewFileObject->FsContext = (void *)( &(PtrNextFCB->NTRequiredFCB.CommonFCBHeader) );
- PtrNewFileObject->SectionObjectPointer = &(PtrNextFCB->NTRequiredFCB.SectionObject) ;
- break;
- }
-
- else if( !Ext2IsFlagOn( PtrNextFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
- {
- // Invalid path...
- // Can have only a directory in the middle of the path...
- //
- RC = STATUS_OBJECT_PATH_NOT_FOUND;
- try_return();
- }
- }
- else // searching on the disk...
- {
- CurrInodeNo = Ext2LocateFileInDisk( PtrVCB, &CurrentName, PtrCurrFCB, &Type );
- if( !CurrInodeNo )
- {
- //
- // Not found...
- // Quit searching...
- //
-
- if( ( NextRemainingName.Length == 0 ) && (
- ( RequestedDisposition == FILE_CREATE ) ||
- ( RequestedDisposition == FILE_OPEN_IF) ||
- ( RequestedDisposition == FILE_OVERWRITE_IF) ) )
-
- {
- //
- // Just the last component was not found...
- // A create was requested...
- //
- if( DirectoryOnlyRequested )
- {
- Type = EXT2_FT_DIR;
- }
- else
- {
- Type = EXT2_FT_REG_FILE;
- }
-
- CurrInodeNo = Ext2CreateFile( PtrIrpContext, PtrVCB,
- &CurrentName, PtrCurrFCB, Type );
-
- if( !CurrInodeNo )
- {
- RC = STATUS_OBJECT_PATH_NOT_FOUND;
- try_return();
- }
- // Set the allocation size for the object is specified
- //IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
- // RC = STATUS_SUCCESS;
- ReturnedInformation = FILE_CREATED;
-
- // Should also create a CCB structure...
- // Doing that a little fathre down... ;)
-
- }
- else if( NextRemainingName.Length == 0 && OpenTargetDirectory )
- {
- //
- // This is for a rename/move operation...
- // Just the last component was not found...
- //
- ReturnedInformation = FILE_DOES_NOT_EXIST;
-
- // Now replace the file name field with that of the
- // Target file name...
- Ext2CopyUnicodeString(
- &RenameLinkTargetFileName,
- &CurrentName );
- /*
- for( i = 0; i < (CurrentName.Length/2); i++ )
- {
- PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
- }
- PtrNewFileObject->FileName.Length = CurrentName.Length;
- */
-
- // Now open the Parent Directory...
- PtrNextFCB = PtrCurrFCB;
- CurrInodeNo = PtrNextFCB->INodeNo;
- // Initialize the FsContext
- PtrNewFileObject->FsContext = &PtrNextFCB->NTRequiredFCB.CommonFCBHeader;
- // Initialize the section object pointer...
- PtrNewFileObject->SectionObjectPointer = &(PtrNextFCB->NTRequiredFCB.SectionObject);
- PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
- PtrNewFileObject->PrivateCacheMap = NULL;
-
- break;
- }
- else
- {
- RC = STATUS_OBJECT_PATH_NOT_FOUND;
- try_return();
- }
- }
-
- if( NextRemainingName.Length )
- {
- // Should be a directory...
- if( Type != EXT2_FT_DIR )
- {
- // Invalid path...
- // Can have only a directory in the middle of the path...
- //
- RC = STATUS_OBJECT_PATH_NOT_FOUND;
- try_return();
- }
-
- PtrCurrFileObject = NULL;
- }
- else
- {
- //
- // Done Parsing...
- // Found the file...
- //
- Found = TRUE;
-
- //
- // Was I supposed to create a new file?
- //
- if (RequestedDisposition == FILE_CREATE &&
- ReturnedInformation != FILE_CREATED )
- {
- ReturnedInformation = FILE_EXISTS;
- RC = STATUS_OBJECT_NAME_COLLISION;
- try_return();
- }
-
- // Is this the type of file I was looking for?
- // Do some checking here...
-
- if( Type != EXT2_FT_DIR && Type != EXT2_FT_REG_FILE )
- {
- // Deny access!
- // Cannot open a special file...
- RC = STATUS_ACCESS_DENIED;
- try_return();
-
- }
- if( DirectoryOnlyRequested && Type != EXT2_FT_DIR )
- {
- RC = STATUS_NOT_A_DIRECTORY;
- try_return();
- }
- if( FileOnlyRequested && Type == EXT2_FT_DIR )
- {
- RC = STATUS_FILE_IS_A_DIRECTORY;
- try_return();
- }
-
- PtrCurrFileObject = PtrNewFileObject;
- // Things seem to be ok enough!
- // Proceeing with the Open/Create...
-
- }
-
-
- //
- // Create an FCB and initialise it...
- //
- {
- PtrExt2ObjectName PtrObjectName;
-
- // Initialising the object name...
- PtrObjectName = Ext2AllocateObjectName();
- Ext2CopyUnicodeString( &PtrObjectName->ObjectName, &CurrentName );
- // RtlInitUnicodeString( &PtrObjectName->ObjectName, CurrentName.Buffer );
-
- if( !NT_SUCCESS( Ext2CreateNewFCB(
- &PtrNextFCB, // the new FCB
- ZeroSize, // AllocationSize,
- ZeroSize, // EndOfFile,
- PtrCurrFileObject, // The File Object
- PtrVCB,
- PtrObjectName ) ) )
- {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- if( Type == EXT2_FT_DIR )
- PtrNextFCB->FCBFlags |= EXT2_FCB_DIRECTORY;
- else if( Type != EXT2_FT_REG_FILE )
- PtrNextFCB->FCBFlags |= EXT2_FCB_SPECIAL_FILE;
-
- PtrNextFCB->INodeNo = CurrInodeNo ;
- PtrNextFCB->ParentINodeNo = PtrCurrFCB->INodeNo;
-
- if( PtrCurrFileObject == NULL && CurrInodeNo != EXT2_ROOT_INO )
- {
- // This is an FCB created to cache the reads done while parsing
- // Put this FCB on the ClosableFCBList
- if( !PtrNextFCB->ClosableFCBs.OnClosableFCBList )
- {
- InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
- &PtrNextFCB->ClosableFCBs.ClosableFCBList );
- PtrVCB->ClosableFCBs.Count++;
- PtrNextFCB->ClosableFCBs.OnClosableFCBList = TRUE;
- }
- }
- }
- }
-
- //
- // Still not done parsing...
- // miles to go before I open... ;)
- //
- PtrCurrFCB = PtrNextFCB;
- }
-
- PtrNewFCB = PtrNextFCB;
- }
-
-
- // If I get this far...
- // it means, I have located the file...
- // I even have an FCB to represent it!!!
-
- if ( NT_SUCCESS (RC) )
- {
-
- if ((PtrNewFCB->FCBFlags & EXT2_FCB_DIRECTORY) && ((RequestedDisposition == FILE_SUPERSEDE) ||
- (RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF )))
- {
- RC = STATUS_FILE_IS_A_DIRECTORY;
- try_return();
- }
-
-
- // Check share access and fail if the share conflicts with an existing
- // open.
-
- if (PtrNewFCB->OpenHandleCount > 0)
- {
- // The FCB is currently in use by some thread.
- // We must check whether the requested access/share access
- // conflicts with the existing open operations.
-
- if (!NT_SUCCESS(RC = IoCheckShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject,
- &(PtrNewFCB->FCBShareAccess), TRUE)))
- {
- // Ext2CloseCCB(PtrNewCCB);
- try_return();
- }
- }
- else
- {
- IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
- }
-
- //
- // Allocating a new CCB Structure...
- //
- Ext2CreateNewCCB( &PtrNewCCB, PtrNewFCB, PtrNewFileObject);
- PtrNewFileObject->FsContext2 = (void *) PtrNewCCB;
- Ext2CopyUnicodeString( &(PtrNewCCB->AbsolutePathName), &AbsolutePathName );
-
- if( ReturnedInformation == -1 )
- {
- //
- // ReturnedInformation has not been set so far...
- //
- ReturnedInformation = FILE_OPENED;
- }
-
- // If a supersede or overwrite was requested, do so now ...
- if (RequestedDisposition == FILE_SUPERSEDE)
- {
- // Attempt the operation here ...
- if( Ext2SupersedeFile( PtrNewFCB, PtrIrpContext) )
- {
- ReturnedInformation = FILE_SUPERSEDED;
- }
- }
-
- else if ((RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF))
- {
- // Attempt the overwrite operation...
- if( Ext2OverwriteFile( PtrNewFCB, PtrIrpContext) )
- {
- ReturnedInformation = FILE_OVERWRITTEN;
- }
- }
- if( AllocationSize )
- {
- if( ReturnedInformation == FILE_CREATED ||
- ReturnedInformation == FILE_SUPERSEDED )
- {
- ULONG CurrentSize;
- ULONG LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-
- for( CurrentSize = 0; CurrentSize < AllocationSize; CurrentSize += LogicalBlockSize )
- {
- Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrNewFCB, PtrNewFileObject, FALSE );
- }
- }
- }
-
- if( ReturnedInformation == FILE_CREATED )
- {
- // Allocate some data blocks if
- // 1. initial file size has been specified...
- // 2. if the file is a Directory...
- // In case of (2) make entries for '.' and '..'
- // Zero out the Blocks...
-
- UNICODE_STRING Name;
-
- if( DirectoryOnlyRequested )
- {
-
- Ext2CopyCharToUnicodeString( &Name, ".", 1 );
- Ext2MakeNewDirectoryEntry( PtrIrpContext, PtrNewFCB, PtrNewFileObject, &Name, EXT2_FT_DIR, PtrNewFCB->INodeNo);
-
- Name.Buffer[1] = '.';
- Name.Buffer[2] = '\0';
- Name.Length += 2;
- Ext2MakeNewDirectoryEntry( PtrIrpContext, PtrNewFCB, PtrNewFileObject, &Name, EXT2_FT_DIR, PtrNewFCB->ParentINodeNo );
- Ext2DeallocateUnicodeString( &Name );
- }
- }
- if( OpenTargetDirectory )
- {
- //
- // Save the taget file name in the CCB...
- //
- Ext2CopyUnicodeString(
- &PtrNewCCB->RenameLinkTargetFileName,
- &RenameLinkTargetFileName );
- Ext2DeallocateUnicodeString( &RenameLinkTargetFileName );
- }
- }
-
- try_exit: NOTHING;
-
- }
- finally
- {
- if (AcquiredVCB)
- {
- ASSERT(PtrVCB);
- Ext2ReleaseResource(&(PtrVCB->VCBResource));
-
- AcquiredVCB = FALSE;
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB released [Create]", 0);
-
- if( PtrNewFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Create]", PtrNewFileObject);
- }
- }
-
- if (AbsolutePathName.Buffer != NULL)
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Create]", AbsolutePathName.Buffer );
- ExFreePool(AbsolutePathName.Buffer);
- }
-
- // Complete the request unless we are here as part of unwinding
- // when an exception condition was encountered, OR
- // if the request has been deferred (i.e. posted for later handling)
- if (RC != STATUS_PENDING)
- {
- // If we acquired any FCB resources, release them now ...
-
- // If any intermediate (directory) open operations were performed,
- // implement the corresponding close (do *not* however close
- // the target you have opened on behalf of the caller ...).
-
- if (NT_SUCCESS(RC))
- {
- // Update the file object such that:
- // (a) the FsContext field points to the NTRequiredFCB field
- // in the FCB
- // (b) the FsContext2 field points to the CCB created as a
- // result of the open operation
-
- // If write-through was requested, then mark the file object
- // appropriately
- if (WriteThroughRequested)
- {
- PtrNewFileObject->Flags |= FO_WRITE_THROUGH;
- }
- DebugTrace( DEBUG_TRACE_SPECIAL, " === Create/Open successful", 0 );
- }
- else
- {
- DebugTrace( DEBUG_TRACE_SPECIAL, " === Create/Open failed", 0 );
- // Perform failure related post-processing now
- }
-
- // As long as this unwinding is not being performed as a result of
- // an exception condition, complete the IRP ...
- if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION))
- {
- PtrIrp->IoStatus.Status = RC;
- PtrIrp->IoStatus.Information = ReturnedInformation;
-
- // Free up the Irp Context
- Ext2ReleaseIrpContext(PtrIrpContext);
-
- // complete the IRP
- IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
- }
- }
- }
- return(RC);
+ NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ UNICODE_STRING FileName;
+ PEXT2_MCB Mcb = NULL;
+ struct dentry *de = NULL;
+
+ USHORT i = 0, End;
+ ULONG Inode;
+
+ BOOLEAN bParent = FALSE;
+ BOOLEAN bDirectory = FALSE;
+ BOOLEAN LockAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
+ LockAcquired = TRUE;
+
+ *Ext2Mcb = NULL;
+
+ DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName));
+
+ /* check names and parameters */
+ if (FullName->Buffer[0] == L'\\') {
+ Parent = Vcb->McbTree;
+ } else if (Parent) {
+ bParent = TRUE;
+ } else {
+ Parent = Vcb->McbTree;
+ }
+
+ /* make sure the parent is NULL */
+ if (!IsMcbDirectory(Parent)) {
+ Status = STATUS_NOT_A_DIRECTORY;
+ _SEH2_LEAVE;
+ }
+
+ /* use symlink's target as parent directory */
+ if (IsMcbSymLink(Parent)) {
+ Parent = Parent->Target;
+ ASSERT(!IsMcbSymLink(Parent));
+ if (IsFileDeleted(Parent)) {
+ Status = STATUS_NOT_A_DIRECTORY;
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (NULL == Parent) {
+ Status = STATUS_NOT_A_DIRECTORY;
+ _SEH2_LEAVE;
+ }
+
+ /* default is the parent Mcb*/
+ Ext2ReferMcb(Parent);
+ Mcb = Parent;
+
+ /* is empty file name or root node */
+ End = FullName->Length/sizeof(WCHAR);
+ if ( (End == 0) || (End == 1 &&
+ FullName->Buffer[0] == L'\\')) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ /* is a directory expected ? */
+ if (FullName->Buffer[End - 1] == L'\\') {
+ bDirectory = TRUE;
+ }
+
+ /* loop with every sub name */
+ while (i < End) {
+
+ USHORT Start = 0;
+
+ /* zero the prefix '\' */
+ while (i < End && FullName->Buffer[i] == L'\\') i++;
+ Start = i;
+
+ /* zero the suffix '\' */
+ while (i < End && (FullName->Buffer[i] != L'\\')) i++;
+
+ if (i > Start) {
+
+ FileName = *FullName;
+ FileName.Buffer += Start;
+ FileName.Length = (USHORT)((i - Start) * 2);
+
+ /* make sure the parent is NULL */
+ if (!IsMcbDirectory(Parent)) {
+ Status = STATUS_NOT_A_DIRECTORY;
+ Ext2DerefMcb(Parent);
+ break;
+ }
+
+ if (IsMcbSymLink(Parent)) {
+ if (IsFileDeleted(Parent->Target)) {
+ Status = STATUS_NOT_A_DIRECTORY;
+ Ext2DerefMcb(Parent);
+ break;
+ } else {
+ Ext2ReferMcb(Parent->Target);
+ Ext2DerefMcb(Parent);
+ Parent = Parent->Target;
+ }
+ }
+
+ /* search cached Mcb nodes */
+ Mcb = Ext2SearchMcbWithoutLock(Parent, &FileName);
+
+ if (Mcb) {
+
+ /* derefer the parent Mcb */
+ Ext2DerefMcb(Parent);
+ Status = STATUS_SUCCESS;
+ Parent = Mcb;
+
+ if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) &&
+ (Mcb->Refercount == 1)) {
+
+ ASSERT(Mcb->Target);
+ ASSERT(Mcb->Target->Refercount > 0);
+ Ext2DerefMcb(Mcb->Target);
+ Mcb->Target = NULL;
+ ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+ SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+ Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ } else {
+
+ /* need create new Mcb node */
+
+ /* is a valid ext2 name */
+ if (!Ext2IsNameValid(&FileName)) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ Ext2DerefMcb(Parent);
+ break;
+ }
+
+ /* seach the disk */
+ de = NULL;
+ Status = Ext2ScanDir (
+ IrpContext,
+ Vcb,
+ Parent,
+ &FileName,
+ &Inode,
+ &de);
+
+ if (NT_SUCCESS(Status)) {
+
+ /* check it's real parent */
+ ASSERT (!IsMcbSymLink(Parent));
+
+ /* allocate Mcb ... */
+ Mcb = Ext2AllocateMcb(Vcb, &FileName, &Parent->FullName, 0);
+ if (!Mcb) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ Ext2DerefMcb(Parent);
+ break;
+ }
+ Mcb->de = de;
+ Mcb->de->d_inode = &Mcb->Inode;
+ Mcb->Inode.i_ino = Inode;
+ Mcb->Inode.i_sb = &Vcb->sb;
+ de = NULL;
+
+ /* load inode information */
+ if (!Ext2LoadInode(Vcb, &Mcb->Inode)) {
+ Status = STATUS_CANT_WAIT;
+ Ext2DerefMcb(Parent);
+ Ext2FreeMcb(Vcb, Mcb);
+ break;
+ }
+
+ /* set inode attribute */
+ if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
+ SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+ }
+
+ if (S_ISDIR(Mcb->Inode.i_mode)) {
+ SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+ } else {
+ SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
+ if (!S_ISREG(Mcb->Inode.i_mode) &&
+ !S_ISLNK(Mcb->Inode.i_mode)) {
+ SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+ }
+ }
+
+ /* process special files under root directory */
+ if (IsMcbRoot(Parent)) {
+ /* set hidden and system attributes for
+ Recycled / RECYCLER / pagefile.sys */
+ BOOLEAN IsDirectory = IsMcbDirectory(Mcb);
+ if (Ext2IsSpecialSystemFile(&Mcb->ShortName, IsDirectory)) {
+ SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_HIDDEN);
+ SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_SYSTEM);
+ }
+ }
+
+ Mcb->CreationTime = Ext2NtTime(Mcb->Inode.i_ctime);
+ Mcb->LastAccessTime = Ext2NtTime(Mcb->Inode.i_atime);
+ Mcb->LastWriteTime = Ext2NtTime(Mcb->Inode.i_mtime);
+ Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime);
+
+ /* process symlink */
+ if (S_ISLNK(Mcb->Inode.i_mode)) {
+ Ext2FollowLink( IrpContext,
+ Vcb,
+ Parent,
+ Mcb,
+ Linkdep+1
+ );
+ }
+
+ /* add reference ... */
+ Ext2ReferMcb(Mcb);
+
+ /* add Mcb to it's parent tree*/
+ Ext2InsertMcb(Vcb, Parent, Mcb);
+
+ /* it's safe to deref Parent Mcb */
+ Ext2DerefMcb(Parent);
+
+ /* linking this Mcb*/
+ Ext2LinkTailMcb(Vcb, Mcb);
+
+ /* set parent to preare re-scan */
+ Parent = Mcb;
+
+ } else {
+
+ /* derefernce it's parent */
+ Ext2DerefMcb(Parent);
+ break;
+ }
+ }
+
+ } else {
+
+ /* there seems too many \ or / */
+ /* Mcb should be already set to Parent */
+ ASSERT(Mcb == Parent);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ } _SEH2_FINALLY {
+
+ if (de) {
+ Ext2FreeEntry(de);
+ }
+
+ if (NT_SUCCESS(Status)) {
+ if (bDirectory) {
+ if (IsMcbDirectory(Mcb)) {
+ *Ext2Mcb = Mcb;
+ } else {
+ Ext2DerefMcb(Mcb);
+ Status = STATUS_NOT_A_DIRECTORY;
+ }
+ } else {
+ *Ext2Mcb = Mcb;
+ }
+ }
+
+ if (LockAcquired) {
+ ExReleaseResourceLite(&Vcb->McbLock);
+ }
+ } _SEH2_END;
+
+ return Status;
}
-/*************************************************************************
-*
-* Function: Ext2OpenVolume()
-*
-* Description:
-* Open a logical volume for the caller.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2OpenVolume(
-PtrExt2VCB PtrVCB, // volume to be opened
-PtrExt2IrpContext PtrIrpContext, // IRP context
-PIRP PtrIrp, // original/user IRP
-unsigned short ShareAccess, // share access
-PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access)
-PFILE_OBJECT PtrNewFileObject) // I/O Mgr. created file object
+NTSTATUS
+Ext2ScanDir (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_MCB Parent,
+ IN PUNICODE_STRING FileName,
+ OUT PULONG Inode,
+ OUT struct dentry **dentry
+)
+{
+ struct ext3_dir_entry_2 *dir_entry = NULL;
+ struct buffer_head *bh = NULL;
+ struct dentry *de = NULL;
+
+ NTSTATUS Status = STATUS_NO_SUCH_FILE;
+
+ DEBUG(DL_RES, ("Ext2ScanDir: %wZ\\%wZ\n", &Parent->FullName, FileName));
+
+ _SEH2_TRY {
+
+ /* grab parent's reference first */
+ Ext2ReferMcb(Parent);
+
+ /* bad request ! Can a man be pregnant ? Maybe:) */
+ if (!IsMcbDirectory(Parent)) {
+ Status = STATUS_NOT_A_DIRECTORY;
+ _SEH2_LEAVE;
+ }
+
+ /* parent is a symlink ? */
+ if IsMcbSymLink(Parent) {
+ if (Parent->Target) {
+ Ext2ReferMcb(Parent->Target);
+ Ext2DerefMcb(Parent);
+ Parent = Parent->Target;
+ ASSERT(!IsMcbSymLink(Parent));
+ } else {
+ DbgBreak();
+ Status = STATUS_NOT_A_DIRECTORY;
+ _SEH2_LEAVE;
+ }
+ }
+
+ de = Ext2BuildEntry(Vcb, Parent, FileName);
+ if (!de) {
+ DEBUG(DL_ERR, ( "Ex2ScanDir: failed to allocate dentry.\n"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+
+ bh = ext3_find_entry(IrpContext, de, &dir_entry);
+ if (dir_entry) {
+ Status = STATUS_SUCCESS;
+ *Inode = dir_entry->inode;
+ *dentry = de;
+ }
+
+ } _SEH2_FINALLY {
+
+ Ext2DerefMcb(Parent);
+
+ if (bh)
+ brelse(bh);
+
+ if (!NT_SUCCESS(Status)) {
+ if (de)
+ Ext2FreeEntry(de);
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+NTSTATUS Ext2AddDotEntries(struct ext2_icb *icb, struct inode *dir,
+ struct inode *inode)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2CCB PtrCCB = NULL;
-
- try {
- // check for exclusive open requests (using share modes supplied)
- // and determine whether it is even possible to open the volume
- // with the specified share modes (e.g. if caller does not
- // wish to share read or share write ...)
-
- // Use IoCheckShareAccess() and IoSetShareAccess() here ...
- // They are defined in the DDK.
-
- // You might also wish to check the caller's security context
- // to see whether you wish to allow the volume open or not.
- // Use the SeAccessCheck() routine described in the DDK for this purpose.
-
- // create a new CCB structure
- if (!(PtrCCB = Ext2AllocateCCB()))
- {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- // initialize the CCB
- PtrCCB->PtrFCB = (PtrExt2FCB)(PtrVCB);
- InsertTailList(&(PtrVCB->VolumeOpenListHead), &(PtrCCB->NextCCB));
-
- // initialize the CCB to point to the file object
- PtrCCB->PtrFileObject = PtrNewFileObject;
-
- Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_VOLUME_OPEN);
-
- // initialize the file object appropriately
- PtrNewFileObject->FsContext = (void *)( &(PtrVCB->CommonVCBHeader) );
- PtrNewFileObject->FsContext2 = (void *)(PtrCCB);
-
- // increment the number of outstanding open operations on this
- // logical volume (i.e. volume cannot be dismounted)
-
- // You might be concerned about 32 bit wrap-around though I would
- // argue that it is unlikely ... :-)
- (PtrVCB->VCBOpenCount)++;
-
- // now set the IoStatus Information value correctly in the IRP
- // (caller will set the status field)
- PtrIrp->IoStatus.Information = FILE_OPENED;
-
- try_exit: NOTHING;
- }
- finally
- {
- NOTHING;
- }
-
- return(RC);
+ struct ext3_dir_entry_2 * de;
+ struct buffer_head * bh;
+ ext3_lblk_t block = 0;
+ int rc = 0;
+
+ bh = ext3_append(icb, inode, &block, &rc);
+ if (!bh) {
+ goto errorout;
+ }
+
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ de->inode = cpu_to_le32(inode->i_ino);
+ de->name_len = 1;
+ de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
+ strcpy (de->name, ".");
+ ext3_set_de_type(inode->i_sb, de, S_IFDIR);
+ de = (struct ext3_dir_entry_2 *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ de->inode = cpu_to_le32(dir->i_ino);
+ de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+ de->name_len = 2;
+ strcpy (de->name, "..");
+ ext3_set_de_type(inode->i_sb, de, S_IFDIR);
+ inode->i_nlink = 2;
+ set_buffer_dirty(bh);
+ ext3_mark_inode_dirty(icb, inode);
+
+errorout:
+ if (bh)
+ brelse (bh);
+
+ return Ext2WinntError(rc);
}
-/*************************************************************************
-*
-* Function: Ext2InitializeFCB()
-*
-* Description:
-* Initialize a new FCB structure and also the sent-in file object
-* (if supplied)
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************
-void Ext2InitializeFCB(
-PtrExt2FCB PtrNewFCB, // FCB structure to be initialized
-PtrExt2VCB PtrVCB, // logical volume (VCB) pointer
-PtrExt2ObjectName PtrObjectName, // name of the object
-uint32 Flags, // is this a file/directory, etc.
-PFILE_OBJECT PtrFileObject) // optional file object to be initialized
+NTSTATUS
+Ext2CreateFile(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PBOOLEAN OpPostIrp
+)
{
- // Initialize the disk dependent portion as you see fit
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PIO_STACK_LOCATION IrpSp;
+ PEXT2_FCB Fcb = NULL;
+ PEXT2_MCB Mcb = NULL;
+ PEXT2_MCB SymLink = NULL;
+ PEXT2_CCB Ccb = NULL;
- // Initialize the two ERESOURCE objects
- ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.MainResource));
- ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.PagingIoResource));
+ PEXT2_FCB ParentFcb = NULL;
+ PEXT2_MCB ParentMcb = NULL;
- PtrNewFCB->FCBFlags |= EXT2_INITIALIZED_MAIN_RESOURCE | EXT2_INITIALIZED_PAGING_IO_RESOURCE | Flags;
+ UNICODE_STRING FileName;
+ PIRP Irp;
+
+ ULONG Options;
+ ULONG CreateDisposition;
+
+ BOOLEAN bParentFcbCreated = FALSE;
+
+#ifndef __REACTOS__
+ BOOLEAN bDir = FALSE;
+#endif
+ BOOLEAN bFcbAllocated = FALSE;
+ BOOLEAN bCreated = FALSE;
+ BOOLEAN bMainResourceAcquired = FALSE;
- PtrNewFCB->PtrVCB = PtrVCB;
+ BOOLEAN OpenDirectory;
+ BOOLEAN OpenTargetDirectory;
+ BOOLEAN CreateDirectory;
+ BOOLEAN SequentialOnly;
+ BOOLEAN NoIntermediateBuffering;
+ BOOLEAN IsPagingFile;
+ BOOLEAN DirectoryFile;
+ BOOLEAN NonDirectoryFile;
+ BOOLEAN NoEaKnowledge;
+ BOOLEAN DeleteOnClose;
+ BOOLEAN TemporaryFile;
+ BOOLEAN CaseSensitive;
- // caller MUST ensure that VCB has been acquired exclusively
- InsertTailList(&(PtrVCB->FCBListHead), &(PtrNewFCB->NextFCB));
+ ACCESS_MASK DesiredAccess;
+ ULONG ShareAccess;
- // initialize the various list heads
- InitializeListHead(&(PtrNewFCB->CCBListHead));
+ RtlZeroMemory(&FileName, sizeof(UNICODE_STRING));
-// PtrNewFCB->ReferenceCount = 1;
-// PtrNewFCB->OpenHandleCount = 1;
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
- if( PtrObjectName )
- {
- PtrNewFCB->FCBName = PtrObjectName;
- }
+ Options = IrpSp->Parameters.Create.Options;
- if ( PtrFileObject )
- {
- PtrFileObject->FsContext = (void *)(&(PtrNewFCB->NTRequiredFCB));
- }
+ DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
+ OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
- return;
+ NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
+ SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
+ NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
+ NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
+ DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
+
+ CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
+
+ TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
+ FILE_ATTRIBUTE_TEMPORARY );
+
+ CreateDisposition = (Options >> 24) & 0x000000ff;
+
+ IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
+
+ CreateDirectory = (BOOLEAN)(DirectoryFile &&
+ ((CreateDisposition == FILE_CREATE) ||
+ (CreateDisposition == FILE_OPEN_IF)));
+
+ OpenDirectory = (BOOLEAN)(DirectoryFile &&
+ ((CreateDisposition == FILE_OPEN) ||
+ (CreateDisposition == FILE_OPEN_IF)));
+
+ DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+ ShareAccess = IrpSp->Parameters.Create.ShareAccess;
+
+ *OpPostIrp = FALSE;
+
+ _SEH2_TRY {
+
+ FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
+ FileName.Length = IrpSp->FileObject->FileName.Length;
+
+ if (IrpSp->FileObject->RelatedFileObject) {
+ ParentFcb = (PEXT2_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
+ }
+
+ if (ParentFcb) {
+ ParentMcb = ParentFcb->Mcb;
+ SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+ Ext2ReferMcb(ParentMcb);
+ }
+
+ if (FileName.Length == 0) {
+
+ if (ParentFcb) {
+ Mcb = ParentFcb->Mcb;
+ Ext2ReferMcb(Mcb);
+ Status = STATUS_SUCCESS;
+ goto McbExisting;
+ } else {
+ DbgBreak();
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+ }
+
+ FileName.Buffer = Ext2AllocatePool(
+ PagedPool,
+ FileName.MaximumLength,
+ EXT2_FNAME_MAGIC
+ );
+
+ if (!FileName.Buffer) {
+ DEBUG(DL_ERR, ( "Ex2CreateFile: failed to allocate FileName.\n"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+
+ INC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
+
+ RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
+ RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
+
+ if (ParentFcb && FileName.Buffer[0] == L'\\') {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ if ((FileName.Length > sizeof(WCHAR)) &&
+ (FileName.Buffer[1] == L'\\') &&
+ (FileName.Buffer[0] == L'\\')) {
+
+ FileName.Length -= sizeof(WCHAR);
+
+ RtlMoveMemory( &FileName.Buffer[0],
+ &FileName.Buffer[1],
+ FileName.Length );
+
+ //
+ // Bad Name if there are still beginning backslashes.
+ //
+
+ if ((FileName.Length > sizeof(WCHAR)) &&
+ (FileName.Buffer[1] == L'\\') &&
+ (FileName.Buffer[0] == L'\\')) {
+
+ Status = STATUS_OBJECT_NAME_INVALID;
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID)) {
+ Status = STATUS_NOT_IMPLEMENTED;
+ _SEH2_LEAVE;
+ }
+
+ DEBUG(DL_INF, ( "Ext2CreateFile: %wZ Paging=%d Option: %xh:"
+ "Dir=%d NonDir=%d OpenTarget=%d NC=%d DeleteOnClose=%d\n",
+ &FileName, IsPagingFile, IrpSp->Parameters.Create.Options,
+ DirectoryFile, NonDirectoryFile, OpenTargetDirectory,
+ NoIntermediateBuffering, DeleteOnClose ));
+
+ DEBUG(DL_RES, ("Ext2CreateFile: Lookup 1st: %wZ at %S\n",
+ &FileName, ParentMcb ? ParentMcb->FullName.Buffer : L" "));
+ Status = Ext2LookupFile(
+ IrpContext,
+ Vcb,
+ &FileName,
+ ParentMcb,
+ &Mcb,
+ 0 );
+McbExisting:
+
+ if (!NT_SUCCESS(Status)) {
+
+ UNICODE_STRING PathName;
+ UNICODE_STRING RealName;
+ UNICODE_STRING RemainName;
+
+#ifndef __REACTOS__
+ LONG i = 0;
+#endif
+ PathName = FileName;
+ Mcb = NULL;
+
+ if (PathName.Buffer[PathName.Length/2 - 1] == L'\\') {
+ if (DirectoryFile) {
+ PathName.Length -=2;
+ PathName.Buffer[PathName.Length/2] = 0;
+ } else {
+ DirectoryFile = TRUE;
+ }
+ }
+
+ if (!ParentMcb) {
+ if (PathName.Buffer[0] != L'\\') {
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ _SEH2_LEAVE;
+ } else {
+ ParentMcb = Vcb->McbTree;
+ Ext2ReferMcb(ParentMcb);
+ }
+ }
+
+Dissecting:
+
+ FsRtlDissectName(PathName, &RealName, &RemainName);
+
+ if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
+ (RealName.Length >= 256 * sizeof(WCHAR))) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ _SEH2_LEAVE;
+ }
+
+ if (RemainName.Length != 0) {
+
+ PEXT2_MCB RetMcb = NULL;
+
+ DEBUG(DL_RES, ("Ext2CreateFile: Lookup 2nd: %wZ\\%wZ\n",
+ &ParentMcb->FullName, &RealName));
+
+ Status = Ext2LookupFile (
+ IrpContext,
+ Vcb,
+ &RealName,
+ ParentMcb,
+ &RetMcb,
+ 0);
+
+ /* quit name resolving loop */
+ if (!NT_SUCCESS(Status)) {
+ if (Status == STATUS_NO_SUCH_FILE && RemainName.Length != 0) {
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ _SEH2_LEAVE;
+ }
+
+ /* deref ParentMcb */
+ Ext2DerefMcb(ParentMcb);
+
+ /* RetMcb is already refered */
+ ParentMcb = RetMcb;
+ PathName = RemainName;
+
+ /* symlink must use it's target */
+ if (IsMcbSymLink(ParentMcb)) {
+ Ext2ReferMcb(ParentMcb->Target);
+ Ext2DerefMcb(ParentMcb);
+ ParentMcb = ParentMcb->Target;
+ ASSERT(!IsMcbSymLink(ParentMcb));
+ }
+
+ goto Dissecting;
+ }
+
+ /* is name valid */
+ if ( FsRtlDoesNameContainWildCards(&RealName) ||
+ !Ext2IsNameValid(&RealName)) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ _SEH2_LEAVE;
+ }
+
+ /* clear BUSY bit from original ParentFcb */
+ if (ParentFcb) {
+ ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+ }
+
+ /* get the ParentFcb, allocate it if needed ... */
+ ParentFcb = ParentMcb->Fcb;
+ if (!ParentFcb) {
+ ParentFcb = Ext2AllocateFcb(Vcb, ParentMcb);
+ if (!ParentFcb) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+ bParentFcbCreated = TRUE;
+ Ext2ReferXcb(&ParentFcb->ReferenceCount);
+ }
+ SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+
+ // We need to create a new one ?
+ if ((CreateDisposition == FILE_CREATE ) ||
+ (CreateDisposition == FILE_SUPERSEDE) ||
+ (CreateDisposition == FILE_OPEN_IF) ||
+ (CreateDisposition == FILE_OVERWRITE_IF)) {
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+
+ if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(ParentFcb->Mcb->Inode.i_mode)) {
+ Status = STATUS_ACCESS_DENIED;
+ _SEH2_LEAVE;
+ }
+
+ if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
+ IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
+ Vcb->Vpb->RealDevice );
+ SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+ Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+ }
+
+ if (DirectoryFile) {
+ if (TemporaryFile) {
+ DbgBreak();
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (!ParentFcb) {
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ _SEH2_LEAVE;
+ }
+
+ /* allocate inode and construct entry for this file */
+ Status = Ext2CreateInode(
+ IrpContext,
+ Vcb,
+ ParentFcb,
+ DirectoryFile ? EXT2_FT_DIR : EXT2_FT_REG_FILE,
+ IrpSp->Parameters.Create.FileAttributes,
+ &RealName
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ bCreated = TRUE;
+ DEBUG(DL_RES, ("Ext2CreateFile: Confirm creation: %wZ\\%wZ\n",
+ &ParentMcb->FullName, &RealName));
+
+ Irp->IoStatus.Information = FILE_CREATED;
+ Status = Ext2LookupFile (
+ IrpContext,
+ Vcb,
+ &RealName,
+ ParentMcb,
+ &Mcb,
+ 0);
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ }
+
+ } else if (OpenTargetDirectory) {
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+
+ if (!ParentFcb) {
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ _SEH2_LEAVE;
+ }
+
+ RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
+ IrpSp->FileObject->FileName.MaximumLength);
+ IrpSp->FileObject->FileName.Length = RealName.Length;
+
+ RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
+ RealName.Buffer,
+ RealName.Length );
+
+ Fcb = ParentFcb;
+ Mcb = Fcb->Mcb;
+ Ext2ReferMcb(Mcb);
+
+ Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
+ Status = STATUS_SUCCESS;
+
+ } else {
+
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ _SEH2_LEAVE;
+ }
+
+ } else { // File / Dir already exists.
+
+ /* here already get Mcb referred */
+ if (OpenTargetDirectory) {
+
+ UNICODE_STRING RealName = FileName;
+ USHORT i = 0;
+
+ while (RealName.Buffer[RealName.Length/2 - 1] == L'\\') {
+ RealName.Length -= sizeof(WCHAR);
+ RealName.Buffer[RealName.Length/2] = 0;
+ }
+ i = RealName.Length/2;
+ while (i > 0 && RealName.Buffer[i - 1] != L'\\')
+ i--;
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ Ext2DerefMcb(Mcb);
+ _SEH2_LEAVE;
+ }
+
+ Irp->IoStatus.Information = FILE_EXISTS;
+ Status = STATUS_SUCCESS;
+
+ RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
+ IrpSp->FileObject->FileName.MaximumLength);
+ IrpSp->FileObject->FileName.Length = RealName.Length - i * sizeof(WCHAR);
+ RtlCopyMemory( IrpSp->FileObject->FileName.Buffer, &RealName.Buffer[i],
+ IrpSp->FileObject->FileName.Length );
+
+ // use's it's parent since it's open-target operation
+ Ext2ReferMcb(Mcb->Parent);
+ Ext2DerefMcb(Mcb);
+ Mcb = Mcb->Parent;
+
+ goto Openit;
+ }
+
+ // We can not create if one exists
+ if (CreateDisposition == FILE_CREATE) {
+ Irp->IoStatus.Information = FILE_EXISTS;
+ Status = STATUS_OBJECT_NAME_COLLISION;
+ Ext2DerefMcb(Mcb);
+ _SEH2_LEAVE;
+ }
+
+ /* directory forbits us to do the followings ... */
+ if (IsMcbDirectory(Mcb)) {
+
+ if ((CreateDisposition != FILE_OPEN) &&
+ (CreateDisposition != FILE_OPEN_IF)) {
+
+ Status = STATUS_OBJECT_NAME_COLLISION;
+ Ext2DerefMcb(Mcb);
+ _SEH2_LEAVE;
+ }
+
+ if (NonDirectoryFile) {
+ Status = STATUS_FILE_IS_A_DIRECTORY;
+ Ext2DerefMcb(Mcb);
+ _SEH2_LEAVE;
+ }
+
+ if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
+
+ if (OpenTargetDirectory) {
+ DbgBreak();
+ Status = STATUS_INVALID_PARAMETER;
+ Ext2DerefMcb(Mcb);
+ _SEH2_LEAVE;
+ }
+ }
+
+ } else {
+
+ if (DirectoryFile) {
+ Status = STATUS_NOT_A_DIRECTORY;;
+ Ext2DerefMcb(Mcb);
+ _SEH2_LEAVE;
+ }
+ }
+
+ Irp->IoStatus.Information = FILE_OPENED;
+ }
+
+Openit:
+ /* Mcb should already be referred and symlink is too */
+ if (Mcb) {
+
+ ASSERT(Mcb->Refercount > 0);
+
+ /* refer it's target if it's a symlink, so both refered */
+ if (IsMcbSymLink(Mcb)) {
+ if (IsFileDeleted(Mcb->Target)) {
+ DbgBreak();
+ SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+ ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+ Ext2DerefMcb(Mcb->Target);
+ Mcb->Target = NULL;
+ } else {
+ SymLink = Mcb;
+ Mcb = Mcb->Target;
+ Ext2ReferMcb(Mcb);
+ ASSERT (!IsMcbSymLink(Mcb));
+ }
+ }
+
+ // Check readonly flag
+ if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
+ if (BooleanFlagOn(DesiredAccess, FILE_WRITE_DATA | FILE_APPEND_DATA |
+ FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) {
+ Status = STATUS_ACCESS_DENIED;
+ _SEH2_LEAVE;
+ } else if (IsFlagOn(Options, FILE_DELETE_ON_CLOSE )) {
+ Status = STATUS_CANNOT_DELETE;
+ _SEH2_LEAVE;
+ }
+ }
+
+ Fcb = Mcb->Fcb;
+ if (Fcb == NULL) {
+
+ /* allocate Fcb for this file */
+ Fcb = Ext2AllocateFcb (Vcb, Mcb);
+ if (Fcb) {
+ bFcbAllocated = TRUE;
+ } else {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ } else {
+ if (IsPagingFile) {
+ Status = STATUS_SHARING_VIOLATION;
+ Fcb = NULL;
+ }
+ }
+
+ /* Now it's safe to defer Mcb */
+ Ext2DerefMcb(Mcb);
+ }
+
+ if (Fcb) {
+
+ /* grab Fcb's reference first to avoid the race between
+ Ext2Close (it could free the Fcb we are accessing) */
+ Ext2ReferXcb(&Fcb->ReferenceCount);
+
+ ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+ bMainResourceAcquired = TRUE;
+
+ /* Open target directory ? */
+ if (NULL == Mcb) {
+ DbgBreak();
+ Mcb = Fcb->Mcb;
+ }
+
+ /* check Mcb reference */
+ ASSERT(Fcb->Mcb->Refercount > 0);
+
+ /* file delted ? */
+ if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) {
+ Status = STATUS_FILE_DELETED;
+ _SEH2_LEAVE;
+ }
+
+ if (DeleteOnClose && NULL == SymLink) {
+ Status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ /* check access and oplock access for opened files */
+ if (!bFcbAllocated && !IsDirectory(Fcb)) {
+
+ /* whether there's batch oplock grabed on the file */
+ if (FsRtlCurrentBatchOplock(&Fcb->Oplock)) {
+
+ Irp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
+
+ /* break the batch lock if the sharing check fails */
+ Status = FsRtlCheckOplock( &Fcb->Oplock,
+ IrpContext->Irp,
+ IrpContext,
+ Ext2OplockComplete,
+ Ext2LockIrp );
+
+ if ( Status != STATUS_SUCCESS &&
+ Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
+ *OpPostIrp = TRUE;
+ _SEH2_LEAVE;
+ }
+ }
+ }
+
+ if (bCreated) {
+
+ //
+ // This file is just created.
+ //
+
+ if (DirectoryFile) {
+
+ Status = Ext2AddDotEntries(IrpContext, &ParentMcb->Inode, &Mcb->Inode);
+ if (!NT_SUCCESS(Status)) {
+ Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+ _SEH2_LEAVE;
+ }
+
+ } else {
+
+ if ((LONGLONG)ext3_free_blocks_count(SUPER_BLOCK) <=
+ Ext2TotalBlocks(Vcb, &Irp->Overlay.AllocationSize, NULL)) {
+ DbgBreak();
+ Status = STATUS_DISK_FULL;
+ _SEH2_LEAVE;
+ }
+
+ /* disable data blocks allocation */
+#if 0
+ Fcb->Header.AllocationSize.QuadPart =
+ Irp->Overlay.AllocationSize.QuadPart;
+
+ if (Fcb->Header.AllocationSize.QuadPart > 0) {
+ Status = Ext2ExpandFile(IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ &(Fcb->Header.AllocationSize)
+ );
+ SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
+ if (!NT_SUCCESS(Status)) {
+ Fcb->Header.AllocationSize.QuadPart = 0;
+ Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb,
+ &Fcb->Header.AllocationSize);
+ _SEH2_LEAVE;
+ }
+ }
+#endif
+ }
+
+ } else {
+
+ //
+ // This file alreayd exists.
+ //
+
+ if (DeleteOnClose) {
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+
+ if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+
+ IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
+ Vcb->Vpb->RealDevice );
+
+ SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+
+ Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+ }
+
+ } else {
+
+ //
+ // Just to Open file (Open/OverWrite ...)
+ //
+
+ if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
+ FO_NO_INTERMEDIATE_BUFFERING))) {
+ Fcb->Header.IsFastIoPossible = FastIoIsPossible;
+
+ if (Fcb->SectionObject.DataSectionObject != NULL) {
+
+ if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) {
+
+ if (!IsVcbReadOnly(Vcb)) {
+ CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
+ ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+ }
+
+ CcPurgeCacheSection(&Fcb->SectionObject,
+ NULL,
+ 0,
+ FALSE );
+ }
+ }
+ }
+ }
+ }
+
+ if (!IsDirectory(Fcb)) {
+
+ if (!IsVcbReadOnly(Vcb)) {
+ if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) {
+ DesiredAccess |= DELETE;
+ } else if (((CreateDisposition == FILE_OVERWRITE) ||
+ (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
+ DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
+ FILE_WRITE_ATTRIBUTES );
+ }
+ }
+
+ if (!bFcbAllocated) {
+
+ //
+ // check the oplock state of the file
+ //
+ Status = FsRtlCheckOplock( &Fcb->Oplock,
+ IrpContext->Irp,
+ IrpContext,
+ Ext2OplockComplete,
+ Ext2LockIrp );
+
+ if ( Status != STATUS_SUCCESS &&
+ Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
+ *OpPostIrp = TRUE;
+ _SEH2_LEAVE;
+ }
+ }
+ }
+
+ if (Fcb->OpenHandleCount > 0) {
+
+ /* check the shrae access conflicts */
+ Status = IoCheckShareAccess( DesiredAccess,
+ ShareAccess,
+ IrpSp->FileObject,
+ &(Fcb->ShareAccess),
+ TRUE );
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ } else {
+
+ /* set share access rights */
+ IoSetShareAccess( DesiredAccess,
+ ShareAccess,
+ IrpSp->FileObject,
+ &(Fcb->ShareAccess) );
+ }
+
+ Ccb = Ext2AllocateCcb(SymLink);
+ if (!Ccb) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ if (DeleteOnClose)
+ SetLongFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
+
+ if (SymLink)
+ Ccb->filp.f_dentry = SymLink->de;
+ else
+ Ccb->filp.f_dentry = Fcb->Mcb->de;
+
+ Ccb->filp.f_version = Fcb->Mcb->Inode.i_version;
+ Ext2ReferXcb(&Fcb->OpenHandleCount);
+ Ext2ReferXcb(&Fcb->ReferenceCount);
+
+ if (!IsDirectory(Fcb)) {
+ if (NoIntermediateBuffering) {
+ Fcb->NonCachedOpenCount++;
+ SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
+ } else {
+ SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
+ }
+ }
+
+ Ext2ReferXcb(&Vcb->OpenHandleCount);
+ Ext2ReferXcb(&Vcb->ReferenceCount);
+
+ IrpSp->FileObject->FsContext = (void*) Fcb;
+ IrpSp->FileObject->FsContext2 = (void*) Ccb;
+ IrpSp->FileObject->PrivateCacheMap = NULL;
+ IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
+
+ DEBUG(DL_INF, ( "Ext2CreateFile: %wZ OpenCount=%u ReferCount=%u NonCachedCount=%u\n",
+ &Fcb->Mcb->FullName, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount));
+
+ Status = STATUS_SUCCESS;
+
+ if (bCreated) {
+
+ if (IsDirectory(Fcb)) {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ FILE_ACTION_ADDED );
+ } else {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ FILE_ACTION_ADDED );
+ }
+
+ } else if (!IsDirectory(Fcb)) {
+
+ if ( DeleteOnClose ||
+ IsFlagOn(DesiredAccess, FILE_WRITE_DATA) ||
+ (CreateDisposition == FILE_OVERWRITE) ||
+ (CreateDisposition == FILE_OVERWRITE_IF)) {
+ if (!MmFlushImageSection( &Fcb->SectionObject,
+ MmFlushForWrite )) {
+
+ Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
+ STATUS_SHARING_VIOLATION;
+ _SEH2_LEAVE;
+ }
+ }
+
+ if ((CreateDisposition == FILE_SUPERSEDE) ||
+ (CreateDisposition == FILE_OVERWRITE) ||
+ (CreateDisposition == FILE_OVERWRITE_IF)) {
+
+ if (IsDirectory(Fcb)) {
+ Status = STATUS_FILE_IS_A_DIRECTORY;
+ _SEH2_LEAVE;
+ }
+
+ if (SymLink != NULL) {
+ DbgBreak();
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+
+ if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
+
+ IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
+ Vcb->Vpb->RealDevice );
+ SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+ Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+ }
+
+ Status = Ext2SupersedeOrOverWriteFile(
+ IrpContext,
+ IrpSp->FileObject,
+ Vcb,
+ Fcb,
+ &Irp->Overlay.AllocationSize,
+ CreateDisposition );
+
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ FILE_NOTIFY_CHANGE_LAST_WRITE |
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_SIZE,
+ FILE_ACTION_MODIFIED );
+
+
+ if (CreateDisposition == FILE_SUPERSEDE) {
+ Irp->IoStatus.Information = FILE_SUPERSEDED;
+ } else {
+ Irp->IoStatus.Information = FILE_OVERWRITTEN;
+ }
+ }
+ }
+
+ } else {
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ } _SEH2_FINALLY {
+
+
+ if (ParentMcb) {
+ Ext2DerefMcb(ParentMcb);
+ }
+
+ /* cleanup Fcb and Ccb, Mcb if necessary */
+ if (!NT_SUCCESS(Status)) {
+
+ if (Ccb != NULL) {
+
+ DbgBreak();
+
+ ASSERT(Fcb != NULL);
+ ASSERT(Fcb->Mcb != NULL);
+
+ DEBUG(DL_ERR, ("Ext2CreateFile: failed to create %wZ status = %xh\n",
+ &Fcb->Mcb->FullName, Status));
+
+ Ext2DerefXcb(&Fcb->OpenHandleCount);
+ Ext2DerefXcb(&Fcb->ReferenceCount);
+
+ if (!IsDirectory(Fcb)) {
+ if (NoIntermediateBuffering) {
+ Fcb->NonCachedOpenCount--;
+ } else {
+ ClearFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
+ }
+ }
+
+ Ext2DerefXcb(&Vcb->OpenHandleCount);
+ Ext2DerefXcb(&Vcb->ReferenceCount);
+
+ IoRemoveShareAccess(IrpSp->FileObject, &Fcb->ShareAccess);
+
+ IrpSp->FileObject->FsContext = NULL;
+ IrpSp->FileObject->FsContext2 = NULL;
+ IrpSp->FileObject->PrivateCacheMap = NULL;
+ IrpSp->FileObject->SectionObjectPointer = NULL;
+
+ Ext2FreeCcb(Vcb, Ccb);
+ }
+ }
+
+ if (Fcb && Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
+
+ if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
+
+ LARGE_INTEGER Size;
+ ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
+ _SEH2_TRY {
+ Size.QuadPart = 0;
+ Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+ } _SEH2_FINALLY {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ } _SEH2_END;
+ }
+
+ if (bCreated) {
+ Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+ }
+
+ Ext2FreeFcb(Fcb);
+ Fcb = NULL;
+ bMainResourceAcquired = FALSE;
+ }
+
+ if (bMainResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ /* free file name buffer */
+ if (FileName.Buffer) {
+ DEC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
+ Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC);
+ }
+
+ /* dereference parent Fcb, free it if it goes to zero */
+ if (ParentFcb) {
+ ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+ if (bParentFcbCreated) {
+ if (Ext2DerefXcb(&ParentFcb->ReferenceCount) == 0) {
+ Ext2FreeFcb(ParentFcb);
+ }
+ }
+ }
+
+ /* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer
+ it already. It fails, we need release the refer to let it freed */
+ if (SymLink) {
+ Ext2DerefMcb(SymLink);
+ }
+ } _SEH2_END;
+
+ return Status;
}
-*/
-
-/*************************************************************************
-*
-* Function: Ext2OpenRootDirectory()
-*
-* Description:
-* Open the root directory for a volume
-*
-*
-* Expected Interrupt Level (for execution) :
-*
-* ???
-*
-* Return Value: None
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2OpenRootDirectory(
- PtrExt2VCB PtrVCB, // volume
- PtrExt2IrpContext PtrIrpContext, // IRP context
- PIRP PtrIrp, // original/user IRP
- unsigned short ShareAccess, // share access
- PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access)
- PFILE_OBJECT PtrNewFileObject // I/O Mgr. created file object
- )
+
+NTSTATUS
+Ext2CreateVolume(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
{
- // Declerations...
- PtrExt2CCB PtrCCB;
-
- ASSERT( PtrVCB );
- ASSERT( PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
- ASSERT( PtrVCB->PtrRootDirectoryFCB );
- AssertFCB( PtrVCB->PtrRootDirectoryFCB );
-
- PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO;
-
- // Create a new CCB...
- Ext2CreateNewCCB( &PtrCCB, PtrVCB->PtrRootDirectoryFCB, PtrNewFileObject);
- PtrNewFileObject->FsContext = (void *) &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader);
- PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY;
- PtrNewFileObject->FsContext2 = (void *) PtrCCB;
- PtrNewFileObject->SectionObjectPointer = &PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject;
- PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
-
- Ext2CopyUnicodeString( &(PtrCCB->AbsolutePathName), &PtrVCB->PtrRootDirectoryFCB->FCBName->ObjectName );
-
-
- return STATUS_SUCCESS;
-}
+ PIO_STACK_LOCATION IrpSp;
+ PIRP Irp;
+ PEXT2_CCB Ccb;
+ NTSTATUS Status;
+ ACCESS_MASK DesiredAccess;
+ ULONG ShareAccess;
-PtrExt2FCB NTAPI Ext2LocateChildFCBInCore(
- PtrExt2VCB PtrVCB,
- PUNICODE_STRING PtrName,
- ULONG ParentInodeNo )
-{
+ ULONG Options;
+ BOOLEAN DirectoryFile;
+ BOOLEAN OpenTargetDirectory;
- PtrExt2FCB PtrFCB = NULL;
- PLIST_ENTRY PtrEntry;
-
- if( IsListEmpty( &(PtrVCB->FCBListHead) ) )
- {
- return NULL; // Failure;
- }
-
- for( PtrEntry = PtrVCB->FCBListHead.Flink;
- PtrEntry != &PtrVCB->FCBListHead;
- PtrEntry = PtrEntry->Flink )
- {
- PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, NextFCB );
- ASSERT( PtrFCB );
- if( PtrFCB->ParentINodeNo == ParentInodeNo )
- {
- if( RtlCompareUnicodeString( &PtrFCB->FCBName->ObjectName, PtrName, TRUE ) == 0 )
- return PtrFCB;
- }
- }
-
- return NULL;
-}
+ ULONG CreateDisposition;
-PtrExt2FCB NTAPI Ext2LocateFCBInCore(
- PtrExt2VCB PtrVCB,
- ULONG InodeNo )
-{
- PtrExt2FCB PtrFCB = NULL;
- PLIST_ENTRY PtrEntry;
-
- if( IsListEmpty( &(PtrVCB->FCBListHead) ) )
- {
- return NULL; // Failure;
- }
-
- for( PtrEntry = PtrVCB->FCBListHead.Flink;
- PtrEntry != &PtrVCB->FCBListHead;
- PtrEntry = PtrEntry->Flink )
- {
- PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, NextFCB );
- ASSERT( PtrFCB );
- if( PtrFCB->INodeNo == InodeNo )
- {
- return PtrFCB;
- }
- }
-
- return NULL;
-}
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Options = IrpSp->Parameters.Create.Options;
-ULONG NTAPI Ext2LocateFileInDisk (
- PtrExt2VCB PtrVCB,
- PUNICODE_STRING PtrCurrentName,
- PtrExt2FCB PtrParentFCB,
- ULONG *Type )
-{
+ DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
+ OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
- PFILE_OBJECT PtrFileObject = NULL;
- ULONG InodeNo = 0;
-
- *Type = EXT2_FT_UNKNOWN;
-
- // 1.
- // Initialize the Blocks in the FCB...
- //
- Ext2InitializeFCBInodeInfo( PtrParentFCB );
-
-
- // 2.
- // Is there a file object I can use for caching??
- // If not create one...
- //
- if( !PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject )
- {
- //
- // No Directory File Object?
- // No problem, will create one...
- //
-
- // Acquire the MainResource first though...
-
- PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject = IoCreateStreamFileObject(NULL, PtrVCB->TargetDeviceObject );
- PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject;
-
- if( !PtrFileObject )
- {
- Ext2BreakPoint();
- return 0;
- }
- PtrFileObject->ReadAccess = TRUE;
- PtrFileObject->WriteAccess = TRUE;
-
- // Associate the file stream with the Volume parameter block...
- PtrFileObject->Vpb = PtrVCB->PtrVPB;
-
- // No caching as yet...
- PtrFileObject->PrivateCacheMap = NULL;
-
- // this establishes the FCB - File Object connection...
- PtrFileObject->FsContext = (void *)( & (PtrParentFCB->NTRequiredFCB.CommonFCBHeader) );
-
- // Initialize the section object pointer...
- PtrFileObject->SectionObjectPointer = &(PtrParentFCB->NTRequiredFCB.SectionObject);
- }
- else
- {
- //
- // I do have a file object...
- // I am using it now!
- //
- PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject;
- }
-
- // 3.
- // Got hold of a file object? Good ;)
- // Now initiating Caching, pinned access to be precise ...
- //
- if (PtrFileObject->PrivateCacheMap == NULL)
- {
- CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrParentFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)),
- TRUE, // We utilize pin access for directories
- &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
- PtrParentFCB ); // The context used in callbacks
- }
-
- // 4.
- // Getting down to the real business now... ;)
- // Read in the directory contents and do a search
- // a sequential search to be precise...
- // Wish Mm'm Renuga were reading this
- // Would feel proud... ;)
- //
- {
- LARGE_INTEGER StartBufferOffset;
- ULONG PinBufferLength;
- ULONG BufferIndex;
- PBCB PtrBCB = NULL;
- BYTE * PtrPinnedBlockBuffer = NULL;
- PEXT2_DIR_ENTRY PtrDirEntry = NULL;
- BOOLEAN Found;
- int i;
-
-
- StartBufferOffset.QuadPart = 0;
-
- //
- // Read in the whole damn directory
- // **Bad programming**
- // Will do for now.
- //
- PinBufferLength = PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.LowPart;
- if (!CcMapData( PtrFileObject,
- &StartBufferOffset,
- PinBufferLength,
- TRUE,
- &PtrBCB,
- (PVOID*)&PtrPinnedBlockBuffer ) )
- {
-
-
- }
- //
- // Walking through now...
- //
-
- for( BufferIndex = 0, Found = FALSE; !Found && BufferIndex < ( PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; BufferIndex += PtrDirEntry->rec_len )
- {
- PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ BufferIndex ];
- if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 || PtrDirEntry->inode == 0)
- {
- // Invalid entry...
- // Ignore...
- continue;
- }
- //
- // Comparing ( case sensitive )
- // Directory entry is not NULL terminated...
- // nor is the CurrentName...
- //
- if( PtrDirEntry->name_len != (PtrCurrentName->Length / 2) )
- continue;
-
- for( i = 0, Found = TRUE ; i < PtrDirEntry->name_len ; i++ )
- {
- if( PtrDirEntry->name[ i ] != PtrCurrentName->Buffer[ i ] )
- {
- Found = FALSE;
- break;
-
- }
- }
-
- }
- if( Found )
- {
- InodeNo = PtrDirEntry->inode;
-
- if( PtrDirEntry->file_type == EXT2_FT_UNKNOWN )
- {
-
- // Old Fashioned Directory entries...
- // Will have to read in the Inode to determine the File Type...
- EXT2_INODE Inode;
- // PtrInode = Ext2AllocatePool( NonPagedPool, sizeof( EXT2_INODE ) );
- Ext2ReadInode( PtrVCB, InodeNo, &Inode );
-
- if( Ext2IsModeRegularFile( Inode.i_mode ) )
- {
- *Type = EXT2_FT_REG_FILE;
- }
- else if ( Ext2IsModeDirectory( Inode.i_mode) )
- {
- // Directory...
- *Type = EXT2_FT_DIR;
- }
- else if( Ext2IsModeSymbolicLink(Inode.i_mode) )
- {
- *Type = EXT2_FT_SYMLINK;
- }
- else if( Ext2IsModePipe(Inode.i_mode) )
- {
- *Type = EXT2_FT_FIFO;
- }
- else if( Ext2IsModeCharacterDevice(Inode.i_mode) )
- {
- *Type = EXT2_FT_CHRDEV;
- }
- else if( Ext2IsModeBlockDevice(Inode.i_mode) )
- {
- *Type = EXT2_FT_BLKDEV;
- }
- else if( Ext2IsModeSocket(Inode.i_mode) )
- {
- *Type = EXT2_FT_SOCK;
- }
- else
- {
- *Type = EXT2_FT_UNKNOWN;
- }
-
- //DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Create]", PtrInode );
- //ExFreePool( PtrInode );
- }
- else
- {
- *Type = PtrDirEntry->file_type;
- }
- }
-
- CcUnpinData( PtrBCB );
- PtrBCB = NULL;
-
- return InodeNo;
- }
+ CreateDisposition = (Options >> 24) & 0x000000ff;
+
+ DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+ ShareAccess = IrpSp->Parameters.Create.ShareAccess;
+
+ if (DirectoryFile) {
+ return STATUS_NOT_A_DIRECTORY;
+ }
+
+ if (OpenTargetDirectory) {
+ DbgBreak();
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ( (CreateDisposition != FILE_OPEN) &&
+ (CreateDisposition != FILE_OPEN_IF) ) {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ if ( !FlagOn(ShareAccess, FILE_SHARE_READ) &&
+ Vcb->OpenVolumeCount != 0 ) {
+ return STATUS_SHARING_VIOLATION;
+ }
+
+ Ccb = Ext2AllocateCcb(NULL);
+ if (Ccb == NULL) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto errorout;
+ }
+
+ Status = STATUS_SUCCESS;
+
+ if (Vcb->OpenVolumeCount > 0) {
+ Status = IoCheckShareAccess( DesiredAccess, ShareAccess,
+ IrpSp->FileObject,
+ &(Vcb->ShareAccess), TRUE);
+
+ if (!NT_SUCCESS(Status)) {
+ goto errorout;
+ }
+ } else {
+ IoSetShareAccess( DesiredAccess, ShareAccess,
+ IrpSp->FileObject,
+ &(Vcb->ShareAccess) );
+ }
+
+
+ if (Vcb->OpenVolumeCount == 0 &&
+ !IsFlagOn(ShareAccess, FILE_SHARE_READ) &&
+ !IsFlagOn(ShareAccess, FILE_SHARE_WRITE) ){
+
+ if (!IsVcbReadOnly(Vcb)) {
+ Ext2FlushFiles(IrpContext, Vcb, FALSE);
+ Ext2FlushVolume(IrpContext, Vcb, FALSE);
+ }
+
+ SetLongFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
+ Vcb->LockFile = IrpSp->FileObject;
+ } else {
+ if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA) ) {
+ if (!IsVcbReadOnly(Vcb)) {
+ Ext2FlushFiles(IrpContext, Vcb, FALSE);
+ Ext2FlushVolume(IrpContext, Vcb, FALSE);
+ }
+ }
+ }
+
+ IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+ IrpSp->FileObject->FsContext = Vcb;
+ IrpSp->FileObject->FsContext2 = Ccb;
+ IrpSp->FileObject->Vpb = Vcb->Vpb;
+
+ Ext2ReferXcb(&Vcb->ReferenceCount);
+ Ext2ReferXcb(&Vcb->OpenHandleCount);
+ Ext2ReferXcb(&Vcb->OpenVolumeCount);
+
+ Irp->IoStatus.Information = FILE_OPENED;
+
+errorout:
+
+ return Status;
}
-/*************************************************************************
-*
-* Function: Ext2CreateFile()
-*
-* Description:
-* Creates a new file on the disk
-*
-* Expected Interrupt Level (for execution) :
-* IRQL_PASSIVE_LEVEL
-*
-* Restrictions:
-* Expects the VCB to be acquired Exclusively before being invoked
-*
-* Return Value: None
-*
-*************************************************************************/
-ULONG NTAPI Ext2CreateFile(
- PtrExt2IrpContext PtrIrpContext,
- PtrExt2VCB PtrVCB,
- PUNICODE_STRING PtrName,
- PtrExt2FCB PtrParentFCB,
- ULONG Type)
+NTSTATUS
+Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext)
{
- EXT2_INODE Inode, ParentInode;
-
- ULONG NewInodeNo = 0;
- BOOLEAN FCBAcquired = FALSE;
-
- ULONG LogicalBlockSize = 0;
-
- try
- {
-
-
- // 0. Verify if the creation is possible,,,
- if( Type != EXT2_FT_DIR && Type != EXT2_FT_REG_FILE )
- {
- //
- // Can create only a directory or a regular file...
- //
- return 0;
- }
-
- // 1. Allocate an i-node...
-
- NewInodeNo = Ext2AllocInode( PtrIrpContext, PtrVCB, PtrParentFCB->INodeNo );
-
- // NewInodeNo = 12;
-
- if( !NewInodeNo )
- {
- return 0;
- }
-
- // 2. Acquire the Parent FCB Exclusively...
- if( !ExAcquireResourceExclusiveLite(&( PtrParentFCB->NTRequiredFCB.MainResource ), TRUE) )
- {
- Ext2DeallocInode( PtrIrpContext, PtrVCB, NewInodeNo );
- try_return( NewInodeNo = 0);
- }
- FCBAcquired = TRUE;
-
- // 3. Make an entry in the parent Directory...
- ASSERT( PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject );
-
- Ext2MakeNewDirectoryEntry(
- PtrIrpContext,
- PtrParentFCB,
- PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject,
- PtrName, Type, NewInodeNo );
-
-
- // 4. Initialize an inode entry and write it to disk...
- LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-
- {
- // To be deleted
- Ext2ReadInode( PtrVCB, NewInodeNo, &Inode );
- }
-
- RtlZeroMemory( &Inode, sizeof( EXT2_INODE ) );
- if( Type == EXT2_FT_DIR )
- {
- Inode.i_mode = 0x41ff;
-
- // In addition to the usual link,
- // there will be an additional link in the directory itself - the '.' entry
- Inode.i_links_count = 2;
-
- // Incrementing the link count for the parent as well...
- Ext2ReadInode( PtrVCB, PtrParentFCB->INodeNo, &ParentInode );
- ParentInode.i_links_count++;
- Ext2WriteInode( PtrIrpContext, PtrVCB, PtrParentFCB->INodeNo, &ParentInode );
-
- }
- else
- {
- Inode.i_mode = 0x81ff;
- Inode.i_links_count = 1;
- }
-
-
- {
- //
- // Setting the time fields in the inode...
- //
- ULONG Time;
- Time = Ext2GetCurrentTime();
- Inode.i_ctime = Time;
- Inode.i_atime = Time;
- Inode.i_mtime = Time;
- Inode.i_dtime = 0; // Deleted time;
- }
-
- Ext2WriteInode( PtrIrpContext, PtrVCB, NewInodeNo, &Inode );
-
- try_exit: NOTHING;
- }
- finally
- {
- if( FCBAcquired )
- {
- Ext2ReleaseResource( &(PtrParentFCB->NTRequiredFCB.MainResource) );
- }
- }
-
- return NewInodeNo ;
+ PDEVICE_OBJECT DeviceObject;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
+ PEXT2_VCB Vcb = 0;
+ NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ PEXT2_FCBVCB Xcb = NULL;
+ BOOLEAN PostIrp = FALSE;
+ BOOLEAN VcbResourceAcquired = FALSE;
+
+ DeviceObject = IrpContext->DeviceObject;
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Xcb = (PEXT2_FCBVCB) (IrpSp->FileObject->FsContext);
+
+ if (IsExt2FsDevice(DeviceObject)) {
+
+ DEBUG(DL_INF, ( "Ext2Create: Create on main device object.\n"));
+
+ Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+
+ Ext2CompleteIrpContext(IrpContext, Status);
+
+ return Status;
+ }
+
+ _SEH2_TRY {
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb->Identifier.Type == EXT2VCB);
+ IrpSp->FileObject->Vpb = Vcb->Vpb;
+
+ if (!IsMounted(Vcb)) {
+ DbgBreak();
+ if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
+ Status = STATUS_NO_SUCH_DEVICE;
+ } else {
+ Status = STATUS_VOLUME_DISMOUNTED;
+ }
+ _SEH2_LEAVE;
+ }
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource, TRUE)) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ VcbResourceAcquired = TRUE;
+
+ Ext2VerifyVcb(IrpContext, Vcb);
+
+ if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
+ Status = STATUS_ACCESS_DENIED;
+ if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
+ Status = STATUS_VOLUME_DISMOUNTED;
+ }
+ _SEH2_LEAVE;
+ }
+
+ if ( ((IrpSp->FileObject->FileName.Length == 0) &&
+ (IrpSp->FileObject->RelatedFileObject == NULL)) ||
+ (Xcb && Xcb->Identifier.Type == EXT2VCB) ) {
+ Status = Ext2CreateVolume(IrpContext, Vcb);
+ } else {
+
+ Status = Ext2CreateFile(IrpContext, Vcb, &PostIrp);
+ }
+
+ } _SEH2_FINALLY {
+
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress && !PostIrp) {
+ if ( Status == STATUS_PENDING ||
+ Status == STATUS_CANT_WAIT) {
+ Status = Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
}
-/*************************************************************************
-*
-* Function: Ext2CreateFile()
-*
-* Description:
-* Overwrites an existing file on the disk
-*
-* Expected Interrupt Level (for execution) :
-* IRQL_PASSIVE_LEVEL
-*
-* Restrictions:
-* Expects the VCB to be acquired Exclusively before being invoked
-*
-* Return Value: None
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2OverwriteFile(
- PtrExt2FCB PtrFCB,
- PtrExt2IrpContext PtrIrpContext)
+NTSTATUS
+Ext2CreateInode(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_FCB Parent,
+ ULONG Type,
+ ULONG FileAttr,
+ PUNICODE_STRING FileName)
{
- EXT2_INODE Inode;
- PtrExt2VCB PtrVCB = PtrFCB->PtrVCB;
- ULONG i;
- ULONG Time;
- Time = Ext2GetCurrentTime();
-
- Ext2InitializeFCBInodeInfo( PtrFCB );
- // 1.
- // Update the inode...
- if( !NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
- {
- return FALSE;
- }
-
- Inode.i_size = 0;
- Inode.i_blocks = 0;
- Inode.i_atime = Time;
- Inode.i_mtime = Time;
- Inode.i_dtime = 0;
-
- for( i = 0; i < EXT2_N_BLOCKS; i++ )
- {
- Inode.i_block[ i ] = 0;
- }
-
- if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
- {
- return FALSE;
- }
-
- // 2.
- // Release all the data blocks...
- if( !Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext) )
- {
- return FALSE;
- }
-
- Ext2ClearFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED );
- Ext2InitializeFCBInodeInfo( PtrFCB );
-
- return TRUE;
+ NTSTATUS Status;
+ ULONG iGrp;
+ ULONG iNo;
+ struct inode Inode = { 0 };
+ struct dentry *Dentry = NULL;
+
+ LARGE_INTEGER SysTime;
+
+ iGrp = (Parent->Inode->i_ino - 1) / BLOCKS_PER_GROUP;
+
+ DEBUG(DL_INF, ("Ext2CreateInode: %S in %S(Inode=%xh)\n",
+ FileName->Buffer,
+ Parent->Mcb->ShortName.Buffer,
+ Parent->Inode->i_ino));
+
+ Status = Ext2NewInode(IrpContext, Vcb, iGrp, Type, &iNo);
+ if (!NT_SUCCESS(Status)) {
+ goto errorout;
+ }
+
+ KeQuerySystemTime(&SysTime);
+ Ext2ClearInode(IrpContext, Vcb, iNo);
+ Inode.i_sb = &Vcb->sb;
+ Inode.i_ino = iNo;
+ Inode.i_ctime = Inode.i_mtime =
+ Inode.i_atime = Ext2LinuxTime(SysTime);
+ Inode.i_uid = Parent->Inode->i_uid;
+ Inode.i_gid = Parent->Inode->i_gid;
+ Inode.i_generation = Parent->Inode->i_generation;
+ Inode.i_mode = S_IPERMISSION_MASK &
+ Parent->Inode->i_mode;
+ if (Type == EXT2_FT_DIR) {
+ Inode.i_mode |= S_IFDIR;
+ } else if (Type == EXT2_FT_REG_FILE) {
+ Inode.i_mode &= S_IFATTR;
+ Inode.i_mode |= S_IFREG;
+ } else {
+ DbgBreak();
+ }
+
+ /* Force using extent */
+ if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ Inode.i_flags |= EXT2_EXTENTS_FL;
+ }
+
+ /* add new entry to its parent */
+ Status = Ext2AddEntry(
+ IrpContext,
+ Vcb,
+ Parent,
+ &Inode,
+ FileName,
+ &Dentry
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ Ext2FreeInode(IrpContext, Vcb, iNo, Type);
+ goto errorout;
+ }
+
+ DEBUG(DL_INF, ("Ext2CreateInode: New Inode = %xh (Type=%xh)\n",
+ Inode.i_ino, Type));
+
+errorout:
+
+ if (Dentry)
+ Ext2FreeEntry(Dentry);
+
+ return Status;
}
-/*************************************************************************
-*
-* Function: Ext2SupersedeFile()
-*
-* Description:
-* Supersedes an existing file on the disk
-*
-* Expected Interrupt Level (for execution) :
-* IRQL_PASSIVE_LEVEL
-*
-* Restrictions:
-* Expects the VCB to be acquired Exclusively before being invoked
-*
-* Return Value: None
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2SupersedeFile(
- PtrExt2FCB PtrFCB,
- PtrExt2IrpContext PtrIrpContext)
+
+NTSTATUS
+Ext2SupersedeOrOverWriteFile(
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_FCB Fcb,
+ IN PLARGE_INTEGER AllocationSize,
+ IN ULONG Disposition
+)
{
- EXT2_INODE Inode;
- PtrExt2VCB PtrVCB = PtrFCB->PtrVCB;
-
- Ext2InitializeFCBInodeInfo( PtrFCB );
-
- // 1.
- // Initialize the inode...
- RtlZeroMemory( &Inode, sizeof( EXT2_INODE ) );
-
- // Setting the file mode...
- // This operation is allowed only for a regular file...
- Inode.i_mode = 0x81ff;
-
- // Maintaining the old link count...
- Inode.i_links_count = PtrFCB->LinkCount;
-
- // Setting the time fields in the inode...
- {
- ULONG Time;
- Time = Ext2GetCurrentTime();
- Inode.i_ctime = Time;
- Inode.i_atime = Time;
- Inode.i_mtime = Time;
- Inode.i_dtime = 0; // Deleted time;
- }
-
- if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
- {
- return FALSE;
- }
-
- // 2.
- // Release all the data blocks...
- if( !Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext) )
- {
- return FALSE;
- }
-
- Ext2ClearFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED );
- Ext2InitializeFCBInodeInfo( PtrFCB );
-
- return TRUE;
+ LARGE_INTEGER CurrentTime;
+ LARGE_INTEGER Size;
+
+ KeQuerySystemTime(&CurrentTime);
+
+ Size.QuadPart = 0;
+ if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(Size))) {
+ return STATUS_USER_MAPPED_FILE;
+ }
+
+ /* purge all file cache and shrink cache windows size */
+ CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
+ Fcb->Header.AllocationSize.QuadPart =
+ Fcb->Header.FileSize.QuadPart =
+ Fcb->Header.ValidDataLength.QuadPart = 0;
+ CcSetFileSizes(FileObject,
+ (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
+
+ Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
+ (ULONGLONG)AllocationSize->QuadPart,
+ (ULONGLONG)BLOCK_SIZE);
+
+ if ((loff_t)Size.QuadPart > Fcb->Inode->i_size) {
+ Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+ } else {
+ Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+ }
+
+ Fcb->Header.AllocationSize = Size;
+ if (Fcb->Header.AllocationSize.QuadPart > 0) {
+ SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
+ CcSetFileSizes(FileObject,
+ (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
+ }
+
+ /* remove all extent mappings */
+ DEBUG(DL_EXT, ("Ext2SuperSede ...: %wZ\n", &Fcb->Mcb->FullName));
+ Fcb->Inode->i_size = 0;
+
+ if (Disposition == FILE_SUPERSEDE) {
+ Fcb->Inode->i_ctime = Ext2LinuxTime(CurrentTime);
+ }
+ Fcb->Inode->i_atime =
+ Fcb->Inode->i_mtime = Ext2LinuxTime(CurrentTime);
+ Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
+
+ return STATUS_SUCCESS;
}
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,0,0,3
- PRODUCTVERSION 0,0,0,3
+ FILEVERSION 0,6,2,0
+ PRODUCTVERSION 0,6,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x29L
VALUE "Comments", "Ext2 File System Driver\0"
VALUE "CompanyName", "Purayidathil\0"
VALUE "FileDescription", "Ext2 File System Driver\0"
- VALUE "FileVersion", "0, 0, 0, 3\0"
- VALUE "InternalName", "ext2.sys\0"
- VALUE "LegalCopyright", "Copyright © 2002 Manoj Paul Joseph\0"
+ VALUE "FileVersion", "0, 6, 2, 0\0"
+ VALUE "InternalName", "ext2fs.sys\0"
+ VALUE "LegalCopyright", "Copyright © 2015 Matt Wu\0"
VALUE "LegalTrademarks", " - \0"
- VALUE "OriginalFilename", "ext2.sys\0"
+ VALUE "OriginalFilename", "ext2fs.sys\0"
VALUE "PrivateBuild", " - \0"
- VALUE "ProductName", "Ext2 File System Driver for Windows NT\0"
- VALUE "ProductVersion", "0, 0, 0, 3\0"
+ VALUE "ProductName", "Ext2 File System Driver for Windows\0"
+ VALUE "ProductVersion", "0, 6, 2, 0\0"
VALUE "SpecialBuild", " - \0"
END
END
-/*************************************************************************
-*
-* File: fastio.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the various "fast-io" calls.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_FAST_IO
-
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoCheckIfPossible()
-*
-* Description:
-* To fast-io or not to fast-io, that is the question ...
-* This routine helps the I/O Manager determine whether the FSD wishes
-* to permit fast-io on a specific file stream.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoCheckIfPossible(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN ULONG Length,
-IN BOOLEAN Wait,
-IN ULONG LockKey,
-IN BOOLEAN CheckForReadOperation,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- LARGE_INTEGER IoLength;
-
- // Obtain a pointer to the FCB and CCB for the file stream.
- PtrCCB = (PtrExt2CCB)(FileObject->FsContext2);
- ASSERT(PtrCCB);
- PtrFCB = PtrCCB->PtrFCB;
- ASSERT(PtrFCB);
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoCheckIfPossible - Denying", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- AssertFCBorVCB( PtrFCB );
-
-/* if( !( PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB
- || PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB ) )
- {
- // Ext2BreakPoint();
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Invalid FCB...", 0);
-
- return FALSE;
- }
-*/
-
- return FALSE;
-
- // Validate that this is a fast-IO request to a regular file.
- // The sample FSD for example, will not allow fast-IO requests
- // to volume objects, or to directories.
- if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) ||
- (PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
- {
- // This is not allowed.
- return(ReturnedStatus);
- }
-
- IoLength = RtlConvertUlongToLargeInteger(Length);
-
- // Your FSD can determine the checks that it needs to perform.
- // Typically, a FSD will check whether there exist any byte-range
- // locks that would prevent a fast-IO operation from proceeding.
-
- // ... (FSD specific checks go here).
-
- if (CheckForReadOperation)
- {
- // Chapter 11 describes how to use the FSRTL package for byte-range
- // lock requests. The following routine is exported by the FSRTL
- // package and it returns TRUE if the read operation should be
- // allowed to proceed based on the status of the current byte-range
- // locks on the file stream. If you do not use the FSRTL package
- // for byte-range locking support, then you must substitute your
- // own checks over here.
- // ReturnedStatus = FsRtlFastCheckLockForRead(&(PtrFCB->FCBByteRangeLock),
- // FileOffset, &IoLength, LockKey, FileObject,
- // PsGetCurrentProcess());
- }
- else
- {
- // This is a write request. Invoke the FSRTL byte-range lock package
- // to see whether the write should be allowed to proceed.
- // ReturnedStatus = FsRtlFastCheckLockForWrite(&(PtrFCB->FCBByteRangeLock),
- // FileOffset, &IoLength, LockKey, FileObject,
- // PsGetCurrentProcess());
- }
-
- return(ReturnedStatus);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoRead()
-*
-* Description:
-* Bypass the traditional IRP method to perform a read operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoRead(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN ULONG Length,
-IN BOOLEAN Wait,
-IN ULONG LockKey,
-OUT PVOID Buffer,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
-
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoRead", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
-
- try
- {
-
- try
- {
-
- // Chapter 11 describes how to roll your own fast-IO entry points.
- // Typically, you will acquire appropriate resources here and
- // then (maybe) forward the request to FsRtlCopyRead().
- // If you are a suitably complex file system, you may even choose
- // to do some pre-processing (e.g. prefetching data from someplace)
- // before passing on the request to the FSRTL package.
-
- // Of course, you also have the option of bypassing the FSRTL
- // package completely and simply forwarding the request directly
- // to the NT Cache Manager.
-
- // Bottom line is that you have complete flexibility on determining
- // what you decide to do here. Read Chapter 11 well (and obviously
- // other related issues) before filling in this and other fast-IO
- // dispatch entry points.
-
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
-
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
-
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
-
- }
- } finally {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoWrite()
-*
-* Description:
-* Bypass the traditional IRP method to perform a write operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoWrite(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN ULONG Length,
-IN BOOLEAN Wait,
-IN ULONG LockKey,
-OUT PVOID Buffer,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoWrite", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
- try
- {
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
-
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
-
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
-
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoQueryBasicInfo()
-*
-* Description:
-* Bypass the traditional IRP method to perform a query basic
-* information operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoQueryBasicInfo(
-IN PFILE_OBJECT FileObject,
-IN BOOLEAN Wait,
-OUT PFILE_BASIC_INFORMATION Buffer,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoQueryBasicInfo", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoQueryStdInfo()
-*
-* Description:
-* Bypass the traditional IRP method to perform a query standard
-* information operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoQueryStdInfo(
-IN PFILE_OBJECT FileObject,
-IN BOOLEAN Wait,
-OUT PFILE_STANDARD_INFORMATION Buffer,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoQueryStdInfo", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoLock()
-*
-* Description:
-* Bypass the traditional IRP method to perform a byte range lock
-* operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoLock(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN PLARGE_INTEGER Length,
-PEPROCESS ProcessId,
-ULONG Key,
-BOOLEAN FailImmediately,
-BOOLEAN ExclusiveLock,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoLock", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoUnlockSingle()
-*
-* Description:
-* Bypass the traditional IRP method to perform a byte range unlock
-* operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoUnlockSingle(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN PLARGE_INTEGER Length,
-PEPROCESS ProcessId,
-ULONG Key,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoUnlockSingle", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoUnlockAll()
-*
-* Description:
-* Bypass the traditional IRP method to perform multiple byte range unlock
-* operations.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoUnlockAll(
-IN PFILE_OBJECT FileObject,
-PEPROCESS ProcessId,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoUnlockAll", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoUnlockAllByKey()
-*
-* Description:
-* Bypass the traditional IRP method to perform multiple byte range unlock
-* operations.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoUnlockAllByKey(
-IN PFILE_OBJECT FileObject,
-PVOID ProcessId,
-ULONG Key,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: fastio.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+/* DEFINITIONS *************************************************************/
+
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(PAGE, Ext2FastIoRead)
+#pragma alloc_text(PAGE, Ext2FastIoWrite)
+#pragma alloc_text(PAGE, Ext2FastIoCheckIfPossible)
+#pragma alloc_text(PAGE, Ext2FastIoQueryBasicInfo)
+#pragma alloc_text(PAGE, Ext2FastIoQueryStandardInfo)
+#pragma alloc_text(PAGE, Ext2FastIoQueryNetworkOpenInfo)
+#pragma alloc_text(PAGE, Ext2FastIoLock)
+#pragma alloc_text(PAGE, Ext2FastIoUnlockSingle)
+#pragma alloc_text(PAGE, Ext2FastIoUnlockAll)
+#pragma alloc_text(PAGE, Ext2FastIoUnlockAll)
+#endif
+
+FAST_IO_POSSIBLE
+Ext2IsFastIoPossible(
+ IN PEXT2_FCB Fcb
+)
{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoUnlockAllByKey", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
+ FAST_IO_POSSIBLE IsPossible = FastIoIsNotPossible;
-/*************************************************************************
-*
-* Function: Ext2FastIoAcqCreateSec()
-*
-* Description:
-* Not really a fast-io operation. Used by the VMM to acquire FSD resources
-* before processing a file map (create section object) request.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None (we must be prepared to handle VMM initiated calls)
-*
-*************************************************************************/
-void NTAPI Ext2FastIoAcqCreateSec(
-IN PFILE_OBJECT FileObject)
-{
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
-
- // Obtain a pointer to the FCB and CCB for the file stream.
- PtrCCB = (PtrExt2CCB)(FileObject->FsContext2);
- ASSERT(PtrCCB);
- PtrFCB = PtrCCB->PtrFCB;
- ASSERT(PtrFCB);
-
- AssertFCB( PtrFCB );
-
-/* if( PtrFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB )
- {
- // Ext2BreakPoint();
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Invalid FCB...", 0);
- return;
- } */
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoAcqCreateSec", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- // Acquire the MainResource exclusively for the file stream
-
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Exclusively [FastIo]", 0);
-
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
-
- DebugTrace(DEBUG_TRACE_MISC,"*** FCB acquired [FastIo]", 0);
-
- // Although this is typically not required, the sample FSD will
- // also acquire the PagingIoResource exclusively at this time
- // to conform with the resource acquisition described in the set
- // file information routine. Once again though, you will probably
- // not need to do this.
- DebugTrace(DEBUG_TRACE_MISC,"*** Attempting to acquire FCBPaging Exclusively [FastIo]", 0);
- DebugTraceState( "FCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
- ExAcquireResourceExclusiveLite(&(PtrReqdFCB->PagingIoResource), TRUE);
-
- DebugTrace(DEBUG_TRACE_MISC,"*** FCBPaging acquired [FastIo]", 0);
-
- return;
-}
+ if (!Fcb || !FsRtlOplockIsFastIoPossible(&Fcb->Oplock))
+ return IsPossible;
+ IsPossible = FastIoIsQuestionable;
-/*************************************************************************
-*
-* Function: Ext2FastIoRelCreateSec()
-*
-* Description:
-* Not really a fast-io operation. Used by the VMM to release FSD resources
-* after processing a file map (create section object) request.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2FastIoRelCreateSec(
-IN PFILE_OBJECT FileObject)
-{
+ if (!FsRtlAreThereCurrentFileLocks(&Fcb->FileLockAnchor)) {
+ if (!IsVcbReadOnly(Fcb->Vcb) && !FlagOn(Fcb->Vcb->Flags, VCB_VOLUME_LOCKED)) {
+ IsPossible = FastIoIsPossible;
+ }
+ }
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
-
- // Obtain a pointer to the FCB and CCB for the file stream.
- PtrCCB = (PtrExt2CCB)(FileObject->FsContext2);
- ASSERT(PtrCCB);
- PtrFCB = PtrCCB->PtrFCB;
- ASSERT(PtrFCB);
- AssertFCB( PtrFCB );
-
-/* if( PtrFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB )
- {
- // Ext2BreakPoint();
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Invalid FCB...", 0);
- return;
- }*/
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoRelCreateSec", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- // Release the PagingIoResource for the file stream
- Ext2ReleaseResource(&(PtrReqdFCB->PagingIoResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCBPaging Released in [FastIo]", 0);
- DebugTraceState( "FCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]",
- PtrReqdFCB->PagingIoResource.ActiveCount,
- PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
-
- // Release the MainResource for the file stream
- Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [FastIo]", 0);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]",
- PtrReqdFCB->MainResource.ActiveCount,
- PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->MainResource.NumberOfSharedWaiters );
-
- return;
+ return IsPossible;
}
-/*************************************************************************
-*
-* Function: Ext2AcqLazyWrite()
-*
-* Description:
-* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
-* resources before performing a delayed write (write behind/lazy write)
-* operation.
-* NOTE: this function really must succeed since the Cache Manager will
-* typically ignore failure and continue on ...
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2AcqLazyWrite(
-IN PVOID Context,
-IN BOOLEAN Wait)
+BOOLEAN NTAPI
+Ext2FastIoCheckIfPossible (
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN BOOLEAN Wait,
+ IN ULONG LockKey,
+ IN BOOLEAN CheckForReadOperation,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+)
{
- BOOLEAN ReturnedStatus = TRUE;
-
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
-
- // The context is whatever we passed to the Cache Manager when invoking
- // the CcInitializeCacheMaps() function. In the case of the sample FSD
- // implementation, this context is a pointer to the CCB structure.
-
- ASSERT(Context);
- PtrCCB = (PtrExt2CCB)(Context);
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2AcqLazyWrite", 0);
-
- if(PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB)
- {
- //
- // Acquiring Resource for a file write...
- //
- PtrFCB = PtrCCB->PtrFCB;
- AssertFCB( PtrFCB );
- }
- else if( PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB )
- {
- //
- // Acquiring Resource for a volume write...
- //
- PtrVCB = ( PtrExt2VCB )PtrCCB;
- PtrCCB = NULL;
- DebugTrace(DEBUG_TRACE_MISC,"~~~[FastIO call]~~~ Ext2AcqLazyWrite - for Volume", 0);
-
- // Acquire nothing...
- // Just proceed...
- return TRUE;
-
- }
- else if( PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
- {
- //
- // This must have been a FCB created / maintained on the FSD's initiative...
- // This would have been done to cache access to a directory...
- //
- PtrFCB = ( PtrExt2FCB )PtrCCB;
- PtrCCB = NULL;
- }
- else
- {
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Ext2AcqLazyWrite - Invalid context", 0);
- Ext2BreakPoint();
- return FALSE;
- }
-
- if( PtrCCB && PtrCCB->PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", PtrCCB->PtrFileObject );
- }
-
- AssertFCB( PtrFCB );
-
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
-
- // Acquire the MainResource in the FCB exclusively. Then, set the
- // lazy-writer thread id in the FCB structure for identification when
- // an actual write request is received by the FSD.
- // Note: The lazy-writer typically always supplies WAIT set to TRUE.
-
- DebugTrace(DEBUG_TRACE_MISC,"*** Attempting to acquire FCB Exclusively [FastIo]", 0);
-
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource),
- Wait))
- {
- DebugTrace(DEBUG_TRACE_MISC,"*** Attempt to acquire FCB FAILED [FastIo]", 0);
- ReturnedStatus = FALSE;
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC,"*** FCB acquired [FastIo]", 0);
- // Now, set the lazy-writer thread id.
- ASSERT(!(PtrFCB->LazyWriterThreadID));
- PtrFCB->LazyWriterThreadID = (unsigned int)(PsGetCurrentThread());
- }
-
- // If your FSD needs to perform some special preparations in anticipation
- // of receving a lazy-writer request, do so now.
-
- return(ReturnedStatus);
+ BOOLEAN bPossible = FastIoIsNotPossible;
+ PEXT2_FCB Fcb;
+ PEXT2_CCB Ccb;
+ LARGE_INTEGER lLength;
+
+ lLength.QuadPart = Length;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsDirectory(Fcb)) {
+ _SEH2_LEAVE;
+ }
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ if (Ccb == NULL) {
+ _SEH2_LEAVE;
+ }
+
+ if (CheckForReadOperation) {
+
+ bPossible = FsRtlFastCheckLockForRead(
+ &Fcb->FileLockAnchor,
+ FileOffset,
+ &lLength,
+ LockKey,
+ FileObject,
+ PsGetCurrentProcess());
+
+ } else {
+
+ if (!IsVcbReadOnly(Fcb->Vcb)) {
+ bPossible = FsRtlFastCheckLockForWrite(
+ &Fcb->FileLockAnchor,
+ FileOffset,
+ &lLength,
+ LockKey,
+ FileObject,
+ PsGetCurrentProcess());
+ }
+ }
+
+#if EXT2_DEBUG
+ DEBUG(DL_INF, ("Ext2FastIIOCheckPossible: %s %s %wZ\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_CHECK_IF_POSSIBLE",
+ &Fcb->Mcb->FullName
+ ));
+
+ DEBUG(DL_INF, (
+ "Ext2FastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n",
+ FileOffset->QuadPart,
+ Length,
+ LockKey,
+ (CheckForReadOperation ? "CheckForReadOperation:" :
+ "CheckForWriteOperation:"),
+ (bPossible ? "Succeeded" : "Failed")));
+#endif
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ bPossible = FastIoIsNotPossible;
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+ return bPossible;
}
-/*************************************************************************
-*
-* Function: Ext2RelLazyWrite()
-*
-* Description:
-* Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
-* resources after performing a delayed write (write behind/lazy write)
-* operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2RelLazyWrite(
-IN PVOID Context)
+BOOLEAN NTAPI
+Ext2FastIoRead (IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN BOOLEAN Wait,
+ IN ULONG LockKey,
+ OUT PVOID Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
{
+ PEXT2_FCB Fcb;
+ BOOLEAN Status = FALSE;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
-
- // The context is whatever we passed to the Cache Manager when invoking
- // the CcInitializeCacheMaps() function. In the case of the sample FSD
- // implementation, this context is a pointer to the CCB structure.
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2RelLazyWrite", 0);
-
- ASSERT(Context);
- PtrCCB = (PtrExt2CCB)(Context);
-
- if(PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB)
- {
- PtrFCB = PtrCCB->PtrFCB;
- AssertFCB( PtrFCB );
- }
- else if( PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB )
- {
- PtrVCB = ( PtrExt2VCB )PtrCCB;
- PtrCCB = NULL;
- DebugTrace(DEBUG_TRACE_MISC,"~~~[FastIO call]~~~ Ext2RelLazyWrite - for Volume", 0);
-
- // Acquire was acquired nothing...
- // Just return...
- return;
-
- }
- else if( PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
- {
- //
- // This must have been a FCB created / maintained on the FSD's initiative...
- // This would have been done to cache access to a directory...
- //
- PtrFCB = ( PtrExt2FCB )PtrCCB;
- PtrCCB = NULL;
- }
- else
- {
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Ext2RelLazyWrite - Invalid context", 0);
- Ext2BreakPoint();
- return ;
- }
-
- if( PtrCCB && PtrCCB->PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", PtrCCB->PtrFileObject );
- }
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- // Remove the current thread-id from the FCB and release the MainResource.
- ASSERT( (PtrFCB->LazyWriterThreadID) == (unsigned int)PsGetCurrentThread() );
- PtrFCB->LazyWriterThreadID = 0;
-
-
- // Release the acquired resource.
- Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [FastIo]", 0);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]",
- PtrReqdFCB->MainResource.ActiveCount,
- PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->MainResource.NumberOfSharedWaiters );
-
- //
- // Undo whatever else seems appropriate at this time...
- //
-
- return;
-}
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL) {
+ return FALSE;
+ }
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-/*************************************************************************
-*
-* Function: Ext2AcqReadAhead()
-*
-* Description:
-* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
-* resources before performing a read-ahead operation.
-* NOTE: this function really must succeed since the Cache Manager will
-* typically ignore failure and continue on ...
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2AcqReadAhead(
-IN PVOID Context,
-IN BOOLEAN Wait)
-{
-
- BOOLEAN ReturnedStatus = TRUE;
-
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
-
- // The context is whatever we passed to the Cache Manager when invoking
- // the CcInitializeCacheMaps() function. In the case of the sample FSD
- // implementation, this context is a pointer to the CCB structure.
-
- ASSERT(Context);
- PtrCCB = (PtrExt2CCB)(Context);
- ASSERT(PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB);
+ Status = FsRtlCopyRead (
+ FileObject, FileOffset, Length, Wait,
+ LockKey, Buffer, IoStatus, DeviceObject);
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2AcqReadAhead", 0);
- if( PtrCCB && PtrCCB->PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", PtrCCB->PtrFileObject );
- }
+ DEBUG(DL_IO, ("Ext2FastIoRead: %wZ Offset: %I64xh Length: %xh Key: %u Status: %d\n",
+ &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status));
- PtrFCB = PtrCCB->PtrFCB;
- ASSERT(PtrFCB);
-
- AssertFCB( PtrFCB );
-/*
- if( PtrFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB )
- {
- // Ext2BreakPoint();
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Invalid FCB...", 0);
- return TRUE;
- } */
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- // Acquire the MainResource in the FCB shared.
- // Note: The read-ahead thread typically always supplies WAIT set to TRUE.
- DebugTrace(DEBUG_TRACE_MISC,"*** Attempting to acquire FCB Shared [FastIo]", 0);
-
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), Wait))
- {
- DebugTrace(DEBUG_TRACE_MISC,"*** Attempt to acquire FCB FAILED [FastIo]", 0);
- ReturnedStatus = FALSE;
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC,"*** FCB acquired [FastIo]", 0);
- }
-
- // If your FSD needs to perform some special preparations in anticipation
- // of receving a read-ahead request, do so now.
-
- return ReturnedStatus;
-
+ return Status;
}
-
-
-/*************************************************************************
-*
-* Function: Ext2RelReadAhead()
-*
-* Description:
-* Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
-* resources after performing a read-ahead operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2RelReadAhead(
-IN PVOID Context)
+BOOLEAN NTAPI
+Ext2FastIoWrite (
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN BOOLEAN Wait,
+ IN ULONG LockKey,
+ OUT PVOID Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
{
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
-
+ PEXT2_FCB Fcb = NULL;
+ BOOLEAN Status = FALSE;
+ BOOLEAN Locked = FALSE;
- // The context is whatever we passed to the Cache Manager when invoking
- // the CcInitializeCacheMaps() function. In the case of the sample FSD
- // implementation, this context is a pointer to the CCB structure.
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL)
+ return FALSE;
- ASSERT(Context);
- PtrCCB = (PtrExt2CCB)(Context);
- ASSERT(PtrCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB);
+ _SEH2_TRY {
- PtrFCB = PtrCCB->PtrFCB;
-
- AssertFCB( PtrFCB );
-
- // ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );
+ FsRtlEnterFileSystem();
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2RelReadAhead", 0);
- if( PtrCCB && PtrCCB->PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", PtrCCB->PtrFileObject );
- }
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-/* if( PtrFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB )
- {
- // Ext2BreakPoint();
- DebugTrace(DEBUG_TRACE_ERROR, "~~~[FastIO call]~~~ Invalid FCB...", 0);
- return;
- } */
+ if (IsVcbReadOnly(Fcb->Vcb)) {
+ _SEH2_LEAVE;
+ }
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
+ ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
+ Locked = TRUE;
+ if (IsWritingToEof(*FileOffset) ||
+ Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart ||
+ Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
+ Status = FALSE;
+ } else {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ Locked = FALSE;
+ Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
+ LockKey, Buffer, IoStatus, DeviceObject);
+ }
- // Release the acquired resource.
- Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [FastIo]", 0);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FastIo]",
- PtrReqdFCB->MainResource.ActiveCount,
- PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->MainResource.NumberOfSharedWaiters );
+ } _SEH2_FINALLY {
- // Of course, your FSD should undo whatever else seems appropriate at this
- // time.
+ if (Locked) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
- return;
-}
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+ DEBUG(DL_IO, ("Ext2FastIoWrite: %wZ Offset: %I64xh Length: %xh Key: %xh Status=%d\n",
+ &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status));
-/* the remaining are only valid under NT Version 4.0 and later */
-#if(_WIN32_WINNT >= 0x0400)
-
-
-/*************************************************************************
-*
-* Function: Ext2FastIoQueryNetInfo()
-*
-* Description:
-* Get information requested by a redirector across the network. This call
-* will originate from the LAN Manager server.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoQueryNetInfo(
-IN PFILE_OBJECT FileObject,
-IN BOOLEAN Wait,
-OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoQueryNetInfo", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
+ return Status;
}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoMdlRead()
-*
-* Description:
-* Bypass the traditional IRP method to perform a MDL read operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoMdlRead(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN ULONG Length,
-IN ULONG LockKey,
-OUT PMDL *MdlChain,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoQueryBasicInfo (
+ IN PFILE_OBJECT FileObject,
+ IN BOOLEAN Wait,
+ OUT PFILE_BASIC_INFORMATION Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoMdlRead", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
+ PEXT2_FCB Fcb = NULL;
+ BOOLEAN Status = FALSE;
+ BOOLEAN FcbMainResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "Ext2FastIoQueryBasicInfo: %s %s %wZ\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_QUERY_BASIC_INFO",
+ &Fcb->Mcb->FullName
+ ));
+#endif
+ if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
+ if (!ExAcquireResourceSharedLite(
+ &Fcb->MainResource,
+ Wait)) {
+ _SEH2_LEAVE;
+ }
+ FcbMainResourceAcquired = TRUE;
+ }
+
+ RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
+
+ /*
+ typedef struct _FILE_BASIC_INFORMATION {
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ ULONG FileAttributes;
+ } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
+ */
+
+ if (IsRoot(Fcb)) {
+ Buffer->CreationTime = Buffer->LastAccessTime =
+ Buffer->LastWriteTime = Buffer->ChangeTime = Ext2NtTime(0);
+ } else {
+ Buffer->CreationTime = Fcb->Mcb->CreationTime;
+ Buffer->LastAccessTime = Fcb->Mcb->LastAccessTime;
+ Buffer->LastWriteTime = Fcb->Mcb->LastWriteTime;
+ Buffer->ChangeTime = Fcb->Mcb->ChangeTime;
+ }
+
+ Buffer->FileAttributes = Fcb->Mcb->FileAttr;
+ if (Buffer->FileAttributes == 0) {
+ Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
+ IoStatus->Status = STATUS_SUCCESS;
+
+ Status = TRUE;
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ IoStatus->Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ if (FcbMainResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+#if EXT2_DEBUG
+
+ if (Status == FALSE) {
+
+ DEBUG(DL_ERR, ("Ext2FastIoQueryBasicInfo: %s %s Status: FALSE ***\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_QUERY_BASIC_INFO"));
+
+ } else if (IoStatus->Status != STATUS_SUCCESS) {
+
+ DEBUG(DL_ERR, (
+ "Ext2FastIoQueryBasicInfo: %s %s Status: %#x ***\n",
+ Ext2FastIoQueryBasicInfo,
+ "FASTIO_QUERY_BASIC_INFO",
+ IoStatus->Status
+ ));
+ }
+#endif
+
+ return Status;
}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoMdlReadComplete()
-*
-* Description:
-* Bypass the traditional IRP method to inform the NT Cache Manager and the
-* FSD that the caller no longer requires the data locked in the system cache
-* or the MDL to stay around anymore ..
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoMdlReadComplete(
-IN PFILE_OBJECT FileObject,
-OUT PMDL MdlChain,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoQueryStandardInfo (
+ IN PFILE_OBJECT FileObject,
+ IN BOOLEAN Wait,
+ OUT PFILE_STANDARD_INFORMATION Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+)
{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoMdlReadComplete", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
-
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
-
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
-
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
-}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoPrepareMdlWrite()
-*
-* Description:
-* Bypass the traditional IRP method to prepare for a MDL write operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoPrepareMdlWrite(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-IN ULONG Length,
-IN ULONG LockKey,
-OUT PMDL *MdlChain,
-OUT PIO_STATUS_BLOCK IoStatus,
-IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoPrepareMdlWrite", 0);
- if( FileObject )
- {
- DebugTrace( DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- } except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
-
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
-
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
-
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
+ BOOLEAN Status = FALSE;
+ PEXT2_VCB Vcb;
+ PEXT2_FCB Fcb;
+ BOOLEAN FcbMainResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "Ext2FastIoQueryStandardInfo: %s %s %wZ\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_QUERY_STANDARD_INFO",
+ &Fcb->Mcb->FullName ));
+#endif
+ Vcb = Fcb->Vcb;
+
+ if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
+ if (!ExAcquireResourceSharedLite(
+ &Fcb->MainResource,
+ Wait )) {
+ _SEH2_LEAVE;
+ }
+ FcbMainResourceAcquired = TRUE;
+ }
+
+ RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
+
+ /*
+ typedef struct _FILE_STANDARD_INFORMATION {
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG NumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+ } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
+ */
+
+ Buffer->NumberOfLinks = Fcb->Inode->i_nlink;
+ Buffer->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+
+ if (IsDirectory(Fcb)) {
+ Buffer->Directory = IsDirectory(Fcb);
+ Buffer->AllocationSize.QuadPart = 0;
+ Buffer->EndOfFile.QuadPart = 0;
+ } else {
+ Buffer->Directory = FALSE;
+ Buffer->AllocationSize = Fcb->Header.AllocationSize;
+ Buffer->EndOfFile = Fcb->Header.FileSize;
+ }
+
+ IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
+ IoStatus->Status = STATUS_SUCCESS;
+#if EXT2_DEBUG
+ DEBUG(DL_INF, ( "Ext2FastIoQueryStandInfo: AllocatieonSize = %I64xh FileSize = %I64xh\n",
+ Buffer->AllocationSize.QuadPart, Buffer->EndOfFile.QuadPart));
+#endif
+ Status = TRUE;
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ IoStatus->Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ if (FcbMainResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+#if EXT2_DEBUG
+ if (Status == FALSE) {
+ DEBUG(DL_INF, (
+ "Ext2FastIoQueryStandardInfo: %s %s Status: FALSE ***\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_QUERY_STANDARD_INFO" ));
+ } else if (IoStatus->Status != STATUS_SUCCESS) {
+ DEBUG(DL_INF, (
+ "Ext2FastIoQueryStandardInfo: %s %s Status: %#x ***\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_QUERY_STANDARD_INFO",
+ IoStatus->Status ));
+ }
+#endif
+
+ return Status;
}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoMdlWriteComplete()
-*
-* Description:
-* Bypass the traditional IRP method to inform the NT Cache Manager and the
-* FSD that the caller has updated the contents of the MDL. This data can
-* now be asynchronously written out to secondary storage by the Cache Mgr.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: TRUE/FALSE
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2FastIoMdlWriteComplete(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER FileOffset,
-OUT PMDL MdlChain,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoLock (
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN PLARGE_INTEGER Length,
+ IN PEPROCESS Process,
+ IN ULONG Key,
+ IN BOOLEAN FailImmediately,
+ IN BOOLEAN ExclusiveLock,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+)
{
- BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoMdlWriteComplete", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
-
- try
- {
-
- // See description in Ext2FastIoRead() before filling-in the
- // stub here.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(ReturnedStatus);
+ BOOLEAN Status = FALSE;
+ PEXT2_FCB Fcb;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsDirectory(Fcb)) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "Ext2FastIoLock: %s %s %wZ\n",
+ Ext2GetCurrentProcessName(),
+ "FASTIO_LOCK",
+ &Fcb->Mcb->FullName ));
+
+ DEBUG(DL_INF, (
+ "Ext2FastIoLock: Offset: %I64xh Length: %I64xh Key: %u %s%s\n",
+ FileOffset->QuadPart,
+ Length->QuadPart,
+ Key,
+ (FailImmediately ? "FailImmediately " : ""),
+ (ExclusiveLock ? "ExclusiveLock " : "") ));
+#endif
+
+ if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
+ _SEH2_LEAVE;
+ }
+
+ Status = FsRtlFastLock(
+ &Fcb->FileLockAnchor,
+ FileObject,
+ FileOffset,
+ Length,
+ Process,
+ Key,
+ FailImmediately,
+ ExclusiveLock,
+ IoStatus,
+ NULL,
+ FALSE);
+
+ if (Status) {
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+ }
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ IoStatus->Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+#if EXT2_DEBUG
+ if (Status == FALSE) {
+ DEBUG(DL_ERR, (
+ "Ext2FastIoLock: %s %s *** Status: FALSE ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_LOCK"
+ ));
+ } else if (IoStatus->Status != STATUS_SUCCESS) {
+ DEBUG(DL_ERR, (
+ "Ext2FastIoLock: %s %s *** Status: %s (%#x) ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_LOCK",
+ Ext2NtStatusToString(IoStatus->Status),
+ IoStatus->Status
+ ));
+ }
+#endif
+
+ return Status;
}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoAcqModWrite()
-*
-* Description:
-* Not really a fast-io operation. Used by the VMM to acquire FSD resources
-* before initiating a write operation via the Modified Page/Block Writer.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error (try not to return an error, will 'ya ? :-)
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2FastIoAcqModWrite(
-IN PFILE_OBJECT FileObject,
-IN PLARGE_INTEGER EndingOffset,
-OUT PERESOURCE *ResourceToRelease,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoUnlockSingle (
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN PLARGE_INTEGER Length,
+ IN PEPROCESS Process,
+ IN ULONG Key,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY,"~~~[FastIO call]~~~ Ext2FastIoAcqModWrite", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
- try
- {
-
- // You must determine which resource(s) you would like to
- // acquire at this time. You know that a write is imminent;
- // you will probably therefore acquire appropriate resources
- // exclusively.
-
- // You must first get the FCB and CCB pointers from the file object
- // that is passed in to this function (as an argument). Note that
- // the ending offset (when examined in conjunction with current valid data
- // length) may help you in determining the appropriate resource(s) to acquire.
-
- // For example, if the ending offset is beyond current valid data length,
- // you may decide to acquire *both* the MainResource and the PagingIoResource
- // exclusively; otherwise, you may decide simply to acquire the PagingIoResource.
-
- // Consult the text for more information on synchronization in FSDs.
-
- // One final note; the VMM expects that you will return a pointer to
- // the resource that you acquired (single return value). This pointer
- // will be returned back to you in the release call (below).
-
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
+ BOOLEAN Status = FALSE;
+ PEXT2_FCB Fcb;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsDirectory(Fcb)) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "Ext2FastIoUnlockSingle: %s %s %wZ\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_SINGLE",
+ &Fcb->Mcb->FullName ));
+
+ DEBUG(DL_INF, (
+ "Ext2FastIoUnlockSingle: Offset: %I64xh Length: %I64xh Key: %u\n",
+ FileOffset->QuadPart,
+ Length->QuadPart,
+ Key ));
+#endif
+
+ if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
+ _SEH2_LEAVE;
+ }
+
+ IoStatus->Status = FsRtlFastUnlockSingle(
+ &Fcb->FileLockAnchor,
+ FileObject,
+ FileOffset,
+ Length,
+ Process,
+ Key,
+ NULL,
+ FALSE);
+
+ IoStatus->Information = 0;
+ Status = TRUE;
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ IoStatus->Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+#if EXT2_DEBUG
+ if (Status == FALSE) {
+
+ DEBUG(DL_ERR, (
+ "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_SINGLE" ));
+ } else if (IoStatus->Status != STATUS_SUCCESS) {
+ DEBUG(DL_ERR, (
+ "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_SINGLE",
+ Ext2NtStatusToString(IoStatus->Status),
+ IoStatus->Status ));
+ }
+#endif
+
+ return Status;
}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoRelModWrite()
-*
-* Description:
-* Not really a fast-io operation. Used by the VMM to release FSD resources
-* after processing a modified page/block write operation.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!)
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2FastIoRelModWrite(
-IN PFILE_OBJECT FileObject,
-IN PERESOURCE ResourceToRelease,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoUnlockAll (
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace( DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoRelModWrite", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
- try
- {
-
- // The MPW has complete the write for modified pages and therefore
- // wants you to release pre-acquired resource(s).
-
- // You must undo here whatever it is that you did in the
- // Ext2FastIoAcqModWrite() call above.
-
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
+ BOOLEAN Status = FALSE;
+ PEXT2_FCB Fcb;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsDirectory(Fcb)) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "Ext2FastIoUnlockSingle: %s %s %wZ\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_ALL",
+ &Fcb->Mcb->FullName
+ ));
+#endif
+
+ if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
+ _SEH2_LEAVE;
+ }
+
+ IoStatus->Status = FsRtlFastUnlockAll(
+ &Fcb->FileLockAnchor,
+ FileObject,
+ Process,
+ NULL );
+
+ IoStatus->Information = 0;
+ Status = TRUE;
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ IoStatus->Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+#if EXT2_DEBUG
+ if (Status == FALSE) {
+
+ DEBUG(DL_ERR, (
+ "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_ALL"
+ ));
+ } else if (IoStatus->Status != STATUS_SUCCESS) {
+ DEBUG(DL_ERR, (
+ "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_ALL",
+ Ext2NtStatusToString(IoStatus->Status),
+ IoStatus->Status
+ ));
+ }
+#endif
+
+ return Status;
}
-
-/*************************************************************************
-*
-* Function: Ext2FastIoAcqCcFlush()
-*
-* Description:
-* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
-* resources before performing a CcFlush() operation on a specific file
-* stream.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2FastIoAcqCcFlush(
-IN PFILE_OBJECT FileObject,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoUnlockAllByKey (
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process,
+ IN ULONG Key,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoAcqCcFlush", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
- try
- {
- // Acquire appropriate resources that will allow correct synchronization
- // with a flush call (and avoid deadlock).
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
+ BOOLEAN Status = FALSE;
+ PEXT2_FCB Fcb;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ _SEH2_TRY {
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsDirectory(Fcb)) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "Ext2FastIoUnlockAllByKey: %s %s %wZ\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_ALL_BY_KEY",
+ &Fcb->Mcb->FullName
+ ));
+
+ DEBUG(DL_INF, (
+ "Ext2FastIoUnlockAllByKey: Key: %u\n",
+ Key
+ ));
+#endif
+
+ if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
+ _SEH2_LEAVE;
+ }
+
+ IoStatus->Status = FsRtlFastUnlockAllByKey(
+ &Fcb->FileLockAnchor,
+ FileObject,
+ Process,
+ Key,
+ NULL
+ );
+
+ IoStatus->Information = 0;
+ Status = TRUE;
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+
+ } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+ IoStatus->Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
+
+ } _SEH2_FINALLY {
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+#if EXT2_DEBUG
+ if (Status == FALSE) {
+
+ DEBUG(DL_ERR, (
+ "Ext2FastIoUnlockAllByKey: %s %s *** Status: FALSE ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_ALL_BY_KEY"
+ ));
+ } else if (IoStatus->Status != STATUS_SUCCESS) {
+
+ DEBUG(DL_ERR, (
+ "Ext2FastIoUnlockAllByKey: %s %s *** Status: %s (%#x) ***\n",
+ (PUCHAR) Process + ProcessNameOffset,
+ "FASTIO_UNLOCK_ALL_BY_KEY",
+ Ext2NtStatusToString(IoStatus->Status),
+ IoStatus->Status
+ ));
+ }
+#endif
+
+ return Status;
}
-/*************************************************************************
-*
-* Function: Ext2FastIoRelCcFlush()
-*
-* Description:
-* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
-* resources before performing a CcFlush() operation on a specific file
-* stream.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2FastIoRelCcFlush(
-IN PFILE_OBJECT FileObject,
-IN PDEVICE_OBJECT DeviceObject)
+BOOLEAN NTAPI
+Ext2FastIoQueryNetworkOpenInfo (
+ IN PFILE_OBJECT FileObject,
+ IN BOOLEAN Wait,
+ IN OUT PFILE_NETWORK_OPEN_INFORMATION PFNOI,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
-
- FsRtlEnterFileSystem();
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "~~~[FastIO call]~~~ Ext2FastIoRelCcFlush", 0);
- if( FileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FastIO]", FileObject);
- }
-
- try
- {
- try
- {
- // Release resources acquired in Ext2FastIoAcqCcFlush() above.
- NOTHING;
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, NULL);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- }
- finally
- {
-
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
+ BOOLEAN bResult = FALSE;
+
+ PEXT2_FCB Fcb = NULL;
+
+ BOOLEAN FcbResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ FsRtlEnterFileSystem();
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ DbgBreak();
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+#if EXT2_DEBUG
+ DEBUG(DL_INF, (
+ "%-31s %wZ\n",
+ "FASTIO_QUERY_NETWORK_OPEN_INFO",
+ &Fcb->Mcb->FullName
+ ));
+#endif
+
+ if (FileObject->FsContext2) {
+ _SEH2_LEAVE;
+ }
+
+ if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
+
+ if (!ExAcquireResourceSharedLite(
+ &Fcb->MainResource,
+ Wait
+ )) {
+ _SEH2_LEAVE;
+ }
+
+ FcbResourceAcquired = TRUE;
+ }
+
+ if (IsDirectory(Fcb)) {
+ PFNOI->AllocationSize.QuadPart = 0;
+ PFNOI->EndOfFile.QuadPart = 0;
+ } else {
+ PFNOI->AllocationSize = Fcb->Header.AllocationSize;
+ PFNOI->EndOfFile = Fcb->Header.FileSize;
+ }
+
+ PFNOI->FileAttributes = Fcb->Mcb->FileAttr;
+ if (PFNOI->FileAttributes == 0) {
+ PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ if (IsRoot(Fcb)) {
+ PFNOI->CreationTime =
+ PFNOI->LastAccessTime =
+ PFNOI->LastWriteTime =
+ PFNOI->ChangeTime = Ext2NtTime(0);
+ } else {
+ PFNOI->CreationTime = Fcb->Mcb->CreationTime;
+ PFNOI->LastAccessTime = Fcb->Mcb->LastAccessTime;
+ PFNOI->LastWriteTime = Fcb->Mcb->LastWriteTime;
+ PFNOI->ChangeTime = Fcb->Mcb->ChangeTime;
+ }
+
+ bResult = TRUE;
+
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+
+ } _SEH2_FINALLY {
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ FsRtlExitFileSystem();
+ } _SEH2_END;
+
+ return bResult;
}
-
-#endif //_WIN32_WINNT >= 0x0400
-/*************************************************************************
-*
-* File: fileinfo.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the "set/query file information" dispatch
-* entry points.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_INFORMATION
-#define DEBUG_LEVEL (DEBUG_TRACE_FILEINFO)
-
-
-/*************************************************************************
-*
-* Function: Ext2FileInfo()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a set/query file
-* information request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2FileInfo(
-PDEVICE_OBJECT DeviceObject, // the logical volume device object
-PIRP Irp) // I/O Request Packet
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: fileinfo.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+#include <linux/ext4.h>
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+/* DEFINITIONS *************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2QueryFileInformation)
+#pragma alloc_text(PAGE, Ext2SetFileInformation)
+#pragma alloc_text(PAGE, Ext2ExpandFile)
+#pragma alloc_text(PAGE, Ext2TruncateFile)
+#pragma alloc_text(PAGE, Ext2SetDispositionInfo)
+#pragma alloc_text(PAGE, Ext2SetRenameInfo)
+#pragma alloc_text(PAGE, Ext2DeleteFile)
+#endif
+
+NTSTATUS
+Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PFILE_OBJECT FileObject;
+ PEXT2_VCB Vcb;
+ PEXT2_FCB Fcb;
+ PEXT2_MCB Mcb;
+ PEXT2_CCB Ccb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+ FILE_INFORMATION_CLASS FileInformationClass;
+ ULONG Length;
+ PVOID Buffer;
+ BOOLEAN FcbResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext != NULL);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ FileObject = IrpContext->FileObject;
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ if (Fcb == NULL) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ //
+ // This request is not allowed on volumes
+ //
+ if (Fcb->Identifier.Type == EXT2VCB) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ if (!((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)))) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = Fcb->Vcb;
+
+ {
+ if (!ExAcquireResourceSharedLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
+ )) {
+
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ FcbResourceAcquired = TRUE;
+ }
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ ASSERT(Ccb != NULL);
+ ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
+ (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
+ Mcb = Ccb->SymLink;
+ if (!Mcb)
+ Mcb = Fcb->Mcb;
+
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ FileInformationClass =
+ IoStackLocation->Parameters.QueryFile.FileInformationClass;
+
+ Length = IoStackLocation->Parameters.QueryFile.Length;
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+ RtlZeroMemory(Buffer, Length);
+
+ switch (FileInformationClass) {
+
+ case FileBasicInformation:
+ {
+ PFILE_BASIC_INFORMATION FileBasicInformation;
+
+ if (Length < sizeof(FILE_BASIC_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FileBasicInformation = (PFILE_BASIC_INFORMATION) Buffer;
+
+ FileBasicInformation->CreationTime = Mcb->CreationTime;
+ FileBasicInformation->LastAccessTime = Mcb->LastAccessTime;
+ FileBasicInformation->LastWriteTime = Mcb->LastWriteTime;
+ FileBasicInformation->ChangeTime = Mcb->ChangeTime;
+
+ FileBasicInformation->FileAttributes = Mcb->FileAttr;
+ if (IsLinkInvalid(Mcb)) {
+ ClearFlag(FileBasicInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
+ }
+ if (FileBasicInformation->FileAttributes == 0) {
+ FileBasicInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case FileStandardInformation:
+ {
+ PFILE_STANDARD_INFORMATION FSI;
+
+ if (Length < sizeof(FILE_STANDARD_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FSI = (PFILE_STANDARD_INFORMATION) Buffer;
+
+ FSI->NumberOfLinks = Mcb->Inode.i_nlink;
+
+ if (IsVcbReadOnly(Fcb->Vcb))
+ FSI->DeletePending = FALSE;
+ else
+ FSI->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+
+ if (IsLinkInvalid(Mcb)) {
+ FSI->Directory = FALSE;
+ FSI->AllocationSize.QuadPart = 0;
+ FSI->EndOfFile.QuadPart = 0;
+ } else if (IsMcbDirectory(Mcb)) {
+ FSI->Directory = TRUE;
+ FSI->AllocationSize.QuadPart = 0;
+ FSI->EndOfFile.QuadPart = 0;
+ } else {
+ FSI->Directory = FALSE;
+ FSI->AllocationSize = Fcb->Header.AllocationSize;
+ FSI->EndOfFile = Fcb->Header.FileSize;
+ }
+
+ Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case FileInternalInformation:
+ {
+ PFILE_INTERNAL_INFORMATION FileInternalInformation;
+
+ if (Length < sizeof(FILE_INTERNAL_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FileInternalInformation = (PFILE_INTERNAL_INFORMATION) Buffer;
+
+ /* we use the inode number as the internal index */
+ FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Mcb->Inode.i_ino;
+
+ Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+
+ case FileEaInformation:
+ {
+ PFILE_EA_INFORMATION FileEaInformation;
+
+ if (Length < sizeof(FILE_EA_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FileEaInformation = (PFILE_EA_INFORMATION) Buffer;
+
+ // Romfs doesn't have any extended attributes
+ FileEaInformation->EaSize = 0;
+
+ Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case FileNameInformation:
+ {
+ PFILE_NAME_INFORMATION FileNameInformation;
+ ULONG BytesToCopy = 0;
+
+ if (Length < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) +
+ Mcb->FullName.Length) {
+ BytesToCopy = Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
+ Status = STATUS_BUFFER_OVERFLOW;
+ } else {
+ BytesToCopy = Mcb->FullName.Length;
+ Status = STATUS_SUCCESS;
+ }
+
+ FileNameInformation = (PFILE_NAME_INFORMATION) Buffer;
+ FileNameInformation->FileNameLength = Mcb->FullName.Length;
+
+ RtlCopyMemory(
+ FileNameInformation->FileName,
+ Mcb->FullName.Buffer,
+ BytesToCopy );
+
+ Irp->IoStatus.Information = BytesToCopy +
+ + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
+ }
+ break;
+
+ case FilePositionInformation:
+ {
+ PFILE_POSITION_INFORMATION FilePositionInformation;
+
+ if (Length < sizeof(FILE_POSITION_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
+ FilePositionInformation->CurrentByteOffset =
+ FileObject->CurrentByteOffset;
+
+ Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case FileAllInformation:
+ {
+ PFILE_ALL_INFORMATION FileAllInformation;
+ PFILE_BASIC_INFORMATION FileBasicInformation;
+ PFILE_STANDARD_INFORMATION FSI;
+ PFILE_INTERNAL_INFORMATION FileInternalInformation;
+ PFILE_EA_INFORMATION FileEaInformation;
+ PFILE_POSITION_INFORMATION FilePositionInformation;
+ PFILE_NAME_INFORMATION FileNameInformation;
+
+ if (Length < sizeof(FILE_ALL_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FileAllInformation = (PFILE_ALL_INFORMATION) Buffer;
+
+ FileBasicInformation =
+ &FileAllInformation->BasicInformation;
+
+ FSI =
+ &FileAllInformation->StandardInformation;
+
+ FileInternalInformation =
+ &FileAllInformation->InternalInformation;
+
+ FileEaInformation =
+ &FileAllInformation->EaInformation;
+
+ FilePositionInformation =
+ &FileAllInformation->PositionInformation;
+
+ FileNameInformation =
+ &FileAllInformation->NameInformation;
+
+ FileBasicInformation->CreationTime = Mcb->CreationTime;
+ FileBasicInformation->LastAccessTime = Mcb->LastAccessTime;
+ FileBasicInformation->LastWriteTime = Mcb->LastWriteTime;
+ FileBasicInformation->ChangeTime = Mcb->ChangeTime;
+
+ FileBasicInformation->FileAttributes = Mcb->FileAttr;
+ if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target)) {
+ ClearFlag(FileBasicInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
+ }
+ if (FileBasicInformation->FileAttributes == 0) {
+ FileBasicInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ FSI->NumberOfLinks = Mcb->Inode.i_nlink;
+
+ if (IsVcbReadOnly(Fcb->Vcb))
+ FSI->DeletePending = FALSE;
+ else
+ FSI->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+
+ if (IsLinkInvalid(Mcb)) {
+ FSI->Directory = FALSE;
+ FSI->AllocationSize.QuadPart = 0;
+ FSI->EndOfFile.QuadPart = 0;
+ } else if (IsDirectory(Fcb)) {
+ FSI->Directory = TRUE;
+ FSI->AllocationSize.QuadPart = 0;
+ FSI->EndOfFile.QuadPart = 0;
+ } else {
+ FSI->Directory = FALSE;
+ FSI->AllocationSize = Fcb->Header.AllocationSize;
+ FSI->EndOfFile = Fcb->Header.FileSize;
+ }
+
+ // The "inode number"
+ FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Mcb->Inode.i_ino;
+
+ // Romfs doesn't have any extended attributes
+ FileEaInformation->EaSize = 0;
+
+ FilePositionInformation->CurrentByteOffset =
+ FileObject->CurrentByteOffset;
+
+ FileNameInformation->FileNameLength = Mcb->ShortName.Length;
+
+ if (Length < sizeof(FILE_ALL_INFORMATION) +
+ Mcb->ShortName.Length - sizeof(WCHAR)) {
+ Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
+ Status = STATUS_BUFFER_OVERFLOW;
+ RtlCopyMemory(
+ FileNameInformation->FileName,
+ Mcb->ShortName.Buffer,
+ Length - FIELD_OFFSET(FILE_ALL_INFORMATION,
+ NameInformation.FileName)
+ );
+ _SEH2_LEAVE;
+ }
+
+ RtlCopyMemory(
+ FileNameInformation->FileName,
+ Mcb->ShortName.Buffer,
+ Mcb->ShortName.Length
+ );
+
+ Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
+ Mcb->ShortName.Length - sizeof(WCHAR);
+#if 0
+ sizeof(FILE_ACCESS_INFORMATION) -
+ sizeof(FILE_MODE_INFORMATION) -
+ sizeof(FILE_ALIGNMENT_INFORMATION);
+#endif
+
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ /*
+ case FileAlternateNameInformation:
+ {
+ // TODO: Handle FileAlternateNameInformation
+
+ // Here we would like to use RtlGenerate8dot3Name but I don't
+ // know how to use the argument PGENERATE_NAME_CONTEXT
+ }
+ */
+
+ case FileNetworkOpenInformation:
+ {
+ PFILE_NETWORK_OPEN_INFORMATION PFNOI;
+
+ if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ PFNOI = (PFILE_NETWORK_OPEN_INFORMATION) Buffer;
+
+ PFNOI->FileAttributes = Mcb->FileAttr;
+ if (IsLinkInvalid(Mcb)) {
+ ClearFlag(PFNOI->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
+ PFNOI->AllocationSize.QuadPart = 0;
+ PFNOI->EndOfFile.QuadPart = 0;
+ } else if (IsDirectory(Fcb)) {
+ PFNOI->AllocationSize.QuadPart = 0;
+ PFNOI->EndOfFile.QuadPart = 0;
+ } else {
+ PFNOI->AllocationSize = Fcb->Header.AllocationSize;
+ PFNOI->EndOfFile = Fcb->Header.FileSize;
+ }
+
+ if (PFNOI->FileAttributes == 0) {
+ PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ PFNOI->CreationTime = Mcb->CreationTime;
+ PFNOI->LastAccessTime = Mcb->LastAccessTime;
+ PFNOI->LastWriteTime = Mcb->LastWriteTime;
+ PFNOI->ChangeTime = Mcb->ChangeTime;
+
+
+ Irp->IoStatus.Information =
+ sizeof(FILE_NETWORK_OPEN_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+#if (_WIN32_WINNT >= 0x0500)
+
+ case FileAttributeTagInformation:
+ {
+ PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
+
+ if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
+ FATI->FileAttributes = Mcb->FileAttr;
+ if (IsLinkInvalid(Mcb)) {
+ ClearFlag(FATI->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
+ }
+ if (FATI->FileAttributes == 0) {
+ FATI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+ FATI->ReparseTag = IO_REPARSE_TAG_RESERVED_ZERO;
+ Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+#endif // (_WIN32_WINNT >= 0x0500)
+
+ case FileStreamInformation:
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+
+ default:
+ DEBUG(DL_WRN, ( "Ext2QueryInformation: invalid class: %d\n",
+ FileInformationClass));
+ Status = STATUS_INVALID_PARAMETER; /* STATUS_INVALID_INFO_CLASS; */
+ break;
+ }
+
+ } _SEH2_FINALLY {
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+ if (Status == STATUS_PENDING ||
+ Status == STATUS_CANT_WAIT) {
+ Status = Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
+}
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "File Info Control IRP received...", 0);
- FsRtlEnterFileSystem();
-
- ASSERT(DeviceObject);
- ASSERT(Irp);
+NTSTATUS
+Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PEXT2_VCB Vcb;
+ PFILE_OBJECT FileObject;
+ PEXT2_FCB Fcb;
+ PEXT2_CCB Ccb;
+ PEXT2_MCB Mcb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+ FILE_INFORMATION_CLASS FileInformationClass;
+
+ ULONG NotifyFilter = 0;
+
+ ULONG Length;
+ PVOID Buffer;
+
+ BOOLEAN VcbMainResourceAcquired = FALSE;
+ BOOLEAN FcbMainResourceAcquired = FALSE;
+ BOOLEAN FcbPagingIoResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext != NULL);
+
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ /* check io stack location of irp stack */
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ FileInformationClass =
+ IoStackLocation->Parameters.SetFile.FileInformationClass;
+ Length = IoStackLocation->Parameters.SetFile.Length;
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+ /* check Vcb */
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+ if (!IsMounted(Vcb)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ /* we need grab Vcb in case it's a rename operation */
+ if (FileInformationClass == FileRenameInformation) {
+ if (!ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ VcbMainResourceAcquired = TRUE;
+ }
+
+ if (IsVcbReadOnly(Vcb)) {
+ if (FileInformationClass != FilePositionInformation) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
+ Status = STATUS_ACCESS_DENIED;
+ _SEH2_LEAVE;
+ }
+
+ FileObject = IrpContext->FileObject;
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+
+ // This request is issued to volumes, just return success
+ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) {
+ Status = STATUS_FILE_DELETED;
+ _SEH2_LEAVE;
+ }
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ ASSERT(Ccb != NULL);
+ ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
+ (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
+ Mcb = Ccb->SymLink;
+ if (Mcb) {
+ if (IsFlagOn(Mcb->Flags, MCB_FILE_DELETED)) {
+ Status = STATUS_FILE_DELETED;
+ _SEH2_LEAVE;
+ }
+ } else {
+ Mcb = Fcb->Mcb;
+ }
+
+ if ( !IsDirectory(Fcb) && !FlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
+ ((FileInformationClass == FileEndOfFileInformation) ||
+ (FileInformationClass == FileValidDataLengthInformation) ||
+ (FileInformationClass == FileAllocationInformation))) {
+
+ Status = FsRtlCheckOplock( &Fcb->Oplock,
+ Irp,
+ IrpContext,
+ NULL,
+ NULL );
+
+ if (Status != STATUS_SUCCESS) {
+ _SEH2_LEAVE;
+ }
+
+ //
+ // Set the flag indicating if Fast I/O is possible
+ //
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+ }
+
+ /* for renaming, we must not get any Fcb locks here, function
+ Ext2SetRenameInfo will get Dcb resource exclusively. */
+ if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
+ FileInformationClass != FileRenameInformation) {
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ FcbMainResourceAcquired = TRUE;
+
+ if ( FileInformationClass == FileAllocationInformation ||
+ FileInformationClass == FileEndOfFileInformation ||
+ FileInformationClass == FileValidDataLengthInformation) {
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Fcb->PagingIoResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+ FcbPagingIoResourceAcquired = TRUE;
+ }
+ }
+
+ switch (FileInformationClass) {
+
+ case FileBasicInformation:
+ {
+ PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION) Buffer;
+ struct inode *Inode = &Mcb->Inode;
+
+ if (FBI->CreationTime.QuadPart != 0 && FBI->CreationTime.QuadPart != -1) {
+ Inode->i_ctime = Ext2LinuxTime(FBI->CreationTime);
+ Mcb->CreationTime = Ext2NtTime(Inode->i_ctime);
+ NotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
+ }
+
+ if (FBI->LastAccessTime.QuadPart != 0 && FBI->LastAccessTime.QuadPart != -1) {
+ Inode->i_atime = Ext2LinuxTime(FBI->LastAccessTime);
+ Mcb->LastAccessTime = Ext2NtTime(Inode->i_atime);
+ NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
+ }
+
+ if (FBI->LastWriteTime.QuadPart != 0 && FBI->LastWriteTime.QuadPart != -1) {
+ Inode->i_mtime = Ext2LinuxTime(FBI->LastWriteTime);
+ Mcb->LastWriteTime = Ext2NtTime(Inode->i_mtime);
+ NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+ SetFlag(Ccb->Flags, CCB_LAST_WRITE_UPDATED);
+ }
+
+ if (FBI->ChangeTime.QuadPart !=0 && FBI->ChangeTime.QuadPart != -1) {
+ Mcb->ChangeTime = FBI->ChangeTime;
+ }
+
+ if (FBI->FileAttributes != 0) {
+
+ BOOLEAN bIsDirectory = IsDirectory(Fcb);
+ NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+
+ if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) {
+ Ext2SetOwnerReadOnly(Inode->i_mode);
+ } else {
+ Ext2SetOwnerWritable(Inode->i_mode);
+ }
+
+ if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
+ SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
+ } else {
+ ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
+ }
+
+ Mcb->FileAttr = FBI->FileAttributes;
+ if (bIsDirectory) {
+ SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+ ClearFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
+ }
+ }
+
+ if (NotifyFilter != 0) {
+ if (Ext2SaveInode(IrpContext, Vcb, Inode)) {
+ Status = STATUS_SUCCESS;
+ }
+ }
+
+ ClearFlag(NotifyFilter, FILE_NOTIFY_CHANGE_LAST_ACCESS);
+ Status = STATUS_SUCCESS;
+ }
+
+ break;
+
+ case FileAllocationInformation:
+ {
+ PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
+ LARGE_INTEGER AllocationSize;
+
+ if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* set Mcb to it's target */
+ if (IsMcbSymLink(Mcb)) {
+ ASSERT(Fcb->Mcb == Mcb->Target);
+ }
+ Mcb = Fcb->Mcb;
+
+ /* get user specified allocationsize aligned with BLOCK_SIZE */
+ AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
+ (ULONGLONG)FAI->AllocationSize.QuadPart,
+ (ULONGLONG)BLOCK_SIZE);
+
+ if (AllocationSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) {
+
+ Status = Ext2ExpandFile(IrpContext, Vcb, Mcb, &AllocationSize);
+ Fcb->Header.AllocationSize = AllocationSize;
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
+ SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_SETINFO);
+
+ } else if (AllocationSize.QuadPart < Fcb->Header.AllocationSize.QuadPart) {
+
+ if (MmCanFileBeTruncated(&(Fcb->SectionObject), &AllocationSize)) {
+
+ /* truncate file blocks */
+ Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &AllocationSize);
+
+ if (NT_SUCCESS(Status)) {
+ ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
+ }
+
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
+ Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
+ if (Mcb->Inode.i_size > (loff_t)AllocationSize.QuadPart) {
+ Mcb->Inode.i_size = AllocationSize.QuadPart;
+ }
+ Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
+ if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) {
+ Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+ }
+
+ } else {
+
+ Status = STATUS_USER_MAPPED_FILE;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (NotifyFilter) {
+
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+ Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+ }
+
+ DEBUG(DL_IO, ("Ext2SetInformation: %wZ NewSize=%I64xh AllocationSize=%I64xh "
+ "FileSize=%I64xh VDL=%I64xh i_size=%I64xh status = %xh\n",
+ &Fcb->Mcb->ShortName, AllocationSize.QuadPart,
+ Fcb->Header.AllocationSize.QuadPart,
+ Fcb->Header.FileSize.QuadPart, Fcb->Header.ValidDataLength.QuadPart,
+ Mcb->Inode.i_size, Status));
+ }
+
+ break;
+
+ case FileEndOfFileInformation:
+ {
+ PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
+ LARGE_INTEGER NewSize, OldSize, EndOfFile;
+
+ if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* set Mcb to it's target */
+ if (IsMcbSymLink(Mcb)) {
+ ASSERT(Fcb->Mcb == Mcb->Target);
+ }
+ Mcb = Fcb->Mcb;
+
+ OldSize = Fcb->Header.AllocationSize;
+ EndOfFile = FEOFI->EndOfFile;
+
+ if (IoStackLocation->Parameters.SetFile.AdvanceOnly) {
+
+ if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
+ _SEH2_LEAVE;
+ }
+
+ if (EndOfFile.QuadPart > Fcb->Header.FileSize.QuadPart) {
+ EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
+ }
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
+ if (EndOfFile.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
+ Fcb->Header.ValidDataLength.QuadPart = EndOfFile.QuadPart;
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
+ }
- try
- {
+ _SEH2_LEAVE;
+ }
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
+ NewSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
+ EndOfFile.QuadPart, BLOCK_SIZE);
+
+ if (NewSize.QuadPart > OldSize.QuadPart) {
- RC = Ext2CommonFileInfo(PtrIrpContext, Irp);
+ Fcb->Header.AllocationSize = NewSize;
+ Status = Ext2ExpandFile(
+ IrpContext,
+ Vcb,
+ Mcb,
+ &(Fcb->Header.AllocationSize)
+ );
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
+ SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_SETINFO);
+
+
+ } else if (NewSize.QuadPart == OldSize.QuadPart) {
+
+ /* we are luck ;) */
+ Status = STATUS_SUCCESS;
+
+ } else {
+
+ /* don't truncate file data since it's still being written */
+ if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_WRITE)) {
+
+ Status = STATUS_SUCCESS;
+
+ } else {
+
+ if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &NewSize)) {
+ Status = STATUS_USER_MAPPED_FILE;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ /* truncate file blocks */
+ Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &NewSize);
+
+ /* restore original file size */
+ if (NT_SUCCESS(Status)) {
+ ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
+ }
+
+ /* update file allocateion size */
+ Fcb->Header.AllocationSize.QuadPart = NewSize.QuadPart;
+
+ ASSERT((loff_t)NewSize.QuadPart >= Mcb->Inode.i_size);
+ if ((loff_t)Fcb->Header.FileSize.QuadPart < Mcb->Inode.i_size) {
+ Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
+ }
+ if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) {
+ Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+ }
+
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+ }
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size = EndOfFile.QuadPart;
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+
+ if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
+ !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
+ SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+ Ext2SaveSuper(IrpContext, Vcb);
+ }
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
+ }
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
+ Ext2SaveInode( IrpContext, Vcb, &Mcb->Inode);
- FsRtlExitFileSystem();
+ DEBUG(DL_IO, ("Ext2SetInformation: FileEndOfFileInformation %wZ EndofFile=%I64xh "
+ "AllocatieonSize=%I64xh FileSize=%I64xh VDL=%I64xh i_size=%I64xh status = %xh\n",
+ &Fcb->Mcb->ShortName, EndOfFile.QuadPart, Fcb->Header.AllocationSize.QuadPart,
+ Fcb->Header.FileSize.QuadPart, Fcb->Header.ValidDataLength.QuadPart,
+ Mcb->Inode.i_size, Status));
+ }
- return(RC);
-}
+ break;
+ case FileValidDataLengthInformation:
+ {
+ PFILE_VALID_DATA_LENGTH_INFORMATION FVDL = (PFILE_VALID_DATA_LENGTH_INFORMATION) Buffer;
+ LARGE_INTEGER NewVDL;
+ if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
-/*************************************************************************
-*
-* Function: Ext2CommonFileInfo()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one'
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonFileInfo(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp)
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- PFILE_OBJECT PtrFileObject = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- BOOLEAN MainResourceAcquired = FALSE;
- BOOLEAN VCBResourceAcquired = FALSE;
- BOOLEAN PagingIoResourceAcquired = FALSE;
- void *PtrSystemBuffer = NULL;
- long BufferLength = 0;
- FILE_INFORMATION_CLASS FunctionalityRequested;
- BOOLEAN CanWait = FALSE;
- BOOLEAN PostRequest = FALSE;
-
- try
- {
- // First, get a pointer to the current I/O stack location.
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
-
- // Get the FCB and CCB pointers
- Ext2GetFCB_CCB_VCB_FromFileObject (
- PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
-
- // If the caller has opened a logical volume and is attempting to
- // query information for it as a file stream, return an error.
- if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB)
- {
- // This is not allowed. Caller must use get/set volume information instead.
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- // ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB);
- AssertFCB( PtrFCB );
-
- PtrSystemBuffer = PtrIrp->AssociatedIrp.SystemBuffer;
-
- if (PtrIoStackLocation->MajorFunction == IRP_MJ_QUERY_INFORMATION)
- {
- // ***********************
- // Query File Information
- // ***********************
-
- // Now, obtain some parameters.
- DebugTrace(DEBUG_TRACE_MISC, "Buffer length = 0x%lX[FileInfo]", BufferLength );
-
- BufferLength = PtrIoStackLocation->Parameters.QueryFile.Length;
-
- FunctionalityRequested = PtrIoStackLocation->Parameters.QueryFile.FileInformationClass;
-
- // Read in the file inode if it hasn't already been read...
- Ext2InitializeFCBInodeInfo( PtrFCB );
-
- //
- // Acquire the MainResource shared
- // except for page files...
- //
- if (!(PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE))
- {
- // Acquire the MainResource shared.
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Shared [FileInfo]", 0);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquisition FAILED [FileInfo]", 0);
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- MainResourceAcquired = TRUE;
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [FileInfo]", 0);
- }
-
- // Do whatever the caller asked us to do
- switch (FunctionalityRequested)
- {
- case FileBasicInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileBasicInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2GetBasicInformation(PtrFCB, (PFILE_BASIC_INFORMATION)PtrSystemBuffer, &BufferLength);
- break;
- case FileStandardInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileStandardInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2GetStandardInformation(PtrFCB, (PFILE_STANDARD_INFORMATION)PtrSystemBuffer, &BufferLength);
- break;
- // Similarly, implement all of the other query information routines
- // that your FSD can support.
-#if(_WIN32_WINNT >= 0x0400)
- case FileNetworkOpenInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileNetworkOpenInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2GetNetworkOpenInformation(PtrFCB, (PFILE_NETWORK_OPEN_INFORMATION)PtrSystemBuffer, &BufferLength);
- // RC = STATUS_INVALID_PARAMETER;
- // try_return();
- break;
-#endif // _WIN32_WINNT >= 0x0400
- case FileInternalInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileInternalInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // RC = Ext2GetInternalInformation(...);
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- break;
- case FileEaInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileEaInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- {
- PFILE_EA_INFORMATION EaInformation;
- EaInformation = (PFILE_EA_INFORMATION) PtrSystemBuffer;
- EaInformation->EaSize = 0;
- BufferLength = sizeof( FILE_EA_INFORMATION );
- break;
- }
- // RC = Ext2GetEaInformation(...);
- break;
-
- case FilePositionInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FilePositionInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // This is fairly simple. Copy over the information from the
- // file object.
- {
- PFILE_POSITION_INFORMATION PtrFileInfoBuffer;
-
- PtrFileInfoBuffer = (PFILE_POSITION_INFORMATION)PtrSystemBuffer;
-
- ASSERT(BufferLength >= sizeof(FILE_POSITION_INFORMATION));
- PtrFileInfoBuffer->CurrentByteOffset = PtrFileObject->CurrentByteOffset;
- // Modify the local variable for BufferLength appropriately.
- BufferLength = sizeof(FILE_POSITION_INFORMATION);
- }
- break;
- case FileStreamInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileStreamInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // RC = Ext2GetFileStreamInformation(...);
-
- RC = STATUS_INVALID_PARAMETER;
- try_return();
-
- break;
- case FileAllInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileAllInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // The I/O Manager supplies the Mode, Access, and Alignment
- // information. The rest is up to us to provide.
- // Therefore, decrement the BufferLength appropriately (assuming
- // that the above 3 types on information are already in the
- // buffer)
- {
-
- PFILE_POSITION_INFORMATION PtrFileInfoBuffer;
- PFILE_ALL_INFORMATION PtrAllInfo = (PFILE_ALL_INFORMATION)PtrSystemBuffer;
-
- // Fill in the position information.
-
- PtrFileInfoBuffer = (PFILE_POSITION_INFORMATION)&(PtrAllInfo->PositionInformation);
-
- PtrFileInfoBuffer->CurrentByteOffset = PtrFileObject->CurrentByteOffset;
-
- // Modify the local variable for BufferLength appropriately.
- BufferLength = sizeof(FILE_ALL_INFORMATION);
-
- // Get the remaining stuff.
- if (!NT_SUCCESS(RC = Ext2GetBasicInformation(PtrFCB, (PFILE_BASIC_INFORMATION)&(PtrAllInfo->BasicInformation),
- &BufferLength)))
- {
- try_return();
- }
- if (!NT_SUCCESS(RC = Ext2GetStandardInformation(PtrFCB, &(PtrAllInfo->StandardInformation), &BufferLength)))
- {
- try_return();
- }
- // Similarly, get all of the others ...
- }
- break;
- case FileNameInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileNameInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // RC = Ext2GetFullNameInformation(...);
- RC = Ext2GetFullNameInformation(PtrFCB, PtrCCB, (PFILE_NAME_INFORMATION)PtrSystemBuffer, &BufferLength);
- break;
- case FileAlternateNameInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileAlternateNameInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- // RC = Ext2GetAltNameInformation(...);
- break;
- case FileCompressionInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "FileCompressionInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- // RC = Ext2GetCompressionInformation(...);
- break;
-
- default:
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
-
- // If we completed successfully, the return the amount of information transferred.
- if (NT_SUCCESS(RC))
- {
- PtrIrp->IoStatus.Information = BufferLength;
- }
- else
- {
- PtrIrp->IoStatus.Information = 0;
- }
-
- }
- else
- {
- // ***********************
- // Set File Information
- // ***********************
- ASSERT(PtrIoStackLocation->MajorFunction == IRP_MJ_SET_INFORMATION);
-
- DebugTrace(DEBUG_TRACE_FILEINFO, ">>>>>>>> Set File Information <<<<<<<<< [FileInfo]", 0);
-
-
- // Now, obtain some parameters.
- FunctionalityRequested = PtrIoStackLocation->Parameters.SetFile.FileInformationClass;
-
- // Check oplocks...
-
- //
- // Acquire the VCB resource exclusively for
- // deletion, rename and link operations...
- // To synchronize with create and cleanup operations
- //
- if ((FunctionalityRequested == FileDispositionInformation) ||
- (FunctionalityRequested == FileRenameInformation) ||
- (FunctionalityRequested == FileLinkInformation))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [FileInfo]", 0);
- DebugTraceState( " VCB AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquisition FAILED [FileInfo]", 0);
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- // We have the VCB acquired exclusively.
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired [FileInfo]", 0);
- VCBResourceAcquired = TRUE;
- }
-
-
- // Acquire the FCB exclusively at this time...
- if (!(PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE))
- {
- // Acquire the MainResource shared.
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Exclusively [FileInfo]", 0);
- DebugTraceState( " FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [FileInfo]", 0);
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- MainResourceAcquired = TRUE;
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquired [FileInfo]", 0);
- }
-
- //
- // For delete link (rename),
- // set allocation size, and set EOF, should also acquire the paging-IO
- // resource, thereby synchronizing with paging-IO requests.
- //
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FileInfo]", PtrFileObject);
-
- }
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCBPaging Exclusively [FileInfo]", 0);
- DebugTraceState( " FCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->PagingIoResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempt to acquire FCBPaging FAILED [FileInfo]", 0);
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- PagingIoResourceAcquired = TRUE;
- DebugTrace(DEBUG_TRACE_MISC, "*** Acquired FCBPaging [FileInfo]", 0);
-
- // Do whatever the caller asked us to do
- switch (FunctionalityRequested)
- {
- case FileBasicInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FileBasicInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2SetBasicInformation(PtrIrpContext, PtrFCB, PtrFileObject, (PFILE_BASIC_INFORMATION)PtrSystemBuffer);
- // RC = STATUS_ACCESS_DENIED;
- break;
- case FileAllocationInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FileAllocationInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2SetAllocationInformation(PtrFCB, PtrCCB, PtrVCB, PtrFileObject,
- PtrIrpContext, PtrIrp, PtrSystemBuffer);
- break;
- case FileEndOfFileInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FileEndOfFileInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // RC = Ext2SetEOF(...);
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- break;
-
- case FilePositionInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FilePositionInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- // Check if no intermediate buffering has been specified.
- // If it was specified, do not allow non-aligned set file
- // position requests to succeed.
- {
- PFILE_POSITION_INFORMATION PtrFileInfoBuffer;
-
- PtrFileInfoBuffer = (PFILE_POSITION_INFORMATION)PtrSystemBuffer;
-
- if (PtrFileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING)
- {
- if (PtrFileInfoBuffer->CurrentByteOffset.LowPart & PtrIoStackLocation->DeviceObject->AlignmentRequirement)
- {
- // Invalid alignment.
- try_return(RC = STATUS_INVALID_PARAMETER);
- }
- }
- PtrFileObject->CurrentByteOffset = PtrFileInfoBuffer->CurrentByteOffset;
- }
- break;
-
- case FileDispositionInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FileDispositionInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2SetDispositionInformation(PtrFCB, PtrCCB, PtrVCB, PtrFileObject,
- PtrIrpContext, PtrIrp,
- (PFILE_DISPOSITION_INFORMATION)PtrSystemBuffer);
- break;
-
- case FileRenameInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FileRenameInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = Ext2RenameOrLinkFile( PtrFCB, PtrFileObject, PtrIrpContext,
- PtrIrp, (PFILE_RENAME_INFORMATION)PtrSystemBuffer);
- break;
- case FileLinkInformation:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Attempt to set FileLinkInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- // When you implement your rename/link routine, be careful to
- // check the following two arguments:
- // TargetFileObject = PtrIoStackLocation->Parameters.SetFile.FileObject;
- // ReplaceExistingFile = PtrIoStackLocation->Parameters.SetFile.ReplaceIfExists;
- //
- // The TargetFileObject argument is a pointer to the "target
- // directory" file object obtained during the "create" routine
- // invoked by the NT I/O Manager with the SL_OPEN_TARGET_DIRECTORY
- // flag specified. Remember that it is quite possible that if the
- // rename/link is contained within a single directory, the target
- // and source directories will be the same.
- // The ReplaceExistingFile argument should be used by you to
- // determine if the caller wishes to replace the target (if it
- // currently exists) with the new link/renamed file. If this
- // value is FALSE, and if the target directory entry (being
- // renamed-to, or the target of the link) exists, you should
- // return a STATUS_OBJECT_NAME_COLLISION error to the caller.
-
- // RC = Ext2RenameOrLinkFile(PtrFCB, PtrCCB, PtrFileObject, PtrIrpContext,
- // PtrIrp, (PFILE_RENAME_INFORMATION)PtrSystemBuffer);
-
- // Once you have completed the rename/link operation, do not
- // forget to notify any "notify IRPs" about the actions you have
- // performed.
- // An example is if you renamed across directories, you should
- // report that a new entry was added with the FILE_ACTION_ADDED
- // action type. The actual modification would then be reported
- // as either FILE_NOTIFY_CHANGE_FILE_NAME (if a file was renamed)
- // or FILE_NOTIFY_CHANGE_DIR_NAME (if a directory was renamed).
-
- break;
- default:
- DebugTrace(DEBUG_TRACE_FILEINFO, "Unrecoganised SetFileInformation code for %S", PtrFCB->FCBName->ObjectName.Buffer );
- RC = STATUS_INVALID_PARAMETER;
- try_return();
- }
- }
-
- try_exit: NOTHING;
- }
- finally
- {
- if (PagingIoResourceAcquired)
- {
- Ext2ReleaseResource(&(PtrReqdFCB->PagingIoResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCBPaging Released [FileInfo]", 0);
- DebugTraceState( " FCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]",
- PtrReqdFCB->PagingIoResource.ActiveCount,
- PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FileInfo]", PtrFileObject);
- }
-
- PagingIoResourceAcquired = FALSE;
- }
-
- if (MainResourceAcquired)
- {
- Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [FileInfo]", 0);
- DebugTraceState( " FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]",
- PtrReqdFCB->MainResource.ActiveCount,
- PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [FileInfo]", PtrFileObject);
- }
-
- MainResourceAcquired = FALSE;
- }
-
- if (VCBResourceAcquired)
- {
- Ext2ReleaseResource(&(PtrVCB->VCBResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [FileInfo]", 0);
- DebugTraceState( " VCB AC:0x%LX SW:0x%LX EX:0x%LX [FileInfo]",
- PtrVCB->VCBResource.ActiveCount,
- PtrVCB->VCBResource.NumberOfExclusiveWaiters,
- PtrVCB->VCBResource.NumberOfSharedWaiters );
-
- VCBResourceAcquired = FALSE;
- }
-
- // Post IRP if required
- if (PostRequest)
- {
-
- // Since, the I/O Manager gave us a system buffer, we do not
- // need to "lock" anything.
-
- // Perform the post operation which will mark the IRP pending
- // and will return STATUS_PENDING back to us
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
-
- }
- else
- {
-
- // Can complete the IRP here if no exception was encountered
- if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION)) {
- PtrIrp->IoStatus.Status = RC;
-
- // Free up the Irp Context
- Ext2ReleaseIrpContext(PtrIrpContext);
-
- // complete the IRP
- IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
- }
- } // can we complete the IRP ?
- } // end of "finally" processing
-
- // DbgPrint( "\n === File Info IRP returning --> RC : 0x%lX Bytes: 0x%lX", PtrIrp->IoStatus.Status, PtrIrp->IoStatus.Information );
-
- return(RC);
-}
+ NewVDL = FVDL->ValidDataLength;
+ if ((NewVDL.QuadPart < Fcb->Header.ValidDataLength.QuadPart)) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+ if (NewVDL.QuadPart > Fcb->Header.FileSize.QuadPart)
+ NewVDL = Fcb->Header.FileSize;
+ if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer,
+ &NewVDL)) {
+ Status = STATUS_USER_MAPPED_FILE;
+ _SEH2_LEAVE;
+ }
+
+ Fcb->Header.ValidDataLength = NewVDL;
+ FileObject->Flags |= FO_FILE_MODIFIED;
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+ }
+
+ break;
+
+ case FileDispositionInformation:
+ {
+ PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
+
+ Status = Ext2SetDispositionInfo(IrpContext, Vcb, Fcb, Ccb, FDI->DeleteFile);
+
+ DEBUG(DL_INF, ( "Ext2SetInformation: SetDispositionInformation: DeleteFile=%d %wZ status = %xh\n",
+ FDI->DeleteFile, &Mcb->ShortName, Status));
+ }
+
+ break;
+
+ case FileRenameInformation:
+ {
+ Status = Ext2SetRenameInfo(IrpContext, Vcb, Fcb, Ccb);
+ }
+
+ break;
+
+ //
+ // This is the only set file information request supported on read
+ // only file systems
+ //
+ case FilePositionInformation:
+ {
+ PFILE_POSITION_INFORMATION FilePositionInformation;
+
+ if (Length < sizeof(FILE_POSITION_INFORMATION)) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
+
+ if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
+ (FilePositionInformation->CurrentByteOffset.LowPart &
+ DeviceObject->AlignmentRequirement) ) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ FileObject->CurrentByteOffset =
+ FilePositionInformation->CurrentByteOffset;
+
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ break;
+
+ case FileLinkInformation:
+
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+
+ default:
+ DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n",
+ FileInformationClass));
+ Status = STATUS_INVALID_PARAMETER;/* STATUS_INVALID_INFO_CLASS; */
+ }
+
+ } _SEH2_FINALLY {
+
+ if (FcbPagingIoResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ }
+
+ if (NT_SUCCESS(Status) && (NotifyFilter != 0)) {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Mcb,
+ NotifyFilter,
+ FILE_ACTION_MODIFIED );
+
+ }
+
+ if (FcbMainResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ if (VcbMainResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+ if (Status == STATUS_PENDING ||
+ Status == STATUS_CANT_WAIT ) {
+ DbgBreak();
+ Status = Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
-/*************************************************************************
-*
-* Function: Ext2GetBasicInformation()
-*
-* Description:
-* Return some time-stamps and file attributes to the caller.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2GetBasicInformation(
-PtrExt2FCB PtrFCB,
-PFILE_BASIC_INFORMATION PtrBuffer,
-long *PtrReturnedLength )
-{
- NTSTATUS RC = STATUS_SUCCESS;
-
- try
- {
- if (*PtrReturnedLength < sizeof(FILE_BASIC_INFORMATION))
- {
- try_return(RC = STATUS_BUFFER_OVERFLOW);
- }
-
- // Zero out the supplied buffer.
- RtlZeroMemory(PtrBuffer, sizeof(FILE_BASIC_INFORMATION));
-
- // Get information from the FCB.
- PtrBuffer->CreationTime = PtrFCB->CreationTime;
- PtrBuffer->LastAccessTime = PtrFCB->LastAccessTime;
- PtrBuffer->LastWriteTime = PtrFCB->LastWriteTime;
- PtrBuffer->ChangeTime = PtrFCB->LastWriteTime;
-
- // Now fill in the attributes.
- PtrBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
- {
- PtrBuffer->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
- }
- else if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_SPECIAL_FILE ) )
- {
- // Special File...
- // Treated with respect... ;)
- //
- PtrBuffer->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY) ;
- }
-
- if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_HIDDEN_FILE ) )
- {
- PtrBuffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
- }
-
- if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_READ_ONLY ) )
- {
- PtrBuffer->FileAttributes |= FILE_ATTRIBUTE_READONLY;
- }
-
- try_exit: NOTHING;
- }
- finally
- {
- if (NT_SUCCESS(RC))
- {
- // Return the amount of information filled in.
- *PtrReturnedLength = sizeof(FILE_BASIC_INFORMATION);
- }
- }
- return(RC);
+ return Status;
}
-NTSTATUS NTAPI Ext2GetStandardInformation(
-PtrExt2FCB PtrFCB,
+ULONG
+Ext2TotalBlocks(
+ PEXT2_VCB Vcb,
+ PLARGE_INTEGER Size,
+ PULONG pMeta
+)
+{
+ ULONG Blocks, Meta =0, Remain;
+
+ Blocks = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
+ if (Blocks <= EXT2_NDIR_BLOCKS)
+ goto errorout;
+ Blocks -= EXT2_NDIR_BLOCKS;
+
+ Meta += 1;
+ if (Blocks <= Vcb->max_blocks_per_layer[1]) {
+ goto errorout;
+ }
+ Blocks -= Vcb->max_blocks_per_layer[1];
+
+level2:
+
+ if (Blocks <= Vcb->max_blocks_per_layer[2]) {
+ Meta += 1 + ((Blocks + BLOCK_SIZE/4 - 1) >> (BLOCK_BITS - 2));
+ goto errorout;
+ }
+ Meta += 1 + BLOCK_SIZE/4;
+ Blocks -= Vcb->max_blocks_per_layer[2];
+
+ if (Blocks > Vcb->max_blocks_per_layer[3]) {
+ Blocks = Vcb->max_blocks_per_layer[3];
+ }
+
+ ASSERT(Vcb->max_blocks_per_layer[2]);
+ Remain = Blocks % Vcb->max_blocks_per_layer[2];
+ Blocks = Blocks / Vcb->max_blocks_per_layer[2];
+ Meta += 1 + Blocks * (1 + BLOCK_SIZE/4);
+ if (Remain) {
+ Blocks = Remain;
+ goto level2;
+ }
+
+errorout:
+
+ if (pMeta)
+ *pMeta = Meta;
+ Blocks = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
+ return (Blocks + Meta);
+}
-PFILE_STANDARD_INFORMATION PtrStdInformation,
-long *PtrReturnedLength )
+NTSTATUS
+Ext2BlockMap(
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_MCB Mcb,
+ IN ULONG Index,
+ IN BOOLEAN bAlloc,
+ OUT PULONG pBlock,
+ OUT PULONG Number
+)
{
+ NTSTATUS status;
- NTSTATUS RC = STATUS_SUCCESS;
-
-
- try
- {
- if (*PtrReturnedLength < sizeof( FILE_STANDARD_INFORMATION ))
- {
- try_return(RC = STATUS_BUFFER_OVERFLOW);
- }
-
- // Zero out the supplied buffer.
- RtlZeroMemory(PtrStdInformation, sizeof(FILE_STANDARD_INFORMATION));
-
-
- PtrStdInformation->AllocationSize = PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize;
- PtrStdInformation->EndOfFile = PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize;
- PtrStdInformation->DeletePending = Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE);
- PtrStdInformation->Directory = Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY );
- PtrStdInformation->NumberOfLinks = PtrFCB->LinkCount;
-
- try_exit: NOTHING;
- }
- finally
- {
- if (NT_SUCCESS(RC))
- {
- // Return the amount of information filled in.
- *PtrReturnedLength = sizeof( FILE_STANDARD_INFORMATION );
- }
- }
- return(RC);
+ if (INODE_HAS_EXTENT(&Mcb->Inode)) {
+ status = Ext2MapExtent(IrpContext, Vcb, Mcb, Index,
+ bAlloc, pBlock, Number );
+ } else {
+ status = Ext2MapIndirect(IrpContext, Vcb, Mcb, Index,
+ bAlloc, pBlock, Number );
+ }
+
+ return status;
}
-NTSTATUS NTAPI Ext2GetNetworkOpenInformation(
- PtrExt2FCB PtrFCB,
- PFILE_NETWORK_OPEN_INFORMATION PtrNetworkOpenInformation,
- long *PtrReturnedLength )
+
+NTSTATUS
+Ext2ExpandFile(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_MCB Mcb,
+ PLARGE_INTEGER Size
+)
{
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG Start = 0;
+ ULONG End = 0;
- NTSTATUS RC = STATUS_SUCCESS;
-
- try
- {
- if (*PtrReturnedLength < sizeof( FILE_NETWORK_OPEN_INFORMATION ))
- {
- try_return(RC = STATUS_BUFFER_OVERFLOW);
- }
-
- // Zero out the supplied buffer.
- RtlZeroMemory(PtrNetworkOpenInformation, sizeof(FILE_NETWORK_OPEN_INFORMATION));
-
- PtrNetworkOpenInformation->CreationTime = PtrFCB->CreationTime;
- PtrNetworkOpenInformation->LastAccessTime = PtrFCB->LastAccessTime;
- PtrNetworkOpenInformation->LastWriteTime = PtrFCB->LastWriteTime;
- PtrNetworkOpenInformation->ChangeTime = PtrFCB->LastWriteTime;
- PtrNetworkOpenInformation->AllocationSize = PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize;
- PtrNetworkOpenInformation->EndOfFile = PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize;
-
- // Now fill in the attributes.
- PtrNetworkOpenInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
-
- if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
- {
- PtrNetworkOpenInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
- }
- else if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_SPECIAL_FILE ) )
- {
- // Special File...
- // Treated with respect... ;)
- //
- PtrNetworkOpenInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY) ;
- }
- if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_HIDDEN_FILE ) )
- {
- PtrNetworkOpenInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
- }
-
- if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_READ_ONLY ) )
- {
- PtrNetworkOpenInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
- }
- try_exit: NOTHING;
- }
- finally
- {
- if (NT_SUCCESS(RC))
- {
- // Return the amount of information filled in.
- *PtrReturnedLength = sizeof( FILE_NETWORK_OPEN_INFORMATION );
- }
- }
- return(RC);
+ Start = (ULONG)((Mcb->Inode.i_size + BLOCK_SIZE - 1) >> BLOCK_BITS);
+ End = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
+
+ /* it's a truncate operation, not expanding */
+ if (Start >= End) {
+ Size->QuadPart = ((LONGLONG) Start) << BLOCK_BITS;
+ return STATUS_SUCCESS;
+ }
+
+ /* ignore special files */
+ if (IsMcbSpecialFile(Mcb)) {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ /* expandind file extents */
+ if (INODE_HAS_EXTENT(&Mcb->Inode)) {
+
+ status = Ext2ExpandExtent(IrpContext, Vcb, Mcb, Start, End, Size);
+
+ } else {
+
+ BOOLEAN do_expand;
+
+#if EXT2_PRE_ALLOCATION_SUPPORT
+ do_expand = TRUE;
+#else
+ do_expand = (IrpContext->MajorFunction == IRP_MJ_WRITE) ||
+ IsMcbDirectory(Mcb);
+#endif
+ if (!do_expand)
+ goto errorout;
+
+ status = Ext2ExpandIndirect(IrpContext, Vcb, Mcb, Start, End, Size);
+ }
+
+errorout:
+ return status;
}
-NTSTATUS NTAPI Ext2GetFullNameInformation(
- PtrExt2FCB PtrFCB,
- PtrExt2CCB PtrCCB,
- PFILE_NAME_INFORMATION PtrNameInformation,
- long *PtrReturnedLength )
+NTSTATUS
+Ext2TruncateFile(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_MCB Mcb,
+ PLARGE_INTEGER Size
+)
{
+ NTSTATUS status = STATUS_SUCCESS;
- NTSTATUS RC = STATUS_SUCCESS;
-
- try
- {
- if (*PtrReturnedLength <
- (long)( sizeof(FILE_NAME_INFORMATION) + PtrCCB->AbsolutePathName.Length) )
- {
- try_return(RC = STATUS_BUFFER_OVERFLOW);
- }
-
- // Zero out the supplied buffer.
- RtlZeroMemory(PtrNameInformation, sizeof( FILE_NAME_INFORMATION ) );
-
- if( PtrCCB->AbsolutePathName.Length )
- {
- RtlCopyMemory(
- PtrNameInformation->FileName, // Destination,
- PtrCCB->AbsolutePathName.Buffer, // Source,
- PtrCCB->AbsolutePathName.Length ); // Length
-
- PtrNameInformation->FileNameLength = PtrCCB->AbsolutePathName.Length;
- try_return(RC = STATUS_SUCCESS);
- }
- else
- {
- try_return(RC = STATUS_INVALID_PARAMETER);
- }
-
- try_exit: NOTHING;
- }
- finally
- {
- if (NT_SUCCESS(RC))
- {
- // Return the amount of information filled in.
- *PtrReturnedLength =
- sizeof( FILE_NAME_INFORMATION ) +
- PtrCCB->AbsolutePathName.Length;
- }
+ if (INODE_HAS_EXTENT(&Mcb->Inode)) {
+ status = Ext2TruncateExtent(IrpContext, Vcb, Mcb, Size);
+ } else {
+ status = Ext2TruncateIndirect(IrpContext, Vcb, Mcb, Size);
}
- return(RC);
+
+ /* check and clear data/meta mcb extents */
+ if (Size->QuadPart == 0) {
+
+ /* check and remove all data extents */
+ if (Ext2ListExtents(&Mcb->Extents)) {
+ DbgBreak();
+ }
+ Ext2ClearAllExtents(&Mcb->Extents);
+ /* check and remove all meta extents */
+ if (Ext2ListExtents(&Mcb->MetaExts)) {
+ DbgBreak();
+ }
+ Ext2ClearAllExtents(&Mcb->MetaExts);
+ ClearLongFlag(Mcb->Flags, MCB_ZONE_INITED);
+ }
+
+ return status;
}
-/*************************************************************************
-*
-* Function: Ext2SetBasicInformation()
-*
-* Description:
-* Set some time-stamps and file attributes supplied by the caller.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2SetBasicInformation(
- PtrExt2IrpContext PtrIrpContext,
- PtrExt2FCB PtrFCB,
- PFILE_OBJECT PtrFileObject,
- PFILE_BASIC_INFORMATION PtrFileInformation )
+
+NTSTATUS
+Ext2IsFileRemovable(
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_FCB Fcb,
+ IN PEXT2_CCB Ccb
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
-
- PtrExt2VCB PtrVCB = PtrFCB->PtrVCB;
- AssertVCB( PtrVCB );
-
- // BOOLEAN CreationTimeChanged = FALSE;
- // BOOLEAN AttributesChanged = FALSE;
-
-// return STATUS_INVALID_PARAMETER;
-
- try
- {
- EXT2_INODE Inode;
- RtlZeroMemory(&Inode, sizeof( EXT2_INODE ));
-
- if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
- {
- //
- // Update time stamps in the inode
- // and in the FCB...
- //
- if( PtrFileInformation->CreationTime.QuadPart )
- {
- PtrFCB->CreationTime.QuadPart = PtrFileInformation->CreationTime.QuadPart;
- Inode.i_ctime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
-
- }
- if( PtrFileInformation->LastAccessTime.QuadPart )
- {
- PtrFCB->LastAccessTime.QuadPart = PtrFileInformation->LastAccessTime.QuadPart;
- Inode.i_atime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
-
- }
- if( PtrFileInformation->LastWriteTime.QuadPart )
- {
- PtrFCB->LastWriteTime.QuadPart = PtrFileInformation->LastWriteTime.QuadPart;
- Inode.i_mtime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
- - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- }
-
- // Now come the attributes.
- if (PtrFileInformation->FileAttributes)
- {
- if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_READONLY )
- {
- // Turn off the write bits...
- Ext2SetModeReadOnly( Inode.i_mode );
- }
- if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_HIDDEN )
- {
- // Turn off the read and write bits...
- Ext2SetModeHidden( Inode.i_mode );
-
- }
- if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_SYSTEM )
- {
- // Just turn off the read and write bits...
- // No special field to indicate that this is a system file...
- Ext2SetModeReadOnly( Inode.i_mode );
- Ext2SetModeHidden( Inode.i_mode );
- }
- }
-
- // Updating the inode...
- Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode );
- }
-
- if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_TEMPORARY)
- {
- Ext2SetFlag(PtrFileObject->Flags, FO_TEMPORARY_FILE);
- }
- else
- {
- Ext2ClearFlag(PtrFileObject->Flags, FO_TEMPORARY_FILE);
- }
- }
- finally
- {
- ;
- }
- return(RC);
+ PEXT2_MCB Mcb = Fcb->Mcb;
+
+ if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
+ return STATUS_CANNOT_DELETE;
+ }
+
+ if (IsMcbDirectory(Mcb)) {
+ if (!Ext2IsDirectoryEmpty(IrpContext, Vcb, Mcb)) {
+ return STATUS_DIRECTORY_NOT_EMPTY;
+ }
+ }
+
+ if (!MmFlushImageSection(&Fcb->SectionObject,
+ MmFlushForDelete )) {
+ return STATUS_CANNOT_DELETE;
+ }
+
+ if (IsMcbDirectory(Mcb)) {
+ FsRtlNotifyFullChangeDirectory(
+ Vcb->NotifySync,
+ &Vcb->NotifyList,
+ Ccb,
+ NULL,
+ FALSE,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ NULL
+ );
+ }
+
+ return STATUS_SUCCESS;
}
+NTSTATUS
+Ext2SetDispositionInfo(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_FCB Fcb,
+ PEXT2_CCB Ccb,
+ BOOLEAN bDelete
+)
+{
+ PIRP Irp = IrpContext->Irp;
+ PIO_STACK_LOCATION IrpSp;
+ NTSTATUS status = STATUS_SUCCESS;
+ PEXT2_MCB Mcb = Fcb->Mcb;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
-/*************************************************************************
-*
-* Function: Ext2SetDispositionInformation()
-*
-* Description:
-* Mark/Unmark a file for deletion.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2SetDispositionInformation(
-PtrExt2FCB PtrFCB,
-PtrExt2CCB PtrCCB,
-PtrExt2VCB PtrVCB,
-PFILE_OBJECT PtrFileObject,
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-PFILE_DISPOSITION_INFORMATION PtrBuffer)
+ DEBUG(DL_INF, ( "Ext2SetDispositionInfo: bDelete=%x\n", bDelete));
+
+ if (bDelete) {
+
+ DEBUG(DL_INF, ( "Ext2SetDispositionInformation: Removing %wZ.\n",
+ &Mcb->FullName));
+
+ /* always allow deleting on symlinks */
+ if (Ccb->SymLink == NULL) {
+ status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
+ }
+
+ if (NT_SUCCESS(status)) {
+ SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
+ IrpSp->FileObject->DeletePending = TRUE;
+ }
+
+ } else {
+
+ ClearLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
+ IrpSp->FileObject->DeletePending = FALSE;
+ }
+
+ return status;
+}
+
+NTSTATUS
+Ext2SetRenameInfo(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_FCB Fcb,
+ PEXT2_CCB Ccb
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
-
- try
- {
- if (!PtrBuffer->DeleteFile)
- {
- // "un-delete" the file.
- Ext2ClearFlag(PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE);
- PtrFileObject->DeletePending = FALSE;
- try_return();
- }
-
- // Do some checking to see if the file can even be deleted.
-
- if (PtrFCB->FCBFlags & EXT2_FCB_DELETE_ON_CLOSE)
- {
- // All done!
- try_return();
- }
-
- if (PtrFCB->FCBFlags & EXT2_FCB_READ_ONLY)
- {
- try_return(RC = STATUS_CANNOT_DELETE);
- }
-
- if (PtrVCB->VCBFlags & EXT2_VCB_FLAGS_VOLUME_READ_ONLY)
- {
- try_return(RC = STATUS_CANNOT_DELETE);
- }
-
- // An important step is to check if the file stream has been
- // mapped by any process. The delete cannot be allowed to proceed
- // in this case.
- if (!MmFlushImageSection(&(PtrFCB->NTRequiredFCB.SectionObject), MmFlushForDelete))
- {
- try_return(RC = STATUS_CANNOT_DELETE);
- }
-
- // Disallow deletion of either a root
- // directory or a directory that is not empty.
- if( PtrFCB->INodeNo == EXT2_ROOT_INO )
- {
- try_return(RC = STATUS_CANNOT_DELETE);
- }
-
- if (PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)
- {
- if (!Ext2IsDirectoryEmpty(PtrFCB, PtrCCB, PtrIrpContext))
- {
- try_return(RC = STATUS_DIRECTORY_NOT_EMPTY);
- }
- }
-
- // Set a flag to indicate that this directory entry will become history
- // at cleanup.
- Ext2SetFlag(PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE);
- PtrFileObject->DeletePending = TRUE;
-
- try_exit: NOTHING;
- }
- finally
- {
- ;
- }
- return(RC);
+ PEXT2_MCB Mcb = Fcb->Mcb;
+
+ PEXT2_FCB TargetDcb = NULL; /* Dcb of target directory */
+ PEXT2_MCB TargetMcb = NULL;
+ PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */
+ PEXT2_MCB ParentMcb = NULL;
+
+ PEXT2_FCB ExistingFcb = NULL; /* Target file Fcb if it exists*/
+ PEXT2_MCB ExistingMcb = NULL;
+
+ UNICODE_STRING FileName;
+
+ NTSTATUS Status;
+
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
+
+ PFILE_OBJECT FileObject;
+ PFILE_OBJECT TargetObject;
+
+ struct dentry *NewEntry = NULL;
+
+ BOOLEAN ReplaceIfExists;
+ BOOLEAN bMove = FALSE;
+ BOOLEAN bTargetRemoved = FALSE;
+
+ BOOLEAN bNewTargetDcb = FALSE;
+ BOOLEAN bNewParentDcb = FALSE;
+
+ PFILE_RENAME_INFORMATION FRI;
+
+ if (Ccb->SymLink) {
+ Mcb = Ccb->SymLink;
+ }
+
+ if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto errorout;
+ }
+
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ FileObject = IrpSp->FileObject;
+ TargetObject = IrpSp->Parameters.SetFile.FileObject;
+ ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
+
+ FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
+
+ if (TargetObject == NULL) {
+
+ UNICODE_STRING NewName;
+
+ NewName.Buffer = FRI->FileName;
+ NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
+
+ while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') {
+ NewName.Buffer[NewName.Length/2 - 1] = 0;
+ NewName.Length -= 2;
+ }
+
+ while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') {
+ NewName.Length -= 2;
+ }
+
+ NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
+ NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
+
+ FileName = NewName;
+
+ TargetMcb = Mcb->Parent;
+ if (IsMcbSymLink(TargetMcb)) {
+ TargetMcb = TargetMcb->Target;
+ ASSERT(!IsMcbSymLink(TargetMcb));
+ }
+
+ if (TargetMcb == NULL || FileName.Length >= EXT2_NAME_LEN*2) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ goto errorout;
+ }
+
+ } else {
+
+ TargetDcb = (PEXT2_FCB)(TargetObject->FsContext);
+
+ if (!TargetDcb || TargetDcb->Vcb != Vcb) {
+
+ DbgBreak();
+
+ Status = STATUS_INVALID_PARAMETER;
+ goto errorout;
+ }
+
+ TargetMcb = TargetDcb->Mcb;
+ FileName = TargetObject->FileName;
+ }
+
+ if (FsRtlDoesNameContainWildCards(&FileName)) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ goto errorout;
+ }
+
+ if (TargetMcb->Inode.i_ino == Mcb->Parent->Inode.i_ino) {
+ if (FsRtlAreNamesEqual( &FileName,
+ &(Mcb->ShortName),
+ FALSE,
+ NULL )) {
+ Status = STATUS_SUCCESS;
+ goto errorout;
+ }
+ } else {
+ bMove = TRUE;
+ }
+
+ TargetDcb = TargetMcb->Fcb;
+ if (TargetDcb == NULL) {
+ TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
+ if (TargetDcb) {
+ Ext2ReferXcb(&TargetDcb->ReferenceCount);
+ bNewTargetDcb = TRUE;
+ }
+ }
+ if (TargetDcb) {
+ SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
+ }
+
+ ParentMcb = Mcb->Parent;
+ ParentDcb = ParentMcb->Fcb;
+
+ if ((TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino)) {
+
+ if (ParentDcb == NULL) {
+ ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
+ if (ParentDcb) {
+ Ext2ReferXcb(&ParentDcb->ReferenceCount);
+ bNewParentDcb = TRUE;
+ }
+ }
+ if (ParentDcb) {
+ SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
+ }
+ }
+
+ if (!TargetDcb || !ParentDcb) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto errorout;
+ }
+
+ DEBUG(DL_RES, ("Ext2SetRenameInfo: rename %wZ to %wZ\\%wZ\n",
+ &Mcb->FullName, &TargetMcb->FullName, &FileName));
+
+ Status = Ext2LookupFile(
+ IrpContext,
+ Vcb,
+ &FileName,
+ TargetMcb,
+ &ExistingMcb,
+ 0
+ );
+
+ if (NT_SUCCESS(Status) && ExistingMcb != Mcb) {
+
+ if (!ReplaceIfExists) {
+
+ Status = STATUS_OBJECT_NAME_COLLISION;
+ DEBUG(DL_RES, ("Ext2SetRenameInfo: Target file %wZ exists\n",
+ &ExistingMcb->FullName));
+ goto errorout;
+
+ } else {
+
+ if ( (ExistingFcb = ExistingMcb->Fcb) && !IsMcbSymLink(ExistingMcb) ) {
+
+ Status = Ext2IsFileRemovable(IrpContext, Vcb, ExistingFcb, Ccb);
+ if (!NT_SUCCESS(Status)) {
+ DEBUG(DL_REN, ("Ext2SetRenameInfo: Target file %wZ cannot be removed.\n",
+ &ExistingMcb->FullName));
+ goto errorout;
+ }
+ }
+
+ Status = Ext2DeleteFile(IrpContext, Vcb, ExistingFcb, ExistingMcb);
+ if (!NT_SUCCESS(Status)) {
+ DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to delete %wZ with status: %xh.\n",
+ &FileName, Status));
+
+ goto errorout;
+ }
+
+ bTargetRemoved = TRUE;
+ }
+ }
+
+ /* remove directory entry of old name */
+ Status = Ext2RemoveEntry(IrpContext, Vcb, ParentDcb, Mcb);
+ if (!NT_SUCCESS(Status)) {
+ DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to remove entry %wZ with status %xh.\n",
+ &Mcb->FullName, Status));
+ DbgBreak();
+ goto errorout;
+ }
+
+ /* add new entry for new target name */
+ Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, &NewEntry);
+ if (!NT_SUCCESS(Status)) {
+ DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to add entry for %wZ with status: %xh.\n",
+ &FileName, Status));
+ Ext2AddEntry(IrpContext, Vcb, ParentDcb, &Mcb->Inode, &Mcb->ShortName, &NewEntry);
+ goto errorout;
+ }
+
+ /* correct the inode number in .. entry */
+ if (IsMcbDirectory(Mcb)) {
+ Status = Ext2SetParentEntry(
+ IrpContext, Vcb, Fcb,
+ ParentMcb->Inode.i_ino,
+ TargetMcb->Inode.i_ino );
+ if (!NT_SUCCESS(Status)) {
+ DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to set parent refer of %wZ with %xh.\n",
+ &Mcb->FullName, Status));
+ DbgBreak();
+ goto errorout;
+ }
+ }
+
+ /* Update current dentry from the newly created one. We need keep the original
+ dentry to assure children's links are valid if current entry is a directory */
+ if (Mcb->de) {
+ char *np = Mcb->de->d_name.name;
+ *(Mcb->de) = *NewEntry;
+ NewEntry->d_name.name = np;
+ }
+
+ if (bTargetRemoved) {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ ExistingMcb,
+ (IsMcbDirectory(ExistingMcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_REMOVED);
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ if (bMove) {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Mcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_REMOVED);
+
+ } else {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Mcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_RENAMED_OLD_NAME);
+
+ }
+
+ if (TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino) {
+ Ext2RemoveMcb(Vcb, Mcb);
+ Ext2InsertMcb(Vcb, TargetMcb, Mcb);
+ }
+
+ if (!Ext2BuildName( &Mcb->ShortName,
+ &FileName, NULL )) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto errorout;
+ }
+
+ if (!Ext2BuildName( &Mcb->FullName,
+ &FileName,
+ &TargetMcb->FullName)) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto errorout;
+ }
+
+ if (bMove) {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Mcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_ADDED);
+ } else {
+ Ext2NotifyReportChange(
+ IrpContext,
+ Vcb,
+ Mcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_RENAMED_NEW_NAME );
+
+ }
+ }
+
+errorout:
+
+ if (NewEntry)
+ Ext2FreeEntry(NewEntry);
+
+ if (TargetDcb) {
+ if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) {
+ ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
+ }
+ ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
+ }
+
+ if (bNewTargetDcb) {
+ ASSERT(TargetDcb != NULL);
+ if (Ext2DerefXcb(&TargetDcb->ReferenceCount) == 0) {
+ Ext2FreeFcb(TargetDcb);
+ TargetDcb = NULL;
+ } else {
+ DEBUG(DL_RES, ( "Ext2SetRenameInfo: TargetDcb is resued by other threads.\n"));
+ }
+ }
+
+ if (bNewParentDcb) {
+ ASSERT(ParentDcb != NULL);
+ if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) {
+ Ext2FreeFcb(ParentDcb);
+ ParentDcb = NULL;
+ } else {
+ DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n"));
+ }
+ }
+
+ if (ExistingMcb)
+ Ext2DerefMcb(ExistingMcb);
+
+ return Status;
}
+ULONG
+Ext2InodeType(PEXT2_MCB Mcb)
+{
+ if (IsMcbSymLink(Mcb)) {
+ return EXT2_FT_SYMLINK;
+ }
+
+ if (IsMcbDirectory(Mcb)) {
+ return EXT2_FT_DIR;
+ }
+ return EXT2_FT_REG_FILE;
+}
-/*************************************************************************
-*
-* Function: Ext2SetAllocationInformation()
-*
-* Description:
-* Mark/Unmark a file for deletion.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2SetAllocationInformation(
-PtrExt2FCB PtrFCB,
-PtrExt2CCB PtrCCB,
-PtrExt2VCB PtrVCB,
-PFILE_OBJECT PtrFileObject,
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-PFILE_ALLOCATION_INFORMATION PtrBuffer)
+NTSTATUS
+Ext2DeleteFile(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_FCB Fcb,
+ PEXT2_MCB Mcb
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- BOOLEAN TruncatedFile = FALSE;
- BOOLEAN ModifiedAllocSize = FALSE;
-
- try
- {
-
- // Are we increasing the allocation size?
- if (RtlLargeIntegerLessThan(
- PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize,
- PtrBuffer->AllocationSize))
- {
- ULONG CurrentSize;
- ULONG LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-
- for( CurrentSize = 0; CurrentSize < PtrBuffer->AllocationSize.QuadPart; CurrentSize += LogicalBlockSize )
- {
- Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrFCB, PtrFileObject, FALSE );
- }
- ModifiedAllocSize = TRUE;
- }
- else if (RtlLargeIntegerGreaterThan(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize,
- PtrBuffer->AllocationSize))
- {
- // This is the painful part. See if the VMM will allow us to proceed.
- // The VMM will deny the request if:
- // (a) any image section exists OR
- // (b) a data section exists and the size of the user mapped view
- // is greater than the new size
- // Otherwise, the VMM should allow the request to proceed.
- if (!MmCanFileBeTruncated(&(PtrFCB->NTRequiredFCB.SectionObject), &(PtrBuffer->AllocationSize)))
- {
- // VMM said no way!
- try_return(RC = STATUS_USER_MAPPED_FILE);
- }
-
- if( !Ext2TruncateFileAllocationSize( PtrIrpContext, PtrFCB, PtrFileObject, &PtrBuffer->AllocationSize) )
- {
- // This will do until I figure out a better error message code ;)
- RC = STATUS_INSUFFICIENT_RESOURCES;
-
- }
-
- ModifiedAllocSize = TRUE;
- TruncatedFile = TRUE;
- }
-
- try_exit:
-
- // This is a good place to check if we have performed a truncate
- // operation. If we have perform a truncate (whether we extended
- // or reduced file size), you should update file time stamps.
-
- // Last, but not the lease, you must inform the Cache Manager of file size changes.
- if (ModifiedAllocSize && NT_SUCCESS(RC))
- {
- // Update the FCB Header with the new allocation size.
- PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize = PtrBuffer->AllocationSize;
-
- // If we decreased the allocation size to less than the
- // current file size, modify the file size value.
- // Similarly, if we decreased the value to less than the
- // current valid data length, modify that value as well.
- if (TruncatedFile)
- {
- if (RtlLargeIntegerLessThan(PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize, PtrBuffer->AllocationSize))
- {
- // Decrease the file size value.
- PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize = PtrBuffer->AllocationSize;
- }
-
- if (RtlLargeIntegerLessThan(PtrFCB->NTRequiredFCB.CommonFCBHeader.ValidDataLength, PtrBuffer->AllocationSize))
- {
- // Decrease the valid data length value.
- PtrFCB->NTRequiredFCB.CommonFCBHeader.ValidDataLength = PtrBuffer->AllocationSize;
- }
- }
-
-
- // If the FCB has not had caching initiated, it is still valid
- // for you to invoke the NT Cache Manager. It is possible in such
- // situations for the call to be no'oped (unless some user has
- // mapped in the file)
-
- // NOTE: The invocation to CcSetFileSizes() will quite possibly
- // result in a recursive call back into the file system.
- // This is because the NT Cache Manager will typically
- // perform a flush before telling the VMM to purge pages
- // especially when caching has not been initiated on the
- // file stream, but the user has mapped the file into
- // the process' virtual address space.
- CcSetFileSizes(PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
-
- // Inform any pending IRPs (notify change directory).
- }
-
- }
- finally
- {
- ;
- }
- return(RC);
+ PEXT2_FCB Dcb = NULL;
+
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ BOOLEAN VcbResourceAcquired = FALSE;
+ BOOLEAN FcbPagingIoAcquired = FALSE;
+ BOOLEAN FcbResourceAcquired = FALSE;
+ BOOLEAN DcbResourceAcquired = FALSE;
+
+ LARGE_INTEGER Size;
+ LARGE_INTEGER SysTime;
+
+ BOOLEAN bNewDcb = FALSE;
+
+ DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n",
+ &Mcb->FullName, Mcb->Inode.i_ino));
+
+ if (IsFlagOn(Mcb->Flags, MCB_FILE_DELETED)) {
+ return STATUS_SUCCESS;
+ }
+
+ if (!IsMcbSymLink(Mcb) && IsMcbDirectory(Mcb)) {
+ if (!Ext2IsDirectoryEmpty(IrpContext, Vcb, Mcb)) {
+ return STATUS_DIRECTORY_NOT_EMPTY;
+ }
+ }
+
+
+ _SEH2_TRY {
+
+ Ext2ReferMcb(Mcb);
+
+ ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
+ VcbResourceAcquired = TRUE;
+
+ if (!(Dcb = Mcb->Parent->Fcb)) {
+ Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent);
+ if (Dcb) {
+ Ext2ReferXcb(&Dcb->ReferenceCount);
+ bNewDcb = TRUE;
+ }
+ }
+
+ if (Dcb) {
+ SetLongFlag(Dcb->Flags, FCB_STATE_BUSY);
+ DcbResourceAcquired =
+ ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
+
+ /* remove it's entry form it's parent */
+ Status = Ext2RemoveEntry(IrpContext, Vcb, Dcb, Mcb);
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ SetFlag(Mcb->Flags, MCB_FILE_DELETED);
+ Ext2RemoveMcb(Vcb, Mcb);
+
+ if (Fcb) {
+ FcbResourceAcquired =
+ ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+
+ FcbPagingIoAcquired =
+ ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
+ }
+
+ if (DcbResourceAcquired) {
+ ExReleaseResourceLite(&Dcb->MainResource);
+ DcbResourceAcquired = FALSE;
+ }
+
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ VcbResourceAcquired = FALSE;
+ }
+
+ if (IsMcbSymLink(Mcb)) {
+ if (Mcb->Inode.i_nlink > 0) {
+ Status = STATUS_CANNOT_DELETE;
+ _SEH2_LEAVE;
+ }
+ } else if (!IsMcbDirectory(Mcb)) {
+ if (Mcb->Inode.i_nlink > 0) {
+ _SEH2_LEAVE;
+ }
+ } else {
+ if (Mcb->Inode.i_nlink >= 2) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (S_ISLNK(Mcb->Inode.i_mode)) {
+
+ /* for symlink, we should do differenctly */
+ if (Mcb->Inode.i_size > EXT2_LINKLEN_IN_INODE) {
+ Size.QuadPart = (LONGLONG)0;
+ Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &Size);
+ }
+
+ } else {
+
+ /* truncate file size */
+ Size.QuadPart = (LONGLONG)0;
+ Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &Size);
+
+ /* check file offset mappings */
+ DEBUG(DL_EXT, ("Ext2DeleteFile ...: %wZ\n", &Mcb->FullName));
+
+ if (Fcb) {
+ Fcb->Header.AllocationSize.QuadPart = Size.QuadPart;
+ if (Fcb->Header.FileSize.QuadPart > Size.QuadPart) {
+ Fcb->Header.FileSize.QuadPart = Size.QuadPart;
+ Fcb->Mcb->Inode.i_size = Size.QuadPart;
+ }
+ if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) {
+ Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+ }
+ } else if (Mcb) {
+ /* Update the inode's data length . It should be ZERO if succeeds. */
+ if (Mcb->Inode.i_size > (loff_t)Size.QuadPart) {
+ Mcb->Inode.i_size = Size.QuadPart;
+ }
+ }
+ }
+
+ /* set delete time and free the inode */
+ KeQuerySystemTime(&SysTime);
+ Mcb->Inode.i_nlink = 0;
+ Mcb->Inode.i_dtime = Ext2LinuxTime(SysTime);
+ Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
+ Ext2FreeInode(IrpContext, Vcb, Mcb->Inode.i_ino, Ext2InodeType(Mcb));
+ }
+
+ } _SEH2_FINALLY {
+
+ if (FcbPagingIoAcquired) {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ }
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ if (DcbResourceAcquired) {
+ ExReleaseResourceLite(&Dcb->MainResource);
+ }
+
+ if (Dcb) {
+ ClearLongFlag(Dcb->Flags, FCB_STATE_BUSY);
+ if (bNewDcb) {
+ if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) {
+ Ext2FreeFcb(Dcb);
+ } else {
+ DEBUG(DL_ERR, ( "Ext2DeleteFile: Dcb %wZ used by other threads.\n",
+ &Mcb->FullName ));
+ }
+ }
+ }
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ Ext2DerefMcb(Mcb);
+ } _SEH2_END;
+
+ DEBUG(DL_INF, ( "Ext2DeleteFile: %wZ Succeed... EXT2SB->S_FREE_BLOCKS = %I64xh .\n",
+ &Mcb->FullName, ext3_free_blocks_count(SUPER_BLOCK)));
+
+ return Status;
}
-/*************************************************************************
-*
-* File: flush.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the "Flush Buffers" dispatch entry point.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_FLUSH
-
-#define DEBUG_LEVEL (DEBUG_TRACE_FLUSH)
-
-
-/*************************************************************************
-*
-* Function: Ext2Flush()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a flush buffers
-* request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Flush(
- PDEVICE_OBJECT DeviceObject, // the logical volume device object
- PIRP Irp) // I/O Request Packet
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Flush IRP Received...", 0);
-
- // Ext2BreakPoint();
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: flush.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
+/* INCLUDES *****************************************************************/
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
+#include "ext2fs.h"
- try
- {
+/* GLOBALS ***************************************************************/
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
+extern PEXT2_GLOBAL Ext2Global;
- RC = Ext2CommonFlush(PtrIrpContext, Irp);
+/* DEFINITIONS *************************************************************/
- } except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
+NTSTATUS NTAPI
+Ext2FlushCompletionRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context )
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
+{
+ if (Irp->PendingReturned)
+ IoMarkIrpPending( Irp );
- if (AreWeTopLevel) {
- IoSetTopLevelIrp(NULL);
- }
- FsRtlExitFileSystem();
+ if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
+ Irp->IoStatus.Status = STATUS_SUCCESS;
- return(RC);
+ return STATUS_SUCCESS;
}
-
-/*************************************************************************
-*
-* Function: Ext2CommonFlush()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one'
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonFlush(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp)
+NTSTATUS
+Ext2FlushFiles(
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN BOOLEAN bShutDown
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- PFILE_OBJECT PtrFileObject = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- BOOLEAN AcquiredFCB = FALSE;
- BOOLEAN PostRequest = FALSE;
- BOOLEAN CanWait = TRUE;
-
- try {
- // First, get a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
-
- // Get the FCB and CCB pointers
- PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
- ASSERT(PtrCCB);
- PtrFCB = PtrCCB->PtrFCB;
- AssertFCB( PtrFCB );
-
- /*ASSERT(PtrFCB);
- ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- // Get some of the parameters supplied to us
- CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
-
- // If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous.
- if (!CanWait) {
- PostRequest = TRUE;
- try_return();
- }
-
- // Check the type of object passed-in. That will determine the course of
- // action we take.
- if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) {
-
- if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) {
- PtrVCB = (PtrExt2VCB)(PtrFCB);
- } else {
- PtrVCB = PtrFCB->PtrVCB;
- }
-
- // The caller wishes to flush all files for the mounted
- // logical volume. The flush volume routine below should simply
- // walk through all of the open file streams, acquire the
- // FCB resource, and request the flush operation from the Cache
- // Manager. Basically, the sequence of operations listed below
- // for a single file should be executed on all open files.
-
- Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB);
-
- try_return();
- }
-
- if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
- {
- // This is a regular file.
- ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
- AcquiredFCB = TRUE;
-
- // Request the Cache Manager to perform a flush operation.
- // Further, instruct the Cache Manager that we wish to flush the
- // entire file stream.
- Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus));
- RC = PtrIrp->IoStatus.Status;
- // All done. You may want to also flush the directory entry for the
- // file stream at this time.
-
- // Some log-based FSD implementations may wish to flush their
- // log files at this time. Finally, you should update the time-stamp
- // values for the file stream appropriately. This would involve
- // obtaining the current time and modifying the appropriate directory
- // entry fields.
- }
-
- try_exit:
-
- if (AcquiredFCB)
- {
- Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Flush]", 0);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
- PtrReqdFCB->MainResource.ActiveCount,
- PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
- PtrReqdFCB->MainResource.NumberOfSharedWaiters );
-
- AcquiredFCB = FALSE;
- }
-
- if (!PostRequest)
- {
- PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
- NTSTATUS RC1 = STATUS_SUCCESS;
-
- // Send the request down at this point.
- // To do this, you must set the next IRP stack location, and
- // maybe set a completion routine.
- // Be careful about marking the IRP pending if the lower level
- // driver returned pending and you do have a completion routine!
- PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
- *PtrNextIoStackLocation = *PtrIoStackLocation;
-
- // Set the completion routine to "eat-up" any
- // STATUS_INVALID_DEVICE_REQUEST error code returned by the lower
- // level driver.
- IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE);
-
- /*
- * The exception handlers propably masked out the
- * fact that PtrVCB was never set.
- * -- Filip Navara, 18/08/2004
- */
- PtrVCB = PtrFCB->PtrVCB;
- RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
-
- RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1);
- }
-
- } finally {
- if (PostRequest) {
- // Nothing to lock now.
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
- } else {
- // Release the IRP context at this time.
- Ext2ReleaseIrpContext(PtrIrpContext);
- }
- }
-
- return(RC);
+ IO_STATUS_BLOCK IoStatus;
+
+ PEXT2_FCB Fcb;
+ PLIST_ENTRY ListEntry;
+
+ if (IsVcbReadOnly(Vcb)) {
+ return STATUS_SUCCESS;
+ }
+
+ IoStatus.Status = STATUS_SUCCESS;
+
+ DEBUG(DL_INF, ( "Flushing Files ...\n"));
+
+ // Flush all Fcbs in Vcb list queue.
+ for (ListEntry = Vcb->FcbList.Flink;
+ ListEntry != &Vcb->FcbList;
+ ListEntry = ListEntry->Flink ) {
+
+ Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
+ ExAcquireResourceExclusiveLite(
+ &Fcb->MainResource, TRUE);
+ IoStatus.Status = Ext2FlushFile(IrpContext, Fcb, NULL);
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+
+ return IoStatus.Status;
}
-/*************************************************************************
-*
-* Function: Ext2FlushAFile()
-*
-* Description:
-* Tell the Cache Manager to perform a flush.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2FlushAFile(
-PtrExt2NTRequiredFCB PtrReqdFCB,
-PIO_STATUS_BLOCK PtrIoStatus)
+NTSTATUS
+Ext2FlushVolume (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN BOOLEAN bShutDown
+)
{
- CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus);
- return;
+ IO_STATUS_BLOCK IoStatus;
+
+ DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
+
+ ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+ CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
+
+ return IoStatus.Status;
}
-/*************************************************************************
-*
-* Function: Ext2FlushLogicalVolume()
-*
-* Description:
-* Flush everything beginning at root directory.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2FlushLogicalVolume(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-PtrExt2VCB PtrVCB)
+NTSTATUS
+Ext2FlushFile (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_FCB Fcb,
+ IN PEXT2_CCB Ccb
+)
{
- BOOLEAN AcquiredVCB = FALSE;
-
- try {
- ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
-
- AcquiredVCB = TRUE;
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired Ex [Flush] ", 0);
-
- // Go through the list of FCB's. You would probably
- // flush all of the files. Then, you could flush the
- // directories that you may have have pinned into memory.
-
- // NOTE: This function may also be invoked internally as part of
- // processing a shutdown request.
-
- }
- finally
- {
- if (AcquiredVCB)
- {
- Ext2ReleaseResource(&(PtrVCB->VCBResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Flush]", 0);
- DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
- PtrVCB->VCBResource.ActiveCount,
- PtrVCB->VCBResource.NumberOfExclusiveWaiters,
- PtrVCB->VCBResource.NumberOfSharedWaiters );
- }
- }
-
- return;
-}
+ IO_STATUS_BLOCK IoStatus;
+ ASSERT(Fcb != NULL);
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-/*************************************************************************
-*
-* Function: Ext2FlushCompletion()
-*
-* Description:
-* Eat up any bad errors.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2FlushCompletion(
-PDEVICE_OBJECT PtrDeviceObject,
-PIRP PtrIrp,
-PVOID Context)
-{
- if (PtrIrp->PendingReturned) {
- IoMarkIrpPending(PtrIrp);
- }
+ /* update timestamp and achieve attribute */
+ if (Ccb != NULL) {
+
+ if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
+
+ LARGE_INTEGER SysTime;
+ KeQuerySystemTime(&SysTime);
+
+ Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
+ Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
+ Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
+ }
+ }
- if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) {
- // cannot do much here, can we?
- PtrIrp->IoStatus.Status = STATUS_SUCCESS;
- }
+ if (IsDirectory(Fcb)) {
+ return STATUS_SUCCESS;
+ }
- return(STATUS_SUCCESS);
+ DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
+ Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
+
+ CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
+ ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+
+ return IoStatus.Status;
}
+
+NTSTATUS
+Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION IrpSp = NULL;
+
+ PEXT2_VCB Vcb = NULL;
+ PEXT2_FCB Fcb = NULL;
+ PEXT2_FCBVCB FcbOrVcb = NULL;
+ PEXT2_CCB Ccb = NULL;
+ PFILE_OBJECT FileObject = NULL;
+
+ PDEVICE_OBJECT DeviceObject = NULL;
+
+ BOOLEAN MainResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ ASSERT(IsMounted(Vcb));
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ FileObject = IrpContext->FileObject;
+ FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
+ ASSERT(FcbOrVcb != NULL);
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ if (Ccb == NULL) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ MainResourceAcquired =
+ ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
+
+ ASSERT(MainResourceAcquired);
+ DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
+ FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
+
+ if (FcbOrVcb->Identifier.Type == EXT2VCB) {
+
+ Ext2VerifyVcb(IrpContext, Vcb);
+ Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
+ if (NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
+
+ if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
+ ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
+ }
+
+ } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
+
+ Fcb = (PEXT2_FCB)(FcbOrVcb);
+
+ Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
+ if (NT_SUCCESS(Status)) {
+ if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
+ Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
+ ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ }
+ }
+ }
+
+ DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
+ FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
+
+
+ } _SEH2_FINALLY {
+
+ if (MainResourceAcquired) {
+ ExReleaseResourceLite(&FcbOrVcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+
+ if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
+
+ // Call the disk driver to flush the physial media.
+ NTSTATUS DriverStatus;
+ PIO_STACK_LOCATION NextIrpSp;
+
+ NextIrpSp = IoGetNextIrpStackLocation(Irp);
+
+ *NextIrpSp = *IrpSp;
+
+ IoSetCompletionRoutine( Irp,
+ Ext2FlushCompletionRoutine,
+ NULL,
+ TRUE,
+ TRUE,
+ TRUE );
+
+ DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
+
+ Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
+ Status : DriverStatus;
+
+ IrpContext->Irp = Irp = NULL;
+ }
+
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } _SEH2_END;
+
+ return Status;
+}
\ No newline at end of file
-/*************************************************************************
-*
-* File: misc.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* This file contains some miscellaneous support routines.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_MISC
-
-#define DEBUG_LEVEL ( DEBUG_TRACE_MISC )
-
-/*************************************************************************
-*
-* Function: Ext2InitializeZones()
-*
-* Description:
-* Allocates some memory for global zones used to allocate FSD structures.
-* Either all memory will be allocated or we will back out gracefully.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2InitializeZones(
-void)
-{
- NTSTATUS RC = STATUS_SUCCESS;
- uint32 SizeOfZone = Ext2GlobalData.DefaultZoneSizeInNumStructs;
- uint32 SizeOfObjectNameZone = 0;
- uint32 SizeOfCCBZone = 0;
- uint32 SizeOfFCBZone = 0;
- uint32 SizeOfByteLockZone = 0;
- uint32 SizeOfIrpContextZone = 0;
-
- try {
-
- // initialize the spinlock protecting the zones
- KeInitializeSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock));
-
- // determine memory requirements
- switch (MmQuerySystemSize()) {
- case MmSmallSystem:
- // this is just for illustration purposes. I will multiply
- // number of structures with some arbitrary amount depending
- // upon available memory in the system ... You should choose a
- // more intelligent method suitable to your memory consumption
- // and the amount of memory available.
- SizeOfObjectNameZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2ObjectName))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfCCBZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2CCB))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfFCBZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FCB))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfByteLockZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FileLockInfo))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfIrpContextZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2IrpContext))) + sizeof(ZONE_SEGMENT_HEADER);
- break;
- case MmMediumSystem:
- SizeOfObjectNameZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2ObjectName))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfCCBZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2CCB))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfFCBZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FCB))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfByteLockZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FileLockInfo))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfIrpContextZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2IrpContext))) + sizeof(ZONE_SEGMENT_HEADER);
- break;
- case MmLargeSystem:
- SizeOfObjectNameZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2ObjectName))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfCCBZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2CCB))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfFCBZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FCB))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfByteLockZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FileLockInfo))) + sizeof(ZONE_SEGMENT_HEADER);
- SizeOfIrpContextZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2IrpContext))) + sizeof(ZONE_SEGMENT_HEADER);
- break;
- }
-
- // typical NT methodology (at least until *someone* exposed the "difference" between a server and workstation ;-)
- if (MmIsThisAnNtAsSystem()) {
- SizeOfObjectNameZone *= EXT2_NTAS_MULTIPLE;
- SizeOfCCBZone *= EXT2_NTAS_MULTIPLE;
- SizeOfFCBZone *= EXT2_NTAS_MULTIPLE;
- SizeOfByteLockZone *= EXT2_NTAS_MULTIPLE;
- SizeOfIrpContextZone *= EXT2_NTAS_MULTIPLE;
- }
-
- // allocate memory for each of the zones and initialize the zones ...
- if (!(Ext2GlobalData.ObjectNameZone = Ext2AllocatePool(NonPagedPool, SizeOfObjectNameZone ))) {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- if (!(Ext2GlobalData.CCBZone = Ext2AllocatePool(NonPagedPool, SizeOfCCBZone ))) {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- if (!(Ext2GlobalData.FCBZone = Ext2AllocatePool(NonPagedPool, SizeOfFCBZone ))) {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- if (!(Ext2GlobalData.ByteLockZone = Ext2AllocatePool(NonPagedPool, SizeOfByteLockZone ))) {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- if (!(Ext2GlobalData.IrpContextZone = Ext2AllocatePool(NonPagedPool, SizeOfIrpContextZone ))) {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- // initialize each of the zone headers ...
- if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.ObjectNameZoneHeader),
- Ext2QuadAlign(sizeof(Ext2ObjectName)),
- Ext2GlobalData.ObjectNameZone, SizeOfObjectNameZone))) {
- // failed the initialization, leave ...
- try_return();
- }
-
- if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.CCBZoneHeader),
- Ext2QuadAlign(sizeof(Ext2CCB)),
- Ext2GlobalData.CCBZone,
- SizeOfCCBZone))) {
- // failed the initialization, leave ...
- try_return();
- }
-
- if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.FCBZoneHeader),
- Ext2QuadAlign(sizeof(Ext2FCB)),
- Ext2GlobalData.FCBZone,
- SizeOfFCBZone))) {
- // failed the initialization, leave ...
- try_return();
- }
-
- if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.ByteLockZoneHeader),
- Ext2QuadAlign(sizeof(Ext2FileLockInfo)),
- Ext2GlobalData.ByteLockZone,
- SizeOfByteLockZone))) {
- // failed the initialization, leave ...
- try_return();
- }
-
- if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.IrpContextZoneHeader),
- Ext2QuadAlign(sizeof(Ext2IrpContext)),
- Ext2GlobalData.IrpContextZone,
- SizeOfIrpContextZone))) {
- // failed the initialization, leave ...
- try_return();
- }
-
- try_exit: NOTHING;
-
- } finally {
- if (!NT_SUCCESS(RC)) {
- // invoke the destroy routine now ...
- Ext2DestroyZones();
- } else {
- // mark the fact that we have allocated zones ...
- Ext2SetFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_ZONES_INITIALIZED);
- }
- }
-
- return(RC);
-}
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: misc.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+/* INCLUDES *****************************************************************/
-/*************************************************************************
-*
-* Function: Ext2DestroyZones()
-*
-* Description:
-* Free up the previously allocated memory. NEVER do this once the
-* driver has been successfully loaded.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2DestroyZones(
-void)
-{
- try {
- // free up each of the pools
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.ObjectNameZone);
- ExFreePool(Ext2GlobalData.ObjectNameZone);
-
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.CCBZone);
- ExFreePool(Ext2GlobalData.CCBZone);
-
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.FCBZone);
- ExFreePool(Ext2GlobalData.FCBZone);
-
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.ByteLockZone);
- ExFreePool(Ext2GlobalData.ByteLockZone);
-
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.IrpContextZone);
- ExFreePool(Ext2GlobalData.IrpContextZone);
- }
- finally
- {
- Ext2ClearFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_ZONES_INITIALIZED);
- }
-
- return;
-}
+#include "ext2fs.h"
+/* GLOBALS ***************************************************************/
-/*************************************************************************
-*
-* Function: Ext2IsIrpTopLevel()
-*
-* Description:
-* Helps the FSD determine who the "top level" caller is for this
-* request. A request can originate directly from a user process
-* (in which case, the "top level" will be NULL when this routine
-* is invoked), OR the user may have originated either from the NT
-* Cache Manager/VMM ("top level" may be set), or this could be a
-* recursion into our code in which we would have set the "top level"
-* field the last time around.
-*
-* Expected Interrupt Level (for execution) :
-*
-* whatever level a particular dispatch routine is invoked at.
-*
-* Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked)
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2IsIrpTopLevel(
-PIRP Irp) // the IRP sent to our dispatch routine
-{
- BOOLEAN ReturnCode = FALSE;
-
- if (IoGetTopLevelIrp() == NULL)
- {
- // OK, so we can set ourselves to become the "top level" component
- IoSetTopLevelIrp( Irp );
- ReturnCode = TRUE;
- }
+extern PEXT2_GLOBAL Ext2Global;
- return(ReturnCode);
-}
+/* DEFINITIONS *************************************************************/
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2Sleep)
+#endif
-/*************************************************************************
-*
-* Function: Ext2ExceptionFilter()
-*
-* Description:
-* This routines allows the driver to determine whether the exception
-* is an "allowed" exception i.e. one we should not-so-quietly consume
-* ourselves, or one which should be propagated onwards in which case
-* we will most likely bring down the machine.
-*
-* This routine employs the services of FsRtlIsNtstatusExpected(). This
-* routine returns a BOOLEAN result. A RC of FALSE will cause us to return
-* EXCEPTION_CONTINUE_SEARCH which will probably cause a panic.
-* The FsRtl.. routine returns FALSE iff exception values are (currently) :
-* STATUS_DATATYPE_MISALIGNMENT || STATUS_ACCESS_VIOLATION ||
-* STATUS_ILLEGAL_INSTRUCTION || STATUS_INSTRUCTION_MISALIGNMENT
-*
-* Expected Interrupt Level (for execution) :
-*
-* ?
-*
-* Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH
-*
-*************************************************************************/
-long NTAPI Ext2ExceptionFilter(
-PtrExt2IrpContext PtrIrpContext,
-PEXCEPTION_POINTERS PtrExceptionPointers )
+ULONG
+Ext2Log2(ULONG Value)
{
- long ReturnCode = EXCEPTION_EXECUTE_HANDLER;
- NTSTATUS ExceptionCode = STATUS_SUCCESS;
-
- // figure out the exception code
- ExceptionCode = PtrExceptionPointers->ExceptionRecord->ExceptionCode;
-
- if ((ExceptionCode == STATUS_IN_PAGE_ERROR) && (PtrExceptionPointers->ExceptionRecord->NumberParameters >= 3))
- {
- ExceptionCode = PtrExceptionPointers->ExceptionRecord->ExceptionInformation[2];
- }
-
- if (PtrIrpContext)
- {
- PtrIrpContext->SavedExceptionCode = ExceptionCode;
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_EXCEPTION);
- }
-
- // check if we should propagate this exception or not
- if (!(FsRtlIsNtstatusExpected(ExceptionCode)))
- {
- // we are not ok, propagate this exception.
- // NOTE: we will bring down the machine ...
- ReturnCode = EXCEPTION_CONTINUE_SEARCH;
-
- // better free up the IrpContext now ...
- if (PtrIrpContext)
- {
- Ext2ReleaseIrpContext(PtrIrpContext);
- }
- }
-
- // if you wish to perform some special processing when
- // not propagating the exception, set up the state for
- // special processing now ...
-
- // return the appropriate code
- return(ReturnCode);
+ ULONG Order = 0;
+
+ ASSERT(Value > 0);
+
+ while (Value) {
+ Order++;
+ Value >>= 1;
+ }
+
+ return (Order - 1);
}
-/*************************************************************************
-*
-* Function: Ext2ExceptionHandler()
-*
-* Description:
-* One of the routines in the FSD or in the modules we invoked encountered
-* an exception. We have decided that we will "handle" the exception.
-* Therefore we will prevent the machine from a panic ...
-* You can do pretty much anything you choose to in your commercial
-* driver at this point to ensure a graceful exit. In the sample
-* driver, I will simply free up the IrpContext (if any), set the
-* error code in the IRP and complete the IRP at this time ...
-*
-* Expected Interrupt Level (for execution) :
-*
-* ?
-*
-* Return Value: Error code
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2ExceptionHandler(
-PtrExt2IrpContext PtrIrpContext,
-PIRP Irp)
+LARGE_INTEGER
+Ext2NtTime (IN ULONG i_time)
{
- NTSTATUS RC;
-
- ASSERT(Irp);
-
- if (PtrIrpContext)
- {
- RC = PtrIrpContext->SavedExceptionCode;
- // Free irp context here
- Ext2ReleaseIrpContext(PtrIrpContext);
- }
- else
- {
- // must be insufficient resources ...?
- RC = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- // set the error code in the IRP
- Irp->IoStatus.Status = RC;
- Irp->IoStatus.Information = 0;
-
- // complete the IRP
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(RC);
+ LARGE_INTEGER SysTime;
+
+ SysTime.QuadPart = 0;
+ RtlSecondsSince1970ToTime(i_time, &SysTime);
+
+ return SysTime;
}
-/*************************************************************************
-*
-* Function: Ext2LogEvent()
-*
-* Description:
-* Log a message in the NT Event Log. This is a rather simplistic log
-* methodology since you can potentially utilize the event log to
-* provide a lot of information to the user (and you should too!)
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2LogEvent(
-NTSTATUS Ext2EventLogId, // the Ext2 private message id
-NTSTATUS RC) // any NT error code we wish to log ...
+ULONG
+Ext2LinuxTime (IN LARGE_INTEGER SysTime)
{
- try
- {
-
- // Implement a call to IoAllocateErrorLogEntry() followed by a call
- // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry()
- // will free memory for the entry once the write completes (which in actuality
- // is an asynchronous operation).
-
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- // nothing really we can do here, just do not wish to crash ...
- NOTHING;
- }
-
- return;
+ ULONG Ext2Time = 0;
+
+ if (!RtlTimeToSecondsSince1970(&SysTime, &Ext2Time)) {
+ LARGE_INTEGER NtTime;
+ KeQuerySystemTime(&NtTime);
+ RtlTimeToSecondsSince1970(&NtTime, &Ext2Time);
+ }
+
+ return Ext2Time;
}
-/*************************************************************************
-*
-* Function: Ext2AllocateObjectName()
-*
-* Description:
-* Allocate a new ObjectName structure to represent an open on-disk object.
-* Also initialize the ObjectName structure to NULL.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the ObjectName structure OR NULL.
-*
-*************************************************************************/
-PtrExt2ObjectName NTAPI Ext2AllocateObjectName(
-void)
+
+ULONG
+Ext2MbsToUnicode(
+ struct nls_table * PageTable,
+ IN OUT PUNICODE_STRING Unicode,
+ IN PANSI_STRING Mbs )
{
- PtrExt2ObjectName PtrObjectName = NULL;
- BOOLEAN AllocatedFromZone = TRUE;
- //KIRQL CurrentIrql;
-/*
- // first, try to allocate out of the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- if (!ExIsFullZone(&(Ext2GlobalData.ObjectNameZoneHeader))) {
- // we have enough memory
- PtrObjectName = (PtrExt2ObjectName)ExAllocateFromZone(&(Ext2GlobalData.ObjectNameZoneHeader));
-
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- } else {
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
-
- // if we failed to obtain from the zone, get it directly from the VMM
-*/
- PtrObjectName = (PtrExt2ObjectName)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2ObjectName)) );
- AllocatedFromZone = FALSE;
-/*
- }
-*/
- // if we could not obtain the required memory, bug-check.
- // Do NOT do this in your commercial driver, instead handle the error gracefully ...
- if (!PtrObjectName)
- {
- Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2ObjectName)), 0);
- }
+ ULONG Length = 0;
+ int i, mbc = 0;
+ WCHAR uc;
- // zero out the allocated memory block
- RtlZeroMemory( PtrObjectName, Ext2QuadAlign(sizeof(Ext2ObjectName)) );
+ /* Count the length of the resulting Unicode. */
+ for (i = 0; i < Mbs->Length; i += mbc) {
- // set up some fields ...
- PtrObjectName->NodeIdentifier.NodeType = EXT2_NODE_TYPE_OBJECT_NAME;
- PtrObjectName->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2ObjectName));
+ mbc = PageTable->char2uni(
+ (PUCHAR)&(Mbs->Buffer[i]),
+ Mbs->Length - i,
+ &uc
+ );
+ if (mbc <= 0) {
- if (!AllocatedFromZone)
- {
- Ext2SetFlag(PtrObjectName->ObjectNameFlags, EXT2_OB_NAME_NOT_FROM_ZONE);
- }
+ /* invalid character. */
+ if (mbc == 0 && Length > 0) {
+ break;
+ }
+ return 0;
+ }
- return(PtrObjectName);
-}
+ Length += 2;
+ }
+ if (Unicode) {
+ if (Unicode->MaximumLength < Length) {
-/*************************************************************************
-*
-* Function: Ext2ReleaseObjectName()
-*
-* Description:
-* Deallocate a previously allocated structure.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2ReleaseObjectName(
-PtrExt2ObjectName PtrObjectName)
-{
-#ifdef USE_ZONES
- KIRQL CurrentIrql;
-#endif
+ DbgBreak();
+ return 0;
+ }
- ASSERT(PtrObjectName);
- PtrObjectName->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED;
-#ifdef USE_ZONES
-
- // give back memory either to the zone or to the VMM
- if (!(PtrObjectName->ObjectNameFlags & EXT2_OB_NAME_NOT_FROM_ZONE))
- {
- // back to the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- ExFreeToZone(&(Ext2GlobalData.ObjectNameZoneHeader), PtrObjectName);
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
-#endif
-
- Ext2DeallocateUnicodeString( & PtrObjectName->ObjectName );
+ Unicode->Length = 0;
+ mbc = 0;
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrObjectName);
- ExFreePool(PtrObjectName);
+ for (i = 0; i < Mbs->Length; i += mbc) {
-#ifdef USE_ZONES
- }
-#endif
- return;
+ mbc = PageTable->char2uni(
+ (PUCHAR)&(Mbs->Buffer[i]),
+ Mbs->Length - i,
+ &uc
+ );
+ Unicode->Buffer[Unicode->Length/2] = uc;
+ Unicode->Length += 2;
+ }
+ }
+
+ return Length;
}
-/*************************************************************************
-*
-* Function: Ext2AllocateCCB()
-*
-* Description:
-* Allocate a new CCB structure to represent an open on-disk object.
-* Also initialize the CCB structure to NULL.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the CCB structure OR NULL.
-*
-*************************************************************************/
-PtrExt2CCB NTAPI Ext2AllocateCCB(
-void)
+ULONG
+Ext2UnicodeToMbs (
+ struct nls_table * PageTable,
+ IN OUT PANSI_STRING Mbs,
+ IN PUNICODE_STRING Unicode)
{
- PtrExt2CCB PtrCCB = NULL;
- BOOLEAN AllocatedFromZone = TRUE;
-#ifdef USE_ZONES
- KIRQL CurrentIrql;
-#endif
+ ULONG Length = 0;
+ UCHAR mbs[0x10];
+ int i, mbc;
+ /* Count the length of the resulting mbc-8. */
+ for (i = 0; i < (Unicode->Length / 2); i++) {
-#ifdef USE_ZONES
- // first, try to allocate out of the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- if (!ExIsFullZone(&(Ext2GlobalData.CCBZoneHeader)))
- {
- // we have enough memory
- PtrCCB = (PtrExt2CCB)ExAllocateFromZone(&(Ext2GlobalData.CCBZoneHeader));
-
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- // if we failed to obtain from the zone, get it directly from the VMM
-#endif
+ RtlZeroMemory(mbs, 0x10);
+ mbc = PageTable->uni2char(
+ Unicode->Buffer[i],
+ mbs,
+ 0x10
+ );
- PtrCCB = (PtrExt2CCB)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2CCB)) );
- AllocatedFromZone = FALSE;
+ if (mbc <= 0) {
-#ifdef USE_ZONES
- }
-#endif
+ /* Invalid character. */
+ return 0;
+ }
+
+ Length += mbc;
+ }
+
+ if (Mbs) {
+
+ if (Mbs->MaximumLength < Length) {
+
+ DbgBreak();
+ return 0;
+ }
- // if we could not obtain the required memory, bug-check.
- // Do NOT do this in your commercial driver, instead handle the error gracefully ...
- if (!PtrCCB)
- {
- Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2CCB)), 0);
- }
+ Mbs->Length = 0;
- // zero out the allocated memory block
- RtlZeroMemory(PtrCCB, Ext2QuadAlign(sizeof(Ext2CCB)));
+ for (i = 0; i < (Unicode->Length / 2); i++) {
- // set up some fields ...
- PtrCCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_CCB;
- PtrCCB->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2CCB));
+ mbc = PageTable->uni2char(
+ Unicode->Buffer[i],
+ mbs,
+ 0x10
+ );
+ RtlCopyMemory(
+ (PUCHAR)&(Mbs->Buffer[Mbs->Length]),
+ &mbs[0],
+ mbc
+ );
- if (!AllocatedFromZone)
- {
- Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_NOT_FROM_ZONE);
- }
+ Mbs->Length += (USHORT)mbc;
+ }
+ }
- return(PtrCCB);
+ return Length;
}
-/*************************************************************************
-*
-* Function: Ext2ReleaseCCB()
-*
-* Description:
-* Deallocate a previously allocated structure.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2ReleaseCCB(
-PtrExt2CCB PtrCCB)
+
+ULONG
+Ext2OEMToUnicodeSize(
+ IN PEXT2_VCB Vcb,
+ IN PANSI_STRING Oem
+)
{
-#ifdef USE_ZONES
- KIRQL CurrentIrql;
-#endif
+ ULONG Length = 0;
- ASSERT( PtrCCB );
- if(PtrCCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_CCB)
- {
- Ext2Panic( PtrCCB, PtrCCB->NodeIdentifier.NodeType, EXT2_NODE_TYPE_CCB ) ;
- }
-
- Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
- Ext2DeallocateUnicodeString( &PtrCCB->AbsolutePathName );
- Ext2DeallocateUnicodeString( &PtrCCB->RenameLinkTargetFileName );
-
-
-#ifdef USE_ZONES
-
- // give back memory either to the zone or to the VMM
- if (!(PtrCCB->CCBFlags & EXT2_CCB_NOT_FROM_ZONE))
- {
- // back to the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- ExFreeToZone(&(Ext2GlobalData.CCBZoneHeader), PtrCCB);
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
-#endif
- PtrCCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED;
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrCCB);
- ExFreePool(PtrCCB);
+ if (Vcb->Codepage.PageTable) {
+ Length = Ext2MbsToUnicode(Vcb->Codepage.PageTable, NULL, Oem);
+ if (Length > 0) {
+ goto errorout;
+ }
+ }
-#ifdef USE_ZONES
- }
-#endif
+ Length = RtlOemStringToCountedUnicodeSize(Oem);
+
+errorout:
- return;
+ return Length;
}
-/*************************************************************************
-*
-* Function: Ext2AllocateFCB()
-*
-* Description:
-* Allocate a new FCB structure to represent an open on-disk object.
-* Also initialize the FCB structure to NULL.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the FCB structure OR NULL.
-*
-*************************************************************************/
-PtrExt2FCB NTAPI Ext2AllocateFCB(
-void)
+
+NTSTATUS
+Ext2OEMToUnicode(
+ IN PEXT2_VCB Vcb,
+ IN OUT PUNICODE_STRING Unicode,
+ IN POEM_STRING Oem
+)
{
- PtrExt2FCB PtrFCB = NULL;
- BOOLEAN AllocatedFromZone = TRUE;
-#ifdef USE_ZONES
- KIRQL CurrentIrql;
-#endif
+ NTSTATUS Status;
- // first, try to allocate out of the zone
-#ifdef USE_ZONES
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- if (!ExIsFullZone(&(Ext2GlobalData.FCBZoneHeader))) {
- // we have enough memory
- PtrFCB = (PtrExt2FCB)ExAllocateFromZone(&(Ext2GlobalData.FCBZoneHeader));
+ if (Vcb->Codepage.PageTable) {
+ Status = Ext2MbsToUnicode(Vcb->Codepage.PageTable,
+ Unicode, Oem);
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- } else {
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
-#endif
- // if we failed to obtain from the zone, get it directly from the VMM
- PtrFCB = (PtrExt2FCB)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2FCB)) );
- AllocatedFromZone = FALSE;
+ if (Status >0 && Status == Unicode->Length) {
+ Status = STATUS_SUCCESS;
+ goto errorout;
+ }
+ }
-#ifdef USE_ZONES
- }
-#endif
+ Status = RtlOemStringToUnicodeString(
+ Unicode, Oem, FALSE );
- // if we could not obtain the required memory, bug-check.
- // Do NOT do this in your commercial driver, instead handle the error gracefully ...
- if (!PtrFCB)
- {
- Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2FCB)), 0);
- }
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ goto errorout;
+ }
+
+errorout:
- // zero out the allocated memory block
- RtlZeroMemory(PtrFCB, Ext2QuadAlign(sizeof(Ext2FCB)));
+ return Status;
+}
- // set up some fields ...
- PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FCB;
- PtrFCB->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2FCB));
+ULONG
+Ext2UnicodeToOEMSize(
+ IN PEXT2_VCB Vcb,
+ IN PUNICODE_STRING Unicode
+)
+{
+ ULONG Length = 0;
+ if (Vcb->Codepage.PageTable) {
+ Length = Ext2UnicodeToMbs(Vcb->Codepage.PageTable,
+ NULL, Unicode);
+ if (Length > 0) {
+ return Length;
+ }
- if (!AllocatedFromZone)
- {
- Ext2SetFlag(PtrFCB->FCBFlags, EXT2_FCB_NOT_FROM_ZONE);
- }
+ DbgBreak();
+ }
- return(PtrFCB);
+ return RtlxUnicodeStringToOemSize(Unicode);
}
-/*************************************************************************
-*
-* Function: Ext2CreateNewFCB()
-*
-* Description:
-* We want to create a new FCB. We will also create a new CCB (presumably)
-* later. Simply allocate a new FCB structure and initialize fields
-* appropriately.
-* This function also takes the file size values that the caller must
-* have obtained and will set the file size fields appropriately in the
-* CommonFCBHeader.
-* Finally, this routine will initialize the FileObject structure passed
-* in to this function. If you decide to fail the call later, remember
-* to uninitialize the fields.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the FCB structure OR NULL.
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CreateNewFCB(
-PtrExt2FCB *ReturnedFCB,
-LARGE_INTEGER AllocationSize,
-LARGE_INTEGER EndOfFile,
-PFILE_OBJECT PtrFileObject,
-PtrExt2VCB PtrVCB,
-PtrExt2ObjectName PtrObjectName)
+NTSTATUS
+Ext2UnicodeToOEM (
+ IN PEXT2_VCB Vcb,
+ IN OUT POEM_STRING Oem,
+ IN PUNICODE_STRING Unicode)
{
- NTSTATUS RC = STATUS_SUCCESS;
-
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader = NULL;
-
- ASSERT( PtrVCB );
-
- try
- {
- if( !PtrFileObject )
- {
- PtrFCB = Ext2GetUsedFCB( PtrVCB );
-
- }
- else
- {
- // Obtain a new FCB structure.
- // The function Ext2AllocateFCB() will obtain a new structure either
- // from a zone or from memory requested directly from the VMM.
- PtrFCB = Ext2AllocateFCB();
- }
- if (!PtrFCB)
- {
- // Assume lack of memory.
- try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
- }
-
- // Initialize fields required to interface with the NT Cache Manager.
- // Note that the returned structure has already been zeroed. This means
- // that the SectionObject structure has been zeroed which is a
- // requirement for newly created FCB structures.
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- // Initialize the MainResource and PagingIoResource structures now.
- ExInitializeResourceLite(&(PtrReqdFCB->MainResource));
- Ext2SetFlag(PtrFCB->FCBFlags, EXT2_INITIALIZED_MAIN_RESOURCE);
-
- ExInitializeResourceLite(&(PtrReqdFCB->PagingIoResource));
- Ext2SetFlag(PtrFCB->FCBFlags, EXT2_INITIALIZED_PAGING_IO_RESOURCE);
-
- // Start initializing the fields contained in the CommonFCBHeader.
- PtrCommonFCBHeader = &(PtrReqdFCB->CommonFCBHeader);
-
- // Disallow fast-IO for now.
- PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible;
-
- // Initialize the MainResource and PagingIoResource pointers in
- // the CommonFCBHeader structure to point to the ERESOURCE structures we
- // have allocated and already initialized above.
- PtrCommonFCBHeader->Resource = &(PtrReqdFCB->MainResource);
- PtrCommonFCBHeader->PagingIoResource = &(PtrReqdFCB->PagingIoResource);
-
- // Ignore the Flags field in the CommonFCBHeader for now. Part 3
- // of the book describes it in greater detail.
-
- // Initialize the file size values here.
- PtrCommonFCBHeader->AllocationSize = AllocationSize;
- PtrCommonFCBHeader->FileSize = EndOfFile;
-
- // The following will disable ValidDataLength support. However, your
- // FSD may choose to support this concept.
- PtrCommonFCBHeader->ValidDataLength.LowPart = 0xFFFFFFFF;
- PtrCommonFCBHeader->ValidDataLength.HighPart = 0x7FFFFFFF;
-
- // Initialize other fields for the FCB here ...
- PtrFCB->PtrVCB = PtrVCB;
-
- // caller MUST ensure that VCB has been acquired exclusively
- InsertTailList(&(PtrVCB->FCBListHead), &(PtrFCB->NextFCB));
-
-
- InitializeListHead(&(PtrFCB->CCBListHead));
-
- // Initialize fields contained in the file object now.
- if( PtrFileObject )
- {
- PtrFileObject->PrivateCacheMap = NULL;
- // Note that we could have just as well taken the value of PtrReqdFCB
- // directly below. The bottom line however is that the FsContext
- // field must point to a FSRTL_COMMON_FCB_HEADER structure.
- PtrFileObject->FsContext = (void *)(PtrCommonFCBHeader);
- PtrFileObject->SectionObjectPointer = &(PtrFCB->NTRequiredFCB.SectionObject) ;
- }
-
- // Initialising the object name...
- PtrFCB->FCBName = PtrObjectName;
-
- // Returning the FCB...
- *ReturnedFCB = PtrFCB;
- try_exit: NOTHING;
- }
-
- finally
- {
-
- }
-
- return(RC);
-}
+ NTSTATUS Status;
+ if (Vcb->Codepage.PageTable) {
-/*************************************************************************
-*
-* Function: Ext2ReleaseFCB()
-*
-* Description:
-* Deallocate a previously allocated structure.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2ReleaseFCB(
-PtrExt2FCB PtrFCB)
-{
- //KIRQL CurrentIrql;
-
- AssertFCB( PtrFCB );
-
- if( PtrFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB )
- {
- Ext2Panic( PtrFCB, PtrFCB->NodeIdentifier.NodeType, EXT2_NODE_TYPE_FCB ) ;
- }
-
-
- PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED;
-
- /*
- // give back memory either to the zone or to the VMM
- if (!(PtrFCB->FCBFlags & EXT2_FCB_NOT_FROM_ZONE))
- {
- // back to the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- ExFreeToZone(&(Ext2GlobalData.FCBZoneHeader), PtrFCB);
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
- */
-
- ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.MainResource );
- ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.PagingIoResource );
-
- RemoveEntryList(&(PtrFCB->NextFCB));
-
- if( PtrFCB->FCBName )
- {
- Ext2ReleaseObjectName( PtrFCB->FCBName );
- }
-
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrFCB);
- ExFreePool(PtrFCB);
-
- /*
- }
- */
-
- return;
+ Status = Ext2UnicodeToMbs(Vcb->Codepage.PageTable,
+ Oem, Unicode);
+ if (Status > 0 && Status == Oem->Length) {
+ Status = STATUS_SUCCESS;
+ } else {
+ Status = STATUS_UNSUCCESSFUL;
+ DbgBreak();
+ }
+
+ goto errorout;
+ }
+
+ Status = RtlUnicodeStringToOemString(
+ Oem, Unicode, FALSE );
+
+ if (!NT_SUCCESS(Status))
+ {
+ DbgBreak();
+ goto errorout;
+ }
+
+errorout:
+
+ return Status;
}
-/*************************************************************************
-*
-* Function: Ext2AllocateByteLocks()
-*
-* Description:
-* Allocate a new byte range lock structure and initialize it to NULL.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the Ext2ByteLocks structure OR NULL.
-*
-*************************************************************************/
-PtrExt2FileLockInfo NTAPI Ext2AllocateByteLocks(
-void)
+VOID
+Ext2Sleep(ULONG ms)
{
- PtrExt2FileLockInfo PtrByteLocks = NULL;
- BOOLEAN AllocatedFromZone = TRUE;
- KIRQL CurrentIrql;
-
- // first, try to allocate out of the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- if (!ExIsFullZone(&(Ext2GlobalData.ByteLockZoneHeader)))
- {
- // we have enough memory
- PtrByteLocks = (PtrExt2FileLockInfo)ExAllocateFromZone(&(Ext2GlobalData.ByteLockZoneHeader));
-
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
-
- // if we failed to obtain from the zone, get it directly from the VMM
- PtrByteLocks = (PtrExt2FileLockInfo)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2FileLockInfo)) );
- AllocatedFromZone = FALSE;
- }
-
- // if we could not obtain the required memory, bug-check.
- // Do NOT do this in your commercial driver, instead handle the error gracefully ...
- if (!PtrByteLocks)
- {
- Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2FileLockInfo)), 0);
- }
-
- // zero out the allocated memory block
- RtlZeroMemory(PtrByteLocks, Ext2QuadAlign(sizeof(PtrExt2FileLockInfo)));
-
- if (!AllocatedFromZone)
- {
- Ext2SetFlag(PtrByteLocks->FileLockFlags, EXT2_BYTE_LOCK_NOT_FROM_ZONE);
- }
-
- return(PtrByteLocks);
+ LARGE_INTEGER Timeout;
+ Timeout.QuadPart = (LONGLONG)ms*1000*(-10); /* ms/1000 sec*/
+ KeDelayExecutionThread(KernelMode, TRUE, &Timeout);
}
-/*************************************************************************
-*
-* Function: Ext2ReleaseByteLocks()
-*
-* Description:
-* Deallocate a previously allocated structure.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2ReleaseByteLocks(
-PtrExt2FileLockInfo PtrByteLocks)
+int Ext2LinuxError (NTSTATUS Status)
{
- KIRQL CurrentIrql;
-
- ASSERT(PtrByteLocks);
-
- // give back memory either to the zone or to the VMM
- if (!(PtrByteLocks->FileLockFlags & EXT2_BYTE_LOCK_NOT_FROM_ZONE)) {
- // back to the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- ExFreeToZone(&(Ext2GlobalData.ByteLockZoneHeader), PtrByteLocks);
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrByteLocks);
- ExFreePool(PtrByteLocks);
- }
-
- return;
-}
+ switch (Status) {
+ case STATUS_ACCESS_DENIED:
+ return (-EACCES);
+ case STATUS_ACCESS_VIOLATION:
+ return (-EFAULT);
-/*************************************************************************
-*
-* Function: Ext2AllocateIrpContext()
-*
-* Description:
-* The sample FSD creates an IRP context for each request received. This
-* routine simply allocates (and initializes to NULL) a Ext2IrpContext
-* structure.
-* Most of the fields in the context structure are then initialized here.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the IrpContext structure OR NULL.
-*
-*************************************************************************/
-PtrExt2IrpContext NTAPI Ext2AllocateIrpContext(
-PIRP Irp,
-PDEVICE_OBJECT PtrTargetDeviceObject)
-{
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AllocatedFromZone = TRUE;
- //KIRQL CurrentIrql;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
-
- /*
- // Allocation from zone not done at present...
-
- // first, try to allocate out of the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- if (!ExIsFullZone(&(Ext2GlobalData.IrpContextZoneHeader))) {
- // we have enough memory
- PtrIrpContext = (PtrExt2IrpContext)ExAllocateFromZone(&(Ext2GlobalData.IrpContextZoneHeader));
-
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- } else {
- // release the spinlock
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
-
-
-
-
- // if we failed to obtain from the zone, get it directly from the VMM
- PtrIrpContext = (PtrExt2IrpContext)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2IrpContext)) );
- AllocatedFromZone = FALSE;
- }
-
- //No Zone handling for now
- */
-
- PtrIrpContext = (PtrExt2IrpContext)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2IrpContext)) );
- AllocatedFromZone = FALSE;
-
- // if we could not obtain the required memory, bug-check.
- // Do NOT do this in your commercial driver, instead handle the error gracefully ...
- if (!PtrIrpContext)
- {
- Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2IrpContext)), 0);
- }
-
- // zero out the allocated memory block
- RtlZeroMemory(PtrIrpContext, Ext2QuadAlign(sizeof(Ext2IrpContext)));
-
- // set up some fields ...
- PtrIrpContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IRP_CONTEXT;
- PtrIrpContext->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2IrpContext));
-
-
- PtrIrpContext->Irp = Irp;
- PtrIrpContext->TargetDeviceObject = PtrTargetDeviceObject;
-
- // copy over some fields from the IRP and set appropriate flag values
- if (Irp)
- {
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(Irp);
- ASSERT(PtrIoStackLocation);
-
- PtrIrpContext->MajorFunction = PtrIoStackLocation->MajorFunction;
- PtrIrpContext->MinorFunction = PtrIoStackLocation->MinorFunction;
-
- // Often, a FSD cannot honor a request for asynchronous processing
- // of certain critical requests. For example, a "close" request on
- // a file object can typically never be deferred. Therefore, do not
- // be surprised if sometimes your FSD (just like all other FSD
- // implementations on the Windows NT system) has to override the flag
- // below.
- if( PtrIoStackLocation->FileObject )
- {
- if (IoIsOperationSynchronous(Irp) )
- {
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_CAN_BLOCK);
- }
- }
- else
- {
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_CAN_BLOCK);
- }
- }
-
- if (!AllocatedFromZone)
- {
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_NOT_FROM_ZONE);
- }
-
- // Are we top-level ? This information is used by the dispatching code
- // later (and also by the FSD dispatch routine)
- if (IoGetTopLevelIrp() != Irp)
- {
- // We are not top-level. Note this fact in the context structure
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_NOT_TOP_LEVEL);
- }
-
- InitializeListHead( &PtrIrpContext->SavedBCBsListHead );
-
- return(PtrIrpContext);
-}
+ case STATUS_BUFFER_TOO_SMALL:
+ return (-ETOOSMALL);
+ case STATUS_INVALID_PARAMETER:
+ return (-EINVAL);
-/*************************************************************************
-*
-* Function: Ext2ReleaseIrpContext()
-*
-* Description:
-* Deallocate a previously allocated structure.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2ReleaseIrpContext(
-PtrExt2IrpContext PtrIrpContext)
-{
- KIRQL CurrentIrql;
-
- ASSERT(PtrIrpContext);
-
- // Flush the saved BCBs...
- Ext2FlushSavedBCBs( PtrIrpContext );
-
- // give back memory either to the zone or to the VMM
- if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_NOT_FROM_ZONE))
- {
- // back to the zone
- KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
- ExFreeToZone(&(Ext2GlobalData.IrpContextZoneHeader), PtrIrpContext);
- KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
- }
- else
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrIrpContext);
- ExFreePool(PtrIrpContext);
- }
-
- return;
-}
+ case STATUS_NOT_IMPLEMENTED:
+ case STATUS_NOT_SUPPORTED:
+ return (-EOPNOTSUPP);
-/*************************************************************************
-*
-* Function: Ext2PostRequest()
-*
-* Description:
-* Queue up a request for deferred processing (in the context of a system
-* worker thread). The caller must have locked the user buffer (if required)
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_PENDING
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2PostRequest(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp)
-{
- NTSTATUS RC = STATUS_PENDING;
-
- DebugTrace(DEBUG_TRACE_ASYNC, " === Asynchronous request. Deferring processing", 0);
-
- // mark the IRP pending
- IoMarkIrpPending(PtrIrp);
-
- // queue up the request
- ExInterlockedInsertTailList(
- &Ext2GlobalData.ThreadQueue.ThreadQueueListHead,
- &PtrIrpContext->ThreadQueueListEntry,
- &Ext2GlobalData.ThreadQueue.SpinLock );
-
- KeSetEvent( &Ext2GlobalData.ThreadQueue.QueueEvent, 0, FALSE );
-
-
-/***************** not using system worker threads *****************
- ExInitializeWorkItem(&(PtrIrpContext->WorkQueueItem), Ext2CommonDispatch, PtrIrpContext);
- ExQueueWorkItem( &( PtrIrpContext->WorkQueueItem ), DelayedWorkQueue );
- // CriticalWorkQueue
-*****************************************************************************/
-
- // return status pending
- return(RC);
-}
+ case STATUS_INVALID_ADDRESS:
+ case STATUS_INVALID_ADDRESS_COMPONENT:
+ return (-EADDRNOTAVAIL);
+ case STATUS_NO_SUCH_DEVICE:
+ case STATUS_NO_SUCH_FILE:
+ case STATUS_OBJECT_NAME_NOT_FOUND:
+ case STATUS_OBJECT_PATH_NOT_FOUND:
+ case STATUS_NETWORK_BUSY:
+ case STATUS_INVALID_NETWORK_RESPONSE:
+ case STATUS_UNEXPECTED_NETWORK_ERROR:
+ return (-ENETDOWN);
-/*************************************************************************
-*
-* Function: Ext2CommonDispatch()
-*
-* Description:
-* The common dispatch routine invoked in the context of a system worker
-* thread. All we do here is pretty much case off the major function
-* code and invoke the appropriate FSD dispatch routine for further
-* processing.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2CommonDispatch(
- void *Context ) // actually an IRPContext structure
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- PIRP PtrIrp = NULL;
-
- // The context must be a pointer to an IrpContext structure
- PtrIrpContext = (PtrExt2IrpContext)Context;
- ASSERT(PtrIrpContext);
-
- // Assert that the Context is legitimate
- if ((PtrIrpContext->NodeIdentifier.NodeType != EXT2_NODE_TYPE_IRP_CONTEXT) || (PtrIrpContext->NodeIdentifier.NodeSize != Ext2QuadAlign(sizeof(Ext2IrpContext))))
- {
- // This does not look good
- Ext2Panic(EXT2_ERROR_INTERNAL_ERROR, PtrIrpContext->NodeIdentifier.NodeType, PtrIrpContext->NodeIdentifier.NodeSize);
- }
-
- // Get a pointer to the IRP structure
- PtrIrp = PtrIrpContext->Irp;
- ASSERT(PtrIrp);
-
- // Now, check if the FSD was top level when the IRP was originally invoked
- // and set the thread context (for the worker thread) appropriately
- if (PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_NOT_TOP_LEVEL)
- {
- // The FSD is not top level for the original request
- // Set a constant value in TLS to reflect this fact
- IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
- }
-
- // Since the FSD routine will now be invoked in the context of this worker
- // thread, we should inform the FSD that it is perfectly OK to block in
- // the context of this thread
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_CAN_BLOCK);
-
- FsRtlEnterFileSystem();
-
- try
- {
-
- // Pre-processing has been completed; check the Major Function code value
- // either in the IrpContext (copied from the IRP), or directly from the
- // IRP itself (we will need a pointer to the stack location to do that),
- // Then, switch based on the value on the Major Function code
- switch (PtrIrpContext->MajorFunction)
- {
- case IRP_MJ_CREATE:
- // Invoke the common create routine
- DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_CREATE request asynchronously .", 0);
- (void)Ext2CommonCreate(PtrIrpContext, PtrIrp, FALSE);
- break;
- case IRP_MJ_READ:
- // Invoke the common read routine
- DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_READ request asynchronously .", 0);
- (void)Ext2CommonRead(PtrIrpContext, PtrIrp, FALSE);
- break;
- case IRP_MJ_WRITE:
- // Invoke the common write routine
- DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_WRITE request asynchronously .", 0);
- (void)Ext2CommonWrite(PtrIrpContext, PtrIrp );
- break;
-
- case IRP_MJ_CLEANUP:
- // Invoke the common read routine
- DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_CLEANUP request asynchronously .", 0);
- (void)Ext2CommonCleanup(PtrIrpContext, PtrIrp, FALSE);
- break;
- case IRP_MJ_CLOSE:
- // Invoke the common read routine
- DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_CLOSE request asynchronously .", 0);
- (void)Ext2CommonClose ( PtrIrpContext, PtrIrp, FALSE );
- break;
-
- // Continue with the remaining possible dispatch routines below ...
- default:
- // This is the case where we have an invalid major function
- DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing asynchronous request. \nUnable to recoganise the IRP!!! How can this be!!!", 0);
- PtrIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
- PtrIrp->IoStatus.Information = 0;
-
- Ext2BreakPoint();
-
- IoCompleteRequest(PtrIrp, IO_NO_INCREMENT);
- break;
- }
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, PtrIrp);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
-
- // Enable preemption
- FsRtlExitFileSystem();
-
- // Ensure that the "top-level" field is cleared
- IoSetTopLevelIrp(NULL);
-
- PsTerminateSystemThread( RC );
-
-
- return;
-}
+ case STATUS_BAD_NETWORK_PATH:
+ case STATUS_NETWORK_UNREACHABLE:
+ case STATUS_PROTOCOL_UNREACHABLE:
+ return (-ENETUNREACH);
-/*************************************************************************
-*
-* Function: Ext2InitializeVCB()
-*
-* Description:
-* Perform the initialization for a VCB structure.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2InitializeVCB(
-PDEVICE_OBJECT PtrVolumeDeviceObject,
-PDEVICE_OBJECT PtrTargetDeviceObject,
-PVPB PtrVPB,
-PLARGE_INTEGER AllocationSize )
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2VCB PtrVCB = NULL;
- BOOLEAN VCBResourceInitialized = FALSE;
-
- PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
-
- // Zero it out (typically this has already been done by the I/O
- // Manager but it does not hurt to do it again)!
- RtlZeroMemory(PtrVCB, sizeof(Ext2VCB));
-
- // Initialize the signature fields
- PtrVCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_VCB;
- PtrVCB->NodeIdentifier.NodeSize = sizeof(Ext2VCB);
-
- // Initialize the ERESOURCE objects.
- RC = ExInitializeResourceLite(&(PtrVCB->VCBResource));
- RC = ExInitializeResourceLite(&(PtrVCB->PagingIoResource));
-
- ASSERT(NT_SUCCESS(RC));
- VCBResourceInitialized = TRUE;
-
- PtrVCB->TargetDeviceObject = PtrTargetDeviceObject;
-
- PtrVCB->VCBDeviceObject = PtrVolumeDeviceObject;
-
- PtrVCB->PtrVPB = PtrVPB;
-
- // Initialize the list anchor (head) for some lists in this VCB.
- InitializeListHead(&(PtrVCB->FCBListHead));
- InitializeListHead(&(PtrVCB->NextNotifyIRP));
- InitializeListHead(&(PtrVCB->VolumeOpenListHead));
- InitializeListHead(&(PtrVCB->ClosableFCBs.ClosableFCBListHead));
- PtrVCB->ClosableFCBs.Count = 0;
-
- // Initialize the notify IRP list mutex
- KeInitializeMutex(&(PtrVCB->NotifyIRPMutex), 0);
-
- // Set the initial file size values appropriately. Note that your FSD may
- // wish to guess at the initial amount of information you would like to
- // read from the disk until you have really determined that this a valid
- // logical volume (on disk) that you wish to mount.
- PtrVCB->CommonVCBHeader.AllocationSize.QuadPart = AllocationSize->QuadPart;
-
- PtrVCB->CommonVCBHeader.FileSize.QuadPart = AllocationSize->QuadPart;
- // You typically do not want to bother with valid data length callbacks
- // from the Cache Manager for the file stream opened for volume metadata
- // information
- PtrVCB->CommonVCBHeader.ValidDataLength.LowPart = 0xFFFFFFFF;
- PtrVCB->CommonVCBHeader.ValidDataLength.HighPart = 0x7FFFFFFF;
-
- PtrVCB->CommonVCBHeader.IsFastIoPossible = FastIoIsNotPossible;
-
- PtrVCB->CommonVCBHeader.Resource = &(PtrVCB->VCBResource);
- PtrVCB->CommonVCBHeader.PagingIoResource = &(PtrVCB->PagingIoResource);
-
- // Create a stream file object for this volume.
- PtrVCB->PtrStreamFileObject = IoCreateStreamFileObject(NULL,
- PtrVCB->PtrVPB->RealDevice);
- ASSERT(PtrVCB->PtrStreamFileObject);
-
- // Initialize some important fields in the newly created file object.
- PtrVCB->PtrStreamFileObject->FsContext = (void *)(&PtrVCB->CommonVCBHeader);
- PtrVCB->PtrStreamFileObject->FsContext2 = NULL;
- PtrVCB->PtrStreamFileObject->SectionObjectPointer = &(PtrVCB->SectionObject);
-
- PtrVCB->PtrStreamFileObject->Vpb = PtrVPB;
- PtrVCB->PtrStreamFileObject->ReadAccess = TRUE;
- PtrVCB->PtrStreamFileObject->WriteAccess = TRUE;
-
- // Link this chap onto the global linked list of all VCB structures.
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire Global Resource Exclusively [FileInfo]", 0);
- ExAcquireResourceExclusiveLite(&(Ext2GlobalData.GlobalDataResource), TRUE);
- InsertTailList(&(Ext2GlobalData.NextVCB), &(PtrVCB->NextVCB));
- DebugTrace(DEBUG_TRACE_MISC, "*** Global Resource Acquired [FileInfo]", 0);
-
-
-
- // Initialize caching for the stream file object.
- CcInitializeCacheMap(PtrVCB->PtrStreamFileObject, (PCC_FILE_SIZES)(&(PtrVCB->CommonVCBHeader.AllocationSize)),
- TRUE, // We will use pinned access.
- &(Ext2GlobalData.CacheMgrCallBacks), PtrVCB );
-
-
- Ext2ReleaseResource(&(Ext2GlobalData.GlobalDataResource));
- DebugTrace(DEBUG_TRACE_MISC, "*** Global Resource Released[FileInfo]", 0);
-
- // Mark the fact that this VCB structure is initialized.
- Ext2SetFlag(PtrVCB->VCBFlags, EXT2_VCB_FLAGS_VCB_INITIALIZED);
- PtrVCB->PtrGroupDescriptors = NULL;
- PtrVCB->NoOfGroups = 0;
- return;
-}
+ case STATUS_LOCAL_DISCONNECT:
+ case STATUS_TRANSACTION_ABORTED:
+ case STATUS_CONNECTION_ABORTED:
+ return (-ECONNABORTED);
+ case STATUS_REMOTE_DISCONNECT:
+ case STATUS_LINK_FAILED:
+ case STATUS_CONNECTION_DISCONNECTED:
+ case STATUS_CONNECTION_RESET:
+ case STATUS_PORT_UNREACHABLE:
+ return (-ECONNRESET);
+ case STATUS_INSUFFICIENT_RESOURCES:
+ return (-ENOMEM);
-/*************************************************************************
-*
-* Function: Ext2CompleteRequest()
-*
-* Description:
-* This routine completes a Irp.
-*
-* Expected Interrupt Level (for execution) :
-*
-* ???
-*
-* Arguments:
-*
-* Irp - Supplies the Irp being processed
-*
-* Status - Supplies the status to complete the Irp with
-*
-* Return Value: none
-*
-*************************************************************************/
-void NTAPI Ext2CompleteRequest(
- IN PIRP Irp OPTIONAL,
- IN NTSTATUS Status
- )
-{
- //
- // If we have an Irp then complete the irp.
- //
+ case STATUS_PAGEFILE_QUOTA:
+ case STATUS_NO_MEMORY:
+ case STATUS_CONFLICTING_ADDRESSES:
+ case STATUS_QUOTA_EXCEEDED:
+ case STATUS_TOO_MANY_PAGING_FILES:
+ case STATUS_WORKING_SET_QUOTA:
+ case STATUS_COMMITMENT_LIMIT:
+ case STATUS_TOO_MANY_ADDRESSES:
+ case STATUS_REMOTE_RESOURCES:
+ return (-ENOBUFS);
- if (Irp != NULL)
- {
+ case STATUS_INVALID_CONNECTION:
+ return (-ENOTCONN);
- //
- // We got an error, so zero out the information field before
- // completing the request if this was an input operation.
- // Otherwise IopCompleteRequest will try to copy to the user's buffer.
- //
+ case STATUS_PIPE_DISCONNECTED:
+ return (-ESHUTDOWN);
- if ( NT_ERROR(Status) &&
- FlagOn(Irp->Flags, IRP_INPUT_OPERATION) ) {
+ case STATUS_TIMEOUT:
+ case STATUS_IO_TIMEOUT:
+ case STATUS_LINK_TIMEOUT:
+ return (-ETIMEDOUT);
- Irp->IoStatus.Information = 0;
- }
+ case STATUS_REMOTE_NOT_LISTENING:
+ case STATUS_CONNECTION_REFUSED:
+ return (-ECONNREFUSED);
- Irp->IoStatus.Status = Status;
+ case STATUS_HOST_UNREACHABLE:
+ return (-EHOSTUNREACH);
- IoCompleteRequest( Irp, IO_DISK_INCREMENT );
+ case STATUS_PENDING:
+ case STATUS_DEVICE_NOT_READY:
+ return (-EAGAIN);
+
+ case STATUS_CANCELLED:
+ case STATUS_REQUEST_ABORTED:
+ return (-EINTR);
+
+ case STATUS_BUFFER_OVERFLOW:
+ case STATUS_INVALID_BUFFER_SIZE:
+ return (-EMSGSIZE);
+
+ case STATUS_ADDRESS_ALREADY_EXISTS:
+ return (-EADDRINUSE);
}
- return;
-}
+ if (NT_SUCCESS (Status))
+ return 0;
-/*************************************************************************
-*
-* Function: Ext2CreateNewCCB()
-*
-* Description:
-* We want to create a new CCB.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: A pointer to the CCB structure OR NULL.
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CreateNewCCB(
- PtrExt2CCB *ReturnedCCB,
- PtrExt2FCB PtrFCB,
- PFILE_OBJECT PtrFileObject )
-{
- PtrExt2CCB PtrCCB;
- NTSTATUS RC = STATUS_SUCCESS;
-
- try
- {
-
- PtrCCB = Ext2AllocateCCB();
- if (!PtrFCB)
- {
- // Assume lack of memory.
- try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
- }
- PtrCCB->PtrFCB = PtrFCB;
-
- PtrCCB->PtrFileObject = PtrFileObject;
- PtrCCB->CurrentByteOffset.QuadPart = 0;
-
- if( PtrFCB->ClosableFCBs.OnClosableFCBList )
- {
- // This FCB was on the Closable List...
- // Taking it off the list...
- //
- RemoveEntryList( &PtrFCB->ClosableFCBs.ClosableFCBList );
- PtrFCB->ClosableFCBs.OnClosableFCBList = FALSE;
- PtrFCB->PtrVCB->ClosableFCBs.Count --;
- }
-
- InterlockedIncrement( &PtrFCB->ReferenceCount );
- InterlockedIncrement( &PtrFCB->OpenHandleCount );
-
- InsertTailList( &( PtrFCB->CCBListHead ), &(PtrCCB->NextCCB));
-
- *ReturnedCCB = PtrCCB;
- try_exit: NOTHING;
- }
- finally
- {
-
- }
-
- return(RC);
+ return (-EINVAL);
}
-
-/*************************************************************************
-*
-* Function: Ext2DenyAccess()
-*
-* Description:
-* We want to deny access to an IRP
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: NTSTATUS - STATUS_ACCESS_DENIED (always)
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2DenyAccess( IN PIRP Irp )
+NTSTATUS Ext2WinntError(int rc)
{
- ASSERT( Irp );
-
- // Just return Access Denied
- Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
- IoCompleteRequest( Irp, IO_DISK_INCREMENT );
-
- DebugTrace(DEBUG_TRACE_MISC, "DENYING ACCESS (this will do for now!)...", 0);
-
- return STATUS_ACCESS_DENIED;
-}
+ switch (rc) {
+ case 0:
+ return STATUS_SUCCESS;
+ case -EPERM:
+ case -EACCES:
+ return STATUS_ACCESS_DENIED;
-/*************************************************************************
-*
-* Function: Ext2GetFCB_CCB_VCB_FromFileObject()
-*
-* Description:
-* This routine retrieves the FCB, CCB and VCB from the File Object...
-*
-* Expected Interrupt Level (for execution) :
-*
-* ?
-*
-* Return Value: NTSTATUS - STATUS_SUCCESS(always)
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2GetFCB_CCB_VCB_FromFileObject (
- IN PFILE_OBJECT PtrFileObject,
- OUT PtrExt2FCB *PPtrFCB,
- OUT PtrExt2CCB *PPtrCCB,
- OUT PtrExt2VCB *PPtrVCB )
-{
- (*PPtrCCB) = (PtrExt2CCB)(PtrFileObject->FsContext2);
- if( *PPtrCCB )
- {
- ASSERT((*PPtrCCB)->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB);
- (*PPtrFCB) = (*PPtrCCB)->PtrFCB;
-
- ASSERT((*PPtrFCB));
-
- if ((*PPtrFCB)->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB)
- {
- (*PPtrVCB) = (PtrExt2VCB)(*PPtrFCB);
- AssertVCB( (*PPtrVCB) );
-
- // No FCB
- (*PPtrFCB) = NULL;
- //found a VCB
- }
- else
- {
- AssertFCB( (*PPtrFCB) );
- (*PPtrVCB) = (*PPtrFCB)->PtrVCB;
- AssertVCB( (*PPtrVCB) );
-
- }
- }
- else
- {
- // PtrFileObject->FsContext points to NTRequiredFCB
- (*PPtrFCB) = CONTAINING_RECORD( PtrFileObject->FsContext, Ext2FCB, NTRequiredFCB );
- ASSERT((*PPtrFCB));
- //(*PPtrFCB) = PtrFileObject->FsContext;
-
- if ((*PPtrFCB)->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB)
- {
- // Making sure I got it right...
- AssertFCB( *PPtrFCB );
- (*PPtrVCB) = (*PPtrFCB)->PtrVCB;
- AssertVCB( *PPtrVCB );
- }
- else
- {
- // This should be a VCB
-
- (*PPtrVCB) = CONTAINING_RECORD( PtrFileObject->FsContext, Ext2VCB, CommonVCBHeader );
- AssertVCB( *PPtrVCB );
-
- // No FCB
- (*PPtrFCB) = NULL;
- //found a VCB
- }
-
- }
- return STATUS_SUCCESS;
-}
+ case -ENOENT:
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ case -EFAULT:
+ return STATUS_ACCESS_VIOLATION;
-void NTAPI Ext2CopyUnicodeString( PUNICODE_STRING PtrDestinationString, PUNICODE_STRING PtrSourceString )
-{
- int Count;
- // Allcating space for Destination...
- PtrDestinationString->Length = PtrSourceString->Length;
- PtrDestinationString->MaximumLength = Ext2QuadAlign( PtrSourceString->Length + 2 );
- PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength );
+ case -ETOOSMALL:
+ return STATUS_BUFFER_TOO_SMALL;
- // RtlCopyUnicodeString( PtrDestinationString, PtrSourceString );
+ case -EBADMSG:
+ case -EBADF:
+ case -EINVAL:
+ case -EFBIG:
+ return STATUS_INVALID_PARAMETER;
- for( Count = 0 ; Count < (PtrSourceString->Length/2) ; Count++ )
- {
- PtrDestinationString->Buffer[Count] = PtrSourceString->Buffer[Count];
- }
- PtrDestinationString->Buffer[Count] = 0;
+ case -EBUSY:
+ return STATUS_DEVICE_BUSY;
-}
+ case -ENOSYS:
+ return STATUS_NOT_IMPLEMENTED;
-void NTAPI Ext2CopyWideCharToUnicodeString(
- PUNICODE_STRING PtrDestinationString,
- PCWSTR PtrSourceString )
-{
-
- int Count;
-
- // Determining length...
- for( Count = 0 ; PtrSourceString[Count] != 0 ; Count++ );
-
- // Allcating space for Destination...
- PtrDestinationString->Length = Count * 2;
- PtrDestinationString->MaximumLength = Ext2QuadAlign( Count * 2 + 2 );
- PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength );
-
- // Copying the string over...
- for( Count = 0 ; ; Count++ )
- {
- PtrDestinationString->Buffer[Count] = PtrSourceString[Count];
- if( PtrSourceString[Count] == 0 )
- break;
- }
-}
+ case -ENOSPC:
+ return STATUS_DISK_FULL;
+ case -EOPNOTSUPP:
+ return STATUS_NOT_SUPPORTED;
-void NTAPI Ext2CopyCharToUnicodeString(
- PUNICODE_STRING PtrDestinationString,
- PCSTR PtrSourceString,
- USHORT SourceStringLength )
-{
- int Count;
- // Allcating space for Destination...
- PtrDestinationString->Length = SourceStringLength * 2;
- PtrDestinationString->MaximumLength = Ext2QuadAlign( SourceStringLength * 2 + 2 );
- PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength );
-
- // Copying the string over...
- for( Count = 0 ; Count < SourceStringLength ; Count++ )
- {
- PtrDestinationString->Buffer[Count] = PtrSourceString[Count];
- }
- PtrDestinationString->Buffer[Count] = 0;
+ case -EDEADLK:
+ return STATUS_POSSIBLE_DEADLOCK;
-}
+ case -EEXIST:
+ return STATUS_OBJECT_NAME_COLLISION;
-void NTAPI Ext2CopyZCharToUnicodeString( PUNICODE_STRING PtrDestinationString, PCSTR PtrSourceString )
-{
-
- int Count;
-
- // Determining length...
- for( Count = 0 ; PtrSourceString[Count] != 0 ; Count++ );
-
- // Allcating space for Destination...
- PtrDestinationString->Length = Count * 2;
- PtrDestinationString->MaximumLength = Ext2QuadAlign( Count * 2 + 2 );
- PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength );
-
- // Copying the string over...
- for( Count = 0 ; ; Count++ )
- {
- PtrDestinationString->Buffer[Count] = PtrSourceString[Count];
- if( PtrSourceString[Count] == 0 )
- break;
- }
-}
+ case -EIO:
+ return STATUS_UNEXPECTED_IO_ERROR;
-void NTAPI Ext2ZerooutUnicodeString( PUNICODE_STRING PtrUnicodeString )
-{
- PtrUnicodeString->Length = 0;
- PtrUnicodeString->MaximumLength =0;
- PtrUnicodeString->Buffer = 0;
-}
+ case -ENOTDIR:
+ return STATUS_NOT_A_DIRECTORY;
-void NTAPI Ext2DeallocateUnicodeString( PUNICODE_STRING PtrUnicodeString )
-{
- if( PtrUnicodeString && PtrUnicodeString->Buffer )
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrUnicodeString->Buffer );
- ExFreePool( PtrUnicodeString->Buffer );
- }
- PtrUnicodeString->Length = 0;
- PtrUnicodeString->MaximumLength =0;
- PtrUnicodeString->Buffer = 0;
-}
+ case -EISDIR:
+ return STATUS_FILE_IS_A_DIRECTORY;
-PtrExt2FCB NTAPI Ext2GetUsedFCB(
- PtrExt2VCB PtrVCB )
-{
+ case -ENOTEMPTY:
+ return STATUS_DIRECTORY_NOT_EMPTY;
- BOOLEAN AllocatedFromZone = FALSE;
- PLIST_ENTRY PtrEntry = NULL;
- PtrExt2FCB PtrFCB = NULL;
-
- ASSERT( PtrVCB );
- if( PtrVCB->ClosableFCBs.Count < EXT2_MAXCLOSABLE_FCBS_LL )
- {
- //
- // Too few Closable FCBs
- // Will not reuse any FCBs
- // Allocating a new one
- //
- return Ext2AllocateFCB();
- }
- //
- // Obtaining a used FCB...
- //
-
- // Retrieving the first entry in the closable FCB list...
-
- PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
-
- PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
-
- // Remembering if the FCB was allocated from the Zone...
- AllocatedFromZone = Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_NOT_FROM_ZONE );
-
- //
- // Close this FCB
- //
- if( !Ext2CloseClosableFCB( PtrFCB ) )
- {
- // Couldn't close the FCB!!
- //
- InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
- &PtrFCB->ClosableFCBs.ClosableFCBList );
- return Ext2AllocateFCB();
- }
-
- PtrVCB->ClosableFCBs.Count--;
- DebugTrace( DEBUG_TRACE_SPECIAL, "Count = %ld [Ext2GetUsedFCB]", PtrVCB->ClosableFCBs.Count );
-
- //
- // Getting the FCB ready for reuse by
- // zeroing it out...
- //
- RtlZeroMemory(PtrFCB, Ext2QuadAlign(sizeof(Ext2FCB)));
-
- // set up some fields ...
- PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FCB;
- PtrFCB->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2FCB));
-
-
- if (!AllocatedFromZone)
- {
- Ext2SetFlag(PtrFCB->FCBFlags, EXT2_FCB_NOT_FROM_ZONE);
- }
-
- return PtrFCB;
-}
+ case -ENODEV:
+ return STATUS_NO_SUCH_DEVICE;
-BOOLEAN NTAPI Ext2CloseClosableFCB(
- PtrExt2FCB PtrFCB)
-{
- KIRQL Irql = 0;
- PFILE_OBJECT PtrFileObject = NULL;
-
- AssertFCB( PtrFCB );
-
- // Attempting to acquire the FCB Exclusively...
- if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
- {
- Ext2BreakPoint();
- return FALSE;
- }
-
- Irql = KeGetCurrentIrql( );
-
- if( PtrFCB->ReferenceCount )
- {
- // How the hell can this happen!!!
- Ext2BreakPoint();
- }
- if( PtrFCB->OpenHandleCount )
- {
- // How the hell can this happen!!!
- Ext2BreakPoint();
- }
-
- // Deleting entry from VCB's FCB list...
- RemoveEntryList( &PtrFCB->NextFCB );
-
- PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED;
-
- PtrFileObject = PtrFCB->DcbFcb.Dcb.PtrDirFileObject;
-
- if ( PtrFileObject )
- {
- //
- // Clear the Cache Map...
- //
- if( PtrFileObject->PrivateCacheMap != NULL)
- {
- IO_STATUS_BLOCK Status;
- DebugTrace( DEBUG_TRACE_SPECIAL, ">>.........Flushing cache.........<<", 0 );
- CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status );
- CcUninitializeCacheMap( PtrFileObject, NULL, NULL );
- }
- //
- // The File Object is no longer required...
- // Close it by dereferenceing it!!!
- //
- PtrFileObject->FsContext = NULL;
- PtrFileObject->FsContext2 = NULL;
- ObDereferenceObject( PtrFileObject );
-
- PtrFCB->DcbFcb.Dcb.PtrDirFileObject = NULL;
- PtrFileObject = NULL;
- }
-
- // Uninitialize the Resources...
- ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.MainResource );
- ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.PagingIoResource );
-
- //
- // Releasing the FCB Name Object...
- //
- if( PtrFCB->FCBName )
- {
- DebugTrace( DEBUG_TRACE_SPECIAL, "Reusing FCB - File Name %S", PtrFCB->FCBName->ObjectName.Buffer );
- Ext2ReleaseObjectName( PtrFCB->FCBName );
- }
- else
- {
- DebugTrace( DEBUG_TRACE_SPECIAL, "Reusing FCB - File Name *Unknown*", 0 );
- }
- return TRUE;
-}
+ case -ENXIO:
+ return STATUS_INVALID_ADDRESS;
+ case -EADDRNOTAVAIL:
+ return STATUS_INVALID_ADDRESS;
-BOOLEAN NTAPI Ext2SaveBCB(
- PtrExt2IrpContext PtrIrpContext,
- PBCB PtrBCB,
- PFILE_OBJECT PtrFileObject)
-{
- PEXT2_SAVED_BCBS PtrSavedBCB;
- PLIST_ENTRY PtrEntry = NULL;
-
- if( !PtrIrpContext )
- {
- //
- // NULL passed instead of the IRP Context
- // This call should be ignored...
- //
- return TRUE;
- }
-
- if( !AssertBCB( PtrBCB ) )
- {
- DebugTrace( DEBUG_TRACE_MISC, "Not saving BCB!!! [Ext2SaveBCB]", 0 );
- return FALSE;
- }
-
-
- DebugTrace( DEBUG_TRACE_SPECIAL, "Saving BCB [Ext2SaveBCB]", 0 );
-
- // Has the BCB been saved already?
- for( PtrEntry = PtrIrpContext->SavedBCBsListHead.Flink;
- PtrEntry != &PtrIrpContext->SavedBCBsListHead;
- PtrEntry = PtrEntry->Flink )
- {
- PtrSavedBCB = CONTAINING_RECORD( PtrEntry, EXT2_SAVED_BCBS, SavedBCBsListEntry );
- ASSERT( PtrSavedBCB );
- if( PtrSavedBCB->PtrBCB == PtrBCB )
- {
-
- // A BCB for this file has already been saved for flushing...
- // Won't resave this one...
- return TRUE;
- }
- }
-
-
- // Reference the BCB
- CcRepinBcb( PtrBCB );
-
- // Now allocate a EXT2_SAVED_BCBS
- PtrSavedBCB = Ext2AllocatePool( NonPagedPool,
- Ext2QuadAlign( sizeof( EXT2_SAVED_BCBS ) ) );
- if( !PtrSavedBCB )
- return FALSE;
- PtrSavedBCB->NodeIdentifier.NodeSize = sizeof( EXT2_SAVED_BCBS );
- PtrSavedBCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_SAVED_BCB;
-
- PtrSavedBCB->PtrBCB = PtrBCB;
- // PtrSavedBCB->PtrFileObject = PtrFileObject;
-
- // Now save it in the IRP Context
- InsertHeadList( &PtrIrpContext->SavedBCBsListHead, &PtrSavedBCB->SavedBCBsListEntry );
-
- PtrIrpContext->SavedCount++;
- // Return success...
- return TRUE;
+ case -ENETDOWN:
+ return STATUS_UNEXPECTED_NETWORK_ERROR;
-}
+ case -ENETUNREACH:
+ return STATUS_NETWORK_UNREACHABLE;
+ case -ECONNABORTED:
+ return STATUS_CONNECTION_ABORTED;
-BOOLEAN NTAPI Ext2FlushSavedBCBs(
- PtrExt2IrpContext PtrIrpContext )
-{
-
- PLIST_ENTRY PtrEntry = NULL;
- PEXT2_SAVED_BCBS PtrSavedBCB = NULL;
- IO_STATUS_BLOCK Status;
- BOOLEAN RC = TRUE;
-
- if( !IsListEmpty( &PtrIrpContext->SavedBCBsListHead ) )
- {
- DebugTrace( DEBUG_TRACE_SPECIAL, "Flushing cache... - Ext2FlushSavedBCBs", 0 );
- }
- while( !IsListEmpty( &PtrIrpContext->SavedBCBsListHead ) )
- {
-
- PtrEntry = RemoveTailList( &PtrIrpContext->SavedBCBsListHead );
- if( !PtrEntry )
- {
- // No more entries left...
- break;
- }
-
- // Get the Saved BCB
- PtrSavedBCB = CONTAINING_RECORD( PtrEntry, EXT2_SAVED_BCBS, SavedBCBsListEntry );
- if( PtrSavedBCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_SAVED_BCB )
- {
- // Something is wrong...
- Ext2BreakPoint();
- return FALSE;
- }
-
- if( !AssertBCB( PtrSavedBCB->PtrBCB ) )
- {
- // This BCB shouldn't have been saved in the first place...
- DebugTrace( DEBUG_TRACE_ERROR, "Unable to flush BCB - Skipping!!! [Ext2SaveBCB]", 0 );
- continue;
- }
-
- // Unpin and Flush the cache...
- CcUnpinRepinnedBcb( PtrSavedBCB->PtrBCB, TRUE, &Status );
-
- if( !NT_SUCCESS( Status.Status ) )
- {
- // Failure in flushing...
- DebugTrace( DEBUG_TRACE_SPECIAL, "Failure flushing cache - Ext2FlushSavedBCBs", 0 );
- RC = FALSE;
- }
-
- // Release the Saved BCB
- PtrSavedBCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_INVALID;
-
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrSavedBCB );
- ExFreePool( PtrSavedBCB );
- PtrSavedBCB = NULL;
- PtrIrpContext->SavedCount--;
- }
-
- return RC;
-}
+ case -ECONNRESET:
+ return STATUS_CONNECTION_RESET;
-BOOLEAN NTAPI AssertBCB( PBCB PtrBCB )
-{
- PFILE_OBJECT PtrFileObject = NULL;
-
- /*
- * This routine is simplified version of the original
- * AssertBCB and doesn't make any assumptions about
- * the layout of undocumented BCB structure.
- * -- Filip Navara, 18/08/2004
- */
-
- PtrFileObject = CcGetFileObjectFromBcb ( PtrBCB );
- if( !PtrFileObject )
- {
- Ext2BreakPoint();
- return FALSE;
- }
- else
- {
- return TRUE;
- }
- }
-
-
-ULONG NTAPI Ext2Align( ULONG NumberToBeAligned, ULONG Alignment )
-{
- if( Alignment & ( Alignment - 1 ) )
- {
- //
- // Alignment not a power of 2
- // Just returning
- //
- return NumberToBeAligned;
- }
- if( ( NumberToBeAligned & ( Alignment - 1 ) ) != 0 )
- {
- NumberToBeAligned = NumberToBeAligned + Alignment;
- NumberToBeAligned = NumberToBeAligned & ( ~ (Alignment-1) );
- }
- return NumberToBeAligned;
+ case -ENOMEM:
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ case -ENOBUFS:
+ return STATUS_NO_MEMORY;
+
+ case -ENOTCONN:
+ return STATUS_INVALID_CONNECTION;
+
+ case -ESHUTDOWN:
+ return STATUS_CONNECTION_DISCONNECTED;
+
+ case -ETIMEDOUT:
+ return STATUS_TIMEOUT;
+
+ case -ECONNREFUSED:
+ return STATUS_CONNECTION_REFUSED;
+
+ case -EHOSTUNREACH:
+ return STATUS_HOST_UNREACHABLE;
+
+ case -EAGAIN:
+ return STATUS_DEVICE_NOT_READY;
+
+ case -EINTR:
+ return STATUS_CANCELLED;
+
+ case -EMSGSIZE:
+ return STATUS_INVALID_BUFFER_SIZE;
+
+ case -EADDRINUSE:
+ return STATUS_ADDRESS_ALREADY_EXISTS;
+ }
+
+ return STATUS_UNSUCCESSFUL;
}
-LONGLONG NTAPI Ext2Align64( LONGLONG NumberToBeAligned, LONGLONG Alignment )
+BOOLEAN Ext2IsDot(PUNICODE_STRING name)
{
- if( Alignment & ( Alignment - 1 ) )
- {
- //
- // Alignment not a power of 2
- // Just returning
- //
- return NumberToBeAligned;
- }
- if( ( NumberToBeAligned & ( Alignment - 1 ) ) != 0 )
- {
- NumberToBeAligned = NumberToBeAligned + Alignment;
- NumberToBeAligned = NumberToBeAligned & ( ~ (Alignment-1) );
- }
- return NumberToBeAligned;
+ return (name->Length == 2 && name->Buffer[0] == L'.');
}
-
-ULONG NTAPI Ext2GetCurrentTime()
+BOOLEAN Ext2IsDotDot(PUNICODE_STRING name)
{
- LARGE_INTEGER CurrentTime;
- ULONG Time;
- KeQuerySystemTime( &CurrentTime );
- Time = (ULONG) ( (CurrentTime.QuadPart - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
- return Time;
-}
+ return (name->Length == 4 && name->Buffer[0] == L'.' &&
+ name->Buffer[1] == L'.');
+}
\ No newline at end of file
-/*************************************************************************
-*
-* File: read.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the "Read" dispatch entry point.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_READ
-
-#define DEBUG_LEVEL (DEBUG_TRACE_READ)
-
-
-/*************************************************************************
-*
-* Function: Ext2Read()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a read
-* request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Read(
-PDEVICE_OBJECT DeviceObject, // the logical volume device object
-PIRP Irp) // I/O Request Packet
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Read IRP Received...", 0);
-
- // Ext2BreakPoint();
-
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
-
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
-
- try
- {
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
-
- RC = Ext2CommonRead(PtrIrpContext, Irp, TRUE);
-
- }
- except ( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) )
- {
-
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
-
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
-
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
-}
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: read.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+/* DEFINITIONS *************************************************************/
+NTSTATUS
+Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext);
+NTSTATUS
+Ext2ReadFile (IN PEXT2_IRP_CONTEXT IrpContext);
-/*************************************************************************
-*
-* Function: Ext2CommonRead()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonRead(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp,
-BOOLEAN FirstAttempt )
+NTSTATUS
+Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext);
+
+/* FUNCTIONS *************************************************************/
+
+NTSTATUS
+Ext2CompleteIrpContext (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN NTSTATUS Status )
{
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- LARGE_INTEGER ByteOffset;
- uint32 ReadLength = 0, TruncatedReadLength = 0;
- uint32 NumberBytesRead = 0;
- PFILE_OBJECT PtrFileObject = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- PERESOURCE PtrResourceAcquired = NULL;
- PVOID PtrSystemBuffer = NULL;
- PVOID PtrPinnedReadBuffer = NULL;
-
- BOOLEAN CompleteIrp = TRUE;
- BOOLEAN PostRequest = FALSE;
-
- BOOLEAN CanWait = FALSE;
- BOOLEAN PagingIo = FALSE;
- BOOLEAN NonBufferedIo = FALSE;
- BOOLEAN SynchronousIo = FALSE;
- BOOLEAN ReadTruncated = FALSE;
-
- // Used to cache the Single Indirect blocks pointed to by
- // the Double Indirect block
- PEXT2_SIBLOCKS PtrDIArray = NULL;
- ULONG DIArrayCount = 0;
-
- // Used to cache the Single Indirect blocks pointed to by
- // the Triple Indirect block
- PEXT2_SIBLOCKS PtrTIArray = NULL;
- ULONG TIArrayCount = 0;
-
- EXT2_IO_RUN * PtrIoRuns = NULL;
-
- ULONG Start;
- ULONG End;
- ULONG LogicalBlockIndex;
- ULONG BytesRemaining;
- ULONG BytesReadSoFar;
- ULONG LeftOver;
- ULONG LogicalBlockSize;
- ULONG PhysicalBlockSize;
-
- PBCB PtrPinnedSIndirectBCB = NULL;
- PBCB PtrPinnedDIndirectBCB = NULL;
- PBCB PtrPinnedTIndirectBCB = NULL;
-
- int Index;
-
- try
- {
- try{
- // First, get a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- // If this happens to be a MDL read complete request, then
- // there is not much processing that the FSD has to do.
- if (PtrIoStackLocation->MinorFunction & IRP_MN_COMPLETE)
- {
- // Caller wants to tell the Cache Manager that a previously
- // allocated MDL can be freed.
- Ext2MdlComplete(PtrIrpContext, PtrIrp, PtrIoStackLocation, TRUE);
- // The IRP has been completed.
- CompleteIrp = FALSE;
- try_return(RC = STATUS_SUCCESS);
- }
-
- // If this is a request at IRQL DISPATCH_LEVEL, then post
- // the request (your FSD may choose to process it synchronously
- // if you implement the support correctly; obviously you will be
- // quite constrained in what you can do at such IRQL).
- if (PtrIoStackLocation->MinorFunction & IRP_MN_DPC)
- {
- DebugTrace(DEBUG_TRACE_MISC, " === Deferring Read ", 0 );
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
-
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
-
- // Get the FCB and CCB pointers
- Ext2GetFCB_CCB_VCB_FromFileObject (
- PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
-
- // Get some of the parameters supplied to us
- ByteOffset = PtrIoStackLocation->Parameters.Read.ByteOffset;
- ReadLength = PtrIoStackLocation->Parameters.Read.Length;
-
- CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
- PagingIo = ((PtrIrp->Flags & IRP_PAGING_IO) ? TRUE : FALSE);
- NonBufferedIo = ((PtrIrp->Flags & IRP_NOCACHE) ? TRUE : FALSE);
- SynchronousIo = ((PtrFileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE);
-
- if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
- {
- DebugTrace(DEBUG_TRACE_FILE_NAME, " === Read File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_FILE_NAME, " === Read File Name : -null-", 0);
- }
-
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->ByteCount = 0x%8lx", PtrIoStackLocation->Parameters.Read.Length);
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->ByteOffset.LowPart = 0x%8lx", PtrIoStackLocation->Parameters.Read.ByteOffset.LowPart);
-
- if( CanWait )
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->Can Wait ", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->Can't Wait ", 0 );
- }
-
- if( PagingIo )
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->Paging Io ", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->Not Paging Io", 0 );
- }
-
- if( SynchronousIo )
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->SynchronousIo ", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->ASynchronousIo ", 0 );
- }
-
- if( NonBufferedIo )
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->NonBufferedIo", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, " ->BufferedIo", 0 );
- }
-
-
- if (ReadLength == 0)
- {
- // a 0 byte read can be immediately succeeded
- try_return();
- }
-
- // Is this a read of the volume itself ?
- if ( ( !PtrFCB && PtrVCB ) || PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB )
- {
- //
- // >>>>>>>>>>> Volume Read <<<<<<<<<<<<
- //
- // Yep, we need to send this on to the disk driver after
- // validation of the offset and length.
-
- // PtrVCB = (PtrExt2VCB)(PtrFCB);
-
- if (PtrVCB->VCBFlags & EXT2_FCB_PAGE_FILE )
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, "[Read] *Volume Page File *", 0);
- }
-
- // Acquire the volume resource shared ...
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Read]", PtrFileObject);
- }
-
- if( PagingIo )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Shared [Read]", 0);
- DebugTraceState( "VCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [Read]", PtrVCB->PagingIoResource.ActiveCount, PtrVCB->PagingIoResource.NumberOfExclusiveWaiters, PtrVCB->PagingIoResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceSharedLite(&(PtrVCB->PagingIoResource), FALSE ))
- {
- // post the request to be processed in the context of a worker thread
- DebugTrace(DEBUG_TRACE_MISC, "*** VCBPaging Acquisition FAILED [Read]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- DebugTrace(DEBUG_TRACE_MISC, "*** VCBPaging Acquired [Read]", 0);
-
- PtrResourceAcquired = &(PtrVCB->PagingIoResource);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Shared [Read]", 0);
- DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Read]", PtrVCB->VCBResource.ActiveCount,
- PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceSharedLite(&(PtrVCB->VCBResource), FALSE ))
- {
- // post the request to be processed in the context of a worker thread
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquisition FAILED [Read]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired [Read]", 0);
-
- PtrResourceAcquired = &(PtrVCB->VCBResource);
- }
- if( !PagingIo )
- {
- if( PtrVCB->CommonVCBHeader.AllocationSize.QuadPart < ByteOffset.QuadPart )
- {
- RC = STATUS_END_OF_FILE;
- NumberBytesRead = 0;
- try_return();
- }
- }
- if( PagingIo || NonBufferedIo )
- {
- DebugTrace(DEBUG_TRACE_MISC, "[Volume Read] PagingIo or NonBufferedIo ", 0);
- CompleteIrp = FALSE;
-
- RC = Ext2PassDownSingleReadWriteIRP (
- PtrIrpContext, PtrIrp, PtrVCB,
- ByteOffset, ReadLength, SynchronousIo);
-
- try_return();
- }
- else
- {
- // Buffer Control Block
- PBCB PtrBCB = NULL;
- DebugTrace(DEBUG_TRACE_READ_DETAILS, "[Volume Read] BufferedIo ", 0);
- //
- // Let the cache manager worry about this read...
- // Pinned access should have been initiated.
- // But checking anyway...
- //
- ASSERT( PtrVCB->PtrStreamFileObject );
- ASSERT( PtrVCB->PtrStreamFileObject->PrivateCacheMap );
-
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &ByteOffset,
- ReadLength,
- TRUE,
- &PtrBCB,
- &PtrPinnedReadBuffer) )
- {
-
- RC = STATUS_UNSUCCESSFUL;
- NumberBytesRead = 0;
- try_return();
- }
- else
- {
- PtrSystemBuffer = Ext2GetCallersBuffer(PtrIrp);
- RtlCopyBytes( PtrSystemBuffer, PtrPinnedReadBuffer, ReadLength );
- CcUnpinData( PtrBCB );
- PtrBCB = NULL;
- RC = STATUS_SUCCESS;
- NumberBytesRead = ReadLength;
- try_return();
-
- }
- }
- }
-
-
- // If the read request is directed to a page file
- // send the request directly to the disk driver.
- // For requests directed to a page file, you have to trust
- // that the offsets will be set correctly by the VMM. You should not
- // attempt to acquire any FSD resources either.
-
- if (PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE)
- {
- IoMarkIrpPending(PtrIrp);
- // You will need to set a completion routine before invoking
- // a lower level driver
- // forward request directly to disk driver
- // Ext2PageFileIo(PtrIrpContext, PtrIrp);
- DebugTrace( DEBUG_TRACE_SPECIAL, "[Read] To a *Page File* - Not handled \ngoing into a hang...", 0);
- CompleteIrp = FALSE;
- try_return(RC = STATUS_PENDING);
- }
-
-
- //
- // If this read is directed to a directory...
- // Paging IO is allowed though...
- //
- if ( ( PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY ) && !PagingIo )
- {
- RC = STATUS_INVALID_DEVICE_REQUEST;
- try_return();
- }
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- // Check whether the desired read can be allowed depending
- // on any byte range locks that might exist. Note that for
- // paging-io, no such checks should be performed.
- if (!PagingIo)
- {
- // Insert code to perform the check here ...
- //
- // if (!Ext2CheckForByteLock(PtrFCB, PtrCCB, PtrIrp, PtrCurrentIoStackLocation))
- // {
- // try_return(RC = STATUS_FILE_LOCK_CONFLICT);
- // }
- }
-
- // There are certain complications that arise when the same file stream
- // has been opened for cached and non-cached access. The FSD is then
- // responsible for maintaining a consistent view of the data seen by
- // the caller.
- // Also, it is possible for file streams to be mapped in both as data files
- // and as an executable. This could also lead to consistency problems since
- // there now exist two separate sections (and pages) containing file
- // information.
- // Read Chapter 10 for more information on the issues involved in
- // maintaining data consistency.
- // The test below flushes the data cached in system memory if the current
- // request madates non-cached access (file stream must be cached) and
- // (a) the current request is not paging-io which indicates it is not
- // a recursive I/O operation OR originating in the Cache Manager
- // (b) OR the current request is paging-io BUT it did not originate via
- // the Cache Manager (or is a recursive I/O operation) and we do
- // have an image section that has been initialized.
-
-
-
- #define EXT2_REQ_NOT_VIA_CACHE_MGR(ptr) (!MmIsRecursiveIoFault() && ((ptr)->ImageSectionObject != NULL))
-
- if( NonBufferedIo && (PtrReqdFCB->SectionObject.DataSectionObject != NULL) )
- {
- if (!PagingIo || (EXT2_REQ_NOT_VIA_CACHE_MGR(&(PtrReqdFCB->SectionObject))))
- {
- CcFlushCache(&(PtrReqdFCB->SectionObject), &ByteOffset, ReadLength, &(PtrIrp->IoStatus));
- // If the flush failed, return error to the caller
- if (!NT_SUCCESS(RC = PtrIrp->IoStatus.Status))
- {
- try_return();
- }
- }
- }
-
- //
- // Synchronizing with other reads and writes...
- // Acquire the appropriate FCB resource shared
- //
- if ( PagingIo )
- {
- // Try to acquire the FCB PagingIoResource shared
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Read]", PtrFileObject);
- }
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCBPaging Shared [Read]", 0);
- DebugTraceState( "FCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [Read]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->PagingIoResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCBPaging Acquisition FAILED [Read]", 0);
-
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
-
- DebugTrace(DEBUG_TRACE_MISC, "*** FCBPaging Acquired [Read]", 0);
-
- // Remember the resource that was acquired
- PtrResourceAcquired = &(PtrReqdFCB->PagingIoResource);
- }
- else
- {
- // Try to acquire the FCB MainResource shared
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Read]", PtrFileObject);
- }
- DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Shared [Read]", 0);
- DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Read]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
- if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Read]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquired [Read]", 0);
-
- // Remember the resource that was acquired
- PtrResourceAcquired = &(PtrReqdFCB->MainResource);
- }
-
- // Read in the File inode...
- Ext2InitializeFCBInodeInfo( PtrFCB );
-
- if (!PagingIo)
- {
- LARGE_INTEGER CurrentTime;
- KeQuerySystemTime( &CurrentTime );
- PtrFCB->LastAccessTime.QuadPart = CurrentTime.QuadPart;
- }
-
- // Validate start offset and length supplied.
- if (ByteOffset.QuadPart >= PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart )
- {
- // Starting offset is > file size
- try_return(RC = STATUS_END_OF_FILE);
- }
-
- /*
- * Round down the size of Paging I/O requests too. I'm not
- * sure if the FS driver is responsible for doing that, but
- * all other drivers I have seen do it.
- * -- Filip Navara, 18/08/2004
- */
- if ( ByteOffset.QuadPart + ReadLength > PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart )
- {
- // Read going beyond the end of file...
- // Adjusting the Read Length...
- ReadLength = (UINT)(PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart - ByteOffset.QuadPart);
- if (PagingIo)
- ReadLength = ROUND_TO_PAGES(ReadLength);
- ReadTruncated = TRUE;
- }
-
- // This is also a good place to set whether fast-io can be performed
- // on this particular file or not. Your FSD must make it's own
- // determination on whether or not to allow fast-io operations.
- // Commonly, fast-io is not allowed if any byte range locks exist
- // on the file or if oplocks prevent fast-io. Practically any reason
- // choosen by your FSD could result in your setting FastIoIsNotPossible
- // OR FastIoIsQuestionable instead of FastIoIsPossible.
- //
- // PtrReqdFCB->CommonFCBHeader.IsFastIoPossible = FastIoIsPossible;
-
-
- // Branch here for cached vs non-cached I/O
-
- if (!NonBufferedIo)
- {
- DebugTrace(DEBUG_TRACE_READ_DETAILS, "[File Read] BufferedIo ", 0);
-
- // The caller wishes to perform cached I/O. Initiate caching if
- // this is the first cached I/O operation using this file object
- if (PtrFileObject->PrivateCacheMap == NULL)
- {
- // This is the first cached I/O operation. You must ensure
- // that the FCB Common FCB Header contains valid sizes at this time
- CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)),
- FALSE, // We will not utilize pin access for this file
- &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
- PtrCCB); // The context used in callbacks
- }
-
- // Check and see if this request requires a MDL returned to the caller
- if (PtrIoStackLocation->MinorFunction & IRP_MN_MDL)
- {
- // Caller does want a MDL returned. Note that this mode
- // implies that the caller is prepared to block
- CcMdlRead(PtrFileObject, &ByteOffset, TruncatedReadLength, &(PtrIrp->MdlAddress), &(PtrIrp->IoStatus));
- NumberBytesRead = PtrIrp->IoStatus.Information;
- RC = PtrIrp->IoStatus.Status;
-
- try_return();
- }
-
- // This is a regular run-of-the-mill cached I/O request. Let the
- // Cache Manager worry about it!
- // First though, we need a buffer pointer (address) that is valid
- PtrSystemBuffer = Ext2GetCallersBuffer(PtrIrp);
- ASSERT(PtrSystemBuffer);
-
- if (!CcCopyRead(PtrFileObject, &(ByteOffset), ReadLength, CanWait, PtrSystemBuffer, &(PtrIrp->IoStatus)))
- {
- // The caller was not prepared to block and data is not immediately
- // available in the system cache
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure. Cannot read without blocking...", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- }
-
- // We have the data
- RC = PtrIrp->IoStatus.Status;
- NumberBytesRead = PtrIrp->IoStatus.Information;
- try_return();
- }
- else // NonBuffered or Paged IO
- {
- LONGLONG SingleIndirectBlockSize ;
- LONGLONG DoubleIndirectBlockSize ;
- LONGLONG TripleIndirectBlockSize ;
- LONGLONG DirectBlockSize ;
-
- LONGLONG NoOfDirectBlocks ;
- LONGLONG NoOfSingleIndirectBlocks ;
- LONGLONG NoOfDoubleIndirectBlocks ;
- LONGLONG NoOfTripleIndirectBlocks ;
-
- ULONG * PtrPinnedSIndirectBlock = NULL;
- ULONG * PtrPinnedDIndirectBlock = NULL;
- ULONG * PtrPinnedTIndirectBlock = NULL;
-
- // Used when reading a Triple Indirect Block...
- LONGLONG FirstCachedDIBlockOffset = 0;
-
- // Used when reading a Double Indirect Block...
- LONGLONG FirstCachedSIBlockOffset = 0;
-
- DebugTrace(DEBUG_TRACE_MISC, "[File Read] Paging IO or NonBufferedIo ", 0);
-
- // Calculating where the read should start from...
- LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
- PhysicalBlockSize = PtrVCB->TargetDeviceObject->SectorSize;
-
- NoOfDirectBlocks = EXT2_NDIR_BLOCKS ;
- NoOfSingleIndirectBlocks = LogicalBlockSize / sizeof( ULONG );
- NoOfDoubleIndirectBlocks = NoOfSingleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
- NoOfTripleIndirectBlocks = NoOfDoubleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
-
- DirectBlockSize = LogicalBlockSize * NoOfDirectBlocks;
- SingleIndirectBlockSize = LogicalBlockSize * NoOfSingleIndirectBlocks;
- DoubleIndirectBlockSize = LogicalBlockSize * NoOfDoubleIndirectBlocks ;
- TripleIndirectBlockSize = LogicalBlockSize * NoOfTripleIndirectBlocks;
-
- LogicalBlockIndex = (ULONG)( ByteOffset.QuadPart / LogicalBlockSize);
-
- /*
- if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- //
- // Handle Triple indirect blocks?
- // A Pop up will do for now...
- //
- UNICODE_STRING ErrorMessage;
- Ext2CopyWideCharToUnicodeString( &ErrorMessage, L"Triple indirect blocks not supported as yet. - Ext2.sys" );
- DebugTrace(DEBUG_TRACE_ERROR, "@@@@@@@@ Triple indirect blocks need to be read in! \n@@@@@@@@ This is not supported as yet!", 0);
- IoRaiseInformationalHardError(
- IO_ERR_DRIVER_ERROR,
- &ErrorMessage,
- KeGetCurrentThread( ) );
-
- Ext2DeallocateUnicodeString( &ErrorMessage );
-
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return ( RC );
-
- }
- */
- if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize &&
- ( ByteOffset.QuadPart < DirectBlockSize + SingleIndirectBlockSize ) )
- {
- //
- // Single Indirect Blocks required...
- // Read in the single indirect blocks...
- //
-
- LARGE_INTEGER VolumeByteOffset;
-
- DebugTrace(DEBUG_TRACE_MISC, "Reading in some Single Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize;
-
- //
- // Asking the cache manager to oblige by pinning the single indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedSIndirectBCB,
- (PVOID*)&PtrPinnedSIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
- }
- if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize + SingleIndirectBlockSize &&
- ( ByteOffset.QuadPart ) < DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- //
- // Double Indirect Blocks required...
- // Read in the double indirect blocks...
- //
-
- LONGLONG StartIndirectBlock;
- LONGLONG EndIndirectBlock;
-
-
-
- LARGE_INTEGER VolumeByteOffset;
-
- DebugTrace(DEBUG_TRACE_MISC, "Reading in some Double Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
-
- //
- // Asking the cache manager to oblige by pinning the double indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedDIndirectBCB,
- (PVOID*)&PtrPinnedDIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- // So far so good...
- // Now determine the single indirect blocks that will have to be read in...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize )
- {
- // Request doesnot require any single indirect or direct blocks
- StartIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize);
- StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
- StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
- }
- else
- {
- StartIndirectBlock = 0;
- }
-
- FirstCachedSIBlockOffset = (NoOfSingleIndirectBlocks*(StartIndirectBlock+1)) + NoOfDirectBlocks;
-
- if( ByteOffset.QuadPart + ReadLength >=
- DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize)
- {
- EndIndirectBlock = DoubleIndirectBlockSize;
- }
- else
- {
- EndIndirectBlock = ByteOffset.QuadPart + ReadLength -
- (DirectBlockSize + SingleIndirectBlockSize);
- }
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, LogicalBlockSize )/LogicalBlockSize ;
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, NoOfSingleIndirectBlocks )/NoOfSingleIndirectBlocks;
-
- DIArrayCount = (ULONG)(EndIndirectBlock - StartIndirectBlock);
-
- PtrDIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( DIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
- {
- ULONG i;
-
- for( i = 0; i < DIArrayCount; i++ )
- {
- VolumeByteOffset.QuadPart = PtrPinnedDIndirectBlock[StartIndirectBlock+i] * LogicalBlockSize;
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrDIArray[i].PtrBCB,
- (PVOID*)&PtrDIArray[i].PtrSIBlocks))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- DIArrayCount = i;
- try_return(RC = STATUS_PENDING);
-
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
- }
- }
- }
-
- if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- //
- // Triple Indirect Blocks required...
- // Read in the triple indirect blocks...
- //
- LONGLONG StartTIndirectBlock;
- LONGLONG EndTIndirectBlock;
-
- LONGLONG StartDIndirectBlock;
- LONGLONG EndDIndirectBlock;
- LONGLONG StartIndirectBlock;
- LONGLONG EndIndirectBlock;
-
- LONGLONG ByteOffsetTillHere = 0;
-
- PBCB TempDIBCB;
- LONG* TempDIBuffer;
-
- ULONG TIArrayIndex = 0;
-
- LARGE_INTEGER VolumeByteOffset;
-
- DebugTrace(DEBUG_TRACE_MISC, "Reading in some Triple Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_TIND_BLOCK ] * LogicalBlockSize;
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "ByteOffset = 0x%I64X", ByteOffset );
- DebugTrace(DEBUG_TRACE_TRIPLE, "ReadLength = 0x%lX", ReadLength );
- DebugTrace(DEBUG_TRACE_TRIPLE, "EXT2_TIND_BLOCK = 0x%lX", PtrFCB->IBlock[ EXT2_TIND_BLOCK ] );
- //
- // Asking the cache manager to oblige by pinning the triple indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedTIndirectBCB,
- (PVOID*)&PtrPinnedTIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- // Determine the no of BCBs that need to be saved...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- StartTIndirectBlock = ByteOffset.QuadPart;
- }
- else
- {
- StartTIndirectBlock = DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize;
- }
- EndTIndirectBlock = ByteOffset.QuadPart + ReadLength;
- TIArrayCount = (ULONG)( (EndTIndirectBlock - StartTIndirectBlock) / SingleIndirectBlockSize ) + 2;
-
-
- PtrTIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( TIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
-
- // Now determine the double indirect blocks that will have to be read in...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- // Request doesnot require any single indirect or direct blocks
- StartDIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize);
- StartDIndirectBlock = StartDIndirectBlock / LogicalBlockSize;
- StartDIndirectBlock = StartDIndirectBlock / NoOfDoubleIndirectBlocks;
-
- ByteOffsetTillHere = DirectBlockSize + SingleIndirectBlockSize + (DoubleIndirectBlockSize*(StartDIndirectBlock+1)) ;
- //FirstCachedDIBlockOffset = ByteOffset.QuadPart / LogicalBlockSize;
- FirstCachedDIBlockOffset = ByteOffsetTillHere / LogicalBlockSize;
- }
- else
- {
- ByteOffsetTillHere = DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize;
- FirstCachedDIBlockOffset = ByteOffsetTillHere / LogicalBlockSize;
- StartDIndirectBlock = 0;
- }
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "ByteOffsetTillHere = 0x%lX", ByteOffsetTillHere );
-
- EndDIndirectBlock = ByteOffset.QuadPart + ReadLength -
- (DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize);
- EndDIndirectBlock = Ext2Align64( EndDIndirectBlock, LogicalBlockSize ) / LogicalBlockSize ;
- EndDIndirectBlock = Ext2Align64( EndDIndirectBlock, NoOfDoubleIndirectBlocks ) / NoOfDoubleIndirectBlocks;
-
- {
- // Reading in the necessary double indirect bocks...
- ULONG i;
- LONGLONG Count = EndDIndirectBlock-StartDIndirectBlock;
-
- for( i = 0; i < Count; i++, ByteOffsetTillHere += DoubleIndirectBlockSize)
- {
- VolumeByteOffset.QuadPart = PtrPinnedTIndirectBlock[StartDIndirectBlock+i] * LogicalBlockSize;
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "Double VolOffset = 0x%I64X", VolumeByteOffset );
-
- if( !CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &TempDIBCB,
- (PVOID*)&TempDIBuffer) )
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- try_return(RC = STATUS_PENDING);
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- if( ByteOffset.QuadPart > ByteOffsetTillHere)
- {
- StartIndirectBlock = ByteOffset.QuadPart - (ByteOffsetTillHere);
- StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
- StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
-
- if( TIArrayIndex == 0 )
- {
- FirstCachedDIBlockOffset += StartIndirectBlock * NoOfSingleIndirectBlocks;
- }
- }
- else
- {
- StartIndirectBlock = 0;
- }
-
- if( ByteOffset.QuadPart + ReadLength >= ByteOffsetTillHere + DoubleIndirectBlockSize)
- {
- EndIndirectBlock = DoubleIndirectBlockSize;
- }
- else
- {
- EndIndirectBlock = ByteOffset.QuadPart + ReadLength - ByteOffsetTillHere;
- }
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, LogicalBlockSize )/LogicalBlockSize ;
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, NoOfSingleIndirectBlocks )/NoOfSingleIndirectBlocks;
-
- {
- ULONG i;
-
- for( i = 0; i < (EndIndirectBlock - StartIndirectBlock); i++ )
- {
- VolumeByteOffset.QuadPart = TempDIBuffer[StartIndirectBlock+i] * LogicalBlockSize;
- DebugTrace(DEBUG_TRACE_TRIPLE, "Single VolOffset = 0x%I64X", VolumeByteOffset );
-
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrTIArray[ TIArrayIndex ].PtrBCB,
- (PVOID*)&PtrTIArray[ TIArrayIndex ].PtrSIBlocks))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- DIArrayCount = i;
- try_return(RC = STATUS_PENDING);
-
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
- TIArrayIndex++;
- }
- }
- CcUnpinData( TempDIBCB );
- TempDIBCB = NULL;
- TempDIBuffer = NULL;
- }
- }
- TIArrayCount = TIArrayIndex;
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "TIArrayCount = %ld", TIArrayCount );
- DebugTrace(DEBUG_TRACE_TRIPLE, "FirstCachedDIBlockOffset = 0x%lX", FirstCachedDIBlockOffset );
- }
-
-
- //
- // Allocating memory for IO Runs
- //
- Index = ( (ReadLength - 2) / LogicalBlockSize + 2 );
- PtrIoRuns = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( Index * sizeof( EXT2_IO_RUN) ) );
-
-
- Start = (ULONG) ( ByteOffset.QuadPart - (LogicalBlockSize * LogicalBlockIndex) );
- BytesRemaining = (ULONG)( LogicalBlockSize * (LogicalBlockIndex +1) - ByteOffset.QuadPart );
-
- if( ReadLength > BytesRemaining )
- {
- End = Start + BytesRemaining;
- }
- else
- {
- End = Start + ReadLength;
- }
- BytesReadSoFar = 0;
-
- Index = 0;
- DebugTrace(DEBUG_TRACE_MISC, "\nDetermining the read IRPs that have to be passed down...", 0);
-
- while( 1 )
- {
- BytesReadSoFar += (End-Start);
- if( LogicalBlockIndex < NoOfDirectBlocks )
- {
- // Direct Block
- PtrIoRuns[ Index ].LogicalBlock = PtrFCB->IBlock[ LogicalBlockIndex ];
- }
- else if( LogicalBlockIndex < (NoOfSingleIndirectBlocks + NoOfDirectBlocks) )
- {
- // Single Indirect Block
- PtrIoRuns[ Index ].LogicalBlock = PtrPinnedSIndirectBlock[ LogicalBlockIndex - NoOfDirectBlocks ];
- }
- else if( LogicalBlockIndex < (NoOfDoubleIndirectBlocks + NoOfSingleIndirectBlocks + NoOfDirectBlocks) )
- {
- LONGLONG BlockNo;
- LONGLONG IBlockIndex;
- LONGLONG BlockIndex;
-
- BlockNo = LogicalBlockIndex - FirstCachedSIBlockOffset;
- IBlockIndex = BlockNo / NoOfSingleIndirectBlocks;
- BlockIndex = BlockNo % NoOfSingleIndirectBlocks;
-
- // Double Indirect Block
- PtrIoRuns[ Index ].LogicalBlock =
- PtrDIArray[ IBlockIndex ].PtrSIBlocks[ BlockIndex ];
- }
- else
- {
- // Triple Indirect Block
- LONGLONG BlockNo;
- LONGLONG IBlockIndex;
- LONGLONG BlockIndex;
- BlockNo = LogicalBlockIndex - FirstCachedDIBlockOffset;
- IBlockIndex = BlockNo / NoOfSingleIndirectBlocks;
- BlockIndex = BlockNo % NoOfSingleIndirectBlocks;
-
- DbgPrint( "\nBlock No : 0x%I64X IBlockIndex = 0x%I64X BlockIndex = 0x%I64X", BlockNo, IBlockIndex, BlockIndex);
-
- if( IBlockIndex >= TIArrayCount )
- {
- Ext2BreakPoint();
- }
- if( BlockIndex >= LogicalBlockSize )
- {
- Ext2BreakPoint();
- }
-
- PtrIoRuns[ Index ].LogicalBlock = PtrTIArray[ IBlockIndex ].PtrSIBlocks[ BlockIndex ];
- DbgPrint( "LogicalBlock = 0x%lX", PtrIoRuns[ Index ].LogicalBlock );
- }
-
- if( PtrIoRuns[ Index ].LogicalBlock == 0 )
- {
- //
- // Something is wrong...
- //
- //Ext2BreakPoint();
- Index--;
- break;
-
- }
-
-
- PtrIoRuns[ Index ].StartOffset = Start;
- PtrIoRuns[ Index ].EndOffset = End;
- PtrIoRuns[ Index ].PtrAssociatedIrp = NULL;
-
- DebugTrace( DEBUG_TRACE_MISC, " Index = (%ld)", LogicalBlockIndex );
- DebugTrace( DEBUG_TRACE_MISC, " Logical Block = (0x%lX)", PtrIoRuns[ Index ].LogicalBlock );
- DebugTrace( DEBUG_TRACE_MISC, " Start = (0x%lX)", Start );
- DebugTrace( DEBUG_TRACE_MISC, " End = (0x%lX) ", End );
- DebugTrace( DEBUG_TRACE_MISC, " Bytes read (0x%lX)", BytesReadSoFar );
-
-
-
- if( BytesReadSoFar >= ReadLength )
- break;
- LogicalBlockIndex++;
- Start = 0;
- LeftOver = ReadLength - BytesReadSoFar;
- if( LeftOver > LogicalBlockSize )
- End = LogicalBlockSize;
- else
- End = LeftOver;
- // Loop over to make the read request...
- Index++;
- }
- //
- // Unpin the Indirect Blocks
- //
- if( PtrPinnedSIndirectBCB )
- {
- CcUnpinData( PtrPinnedSIndirectBCB );
- PtrPinnedSIndirectBCB = NULL;
- PtrPinnedSIndirectBlock = NULL;
- }
-
- if( PtrPinnedDIndirectBCB )
- {
- CcUnpinData( PtrPinnedDIndirectBCB );
- PtrPinnedDIndirectBCB = NULL;
- PtrPinnedDIndirectBlock = NULL;
- }
-
- if( PtrPinnedTIndirectBCB)
- {
- CcUnpinData( PtrPinnedTIndirectBCB);
- PtrPinnedTIndirectBCB = NULL;
- PtrPinnedTIndirectBlock = NULL;
- }
-
- if ( PtrDIArray )
- {
- ULONG i;
- for( i = 0; i < DIArrayCount; i++ )
- {
- CcUnpinData( PtrDIArray->PtrBCB );
- }
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Read]", PtrDIArray );
- ExFreePool( PtrDIArray );
- PtrDIArray = NULL;
- }
- if ( PtrTIArray )
- {
- ULONG i;
- for( i = 0; i < TIArrayCount; i++ )
- {
- CcUnpinData( PtrTIArray->PtrBCB );
- }
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Read]", PtrTIArray );
- ExFreePool( PtrTIArray );
- PtrTIArray = NULL;
- }
- //
- // Pass down Associated IRPs to the Target Device Driver...
- //
- DebugTrace( DEBUG_TRACE_MISC, "Passing down the Read IRPs to the disk driver...", 0 );
-
- RC = Ext2PassDownMultiReadWriteIRP( PtrIoRuns, Index+1, ReadLength, PtrIrpContext, PtrFCB, SynchronousIo );
-
- //
- // Irp will be completed automatically
- // when all the Associated IRPs are completed
- //
- if( RC == STATUS_SUCCESS || RC == STATUS_PENDING )
- {
- CompleteIrp = FALSE;
- }
- try_return();
-
- }
- try_exit: NOTHING;
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- DebugTrace(DEBUG_TRACE_ERROR, "@@@@@@@@ Exception Handler", 0);
- }
- }
- finally
- {
- if ( PtrIoRuns )
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Read]", PtrIoRuns );
- ExFreePool( PtrIoRuns );
- }
- //
- // Unpin the Indirect Blocks
- //
- if( PtrPinnedSIndirectBCB )
- {
- CcUnpinData( PtrPinnedSIndirectBCB );
- PtrPinnedSIndirectBCB = NULL;
- }
-
- if( PtrPinnedDIndirectBCB )
- {
- CcUnpinData( PtrPinnedDIndirectBCB );
- PtrPinnedDIndirectBCB = NULL;
- }
- if( PtrPinnedTIndirectBCB )
- {
- CcUnpinData( PtrPinnedTIndirectBCB );
- PtrPinnedTIndirectBCB = NULL;
- }
-
- if ( PtrDIArray )
- {
- ULONG i;
- for( i = 0; i < DIArrayCount; i++ )
- {
- CcUnpinData( PtrDIArray->PtrBCB );
- }
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Read]", PtrDIArray );
- ExFreePool( PtrDIArray );
- }
-
- if ( PtrTIArray )
- {
- ULONG i;
- for( i = 0; i < TIArrayCount; i++ )
- {
- CcUnpinData( PtrTIArray->PtrBCB );
- }
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Read]", PtrTIArray );
- ExFreePool( PtrTIArray );
- }
-
- // Release any resources acquired here ...
- if (PtrResourceAcquired)
- {
- Ext2ReleaseResource(PtrResourceAcquired);
-
- DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Read]",
- PtrResourceAcquired->ActiveCount,
- PtrResourceAcquired->NumberOfExclusiveWaiters,
- PtrResourceAcquired->NumberOfSharedWaiters );
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Read]", PtrFileObject);
- }
- if( PtrVCB && PtrResourceAcquired == &(PtrVCB->VCBResource) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Read]", 0);
- }
- else if( PtrVCB && PtrResourceAcquired == &(PtrVCB->PagingIoResource ) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCBPaging Released [Read]", 0);
- }
- else if( PtrReqdFCB && PtrResourceAcquired == &(PtrReqdFCB->PagingIoResource) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Paging Resource Released [Read]", 0);
- }
- else if(PtrReqdFCB && PtrResourceAcquired == &(PtrReqdFCB->MainResource) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Resource Released [Read]", 0);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Unknown Resource Released [Read]", 0);
- }
-
- PtrResourceAcquired = NULL;
- }
-
- // Post IRP if required
- if ( PostRequest )
- {
-
- // Implement a routine that will queue up the request to be executed
- // later (asynchronously) in the context of a system worker thread.
- // See Chapter 10 for details.
-
- // Lock the callers buffer here. Then invoke a common routine to
- // perform the post operation.
- if (!(PtrIoStackLocation->MinorFunction & IRP_MN_MDL))
- {
- RC = Ext2LockCallersBuffer(PtrIrp, TRUE, ReadLength);
- ASSERT(NT_SUCCESS(RC));
- }
-
- // Perform the post operation which will mark the IRP pending
- // and will return STATUS_PENDING back to us
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
- }
- else if (CompleteIrp && !(RC == STATUS_PENDING))
- {
- // For synchronous I/O, the FSD must maintain the current byte offset
- // Do not do this however, if I/O is marked as paging-io
- if (SynchronousIo && !PagingIo && NT_SUCCESS(RC))
- {
- PtrFileObject->CurrentByteOffset = RtlLargeIntegerAdd(ByteOffset, RtlConvertUlongToLargeInteger((unsigned long)NumberBytesRead));
- }
-
- // If the read completed successfully and this was not a paging-io
- // operation, set a flag in the CCB that indicates that a read was
- // performed and that the file time should be updated at cleanup
- if (NT_SUCCESS(RC) && !PagingIo)
- {
- Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_ACCESSED);
- }
-
- // Can complete the IRP here if no exception was encountered
- if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION))
- {
-
- PtrIrp->IoStatus.Status = RC;
- PtrIrp->IoStatus.Information = NumberBytesRead;
-
- // Free up the Irp Context
- Ext2ReleaseIrpContext(PtrIrpContext);
-
- // complete the IRP
- IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
- }
- } // can we complete the IRP ?
- else
- {
- // Free up the Irp Context
- Ext2ReleaseIrpContext(PtrIrpContext);
- }
- } // end of "finally" processing
-
- return(RC);
-}
+ PIRP Irp = NULL;
+ BOOLEAN bPrint;
+
+ Irp = IrpContext->Irp;
+
+ if (Irp != NULL) {
+
+ if (NT_ERROR(Status)) {
+ Irp->IoStatus.Information = 0;
+ }
+ Irp->IoStatus.Status = Status;
+ bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+ Ext2CompleteRequest(
+ Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)?
+ IO_DISK_INCREMENT : IO_NO_INCREMENT) );
+ IrpContext->Irp = NULL;
+ }
-/*************************************************************************
-*
-* Function: Ext2GetCallersBuffer()
-*
-* Description:
-* Obtain a pointer to the caller's buffer.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-void * NTAPI Ext2GetCallersBuffer (
- PIRP PtrIrp )
+ Ext2FreeIrpContext(IrpContext);
+
+ return Status;
+}
+
+
+NTSTATUS
+Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
- void * ReturnedBuffer = NULL;
-
- // If an MDL is supplied, use it.
- if (PtrIrp->MdlAddress)
- {
- ReturnedBuffer = MmGetSystemAddressForMdl(PtrIrp->MdlAddress);
- }
- else
- {
- ReturnedBuffer = PtrIrp->UserBuffer;
- }
-
- return (ReturnedBuffer);
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ PEXT2_VCB Vcb;
+ PEXT2_CCB Ccb;
+ PEXT2_FCBVCB FcbOrVcb;
+ PFILE_OBJECT FileObject;
+
+ PDEVICE_OBJECT DeviceObject;
+
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION IoStackLocation;
+
+ ULONG Length;
+ LARGE_INTEGER ByteOffset;
+
+ BOOLEAN PagingIo;
+ BOOLEAN Nocache;
+ BOOLEAN SynchronousIo;
+ BOOLEAN MainResourceAcquired = FALSE;
+
+ PUCHAR Buffer = NULL;
+ EXT2_EXTENT BlockArray;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ FileObject = IrpContext->FileObject;
+ FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
+ ASSERT(FcbOrVcb);
+
+ if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
+
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ Irp = IrpContext->Irp;
+ Irp->IoStatus.Information = 0;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ Length = IoStackLocation->Parameters.Read.Length;
+ ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
+
+ PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
+ Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
+ SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
+
+ if (PagingIo) {
+ ASSERT(Nocache);
+ }
+
+ if (Length == 0) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
+ ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ if (ByteOffset.QuadPart >=
+ Vcb->PartitionInformation.PartitionLength.QuadPart ) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_END_OF_FILE;
+ _SEH2_LEAVE;
+ }
+
+ if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
+ Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+ }
+
+ /*
+ * User direct volume access
+ */
+
+ if (Ccb != NULL && !PagingIo) {
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ MainResourceAcquired = TRUE;
+
+ if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {
+
+ if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
+ Ext2FlushVolume(IrpContext, Vcb, FALSE);
+ }
+
+ SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
+ }
+
+ ExReleaseResourceLite(&Vcb->MainResource);
+ MainResourceAcquired = FALSE;
+
+ /* will do Nocache i/o */
+ }
+
+ /*
+ * I/O to volume StreamObject
+ */
+
+ if (!Nocache) {
+
+ if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
+
+ CcMdlRead(
+ Vcb->Volume,
+ &ByteOffset,
+ Length,
+ &Irp->MdlAddress,
+ &Irp->IoStatus );
+
+ Status = Irp->IoStatus.Status;
+
+ } else {
+
+ Buffer = Ext2GetUserBuffer(Irp);
+ if (Buffer == NULL) {
+ DbgBreak();
+ Status = STATUS_INVALID_USER_BUFFER;
+ _SEH2_LEAVE;
+ }
+
+ if (!CcCopyRead(
+ Vcb->Volume,
+ &ByteOffset,
+ Length,
+ Ext2CanIWait(),
+ Buffer,
+ &Irp->IoStatus )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ Status = Irp->IoStatus.Status;
+ }
+
+ } else {
+
+ Length &= ~((ULONG)SECTOR_SIZE - 1);
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoWriteAccess );
+
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ BlockArray.Irp = NULL;
+ BlockArray.Lba = ByteOffset.QuadPart;
+ BlockArray.Offset = 0;
+ BlockArray.Length = Length;
+ BlockArray.Next = NULL;
+
+ Status = Ext2ReadWriteBlocks(IrpContext,
+ Vcb,
+ &BlockArray,
+ Length );
+
+ Irp = IrpContext->Irp;
+ if (!Irp) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ } _SEH2_FINALLY {
+
+ if (MainResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+
+ if (Irp) {
+
+ if (Status == STATUS_PENDING &&
+ !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) {
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoWriteAccess );
+
+ if (NT_SUCCESS(Status)) {
+ Status = Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+
+ } else {
+
+ if (NT_SUCCESS(Status)) {
+
+ if (!PagingIo) {
+
+ if (SynchronousIo) {
+
+ FileObject->CurrentByteOffset.QuadPart =
+ ByteOffset.QuadPart + Irp->IoStatus.Information;
+ }
+
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ }
+ }
+
+ Ext2CompleteIrpContext(IrpContext, Status);;
+ }
+
+ } else {
+ Ext2FreeIrpContext(IrpContext);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
}
+#define SafeZeroMemory(AT,BYTE_COUNT) { \
+ _SEH2_TRY { \
+ if (AT) \
+ RtlZeroMemory((AT), (BYTE_COUNT)); \
+ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
+ Ext2RaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \
+ } _SEH2_END; \
+}
-/*************************************************************************
-*
-* Function: Ext2LockCallersBuffer()
-*
-* Description:
-* Obtain a MDL that describes the buffer. Lock pages for I/O
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2LockCallersBuffer(
-PIRP PtrIrp,
-BOOLEAN IsReadOperation,
-uint32 Length)
+NTSTATUS
+Ext2ReadInode (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_MCB Mcb,
+ IN ULONGLONG Offset,
+ IN PVOID Buffer,
+ IN ULONG Size,
+ IN BOOLEAN bDirectIo,
+ OUT PULONG BytesRead
+)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PMDL PtrMdl = NULL;
-
- ASSERT(PtrIrp);
-
- try
- {
- // Is a MDL already present in the IRP
- if( !(PtrIrp->MdlAddress) )
- {
- // Allocate a MDL
- if (!(PtrMdl = IoAllocateMdl(PtrIrp->UserBuffer, Length, FALSE, FALSE, PtrIrp)))
- {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- // Probe and lock the pages described by the MDL
- // We could encounter an exception doing so, swallow the exception
- // NOTE: The exception could be due to an unexpected (from our
- // perspective), invalidation of the virtual addresses that comprise
- // the passed in buffer
- try
- {
- MmProbeAndLockPages(PtrMdl, PtrIrp->RequestorMode, (IsReadOperation ? IoWriteAccess:IoReadAccess));
- }
- except(EXCEPTION_EXECUTE_HANDLER)
- {
- RC = STATUS_INVALID_USER_BUFFER;
- }
- }
-
- try_exit: NOTHING;
-
- }
- finally
- {
- if (!NT_SUCCESS(RC) && PtrMdl)
- {
- IoFreeMdl(PtrMdl);
- // You MUST NULL out the MdlAddress field in the IRP after freeing
- // the MDL, else the I/O Manager will also attempt to free the MDL
- // pointed to by that field during I/O completion. Obviously, the
- // pointer becomes invalid once you free the allocated MDL and hence
- // you will encounter a system crash during IRP completion.
- PtrIrp->MdlAddress = NULL;
- }
- }
-
- return(RC);
+ PEXT2_EXTENT Chain = NULL;
+ PEXT2_EXTENT Extent = NULL, Prev = NULL;
+
+ IO_STATUS_BLOCK IoStatus;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ ULONG RealSize ;
+
+ if (BytesRead) {
+ *BytesRead = 0;
+ }
+
+ _SEH2_TRY {
+
+ Ext2ReferMcb(Mcb);
+
+ ASSERT((Mcb->Identifier.Type == EXT2MCB) &&
+ (Mcb->Identifier.Size == sizeof(EXT2_MCB)));
+
+ if ((Mcb->Identifier.Type != EXT2MCB) ||
+ (Mcb->Identifier.Size != sizeof(EXT2_MCB))) {
+ _SEH2_LEAVE;
+ }
+
+ if (Buffer == NULL && IrpContext != NULL)
+ Buffer = Ext2GetUserBuffer(IrpContext->Irp);
+
+
+ /* handle fast symlinks */
+ if (S_ISLNK(Mcb->Inode.i_mode) &&
+ Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
+
+ PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]);
+
+ if (!Buffer) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+
+ if (Offset < EXT2_LINKLEN_IN_INODE) {
+ if ((ULONG)Offset + Size >= EXT2_LINKLEN_IN_INODE)
+ Size = EXT2_LINKLEN_IN_INODE - (ULONG)Offset - 1;
+ RtlCopyMemory(Buffer, Data + (ULONG)Offset, Size);
+ Status = STATUS_SUCCESS;
+ } else {
+ Status = STATUS_END_OF_FILE;
+ }
+ _SEH2_LEAVE;
+ }
+
+ //
+ // Build the scatterred block ranges to be read
+ //
+
+ if (bDirectIo) {
+ RealSize = CEILING_ALIGNED(ULONG, Size, SECTOR_SIZE - 1);
+ } else {
+ RealSize = Size;
+ }
+
+ Status = Ext2BuildExtents(
+ IrpContext,
+ Vcb,
+ Mcb,
+ Offset,
+ RealSize,
+ FALSE,
+ &Chain
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ if (Chain == NULL) {
+ SafeZeroMemory((PCHAR)Buffer, Size);
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ /* for sparse file, we need zero the gaps */
+ for (Extent = Chain; Buffer != NULL && Extent != NULL; Extent = Extent->Next) {
+ if (NULL == Prev) {
+ ASSERT(Extent == Chain);
+ if (Extent->Offset) {
+ SafeZeroMemory((PCHAR)Buffer, Extent->Offset);
+ }
+ } else if (Extent->Offset > (Prev->Offset + Prev->Length)) {
+ SafeZeroMemory((PCHAR)Buffer + Prev->Offset + Prev->Length,
+ Extent->Offset - Prev->Offset - Prev->Length);
+ }
+ if (NULL == Extent->Next) {
+ if (Extent->Offset + Extent->Length < Size) {
+ SafeZeroMemory((PCHAR)Buffer + Extent->Offset + Extent->Length,
+ Size - Extent->Offset - Extent->Length);
+ }
+ }
+ Prev = Extent;
+ }
+
+ if (bDirectIo) {
+
+ ASSERT(IrpContext != NULL);
+
+ // Offset should be SECTOR_SIZE aligned ...
+ Status = Ext2ReadWriteBlocks(
+ IrpContext,
+ Vcb,
+ Chain,
+ Size
+ );
+ } else {
+
+ for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
+
+ if (!CcCopyRead(
+ Vcb->Volume,
+ (PLARGE_INTEGER)(&(Extent->Lba)),
+ Extent->Length,
+ PIN_WAIT,
+ (PVOID)((PUCHAR)Buffer + Extent->Offset),
+ &IoStatus
+ )) {
+ Status = STATUS_CANT_WAIT;
+ } else {
+ Status = IoStatus.Status;
+ }
+
+ if (!NT_SUCCESS(Status)) {
+ break;
+ }
+ }
+ }
+
+ } _SEH2_FINALLY {
+
+ if (Chain) {
+ Ext2DestroyExtentChain(Chain);
+ }
+
+ Ext2DerefMcb(Mcb);
+ } _SEH2_END;
+
+ if (NT_SUCCESS(Status)) {
+ if (BytesRead)
+ *BytesRead = Size;
+ }
+
+ return Status;
}
+NTSTATUS
+Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ PEXT2_VCB Vcb;
+ PEXT2_FCB Fcb;
+ PEXT2_CCB Ccb;
+ PFILE_OBJECT FileObject;
+
+ PDEVICE_OBJECT DeviceObject;
+
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+
+ ULONG Length;
+ ULONG ReturnedLength = 0;
+ LARGE_INTEGER ByteOffset;
+
+ BOOLEAN OpPostIrp = FALSE;
+ BOOLEAN PagingIo;
+ BOOLEAN Nocache;
+ BOOLEAN SynchronousIo;
+ BOOLEAN MainResourceAcquired = FALSE;
+ BOOLEAN PagingIoResourceAcquired = FALSE;
+
+ PUCHAR Buffer;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ FileObject = IrpContext->FileObject;
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ ASSERT(Fcb);
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ Length = IoStackLocation->Parameters.Read.Length;
+ ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
+
+ PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
+ Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
+ SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
+
+ if (PagingIo) {
+ ASSERT(Nocache);
+ }
+
+ DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
+ &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
+
+ if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ||
+ IsFileDeleted(Fcb->Mcb)) {
+ Status = STATUS_FILE_DELETED;
+ _SEH2_LEAVE;
+ }
+
+ if (Length == 0) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if (Nocache &&
+ (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
+ Length & (SECTOR_SIZE - 1))) {
+ Status = STATUS_INVALID_PARAMETER;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
+ ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+ Status = STATUS_PENDING;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ if (!PagingIo && Nocache && (FileObject->SectionObjectPointer->DataSectionObject != NULL)) {
+ CcFlushCache( FileObject->SectionObjectPointer,
+ &ByteOffset,
+ Length,
+ &Irp->IoStatus );
+
+ if (!NT_SUCCESS(Irp->IoStatus.Status)) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ ReturnedLength = Length;
+
+ if (PagingIo) {
+
+ if (!ExAcquireResourceSharedLite(
+ &Fcb->PagingIoResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ PagingIoResourceAcquired = TRUE;
+
+ } else {
+
+ if (Nocache) {
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ MainResourceAcquired = TRUE;
+
+ } else {
+
+ if (!ExAcquireResourceSharedLite(
+ &Fcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ MainResourceAcquired = TRUE;
+ }
+
+ if (!FsRtlCheckLockForReadAccess(
+ &Fcb->FileLockAnchor,
+ Irp )) {
+ Status = STATUS_FILE_LOCK_CONFLICT;
+ _SEH2_LEAVE;
+ }
+ }
+
+ if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.FileSize.QuadPart) {
+ if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_END_OF_FILE;
+ _SEH2_LEAVE;
+ }
+ ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+ }
+
+
+ if (!IsDirectory(Fcb) && Ccb != NULL) {
+ Status = FsRtlCheckOplock( &Fcb->Oplock,
+ Irp,
+ IrpContext,
+ Ext2OplockComplete,
+ Ext2LockIrp );
+
+ if (Status != STATUS_SUCCESS) {
+ OpPostIrp = TRUE;
+ _SEH2_LEAVE;
+ }
+
+ //
+ // Set the flag indicating if Fast I/O is possible
+ //
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+ }
+
+ if (!Nocache) {
+
+ if (IsDirectory(Fcb)) {
+ _SEH2_LEAVE;
+ }
+
+ if (FileObject->PrivateCacheMap == NULL) {
+ CcInitializeCacheMap(
+ FileObject,
+ (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
+ FALSE,
+ &Ext2Global->CacheManagerCallbacks,
+ Fcb );
+ CcSetReadAheadGranularity(
+ FileObject,
+ READ_AHEAD_GRANULARITY );
+ }
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
+ CcMdlRead(
+ FileObject,
+ (&ByteOffset),
+ ReturnedLength,
+ &Irp->MdlAddress,
+ &Irp->IoStatus );
+
+ Status = Irp->IoStatus.Status;
+
+ } else {
+
+ Buffer = Ext2GetUserBuffer(Irp);
+ if (Buffer == NULL) {
+ Status = STATUS_INVALID_USER_BUFFER;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+
+ if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength,
+ Ext2CanIWait(), Buffer, &Irp->IoStatus)) {
+
+ if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset,
+ ReturnedLength, TRUE,
+ Buffer, &Irp->IoStatus)) {
+ Status = STATUS_PENDING;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+ }
+ Status = Irp->IoStatus.Status;
+ }
+
+ } else {
+
+ ULONG BytesRead = ReturnedLength;
+ PUCHAR SystemVA = Ext2GetUserBuffer(IrpContext->Irp);
+
+ if (ByteOffset.QuadPart + BytesRead > Fcb->Header.ValidDataLength.QuadPart) {
+
+ if (ByteOffset.QuadPart >= Fcb->Header.ValidDataLength.QuadPart) {
+ if (SystemVA) {
+ SafeZeroMemory(SystemVA, Length);
+ }
+ Irp->IoStatus.Information = ReturnedLength;
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ } else {
+ BytesRead = (ULONG)(Fcb->Header.ValidDataLength.QuadPart - ByteOffset.QuadPart);
+ if (SystemVA) {
+ SafeZeroMemory(SystemVA + BytesRead, Length - BytesRead);
+ }
+ }
+ }
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ BytesRead,
+ IoReadAccess );
+
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ Status = Ext2ReadInode(
+ IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ ByteOffset.QuadPart,
+ NULL,
+ BytesRead,
+ TRUE,
+ NULL );
+
+ /* we need re-queue this request in case STATUS_CANT_WAIT
+ and fail it in other failure cases */
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ /* pended by low level device */
+ if (Status == STATUS_PENDING) {
+ IrpContext->Irp = Irp = NULL;
+ _SEH2_LEAVE;
+ }
+
+ Irp = IrpContext->Irp;
+ ASSERT(Irp);
+ Status = Irp->IoStatus.Status;
+
+ if (!NT_SUCCESS(Status)) {
+ Ext2NormalizeAndRaiseStatus(IrpContext, Status);
+ }
+ }
+
+ Irp->IoStatus.Information = ReturnedLength;
+
+ } _SEH2_FINALLY {
+
+ if (Irp) {
+ if (PagingIoResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ }
+
+ if (MainResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+ }
+
+ if (!OpPostIrp && !IrpContext->ExceptionInProgress) {
+
+ if (Irp) {
+ if ( Status == STATUS_PENDING ||
+ Status == STATUS_CANT_WAIT) {
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoWriteAccess );
+
+ if (NT_SUCCESS(Status)) {
+ Status = Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } else {
+ if (NT_SUCCESS(Status)) {
+ if (!PagingIo) {
+ if (SynchronousIo) {
+ FileObject->CurrentByteOffset.QuadPart =
+ ByteOffset.QuadPart + Irp->IoStatus.Information;
+ }
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ }
+ }
+
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+
+ } else {
+
+ Ext2FreeIrpContext(IrpContext);
+ }
+ }
+ } _SEH2_END;
+
+ DEBUG(DL_IO, ("Ext2ReadFile: %wZ fetch at Off=%I64xh Len=%xh Paging=%xh Nocache=%xh Returned=%xh Status=%xh\n",
+ &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache, ReturnedLength, Status));
+ return Status;
+}
-/*************************************************************************
-*
-* Function: Ext2MdlComplete()
-*
-* Description:
-* Tell Cache Manager to release MDL (and possibly flush).
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None.
-*
-*************************************************************************/
-void NTAPI Ext2MdlComplete(
- PtrExt2IrpContext PtrIrpContext,
- PIRP PtrIrp,
- PIO_STACK_LOCATION PtrIoStackLocation,
- BOOLEAN ReadCompletion)
+NTSTATUS
+Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext)
{
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PFILE_OBJECT FileObject;
+ PIRP Irp;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ FileObject = IrpContext->FileObject;
+ Irp = IrpContext->Irp;
+
+ CcMdlReadComplete(FileObject, Irp->MdlAddress);
+ Irp->MdlAddress = NULL;
+ Status = STATUS_SUCCESS;
+
+ } _SEH2_FINALLY {
+
+ if (!IrpContext->ExceptionInProgress) {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+
+NTSTATUS
+Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ NTSTATUS Status;
+ PEXT2_VCB Vcb;
+ PEXT2_FCBVCB FcbOrVcb;
+ PDEVICE_OBJECT DeviceObject;
+ PFILE_OBJECT FileObject;
+ BOOLEAN bCompleteRequest;
+
+ ASSERT(IrpContext);
+
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ _SEH2_TRY {
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
+
+ Status = Ext2ReadComplete(IrpContext);
+ bCompleteRequest = FALSE;
+
+ } else {
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ bCompleteRequest = TRUE;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ if (Vcb->Identifier.Type != EXT2VCB ||
+ Vcb->Identifier.Size != sizeof(EXT2_VCB) ) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ bCompleteRequest = TRUE;
+
+ _SEH2_LEAVE;
+ }
+
+ FileObject = IrpContext->FileObject;
+
+ if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
+ Vcb->LockFile != FileObject ) {
+ Status = STATUS_ACCESS_DENIED;
+ _SEH2_LEAVE;
+ }
+
+ FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
+
+ if (FcbOrVcb->Identifier.Type == EXT2VCB) {
- NTSTATUS RC = STATUS_SUCCESS;
- PFILE_OBJECT PtrFileObject = NULL;
+ Status = Ext2ReadVolume(IrpContext);
+ bCompleteRequest = FALSE;
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
+ } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
- // Not much to do here.
- if( ReadCompletion )
- {
- CcMdlReadComplete( PtrFileObject, PtrIrp->MdlAddress );
- }
- else
- {
- // The Cache Manager needs the byte offset in the I/O stack location.
- CcMdlWriteComplete( PtrFileObject, &(PtrIoStackLocation->Parameters.Write.ByteOffset), PtrIrp->MdlAddress );
- }
+ if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
+ Status = STATUS_TOO_LATE;
+ bCompleteRequest = TRUE;
+ _SEH2_LEAVE;
+ }
- // Clear the MDL address field in the IRP so the IoCompleteRequest()
- // does not try to play around with the MDL.
- PtrIrp->MdlAddress = NULL;
+ Status = Ext2ReadFile(IrpContext);
+ bCompleteRequest = FALSE;
+ } else {
+ DEBUG(DL_ERR, ( "Ext2Read: Inavlid FileObject (Vcb or Fcb corrupted)\n"));
+ DbgBreak();
- // Free up the Irp Context.
- Ext2ReleaseIrpContext(PtrIrpContext);
+ Status = STATUS_INVALID_PARAMETER;
+ bCompleteRequest = TRUE;
+ }
+ }
- // Complete the IRP.
- PtrIrp->IoStatus.Status = RC;
- PtrIrp->IoStatus.Information = 0;
- IoCompleteRequest(PtrIrp, IO_NO_INCREMENT);
+ } _SEH2_FINALLY {
+ if (bCompleteRequest) {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } _SEH2_END;
- return;
+ return Status;
}
-/*************************************************************************
-*
-* File: shutdown.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the "shutdown notification" dispatch entry point.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_SHUTDOWN
-#define DEBUG_LEVEL (DEBUG_TRACE_SHUTDOWN)
-
-
-/*************************************************************************
-*
-* Function: Ext2Shutdown()
-*
-* Description:
-* All disk-based FSDs can expect to receive this shutdown notification
-* request whenever the system is about to be halted gracefully. If you
-* design and implement a network redirector, you must register explicitly
-* for shutdown notification by invoking the IoRegisterShutdownNotification()
-* routine from your driver entry.
-*
-* Note that drivers that register to receive shutdown notification get
-* invoked BEFORE disk-based FSDs are told about the shutdown notification.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: Irrelevant.
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Shutdown(
- PDEVICE_OBJECT DeviceObject, // the logical volume device object
- PIRP Irp) // I/O Request Packet
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
-
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Shutdown IRP received...", 0);
-
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
-
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
-
- try
- {
-
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
-
- RC = Ext2CommonShutdown(PtrIrpContext, Irp);
-
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
-
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
-
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
-
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
-}
-
-
-/*************************************************************************
-*
-* Function: Ext2CommonShutdown()
-*
-* Description:
-* The actual work is performed here. Basically, all we do here is
-* internally invoke a flush on all mounted logical volumes. This, in
-* tuen, will result in all open file streams being flushed to disk.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: Irrelevant
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonShutdown(
-PtrExt2IrpContext PtrIrpContext,
-PIRP PtrIrp)
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: shutdown.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+/* DEFINITIONS *************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2ShutDown)
+#endif
+
+NTSTATUS
+Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
{
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
-
- try
- {
- // First, get a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- // (a) Block all new "mount volume" requests by acquiring an appropriate
- // global resource/lock.
- // (b) Go through your linked list of mounted logical volumes and for
- // each such volume, do the following:
- // (i) acquire the volume resource exclusively
- // (ii) invoke Ext2FlushLogicalVolume() (internally) to flush the
- // open data streams belonging to the volume from the system
- // cache
- // (iii) Invoke the physical/virtual/logical target device object
- // on which the volume is mounted and inform this device
- // about the shutdown request (Use IoBuildSynchronousFsdRequest()
- // to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you
- // will then issue to the target device object).
- // (iv) Wait for the completion of the shutdown processing by the target
- // device object
- // (v) Release the VCB resource you will have acquired in (i) above.
-
- // Once you have processed all the mounted logical volumes, you can release
- // all acquired global resources and leave (in peace :-)
-
-
-
-/*////////////////////////////////////////////
- //
- // Update the Group...
- //
- if( PtrVCB->LogBlockSize )
- {
- // First block contains the descriptors...
- VolumeByteOffset.QuadPart = LogicalBlockSize;
- }
- else
- {
- // Second block contains the descriptors...
- VolumeByteOffset.QuadPart = LogicalBlockSize * 2;
- }
-
- NumberOfBytesToRead = sizeof( struct ext2_group_desc );
- NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize );
-
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- NumberOfBytesToRead,
- TRUE,
- &PtrBCB,
- &PtrCacheBuffer ))
- {
- DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
- try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
- }
- else
- {
- //
- // Saving up Often Used Group Descriptor Information in the VCB...
- //
- unsigned int DescIndex ;
-
- DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
- PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer;
- for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ )
- {
- PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock
- = PtrGroupDescriptor[ DescIndex ].bg_inode_table;
-
- PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock
- = PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap
- ;
- PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock
- = PtrGroupDescriptor[ DescIndex ].bg_block_bitmap
- ;
- PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount
- = PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count;
-
- PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount
- = PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count;
- }
- CcUnpinData( PtrBCB );
- PtrBCB = NULL;
- }
-*/////////////////////////////////////////////
-
- }
- finally
- {
-
- // See the read/write examples for how to fill in this portion
-
- } // end of "finally" processing
-
- return(RC);
-}
+ NTSTATUS Status;
+
+ PIRP Irp;
+
+ PEXT2_VCB Vcb;
+ PLIST_ENTRY ListEntry;
+
+ BOOLEAN GlobalResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ Status = STATUS_SUCCESS;
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ Irp = IrpContext->Irp;
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Ext2Global->Resource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ GlobalResourceAcquired = TRUE;
+
+ for (ListEntry = Ext2Global->VcbList.Flink;
+ ListEntry != &(Ext2Global->VcbList);
+ ListEntry = ListEntry->Flink ) {
+
+ Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
+
+ if (ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource,
+ TRUE )) {
+
+ if (IsMounted(Vcb)) {
+
+ /* update mount count */
+ Vcb->SuperBlock->s_mnt_count++;
+ if (Vcb->SuperBlock->s_mnt_count >
+ Vcb->SuperBlock->s_max_mnt_count ) {
+ Vcb->SuperBlock->s_mnt_count =
+ Vcb->SuperBlock->s_max_mnt_count;
+ }
+ Ext2SaveSuper(IrpContext, Vcb);
+
+ /* flush dirty cache for all files */
+ Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ }
+
+ /* flush volume stream's cache to disk */
+ Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);
+
+ if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
+ DbgBreak();
+ }
+
+ /* send shutdown request to underlying disk */
+ Ext2DiskShutDown(Vcb);
+ }
+
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+ }
+
+ /*
+ IoUnregisterFileSystem(Ext2Global->DiskdevObject);
+ IoUnregisterFileSystem(Ext2Global->CdromdevObject);
+ */
+
+ } _SEH2_FINALLY {
+
+ if (GlobalResourceAcquired) {
+ ExReleaseResourceLite(&Ext2Global->Resource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+ if (Status == STATUS_PENDING) {
+ Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
+}
\ No newline at end of file
-/*************************************************************************
-*
-* File: volinfo.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the various Volume Information related calls.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-
-
-#include "ext2fsd.h"
-
-
-
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_VOL_INFORMATION
-#define DEBUG_LEVEL (DEBUG_TRACE_VOLINFO)
-
-
-/*************************************************************************
-*
-* Function: Ext2QueryVolInfo()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a
-* Query Volume Info IRP
-*
-* Expected Interrupt Level (for execution) :
-*
-* ???
-*
-* Arguments:
-*
-* DeviceObject - Supplies the volume device object where the
-* file exists
-*
-* Irp - Supplies the Irp being processed
-*
-*
-* Return Value:
-*
-* NTSTATUS - The FSD status for the IRP
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2QueryVolInfo (
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: volinfo.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+/* DEFINITIONS *************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
+#pragma alloc_text(PAGE, Ext2SetVolumeInformation)
+#endif
+
+
+NTSTATUS
+Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
{
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PEXT2_VCB Vcb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+ FS_INFORMATION_CLASS FsInformationClass;
+ ULONG Length;
+ PVOID Buffer;
+ BOOLEAN VcbResourceAcquired = FALSE;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext != NULL);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ if (!IsMounted(Vcb)) {
+ Status = STATUS_VOLUME_DISMOUNTED;
+ _SEH2_LEAVE;
+ }
+
+ if (!ExAcquireResourceSharedLite(
+ &Vcb->MainResource,
+ IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
+ )) {
+
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ VcbResourceAcquired = TRUE;
+
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ FsInformationClass =
+ IoStackLocation->Parameters.QueryVolume.FsInformationClass;
+
+ Length = IoStackLocation->Parameters.QueryVolume.Length;
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+ RtlZeroMemory(Buffer, Length);
+
+ switch (FsInformationClass) {
- // The Return Status
- NTSTATUS Status = STATUS_SUCCESS;
-
- // The IRP Stack Location
- PIO_STACK_LOCATION IrpSp = NULL;
-
- // Volume Control Block
- PtrExt2VCB PtrVCB = NULL;
-
- // The class of the query IRP
- FS_INFORMATION_CLASS FsInformationClass;
-
- // The System Buffer Pointer
- PVOID Buffer = NULL;
-
- // Parameter Length
- ULONG Length = 0;
-
- // Bytes copied...
- ULONG BytesCopied = 0;
-
- // Pointers to the Output Information...
- PFILE_FS_VOLUME_INFORMATION PtrVolumeInformation = NULL;
- PFILE_FS_SIZE_INFORMATION PtrSizeInformation = NULL;
- PFILE_FS_ATTRIBUTE_INFORMATION PtrAttributeInformation = NULL;
- PFILE_FS_DEVICE_INFORMATION PtrDeviceInformation = NULL;
- PFILE_FS_FULL_SIZE_INFORMATION PtrFullSizeInformation = NULL;
-
-
- // Now for the handler code...
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "QueryVolumeInformation IRP", 0);
-
- FsRtlEnterFileSystem();
-
- try
- {
- // Getting a pointer to the current I/O stack location
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
- ASSERT( IrpSp );
-
- // Getting the VCB and Verifying it...
- PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension );
- ASSERT(PtrVCB);
- ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
-
- // Getting the query parameters...
- Length = IrpSp->Parameters.QueryVolume.Length;
- FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
- Buffer = Irp->AssociatedIrp.SystemBuffer;
-
- // Now servicing the request depending on the type...
- switch (FsInformationClass)
- {
case FileFsVolumeInformation:
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsVolumeInformation", 0);
- PtrVolumeInformation = Buffer;
- PtrVolumeInformation->SupportsObjects = FALSE;
- PtrVolumeInformation->VolumeCreationTime.QuadPart = 0;
- RtlCopyMemory(
- PtrVolumeInformation->VolumeLabel, // destination
- PtrVCB->PtrVPB->VolumeLabel, // source
- PtrVCB->PtrVPB->VolumeLabelLength );
- PtrVolumeInformation->VolumeLabelLength = PtrVCB->PtrVPB->VolumeLabelLength;
- PtrVolumeInformation->VolumeSerialNumber = PtrVCB->PtrVPB->SerialNumber;
- BytesCopied = sizeof( FILE_FS_VOLUME_INFORMATION ) + PtrVolumeInformation->VolumeLabelLength - sizeof( WCHAR);
- break;
+ {
+ PFILE_FS_VOLUME_INFORMATION FsVolInfo;
+ ULONG VolumeLabelLength;
+ ULONG RequiredLength;
+
+ if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer;
+ FsVolInfo->VolumeCreationTime.QuadPart = 0;
+ FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
+ VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
+ FsVolInfo->VolumeLabelLength = VolumeLabelLength;
+ /* We don't support ObjectId */
+ FsVolInfo->SupportsObjects = FALSE;
+
+ RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
+ + VolumeLabelLength - sizeof(WCHAR);
+
+ if (Length < RequiredLength) {
+ Irp->IoStatus.Information =
+ sizeof(FILE_FS_VOLUME_INFORMATION);
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
+
+ Irp->IoStatus.Information = RequiredLength;
+ Status = STATUS_SUCCESS;
+ }
+ break;
case FileFsSizeInformation:
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsSizeInformation", 0);
- PtrSizeInformation = Buffer;
- PtrSizeInformation->BytesPerSector = DeviceObject->SectorSize;
- PtrSizeInformation->AvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount;
- PtrSizeInformation->SectorsPerAllocationUnit = ( EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize;
- PtrSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount;
- BytesCopied = sizeof( FILE_FS_SIZE_INFORMATION );
- break;
+ {
+ PFILE_FS_SIZE_INFORMATION FsSizeInfo;
+
+ if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer;
+ FsSizeInfo->TotalAllocationUnits.QuadPart =
+ ext3_blocks_count(SUPER_BLOCK);
+ FsSizeInfo->AvailableAllocationUnits.QuadPart =
+ ext3_free_blocks_count(SUPER_BLOCK);
+ FsSizeInfo->SectorsPerAllocationUnit =
+ Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
+ FsSizeInfo->BytesPerSector =
+ Vcb->DiskGeometry.BytesPerSector;
+
+ Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
case FileFsDeviceInformation:
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsDeviceInformation", 0);
- PtrDeviceInformation = Buffer;
- PtrDeviceInformation->DeviceType = FILE_DEVICE_DISK;
- PtrDeviceInformation->Characteristics = FILE_DEVICE_IS_MOUNTED;
- BytesCopied = sizeof( FILE_FS_DEVICE_INFORMATION );
- break;
+ {
+ PFILE_FS_DEVICE_INFORMATION FsDevInfo;
+
+ if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer;
+ FsDevInfo->DeviceType =
+ Vcb->TargetDeviceObject->DeviceType;
+
+ if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) {
+ DbgBreak();
+ }
+
+ FsDevInfo->Characteristics =
+ Vcb->TargetDeviceObject->Characteristics;
+
+ if (IsVcbReadOnly(Vcb)) {
+ SetFlag( FsDevInfo->Characteristics,
+ FILE_READ_ONLY_DEVICE );
+ }
+
+ Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
case FileFsAttributeInformation:
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsAttributeInformation", 0);
- PtrAttributeInformation = Buffer;
- RtlCopyMemory( PtrAttributeInformation->FileSystemName, L"EXT2", 10 );
- PtrAttributeInformation->FileSystemNameLength = 8;
- PtrAttributeInformation->MaximumComponentNameLength = 255;
- PtrAttributeInformation->FileSystemAttributes =
- FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
- BytesCopied = sizeof( FILE_FS_ATTRIBUTE_INFORMATION ) + 8;
+ {
+ PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
+ ULONG RequiredLength;
+
+ if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FsAttrInfo =
+ (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
+ FsAttrInfo->FileSystemAttributes =
+ FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
+ if (IsVcbReadOnly(Vcb)) {
+ FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
+ }
+ FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN;
+ FsAttrInfo->FileSystemNameLength = 8;
+
+ RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
+ 8 - sizeof(WCHAR);
+
+ if (Length < RequiredLength) {
+ Irp->IoStatus.Information =
+ sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10);
+ } else if (Vcb->IsExt3fs) {
+ RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10);
+ } else {
+ RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10);
+ }
+
+ Irp->IoStatus.Information = RequiredLength;
+ Status = STATUS_SUCCESS;
+ }
+ break;
- break;
+#if (_WIN32_WINNT >= 0x0500)
case FileFsFullSizeInformation:
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsFullSizeInformation", 0);
- PtrFullSizeInformation = Buffer;
- PtrFullSizeInformation->BytesPerSector = DeviceObject->SectorSize;
- PtrFullSizeInformation->ActualAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount;
- PtrFullSizeInformation->SectorsPerAllocationUnit = (EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize;
- PtrFullSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount;
- PtrFullSizeInformation->CallerAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount - PtrVCB->ReservedBlocksCount;
- BytesCopied = sizeof( FILE_FS_FULL_SIZE_INFORMATION );
- break;
+ {
+ PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
+
+ if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) {
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer;
+
+ /*
+ typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
+ LARGE_INTEGER TotalAllocationUnits;
+ LARGE_INTEGER CallerAvailableAllocationUnits;
+ LARGE_INTEGER ActualAvailableAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+ } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
+ */
+
+ {
+ PFFFSI->TotalAllocationUnits.QuadPart =
+ ext3_blocks_count(SUPER_BLOCK);
+
+ PFFFSI->CallerAvailableAllocationUnits.QuadPart =
+ ext3_free_blocks_count(SUPER_BLOCK);
+
+ /* - Vcb->SuperBlock->s_r_blocks_count; */
+ PFFFSI->ActualAvailableAllocationUnits.QuadPart =
+ ext3_free_blocks_count(SUPER_BLOCK);
+ }
+
+ PFFFSI->SectorsPerAllocationUnit =
+ Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
+
+ PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
+
+ Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+#endif // (_WIN32_WINNT >= 0x0500)
default:
- Status = STATUS_INVALID_PARAMETER;
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0);
+ Status = STATUS_INVALID_INFO_CLASS;
break;
}
-
- if( IrpSp->Parameters.QueryVolume.Length < BytesCopied )
- {
- BytesCopied = IrpSp->Parameters.QueryVolume.Length;
- Status = STATUS_BUFFER_OVERFLOW;
- DebugTrace(DEBUG_TRACE_MISC, " === Buffer insufficient", 0);
- }
- }
- finally
- {
- Irp->IoStatus.Information = BytesCopied;
- Ext2CompleteRequest( Irp, Status );
- }
- FsRtlExitFileSystem();
-
- //
- // Now return to the caller
- //
+
+ } _SEH2_FINALLY {
+
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+ if (Status == STATUS_PENDING) {
+ Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
return Status;
}
+NTSTATUS
+Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PEXT2_VCB Vcb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+ FS_INFORMATION_CLASS FsInformationClass;
+ BOOLEAN VcbResourceAcquired = FALSE;
+ _SEH2_TRY {
-NTSTATUS NTAPI Ext2SetVolInfo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- // The Return Status
- NTSTATUS Status = STATUS_SUCCESS;
-
- // The IRP Stack Location
- PIO_STACK_LOCATION IrpSp = NULL;
-
- // Volume Control Block
- PtrExt2VCB PtrVCB = NULL;
-
- // The class of the query IRP
- FS_INFORMATION_CLASS FsInformationClass;
-
- // Pointers to the Output Information...
- PFILE_FS_LABEL_INFORMATION PtrVolumeLabelInformation = NULL;
-
- // Now for the handler code...
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Set Volume Information IRP", 0);
-
- FsRtlEnterFileSystem();
-
- try
- {
- // Getting a pointer to the current I/O stack location
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
- ASSERT( IrpSp );
-
- // Getting the VCB and Verifying it...
- PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension );
- AssertVCB(PtrVCB);
-
- // Getting the query parameters...
- // Length = IrpSp->Parameters.SetVolume.Length;
-#ifdef _GNU_NTIFS_
- FsInformationClass = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.SetVolume.FsInformationClass;
-#else
- FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
-#endif
+ ASSERT(IrpContext != NULL);
+
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+ ASSERT(IsMounted(Vcb));
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+
+ if (!ExAcquireResourceExclusiveLite(
+ &Vcb->MainResource, TRUE)) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ VcbResourceAcquired = TRUE;
+
+ Ext2VerifyVcb(IrpContext, Vcb);
+
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ //Notes: SetVolume is not defined in ntddk.h of win2k ddk,
+ // But it's same to QueryVolume ....
+ FsInformationClass =
+ IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
+
+ switch (FsInformationClass) {
+
+ case FileFsLabelInformation:
+ {
+ PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
+ ULONG VolLabelLen;
+ UNICODE_STRING LabelName ;
+
+ OEM_STRING OemName;
+
+ VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
+ VolLabelLen = VolLabelInfo->VolumeLabelLength;
+
+ if (VolLabelLen > (16 * sizeof(WCHAR))) {
+ Status = STATUS_INVALID_VOLUME_LABEL;
+ _SEH2_LEAVE;
+ }
+
+ RtlCopyMemory( Vcb->Vpb->VolumeLabel,
+ VolLabelInfo->VolumeLabel,
+ VolLabelLen );
+
+ RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16);
+ LabelName.Buffer = VolLabelInfo->VolumeLabel;
+ LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
+ LabelName.Length = (USHORT)VolLabelLen;
+
+ OemName.Buffer = SUPER_BLOCK->s_volume_name;
+ OemName.Length = 0;
+ OemName.MaximumLength = 16;
+
+ Ext2UnicodeToOEM(Vcb, &OemName, &LabelName);
+ Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen;
+
+ if (Ext2SaveSuper(IrpContext, Vcb)) {
+ Status = STATUS_SUCCESS;
+ }
+
+ Irp->IoStatus.Information = 0;
+ }
+ break;
- // Now servicing the request depending on the type...
- switch (FsInformationClass)
- {
- case FileFsLabelInformation:
- PtrVolumeLabelInformation = Irp->AssociatedIrp.SystemBuffer;
- if( PtrVolumeLabelInformation->VolumeLabelLength > MAXIMUM_VOLUME_LABEL_LENGTH || // This is the maximum that the
- // VPB can take...
- PtrVolumeLabelInformation->VolumeLabelLength > 32 ) // this is the maximum that Ext2 FS can support..
- {
- try_return( Status = STATUS_INVALID_VOLUME_LABEL );
- }
-
- PtrVCB->PtrVPB->VolumeLabelLength = (USHORT)PtrVolumeLabelInformation->VolumeLabelLength ;
- RtlCopyMemory(
- PtrVCB->PtrVPB->VolumeLabel, // destination
- PtrVolumeLabelInformation->VolumeLabel, // source
- PtrVolumeLabelInformation->VolumeLabelLength );
-
- {
- // Now update the volume's super block...
-
- PEXT2_SUPER_BLOCK PtrSuperBlock = NULL;
- PBCB PtrSuperBlockBCB = NULL;
- LARGE_INTEGER VolumeByteOffset;
- ULONG LogicalBlockSize = 0;
- ULONG NumberOfBytesToRead = 0;
-
-
- // Reading in the super block...
- VolumeByteOffset.QuadPart = 1024;
-
- LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-
- // THis shouldn't be more than a block in size...
- NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize );
-
- if( !CcPinRead( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- NumberOfBytesToRead,
- TRUE,
- &PtrSuperBlockBCB,
- (PVOID*)&PtrSuperBlock ) )
- {
- DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
- try_return( Status = STATUS_INVALID_VOLUME_LABEL );
- }
- else
- {
- ULONG i;
- for( i = 0; i < (PtrVolumeLabelInformation->VolumeLabelLength/2) ; i++ )
- {
- PtrSuperBlock->s_volume_name[i] =
- (char) PtrVolumeLabelInformation->VolumeLabel[i] ;
- if( PtrSuperBlock->s_volume_name[i] == 0 )
- {
- break;
- }
- }
- if( i < 16 )
- {
- PtrSuperBlock->s_volume_name[i] = 0;
- }
-
-
- CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL );
-
- // Not saving and flushing this information synchronously...
- // This is not a critical information..
- // Settling for lazy writing of this information
-
- // Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject );
-
- if( PtrSuperBlockBCB )
- {
- CcUnpinData( PtrSuperBlockBCB );
- PtrSuperBlockBCB = NULL;
- }
-
- }
- }
-
- break;
default:
- Status = STATUS_INVALID_PARAMETER;
- DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0);
- break;
- }
-
- try_exit: NOTHING;
- }
- finally
- {
- Irp->IoStatus.Information = 0;
- Ext2CompleteRequest( Irp, Status );
- }
- FsRtlExitFileSystem();
-
- //
- // Now return to the caller
- //
+ Status = STATUS_INVALID_INFO_CLASS;
+ }
+
+ } _SEH2_FINALLY {
+
+ if (VcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+ if (Status == STATUS_PENDING) {
+ Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
return Status;
-}
+}
\ No newline at end of file
-/*************************************************************************
-*
-* File: write.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-* Contains code to handle the "Write" dispatch entry point.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include "ext2fsd.h"
-
-// define the file specific bug-check id
-#define EXT2_BUG_CHECK_ID EXT2_FILE_WRITE
-
-#define DEBUG_LEVEL (DEBUG_TRACE_WRITE)
-
-
-/*************************************************************************
-*
-* Function: Ext2Write()
-*
-* Description:
-* The I/O Manager will invoke this routine to handle a write
-* request
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-* to be deferred to a worker thread context)
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Write(
-PDEVICE_OBJECT DeviceObject, // the logical volume device object
-PIRP Irp) // I/O Request Packet
+/*
+ * COPYRIGHT: See COPYRIGHT.TXT
+ * PROJECT: Ext2 File System Driver for WinNT/2K/XP
+ * FILE: write.c
+ * PROGRAMMER: Matt Wu <mattwu@163.com>
+ * HOMEPAGE: http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ext2fs.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PEXT2_GLOBAL Ext2Global;
+
+#define DL_FLP DL_DBG
+
+/* DEFINITIONS *************************************************************/
+
+#define EXT2_FLPFLUSH_MAGIC 'FF2E'
+
+typedef struct _EXT2_FLPFLUSH_CONTEXT {
+
+ PEXT2_VCB Vcb;
+ PEXT2_FCB Fcb;
+ PFILE_OBJECT FileObject;
+
+ KDPC Dpc;
+ KTIMER Timer;
+ WORK_QUEUE_ITEM Item;
+
+} EXT2_FLPFLUSH_CONTEXT, *PEXT2_FLPFLUSH_CONTEXT;
+
+VOID NTAPI
+Ext2FloppyFlush(IN PVOID Parameter);
+
+VOID NTAPI
+Ext2FloppyFlushDpc (
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2);
+
+
+NTSTATUS
+Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext);
+
+NTSTATUS
+Ext2WriteFile (IN PEXT2_IRP_CONTEXT IrpContext);
+
+NTSTATUS
+Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext);
+
+VOID
+Ext2DeferWrite(IN PEXT2_IRP_CONTEXT, PIRP Irp);
+
+
+/* FUNCTIONS *************************************************************/
+
+VOID NTAPI
+Ext2FloppyFlush(IN PVOID Parameter)
+{
+ PEXT2_FLPFLUSH_CONTEXT Context;
+ PFILE_OBJECT FileObject;
+ PEXT2_FCB Fcb;
+ PEXT2_VCB Vcb;
+
+ Context = (PEXT2_FLPFLUSH_CONTEXT) Parameter;
+ FileObject = Context->FileObject;
+ Fcb = Context->Fcb;
+ Vcb = Context->Vcb;
+
+ DEBUG(DL_FLP, ("Ext2FloppyFlushing ...\n"));
+
+ IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
+
+ if (FileObject) {
+ ASSERT(Fcb == (PEXT2_FCB)FileObject->FsContext);
+
+ ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+ CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);
+
+ ObDereferenceObject(FileObject);
+ }
+
+ if (Vcb) {
+ ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+ CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
+ }
+
+ IoSetTopLevelIrp(NULL);
+ Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC);
+}
+
+VOID NTAPI
+Ext2FloppyFlushDpc (
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+)
+{
+ PEXT2_FLPFLUSH_CONTEXT Context;
+
+ Context = (PEXT2_FLPFLUSH_CONTEXT) DeferredContext;
+
+ DEBUG(DL_FLP, ("Ext2FloppyFlushDpc is to be started...\n"));
+
+ ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
+}
+
+VOID
+Ext2StartFloppyFlushDpc (
+ PEXT2_VCB Vcb,
+ PEXT2_FCB Fcb,
+ PFILE_OBJECT FileObject )
{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrExt2IrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
+ LARGE_INTEGER OneSecond;
+ PEXT2_FLPFLUSH_CONTEXT Context;
- DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Write IRP Received...", 0);
+ ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK));
- // Ext2BreakPoint();
+ Context = Ext2AllocatePool(
+ NonPagedPool,
+ sizeof(EXT2_FLPFLUSH_CONTEXT),
+ EXT2_FLPFLUSH_MAGIC
+ );
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
+ if (!Context) {
+ DEBUG(DL_ERR, ( "Ex2StartFloppy...: failed to allocate Context\n"));
+ DbgBreak();
+ return;
+ }
- // set the top level context
- AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
+ KeInitializeTimer(&Context->Timer);
- try
- {
- // get an IRP context structure and issue the request
- PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
+ KeInitializeDpc( &Context->Dpc,
+ Ext2FloppyFlushDpc,
+ Context );
- RC = Ext2CommonWrite(PtrIrpContext, Irp);
- }
- except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
- {
- RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
- Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
- }
+ ExInitializeWorkItem( &Context->Item,
+ Ext2FloppyFlush,
+ Context );
- if (AreWeTopLevel)
- {
- IoSetTopLevelIrp(NULL);
- }
+ Context->Vcb = Vcb;
+ Context->Fcb = Fcb;
+ Context->FileObject = FileObject;
- FsRtlExitFileSystem();
+ if (FileObject) {
+ ObReferenceObject(FileObject);
+ }
- return(RC);
+ OneSecond.QuadPart = (LONGLONG)-1*1000*1000*10;
+ KeSetTimer( &Context->Timer,
+ OneSecond,
+ &Context->Dpc );
}
+BOOLEAN
+Ext2ZeroData (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER Start,
+ IN PLARGE_INTEGER End
+ )
+{
+ PEXT2_FCB Fcb;
+ PBCB Bcb;
+ PVOID Ptr;
+ ULONG Size;
+#ifndef __REACTOS__
+ BOOLEAN rc = TRUE;
+#endif
+ ASSERT (End && Start && End->QuadPart > Start->QuadPart);
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+
+ /* skip data zero if we've already tracked unwritten part */
+ if (0 == ( End->LowPart & (BLOCK_SIZE -1)) &&
+ 0 == (Start->LowPart & (BLOCK_SIZE -1))) {
+
+ if (INODE_HAS_EXTENT(Fcb->Inode)) {
+ return TRUE;
+ } else {
+#if !EXT2_PRE_ALLOCATION_SUPPORT
+ return TRUE;
+#endif
+ }
+ }
+
+ /* clear data in range [Start, End) */
+ return CcZeroData(FileObject, Start, End, Ext2CanIWait());
+}
-/*************************************************************************
-*
-* Function: Ext2CommonWrite()
-*
-* Description:
-* The actual work is performed here. This routine may be invoked in one'
-* of the two possible contexts:
-* (a) in the context of a system worker thread
-* (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonWrite(
- PtrExt2IrpContext PtrIrpContext,
- PIRP PtrIrp)
+VOID
+Ext2DeferWrite(IN PEXT2_IRP_CONTEXT IrpContext, PIRP Irp)
{
+ ASSERT(IrpContext->Irp == Irp);
- NTSTATUS RC = STATUS_SUCCESS;
- PIO_STACK_LOCATION PtrIoStackLocation = NULL;
- LARGE_INTEGER ByteOffset;
- uint32 WriteLength = 0;
- uint32 NumberBytesWritten = 0;
- PFILE_OBJECT PtrFileObject = NULL;
- PtrExt2FCB PtrFCB = NULL;
- PtrExt2CCB PtrCCB = NULL;
- PtrExt2VCB PtrVCB = NULL;
- PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
- PERESOURCE PtrResourceAcquired = NULL;
- void *PtrSystemBuffer = NULL;
-
- BOOLEAN CompleteIrp = TRUE;
- BOOLEAN PostRequest = FALSE;
-
- BOOLEAN CanWait = FALSE;
- BOOLEAN PagingIo = FALSE;
- BOOLEAN NonBufferedIo = FALSE;
- BOOLEAN SynchronousIo = FALSE;
- BOOLEAN IsThisADeferredWrite = FALSE;
- BOOLEAN WritingAtEndOfFile = FALSE;
-
- EXT2_IO_RUN *PtrIoRuns = NULL;
-
- PBCB PtrPinnedSIndirectBCB = NULL;
- PBCB PtrPinnedDIndirectBCB = NULL;
- PBCB PtrPinnedTIndirectBCB = NULL;
-
- // Used to cache the Single Indirect blocks pointed to by
- // the Double Indirect block
- PEXT2_SIBLOCKS PtrDIArray = NULL;
- ULONG DIArrayCount = 0;
-
- // Used to cache the Single Indirect blocks pointed to by
- // the Triple Indirect block
- PEXT2_SIBLOCKS PtrTIArray = NULL;
- ULONG TIArrayCount = 0;
-
-
- try
- {
- // First, get a pointer to the current I/O stack location
- PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
- ASSERT(PtrIoStackLocation);
-
- PtrFileObject = PtrIoStackLocation->FileObject;
- ASSERT(PtrFileObject);
-
- // If this happens to be a MDL write complete request, then
- // allocated MDL can be freed.
- if(PtrIoStackLocation->MinorFunction & IRP_MN_COMPLETE)
- {
- // Caller wants to tell the Cache Manager that a previously
- // allocated MDL can be freed.
- Ext2MdlComplete(PtrIrpContext, PtrIrp, PtrIoStackLocation, FALSE);
- // The IRP has been completed.
- CompleteIrp = FALSE;
- try_return(RC = STATUS_SUCCESS);
- }
-
- // If this is a request at IRQL DISPATCH_LEVEL, then post the request
- if (PtrIoStackLocation->MinorFunction & IRP_MN_DPC)
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
-
-
- // Get the FCB and CCB pointers
- Ext2GetFCB_CCB_VCB_FromFileObject (
- PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
-
-
- // Get some of the parameters supplied to us
- ByteOffset = PtrIoStackLocation->Parameters.Write.ByteOffset;
- WriteLength = PtrIoStackLocation->Parameters.Write.Length;
-
- CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
- PagingIo = ((PtrIrp->Flags & IRP_PAGING_IO) ? TRUE : FALSE);
- NonBufferedIo = ((PtrIrp->Flags & IRP_NOCACHE) ? TRUE : FALSE);
- SynchronousIo = ((PtrFileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE);
-
- if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
- {
- DebugTrace(DEBUG_TRACE_FILE_NAME, " === Write File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_FILE_NAME, " === Write File Name : -null-", 0);
- }
-
- DebugTrace( DEBUG_TRACE_SPECIAL, " ->ByteCount = 0x%8lx", PtrIoStackLocation->Parameters.Read.Length);
- DebugTrace( DEBUG_TRACE_SPECIAL, " ->ByteOffset.LowPart = 0x%8lx", PtrIoStackLocation->Parameters.Read.ByteOffset.LowPart);
-
- if( CanWait )
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->Can Wait ", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->Can't Wait ", 0 );
- }
-
- if( PagingIo )
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->Paging Io ", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->Not Paging Io", 0 );
- }
-
- if( SynchronousIo )
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->SynchronousIo ", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->ASynchronousIo ", 0 );
- }
-
- if( NonBufferedIo )
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->NonBufferedIo", 0 );
- }
- else
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, " ->BufferedIo", 0 );
- }
- // Check at this point whether the file object being
- // used for write really did have write permission requested when the
- // create/open operation was performed.
- // Don't do this for paging io...
-
- if (WriteLength == 0)
- {
- // a 0 byte write can be immediately succeeded
- try_return();
- }
-
- // Is this a write of the volume itself ?
- if ( ( !PtrFCB && PtrVCB ) || PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB)
- {
- //
- // >>>>>>>>>>>>>>>>>> VOLUME WRITE <<<<<<<<<<<<<<
- //
-
- // Validate the offset and length first...
- // .......................................
-
- // Acquire the volume resource exclusively
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Write]", PtrFileObject);
- }
-
- if( PagingIo )
- {
- // This is Paging IO...
-
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCBPaging Exclusively [Write]", 0);
- DebugTraceState( "VCBPaging AC:0x%LX SW:0x%LX EX:0x%LX [Write]", PtrVCB->PagingIoResource.ActiveCount, PtrVCB->PagingIoResource.NumberOfExclusiveWaiters, PtrVCB->PagingIoResource.NumberOfSharedWaiters );
-
- if( !ExAcquireResourceExclusiveLite( &( PtrVCB->PagingIoResource ), FALSE ) )
- {
- // post the request to be processed in the context of a worker thread
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCBPaging Acquisition FAILED [Write]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
-
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCBPaging Acquired [Write]", 0);
- PtrResourceAcquired = &(PtrVCB->PagingIoResource);
- }
- else
- {
- // This is not Paging IO...
-
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCB Exclusively [Write]", 0);
- DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Write]", PtrVCB->VCBResource.ActiveCount,
- PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
-
- if( !ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
- {
- // post the request to be processed in the context of a worker thread
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquisition FAILED [Write]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
-
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquired [Write]", 0);
- PtrResourceAcquired = &(PtrVCB->VCBResource);
- }
-
- // Validate the caller supplied offset here
- if( !PagingIo )
- {
- if( PtrVCB->CommonVCBHeader.AllocationSize.QuadPart < ByteOffset.QuadPart )
- {
- // Write extending beyond the end of volume.
- // Deny access...
- //
- RC = STATUS_END_OF_FILE;
- NumberBytesWritten = 0;
- try_return();
- }
- }
-
- // Lock the callers buffer
- if (!NT_SUCCESS(RC = Ext2LockCallersBuffer(PtrIrp, TRUE, WriteLength)))
- {
- try_return();
- }
-
- // Forward the request to the lower level driver
- if( PagingIo || NonBufferedIo )
- {
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, "[Volume Write] PagingIo or NonBufferedIo ", 0);
- CompleteIrp = FALSE;
-
- //
- // Do the write operation...
- // Send down the IRP to the lower level driver...
- //
- // Returned Informations and Status will be set by the lower level driver...
- // The IRP will also be completed by the lower level driver...
-
- RC = Ext2PassDownSingleReadWriteIRP (
- PtrIrpContext, PtrIrp, PtrVCB,
- ByteOffset, WriteLength, SynchronousIo );
-
- try_return();
- }
- else
- {
- PBCB PtrBCB = NULL;
- PVOID PtrBuffer = NULL;
-
- DebugTrace(DEBUG_TRACE_READ_DETAILS, "[Volume Write] BufferedIo ", 0);
- //
- // Let the cache manager worry about this write...
- // Pinned access should have been initiated.
- // But checking anyway...
- //
- ASSERT( PtrVCB->PtrStreamFileObject );
- ASSERT( PtrVCB->PtrStreamFileObject->PrivateCacheMap );
-
- CcPreparePinWrite(
- PtrVCB->PtrStreamFileObject,
- &ByteOffset,
- WriteLength,
- FALSE, // Don't Zero...
- TRUE, // Can Wait...
- &PtrBCB,
- &PtrBuffer);
-
- // Do the write now...
- // Write to the Pinned buffer...
- // Cache Manager will do the disk write...
- RtlCopyBytes( PtrBuffer, PtrSystemBuffer, WriteLength );
- // CcSetDirtyPinnedData( PtrBCB, NULL );
- CcUnpinData( PtrBCB );
- PtrBuffer = NULL;
- PtrBCB = NULL;
-
- NumberBytesWritten = WriteLength;
-
- // Go ahead and complete the IRP...
- }
- try_return();
- }
-
-
- IsThisADeferredWrite = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_DEFERRED_WRITE) ? TRUE : FALSE);
-
- if (!NonBufferedIo)
- {
- /****************************************************************************
- if (!CcCanIWrite(PtrFileObject, WriteLength, CanWait, IsThisADeferredWrite))
- {
- // Cache Manager and/or the VMM does not want us to perform
- // the write at this time. Post the request.
- Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_DEFERRED_WRITE);
- CcDeferWrite( PtrFileObject, Ext2DeferredWriteCallBack, PtrIrpContext, PtrIrp, WriteLength, IsThisADeferredWrite);
- CompleteIrp = FALSE;
- try_return( RC = STATUS_PENDING );
- }
- ****************************************************************************/
- }
-
- // If the write request is directed to a page file
- // send the request directly to the disk
- // driver. For requests directed to a page file, you have to trust
- // that the offsets will be set correctly by the VMM. You should not
- // attempt to acquire any FSD resources either.
- if (PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE)
- {
- IoMarkIrpPending(PtrIrp);
-
- // You will need to set a completion routine before invoking a lower level driver.
- // Forward request directly to disk driver.
- // Ext2PageFileIo(PtrIrpContext, PtrIrp);
-
- CompleteIrp = FALSE;
-
- try_return(RC = STATUS_PENDING);
- }
-
- // Check whether this write operation is targeted
- // to a directory object...
-
- if (PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)
- {
- //
- // Is this a write a result of
- // cached directory manipulation operatio
- // by the FSD itself?
- //
- if( PagingIo )
- {
- // Yep! Allow it to proceed...
- }
- else
- {
- // Nope... User initiated directory writes are not allowed!
- // Fail this request...
- RC = STATUS_INVALID_DEVICE_REQUEST;
- try_return();
- }
- }
-
- PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
-
- //
- // Synchronizing with other reads and writes...
- // Acquire the appropriate FCB resource exclusively
- //
- if (PagingIo)
- {
- // Try to acquire the FCB PagingIoResource exclusively
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCBpaging Exclusively [Write]", 0);
-
- if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->PagingIoResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCBpaging Acquisition FAILED [Write]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- // Remember the resource that was acquired
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCBpaging Acquired [Write]", 0);
- PtrResourceAcquired = &(PtrReqdFCB->PagingIoResource);
- }
- else
- {
- // Try to acquire the FCB MainResource exclusively
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCB Exclusively [Write]", 0);
- if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), CanWait))
- {
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquisition FAILED [Write]", 0);
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- try_return(RC = STATUS_PENDING);
- }
- // Remember the resource that was acquired
- DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquired [Write]", 0);
- PtrResourceAcquired = &(PtrReqdFCB->MainResource);
- }
-
- // Validate start offset and length supplied.
- // Here is a special check that determines whether the caller wishes to
- // begin the write at current end-of-file (whatever the value of that
- // offset might be)
- if ((ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE) && (ByteOffset.HighPart == 0xFFFFFFFF))
- {
- WritingAtEndOfFile = TRUE;
- ByteOffset.QuadPart = PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart;
- }
-
- //
- // If this is a Non Cached io and if caching has been initiated,
- // Flush and purge the cache
- //
- if (NonBufferedIo && !PagingIo && (PtrReqdFCB->SectionObject.DataSectionObject != NULL))
- {
- // Flush and then attempt to purge the cache
- CcFlushCache(&(PtrReqdFCB->SectionObject), &ByteOffset, WriteLength, &(PtrIrp->IoStatus));
- // If the flush failed, return error to the caller
- if (!NT_SUCCESS(RC = PtrIrp->IoStatus.Status))
- {
- try_return();
- }
-
- // Attempt the purge and ignore the return code
- CcPurgeCacheSection( &(PtrReqdFCB->SectionObject), (WritingAtEndOfFile ? &(PtrReqdFCB->CommonFCBHeader.FileSize) : &(ByteOffset)),
- WriteLength, FALSE);
- // We are finished with our flushing and purging
- }
-
- if (!PagingIo)
- {
- // Insert code to perform the check here ...
- //
- // if (!Ext2CheckForByteLock(PtrFCB, PtrCCB, PtrIrp,
- // PtrCurrentIoStackLocation))
- // {
- // try_return(RC = STATUS_FILE_LOCK_CONFLICT);
- // }
- }
-
- // Read in the File inode...
- Ext2InitializeFCBInodeInfo( PtrFCB );
-
- if (!PagingIo)
- {
- LARGE_INTEGER CurrentTime;
- KeQuerySystemTime( &CurrentTime );
- PtrFCB->LastAccessTime.QuadPart = CurrentTime.QuadPart;
- PtrFCB->LastWriteTime.QuadPart = CurrentTime.QuadPart;
- }
-
- {
- //
- // Validate start offset and length supplied.
- //
- ULONG LogicalBlockSize = 0;
- LONGLONG NoOfNewBlocksRequired = 0;
- LONGLONG NoOfBytesRequired = 0;
- LONGLONG i;
- BOOLEAN ZeroOut = FALSE;
- LARGE_INTEGER StartOffsetForZeroing;
- LARGE_INTEGER EndOffsetForZeroing;
-
-
- LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-
- if ( ByteOffset.QuadPart + WriteLength > PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart )
- {
- if( PagingIo )
- {
- //
- // A paging request never modifies the file size...
- //
- if( ByteOffset.QuadPart
- >= PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart )
- {
- // Page request for writing outside the file...
- // No op this IRP by completing it...
- //
- try_return();
- }
- if( ByteOffset.QuadPart + WriteLength
- > PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart )
- {
- // Page request for writing outside the file alocation size...
- // Truncate the write size so that it is within the allocation limit...
- //
- WriteLength = (ULONG) (PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart - ByteOffset.QuadPart);
- }
- }
- else
- {
-
- // Starting offset is > file size
- // Allocate new blocks?
- NoOfBytesRequired = ByteOffset.QuadPart + WriteLength
- - PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart;
-
- if( NoOfBytesRequired )
- {
- NoOfNewBlocksRequired = Ext2Align64( NoOfBytesRequired, LogicalBlockSize )
- / LogicalBlockSize;
- for( i = 0; i < NoOfNewBlocksRequired ; i++ )
- {
- Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrFCB, PtrFileObject, FALSE );
- }
-
- ZeroOut = TRUE;
-
- if( PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart < ByteOffset.QuadPart )
- {
- // Curr EOF --> | | <--New EOF
- // -----------------------------------------------
- // | | |///////////| |
- // | File Contents | Free |// Write //| Free | <- End of Allocation
- // | | |///////////| |
- // -----------------------------------------------
- // | |
-
- // Write is beyond the current end of file...
- // This will create a hole...
- // Will have to zero this out...
-
- // Start offset is the Current File size
- StartOffsetForZeroing = PtrReqdFCB->CommonFCBHeader.FileSize;
- // End offset is the point at which this write is going to start
- EndOffsetForZeroing = ByteOffset;
- }
- else
- {
- // Curr EOF --> | | <--New EOF
- // ------------------------------------------
- // | |///////////////| |
- // | File Contents |//// Write ////| Free | <- End of Allocation
- // | |///////////////| |
- // ------------------------------------------
- // | |
-
- // Just zero out the end of the file
- // not covered by the file size
-
- // Start offset is the New File size
- StartOffsetForZeroing.QuadPart =
- ByteOffset.QuadPart + WriteLength;
- // End offset is the New Allocation size
- EndOffsetForZeroing.QuadPart = PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart;
- }
- }
-
- PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart =
- ByteOffset.QuadPart + WriteLength;
-
- ASSERT( PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart <= PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart );
-
- Ext2UpdateFileSize( PtrIrpContext, PtrFileObject, PtrFCB );
-
- try
- {
- //
- // Zero the blocks out...
- // This routine can be used even if caching has not been initiated...
- //
- if( ZeroOut == TRUE && StartOffsetForZeroing.QuadPart != EndOffsetForZeroing.QuadPart )
- {
- CcZeroData( PtrFileObject,
- &StartOffsetForZeroing,
- &EndOffsetForZeroing,
- FALSE );
-
- if( EndOffsetForZeroing.QuadPart != PtrReqdFCB->CommonFCBHeader.AllocationSize.QuadPart )
- {
- // Also zero out the file tip...
- CcZeroData( PtrFileObject,
- &PtrReqdFCB->CommonFCBHeader.FileSize,
- &PtrReqdFCB->CommonFCBHeader.AllocationSize,
- FALSE );
- }
- }
- }
- finally
- {
- // Swallow an exceptions that are raised...
- }
- }
- }
- }
-
- //
- // Branch here for cached vs non-cached I/O
- //
- if (!NonBufferedIo)
- {
-
- // The caller wishes to perform cached I/O.
- // Initiate caching if it hasn't been done already...
- if (PtrFileObject->PrivateCacheMap == NULL)
- {
- CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)),
- FALSE, // We will not utilize pin access for this file
- &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
- PtrCCB); // The context used in callbacks
- }
-
- // Check and see if this request requires a MDL returned to the caller
- if (PtrIoStackLocation->MinorFunction & IRP_MN_MDL)
- {
- // Caller does want a MDL returned. Note that this mode
- // implies that the caller is prepared to block
- CcPrepareMdlWrite(PtrFileObject, &ByteOffset, WriteLength, &(PtrIrp->MdlAddress), &(PtrIrp->IoStatus));
- NumberBytesWritten = PtrIrp->IoStatus.Information;
- RC = PtrIrp->IoStatus.Status;
-
- try_return();
- }
-
- // This is a regular run-of-the-mill cached I/O request. Let the
- // Cache Manager worry about it!
-
- // First though, we need a buffer pointer (address) that is valid
- PtrSystemBuffer = Ext2GetCallersBuffer(PtrIrp);
- ASSERT(PtrSystemBuffer);
- if ( !CcCopyWrite(PtrFileObject, &(ByteOffset), WriteLength, CanWait, PtrSystemBuffer))
- {
- // The caller was not prepared to block and data is not immediately
- // available in the system cache
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- // Mark Irp Pending ...
- try_return(RC = STATUS_PENDING);
- }
- else
- {
- // We have the data
- PtrIrp->IoStatus.Status = RC;
- PtrIrp->IoStatus.Information = NumberBytesWritten = WriteLength;
- }
- }
- else // NonBuffered or Paged IO
- {
-
- ULONG Start = 0;
- ULONG End = 0;
- ULONG LogicalBlockIndex = 0;
- ULONG BytesRemaining = 0;
- ULONG BytesWrittenSoFar = 0;
- ULONG LeftOver = 0;
- ULONG LogicalBlockSize = 0;
- ULONG PhysicalBlockSize = 0;
- ULONG Index = 0;
-
- LONGLONG SingleIndirectBlockSize = 0;
- LONGLONG DoubleIndirectBlockSize = 0;
- LONGLONG TripleIndirectBlockSize = 0;
- LONGLONG DirectBlockSize = 0;
-
- LONGLONG NoOfDirectBlocks ;
- LONGLONG NoOfSingleIndirectBlocks ;
- LONGLONG NoOfDoubleIndirectBlocks ;
- LONGLONG NoOfTripleIndirectBlocks ;
-
- ULONG * PtrPinnedSIndirectBlock = NULL;
- ULONG * PtrPinnedDIndirectBlock = NULL;
- ULONG * PtrPinnedTIndirectBlock = NULL;
-
- // Used when reading a Triple Indirect Block...
- LONGLONG FirstCachedDIBlockOffset = 0;
-
- // Used when reading a Double Indirect Block...
- LONGLONG FirstCachedSIBlockOffset = 0;
-
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, "[File Write] Paging IO or NonBufferedIo ", 0);
-
- // Calculating where the write should start from...
- LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
- PhysicalBlockSize = PtrVCB->TargetDeviceObject->SectorSize;
-
- NoOfDirectBlocks = EXT2_NDIR_BLOCKS ;
- NoOfSingleIndirectBlocks = LogicalBlockSize / sizeof( ULONG );
- NoOfDoubleIndirectBlocks = NoOfSingleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
- NoOfTripleIndirectBlocks = NoOfDoubleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
-
- DirectBlockSize = LogicalBlockSize * NoOfDirectBlocks;
- SingleIndirectBlockSize = LogicalBlockSize * NoOfSingleIndirectBlocks;
- DoubleIndirectBlockSize = LogicalBlockSize * NoOfDoubleIndirectBlocks ;
- TripleIndirectBlockSize = LogicalBlockSize * NoOfTripleIndirectBlocks;
-
- LogicalBlockIndex = (ULONG)( ByteOffset.QuadPart / LogicalBlockSize);
-
- if( ( ByteOffset.QuadPart + WriteLength ) > DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- //
- // Handle Triple indirect blocks?
- // A Pop up will do for now...
- //
- UNICODE_STRING ErrorMessage;
- Ext2CopyWideCharToUnicodeString( &ErrorMessage, L"Triple indirect blocks not supported as yet. - Ext2.sys" );
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, "@@@@@@@@ Triple indirect blocks need to be written to! \n@@@@@@@@ This is not supported as yet!", 0);
- /* REACTOS FIXME */
- IoRaiseInformationalHardError(
- /* IO_ERR_DRIVER_ERROR */(NTSTATUS)0xC0040004L,
- &ErrorMessage,
- KeGetCurrentThread( ) );
-
- Ext2DeallocateUnicodeString( &ErrorMessage );
- RC = STATUS_INSUFFICIENT_RESOURCES;
- try_return();
- }
-
- if( ( ByteOffset.QuadPart + WriteLength ) > DirectBlockSize &&
- ( ByteOffset.QuadPart < DirectBlockSize + SingleIndirectBlockSize ) )
- {
- LARGE_INTEGER VolumeByteOffset;
-
- //
- // Indirect Blocks required...
- // Read in the single indirect blocks...
- //
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, "Reading in some Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_NDIR_BLOCKS ] * LogicalBlockSize;
-
- //
- // Asking the cache manager to oblige by pinning the single indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedSIndirectBCB,
- (PVOID*)&PtrPinnedSIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data", 0);
- }
- }
- if( ( ByteOffset.QuadPart + WriteLength ) > DirectBlockSize + SingleIndirectBlockSize &&
- ( ByteOffset.QuadPart ) < DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- //
- // Double Indirect Blocks required...
- // Read in the double indirect blocks...
- //
-
- LONGLONG StartIndirectBlock;
- LONGLONG EndIndirectBlock;
-
-
-
- LARGE_INTEGER VolumeByteOffset;
-
- DebugTrace(DEBUG_TRACE_MISC, "Reading in some Double Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
-
- //
- // Asking the cache manager to oblige by pinning the double indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedDIndirectBCB,
- (PVOID*)&PtrPinnedDIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- // So far so good...
- // Now determine the single indirect blocks that will have to be read in...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize )
- {
- // Request doesnot require any single indirect or direct blocks
- StartIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize);
- StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
- StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
- }
- else
- {
- StartIndirectBlock = 0;
- }
-
- FirstCachedSIBlockOffset = (NoOfSingleIndirectBlocks*(StartIndirectBlock+1)) + NoOfDirectBlocks;
-
- if( ByteOffset.QuadPart + WriteLength >=
- DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize)
- {
- EndIndirectBlock = DoubleIndirectBlockSize;
- }
- else
- {
- EndIndirectBlock = ByteOffset.QuadPart + WriteLength -
- (DirectBlockSize + SingleIndirectBlockSize);
- }
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, LogicalBlockSize )/LogicalBlockSize ;
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, NoOfSingleIndirectBlocks )/NoOfSingleIndirectBlocks;
-
- DIArrayCount = (ULONG)(EndIndirectBlock - StartIndirectBlock);
-
- PtrDIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( DIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
- {
- ULONG i;
-
- for( i = 0; i < DIArrayCount; i++ )
- {
- VolumeByteOffset.QuadPart = PtrPinnedDIndirectBlock[StartIndirectBlock+i] * LogicalBlockSize;
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrDIArray[i].PtrBCB,
- (PVOID*)&PtrDIArray[i].PtrSIBlocks))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- DIArrayCount = i;
- try_return(RC = STATUS_PENDING);
-
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
- }
- }
- }
-
-/* {
- //
- // Double Indirect Blocks required...
- // Read in the double indirect blocks...
- //
-
- LONGLONG StartIndirectBlock;
- LONGLONG EndIndirectBlock;
-
- LARGE_INTEGER VolumeByteOffset;
-
- DebugTrace(DEBUG_TRACE_MISC, "Reading in some Double Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
-
- //
- // Asking the cache manager to oblige by pinning the double indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedDIndirectBCB,
- (PVOID*)&PtrPinnedDIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- // So far so good...
- // Now determine the single indirect blocks that will have to be read in...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize )
- {
- // Request doesnot require any single indirect or direct blocks
- StartIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize);
- StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
- StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
- }
- else
- {
- StartIndirectBlock = 0;
- }
-
- if( ByteOffset.QuadPart + WriteLength >=
- DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize)
- {
- EndIndirectBlock = DoubleIndirectBlockSize;
- }
- else
- {
- EndIndirectBlock = ByteOffset.QuadPart + WriteLength -
- (DirectBlockSize + SingleIndirectBlockSize);
- if( EndIndirectBlock % LogicalBlockSize )
- {
- EndIndirectBlock += LogicalBlockSize;
- }
- EndIndirectBlock = EndIndirectBlock / LogicalBlockSize;
- if( EndIndirectBlock % NoOfSingleIndirectBlocks)
- {
- EndIndirectBlock += NoOfSingleIndirectBlocks;
- }
- EndIndirectBlock = EndIndirectBlock / NoOfSingleIndirectBlocks;
- }
- DIArrayCount = (ULONG)(EndIndirectBlock - StartIndirectBlock);
- PtrDIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( DIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
- {
- ULONG i;
-
- for( i = 0; i < DIArrayCount; i++ )
- {
- VolumeByteOffset.QuadPart = PtrPinnedDIndirectBlock[StartIndirectBlock+i] * LogicalBlockSize;
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrDIArray[i].PtrBCB,
- (PVOID*)&PtrDIArray[i].PtrSIBlocks))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- DIArrayCount = i;
- try_return(RC = STATUS_PENDING);
-
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
- }
- }
- }
-*/
- if( ( ByteOffset.QuadPart + WriteLength ) > DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- //
- // Triple Indirect Blocks required...
- // Read in the triple indirect blocks...
- //
- LONGLONG StartTIndirectBlock;
- LONGLONG EndTIndirectBlock;
-
- LONGLONG StartDIndirectBlock;
- LONGLONG EndDIndirectBlock;
- LONGLONG StartIndirectBlock;
- LONGLONG EndIndirectBlock;
-
- LONGLONG ByteOffsetTillHere = 0;
-
- PBCB TempDIBCB;
- LONG* TempDIBuffer;
-
- ULONG TIArrayIndex = 0;
-
- LARGE_INTEGER VolumeByteOffset;
-
- DebugTrace(DEBUG_TRACE_MISC, "Reading in some Triple Indirect Blocks", 0);
-
- VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_TIND_BLOCK ] * LogicalBlockSize;
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "ByteOffset = 0x%I64X", ByteOffset );
- DebugTrace(DEBUG_TRACE_TRIPLE, "WriteLength = 0x%lX", WriteLength );
- DebugTrace(DEBUG_TRACE_TRIPLE, "EXT2_TIND_BLOCK = 0x%lX", PtrFCB->IBlock[ EXT2_TIND_BLOCK ] );
- //
- // Asking the cache manager to oblige by pinning the triple indirect block...
- //
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrPinnedTIndirectBCB,
- (PVOID*)&PtrPinnedTIndirectBlock ))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
-
- // Mark Irp Pending ...
- IoMarkIrpPending( PtrIrp );
- RC = STATUS_PENDING;
- try_return();
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- // Determine the no of BCBs that need to be saved...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- StartTIndirectBlock = ByteOffset.QuadPart;
- }
- else
- {
- StartTIndirectBlock = DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize;
- }
- EndTIndirectBlock = ByteOffset.QuadPart + WriteLength;
- TIArrayCount = (ULONG)( (EndTIndirectBlock - StartTIndirectBlock) / SingleIndirectBlockSize ) + 2;
-
-
- PtrTIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( TIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
-
- // Now determine the double indirect blocks that will have to be read in...
- if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
- {
- // Request doesnot require any single indirect or direct blocks
- StartDIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize);
- StartDIndirectBlock = StartDIndirectBlock / LogicalBlockSize;
- StartDIndirectBlock = StartDIndirectBlock / NoOfDoubleIndirectBlocks;
-
- ByteOffsetTillHere = DirectBlockSize + SingleIndirectBlockSize + (DoubleIndirectBlockSize*(StartDIndirectBlock+1)) ;
- //FirstCachedDIBlockOffset = ByteOffset.QuadPart / LogicalBlockSize;
- FirstCachedDIBlockOffset = ByteOffsetTillHere / LogicalBlockSize;
- }
- else
- {
- ByteOffsetTillHere = DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize;
- FirstCachedDIBlockOffset = ByteOffsetTillHere / LogicalBlockSize;
- StartDIndirectBlock = 0;
- }
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "ByteOffsetTillHere = 0x%lX", ByteOffsetTillHere );
-
- EndDIndirectBlock = ByteOffset.QuadPart + WriteLength -
- (DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize);
- EndDIndirectBlock = Ext2Align64( EndDIndirectBlock, LogicalBlockSize ) / LogicalBlockSize ;
- EndDIndirectBlock = Ext2Align64( EndDIndirectBlock, NoOfDoubleIndirectBlocks ) / NoOfDoubleIndirectBlocks;
-
- {
- // Reading in the necessary double indirect bocks...
- ULONG i;
- LONGLONG Count = EndDIndirectBlock-StartDIndirectBlock;
-
- for( i = 0; i < Count; i++, ByteOffsetTillHere += DoubleIndirectBlockSize)
- {
- VolumeByteOffset.QuadPart = PtrPinnedTIndirectBlock[StartDIndirectBlock+i] * LogicalBlockSize;
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "Double VolOffset = 0x%I64X", VolumeByteOffset );
-
- if( !CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &TempDIBCB,
- (PVOID*)&TempDIBuffer) )
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- try_return(RC = STATUS_PENDING);
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
-
- if( ByteOffset.QuadPart > ByteOffsetTillHere)
- {
- StartIndirectBlock = ByteOffset.QuadPart - (ByteOffsetTillHere);
- StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
- StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
-
- if( TIArrayIndex == 0 )
- {
- FirstCachedDIBlockOffset += StartIndirectBlock * NoOfSingleIndirectBlocks;
- }
- }
- else
- {
- StartIndirectBlock = 0;
- }
-
- if( ByteOffset.QuadPart + WriteLength >= ByteOffsetTillHere + DoubleIndirectBlockSize)
- {
- EndIndirectBlock = DoubleIndirectBlockSize;
- }
- else
- {
- EndIndirectBlock = ByteOffset.QuadPart + WriteLength - ByteOffsetTillHere;
- }
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, LogicalBlockSize )/LogicalBlockSize ;
- EndIndirectBlock = Ext2Align64( EndIndirectBlock, NoOfSingleIndirectBlocks )/NoOfSingleIndirectBlocks;
-
- {
- ULONG i;
-
- for( i = 0; i < (EndIndirectBlock - StartIndirectBlock); i++ )
- {
- VolumeByteOffset.QuadPart = TempDIBuffer[StartIndirectBlock+i] * LogicalBlockSize;
- DebugTrace(DEBUG_TRACE_TRIPLE, "Single VolOffset = 0x%I64X", VolumeByteOffset );
-
- if (!CcMapData( PtrVCB->PtrStreamFileObject,
- &VolumeByteOffset,
- LogicalBlockSize,
- CanWait,
- &PtrTIArray[ TIArrayIndex ].PtrBCB,
- (PVOID*)&PtrTIArray[ TIArrayIndex ].PtrSIBlocks))
- {
- CompleteIrp = FALSE;
- PostRequest = TRUE;
- IoMarkIrpPending( PtrIrp );
- DIArrayCount = i;
- try_return(RC = STATUS_PENDING);
-
- DebugTrace(DEBUG_TRACE_ASYNC, "Cache read failiure while reading in volume meta data - Retrying", 0);
- }
- TIArrayIndex++;
- }
- }
- CcUnpinData( TempDIBCB );
- TempDIBCB = NULL;
- TempDIBuffer = NULL;
- }
- }
- TIArrayCount = TIArrayIndex;
-
- DebugTrace(DEBUG_TRACE_TRIPLE, "TIArrayCount = %ld", TIArrayCount );
- DebugTrace(DEBUG_TRACE_TRIPLE, "FirstCachedDIBlockOffset = 0x%lX", FirstCachedDIBlockOffset );
- }
-
- //
- // Allocating memory for IO Runs
- //
- Index = ( (WriteLength - 2) / LogicalBlockSize + 2 );
- PtrIoRuns = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( Index * sizeof( EXT2_IO_RUN) ) );
-
-
- Start = (ULONG) ( ByteOffset.QuadPart - (LogicalBlockSize * LogicalBlockIndex) );
- BytesRemaining = (ULONG)( LogicalBlockSize * (LogicalBlockIndex +1) - ByteOffset.QuadPart );
-
- if( WriteLength > BytesRemaining )
- End = Start + BytesRemaining;
- else
- End = Start + WriteLength;
- BytesWrittenSoFar = 0;
-
- Index = 0;
- DebugTrace(DEBUG_TRACE_WRITE_DETAILS, "\nDetermining the write IRPs that have to be passed down...", 0);
-
- while( 1 )
- {
- BytesWrittenSoFar += (End-Start);
- if( LogicalBlockIndex < EXT2_NDIR_BLOCKS )
- {
- // Direct Block
- PtrIoRuns[ Index ].LogicalBlock = PtrFCB->IBlock[ LogicalBlockIndex ];
- }
- else if( LogicalBlockIndex < (NoOfSingleIndirectBlocks + NoOfDirectBlocks) )
- {
- // Single Indirect Block
- PtrIoRuns[ Index ].LogicalBlock = PtrPinnedSIndirectBlock[ LogicalBlockIndex - EXT2_NDIR_BLOCKS ];
- }
- else if( LogicalBlockIndex < (NoOfDoubleIndirectBlocks + NoOfSingleIndirectBlocks + NoOfDirectBlocks) )
- {
- LONGLONG BlockNo;
- LONGLONG IBlockIndex;
- LONGLONG BlockIndex;
-
- BlockNo = LogicalBlockIndex - FirstCachedSIBlockOffset;
- IBlockIndex = BlockNo / NoOfSingleIndirectBlocks;
- BlockIndex = BlockNo % NoOfSingleIndirectBlocks;
-
- // Double Indirect Block
- PtrIoRuns[ Index ].LogicalBlock =
- PtrDIArray[ IBlockIndex ].PtrSIBlocks[ BlockIndex ];
- }
- else
- {
- // Triple Indirect Block
- LONGLONG BlockNo;
- LONGLONG IBlockIndex;
- LONGLONG BlockIndex;
- BlockNo = LogicalBlockIndex - FirstCachedDIBlockOffset;
- IBlockIndex = BlockNo / NoOfSingleIndirectBlocks;
- BlockIndex = BlockNo % NoOfSingleIndirectBlocks;
-
- DbgPrint( "\nBlock No : 0x%I64X IBlockIndex = 0x%I64X BlockIndex = 0x%I64X", BlockNo, IBlockIndex, BlockIndex);
-
- if( IBlockIndex >= TIArrayCount )
- {
- Ext2BreakPoint();
- }
- if( BlockIndex >= LogicalBlockSize )
- {
- Ext2BreakPoint();
- }
-
- PtrIoRuns[ Index ].LogicalBlock = PtrTIArray[ IBlockIndex ].PtrSIBlocks[ BlockIndex ];
- DbgPrint( "LogicalBlock = 0x%lX", PtrIoRuns[ Index ].LogicalBlock );
- }
-
- if( PtrIoRuns[ Index ].LogicalBlock == 0 )
- {
- //
- // Something is wrong...
- //
- Ext2BreakPoint();
- break;
-
- }
- PtrIoRuns[ Index ].StartOffset = Start;
- PtrIoRuns[ Index ].EndOffset = End;
- PtrIoRuns[ Index ].PtrAssociatedIrp = NULL;
-
- DebugTrace( DEBUG_TRACE_WRITE_DETAILS, " Index = (%ld)", LogicalBlockIndex );
- DebugTrace( DEBUG_TRACE_WRITE_DETAILS, " Logical Block = (0x%lX)", PtrFCB->IBlock[ LogicalBlockIndex ] );
- DebugTrace( DEBUG_TRACE_WRITE_DETAILS, " Start = (0x%lX)", Start );
- DebugTrace( DEBUG_TRACE_WRITE_DETAILS, " End = (0x%lX) ", End );
- DebugTrace( DEBUG_TRACE_WRITE_DETAILS, " Bytes written (0x%lX)", BytesWrittenSoFar );
-
-
-
- if( BytesWrittenSoFar >= WriteLength )
- break;
- LogicalBlockIndex++;
- Start = 0;
- LeftOver = WriteLength - BytesWrittenSoFar;
- if( LeftOver > LogicalBlockSize )
- End = LogicalBlockSize;
- else
- End = LeftOver;
- // Loop over to make the write request...
- Index++;
- }
-
- //
- // Unpin the Indirect Blocks
- //
- if( PtrPinnedSIndirectBCB )
- {
- CcUnpinData( PtrPinnedSIndirectBCB );
- PtrPinnedSIndirectBCB = NULL;
- PtrPinnedSIndirectBlock = NULL;
- }
- if( PtrPinnedDIndirectBCB )
- {
- CcUnpinData( PtrPinnedDIndirectBCB );
- PtrPinnedDIndirectBCB = NULL;
- PtrPinnedDIndirectBlock = NULL;
- }
- //
- // Pass down Associated IRPs to the Target Device Driver...
- //
- DebugTrace( DEBUG_TRACE_WRITE_DETAILS, "Passing down the Write IRPs to the disk driver...", 0 );
-
- RC = Ext2PassDownMultiReadWriteIRP( PtrIoRuns, Index+1, WriteLength, PtrIrpContext, PtrFCB, SynchronousIo );
-
- //
- // Irp will be completed automatically
- // when all the Associated IRPs are completed
- //
- if( RC == STATUS_SUCCESS || RC == STATUS_PENDING )
- {
- CompleteIrp = FALSE;
- }
- try_return();
- }
-
- try_exit: NOTHING;
-
- }
- finally
- {
- if ( PtrIoRuns )
- {
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Write]", PtrIoRuns );
- ExFreePool( PtrIoRuns );
- }
- if( PtrPinnedSIndirectBCB )
- {
- CcUnpinData( PtrPinnedSIndirectBCB );
- PtrPinnedSIndirectBCB = NULL;
- }
- if( PtrPinnedDIndirectBCB )
- {
- CcUnpinData( PtrPinnedDIndirectBCB );
- PtrPinnedDIndirectBCB = NULL;
- }
- if ( PtrDIArray )
- {
- ULONG i;
- for( i = 0; i < DIArrayCount; i++ )
- {
- CcUnpinData( PtrDIArray->PtrBCB );
- }
- DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Read]", PtrDIArray );
- ExFreePool( PtrDIArray );
- PtrDIArray = NULL;
- }
- // Release resources ...
- //
- if (PtrResourceAcquired)
- {
- Ext2ReleaseResource(PtrResourceAcquired);
-
- DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** Resource Released [Write]", 0);
- DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Write]",
- PtrResourceAcquired->ActiveCount,
- PtrResourceAcquired->NumberOfExclusiveWaiters,
- PtrResourceAcquired->NumberOfSharedWaiters );
-
- if( PtrFileObject )
- {
- DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Write]", PtrFileObject);
- }
- if( PtrVCB && PtrResourceAcquired == &(PtrVCB->VCBResource) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Write]", 0);
- }
- else if( PtrVCB && PtrResourceAcquired == &(PtrVCB->PagingIoResource ) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** VCBPaging Released [Write]", 0);
- }
- else if( PtrReqdFCB && PtrResourceAcquired == &(PtrReqdFCB->PagingIoResource) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Paging Resource Released [Write]", 0);
- }
- else if(PtrReqdFCB && PtrResourceAcquired == &(PtrReqdFCB->MainResource) )
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** FCB Resource Released [Write]", 0);
- }
- else
- {
- DebugTrace(DEBUG_TRACE_MISC, "*** Unknown Resource Released [Write]", 0);
- }
-
- PtrResourceAcquired = NULL;
- }
-
- if (PostRequest)
- {
- RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
- }
- else if ( CompleteIrp && !(RC == STATUS_PENDING))
- {
- // For synchronous I/O, the FSD must maintain the current byte offset
- // Do not do this however, if I/O is marked as paging-io
- if (SynchronousIo && !PagingIo && NT_SUCCESS(RC))
- {
- PtrFileObject->CurrentByteOffset = RtlLargeIntegerAdd(ByteOffset,
- RtlConvertUlongToLargeInteger((unsigned long)NumberBytesWritten));
- }
-
- // If the write completed successfully and this was not a paging-io
- // operation, set a flag in the CCB that indicates that a write was
- // performed and that the file time should be updated at cleanup
- if (NT_SUCCESS(RC) && !PagingIo)
- {
- Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_MODIFIED);
- }
-
- // If the file size was changed, set a flag in the FCB indicating that
- // this occurred.
-
- // If the request failed, and we had done some nasty stuff like
- // extending the file size (including informing the Cache Manager
- // about the new file size), and allocating on-disk space etc., undo
- // it at this time.
-
- // Can complete the IRP here if no exception was encountered
- if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION))
- {
- PtrIrp->IoStatus.Status = RC;
- PtrIrp->IoStatus.Information = NumberBytesWritten;
-
- // complete the IRP
- IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
- }
-
- // Free up the Irp Context
- Ext2ReleaseIrpContext(PtrIrpContext);
-
- } // can we complete the IRP ?
- else
- {
- // Free up the Irp Context
- Ext2ReleaseIrpContext(PtrIrpContext);
- }
- } // end of "finally" processing
- return(RC);
+ Ext2QueueRequest(IrpContext);
}
-/*************************************************************************
-*
-* Function: Ext2DeferredWriteCallBack()
-*
-* Description:
-* Invoked by the cache manager in the context of a worker thread.
-* Typically, you can simply post the request at this point (just
-* as you would have if the original request could not block) to
-* perform the write in the context of a system worker thread.
-*
-* Expected Interrupt Level (for execution) :
-*
-* IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************/
-void NTAPI Ext2DeferredWriteCallBack (
-void *Context1, // Should be PtrIrpContext
-void *Context2 ) // Should be PtrIrp
+NTSTATUS
+Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
- // You should typically simply post the request to your internal
- // queue of posted requests (just as you would if the original write
- // could not be completed because the caller could not block).
- // Once you post the request, return from this routine. The write
- // will then be retried in the context of a system worker thread
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ PEXT2_VCB Vcb;
+ PEXT2_CCB Ccb;
+ PEXT2_FCBVCB FcbOrVcb;
+ PFILE_OBJECT FileObject;
+
+ PDEVICE_OBJECT DeviceObject;
+
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION IoStackLocation;
+
+ ULONG Length;
+ LARGE_INTEGER ByteOffset;
+
+ BOOLEAN PagingIo = FALSE;
+ BOOLEAN Nocache = FALSE;
+ BOOLEAN SynchronousIo = FALSE;
+ BOOLEAN MainResourceAcquired = FALSE;
+
+ BOOLEAN bDeferred = FALSE;
+
+ PUCHAR Buffer = NULL;
+ PEXT2_EXTENT Chain = NULL;
+ EXT2_EXTENT BlockArray;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ FileObject = IrpContext->FileObject;
+ FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
+ ASSERT(FcbOrVcb);
+
+ if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ Length = IoStackLocation->Parameters.Write.Length;
+ ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
+
+ PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
+ Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
+ SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
+
+ if (PagingIo) {
+ ASSERT(Nocache);
+ }
+
+ DEBUG(DL_INF, ("Ext2WriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
+ ByteOffset.QuadPart, Length, PagingIo, Nocache));
+
+ if (Length == 0) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if (Nocache &&
+ (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
+ Length & (SECTOR_SIZE - 1))) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
+ ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ if (ByteOffset.QuadPart >=
+ Vcb->PartitionInformation.PartitionLength.QuadPart ) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_END_OF_FILE;
+ _SEH2_LEAVE;
+ }
+
+ if (!Nocache) {
+
+ BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+ BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+ BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+
+ if ( !CcCanIWrite(
+ FileObject,
+ Length,
+ (bWait && bQueue),
+ bAgain ) ) {
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoReadAccess);
+ if (NT_SUCCESS(Status)) {
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+ CcDeferWrite( FileObject,
+ (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
+ IrpContext,
+ Irp,
+ Length,
+ bAgain );
+
+ bDeferred = TRUE;
+ Status = STATUS_PENDING;
+
+ _SEH2_LEAVE;
+ }
+ }
+ }
+
+ /*
+ * User direct volume access
+ */
+
+ if (Ccb != NULL && !PagingIo) {
+
+ if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {
+
+ if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
+ Status = Ext2PurgeVolume( Vcb, TRUE);
+ }
+
+ SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
+ }
+
+ if (!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) {
+ if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
+ Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+ }
+ }
+
+ } else if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) {
+
+ ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
+ MainResourceAcquired = TRUE;
+
+ ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+ CcFlushCache( &(Vcb->SectionObject),
+ &ByteOffset,
+ Length,
+ &(Irp->IoStatus));
+
+ if (!NT_SUCCESS(Irp->IoStatus.Status)) {
+ Status = Irp->IoStatus.Status;
+ _SEH2_LEAVE;
+ }
+
+ ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+ CcPurgeCacheSection( &(Vcb->SectionObject),
+ (PLARGE_INTEGER)&(ByteOffset),
+ Length,
+ FALSE );
+
+ ExReleaseResourceLite(&Vcb->MainResource);
+ MainResourceAcquired = FALSE;
+ }
+
+ if ( (ByteOffset.QuadPart + Length) > Vcb->Header.FileSize.QuadPart) {
+ Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+ }
+
+ if (!Nocache) {
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
+
+ CcPrepareMdlWrite (
+ Vcb->Volume,
+ &ByteOffset,
+ Length,
+ &Irp->MdlAddress,
+ &Irp->IoStatus );
+
+ Status = Irp->IoStatus.Status;
+
+ } else {
+
+ Buffer = Ext2GetUserBuffer(Irp);
+ if (Buffer == NULL) {
+ DbgBreak();
+
+ Status = STATUS_INVALID_USER_BUFFER;
+ _SEH2_LEAVE;
+ }
+
+ if (!CcCopyWrite( Vcb->Volume,
+ (PLARGE_INTEGER)(&ByteOffset),
+ Length,
+ TRUE,
+ Buffer )) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ Status = Irp->IoStatus.Status;
+ Ext2AddVcbExtent(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
+ }
+
+ if (NT_SUCCESS(Status)) {
+ Irp->IoStatus.Information = Length;
+ }
+
+ } else if (PagingIo) {
+
+ LONGLONG DirtyStart;
+ LONGLONG DirtyLba;
+ LONGLONG DirtyLength;
+ LONGLONG RemainLength;
+
+ PEXT2_EXTENT Extent = NULL;
+ PEXT2_EXTENT List = NULL;
+
+ Length &= ~((ULONG)SECTOR_SIZE - 1);
+
+ Status = Ext2LockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ DirtyLba = ByteOffset.QuadPart;
+ RemainLength = (LONGLONG) Length;
+
+ ASSERT(Length >= SECTOR_SIZE);
+
+ while (RemainLength > 0) {
+
+ DirtyStart = DirtyLba;
+ ASSERT(DirtyStart >= ByteOffset.QuadPart);
+ ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
+
+ if (Ext2LookupVcbExtent(Vcb, DirtyStart, &DirtyLba, &DirtyLength)) {
+
+ if (DirtyLba == -1) {
+
+ DirtyLba = DirtyStart + DirtyLength;
+ if (ByteOffset.QuadPart + Length > DirtyLba) {
+ RemainLength = ByteOffset.QuadPart + Length - DirtyLba;
+ ASSERT(DirtyStart >= ByteOffset.QuadPart);
+ ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
+ } else {
+ RemainLength = 0;
+ }
+ continue;
+ }
+
+ ASSERT(DirtyLba <= DirtyStart);
+ Extent = Ext2AllocateExtent();
+
+ if (!Extent) {
+ DEBUG(DL_ERR, ( "Ex2WriteVolume: failed to allocate Extent\n"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH2_LEAVE;
+ }
+
+ Extent->Irp = NULL;
+ Extent->Lba = DirtyLba;
+ Extent->Offset = (ULONG)( DirtyStart + Length -
+ RemainLength - DirtyLba );
+ ASSERT(Extent->Offset <= Length);
+
+ if (DirtyLba + DirtyLength >= DirtyStart + RemainLength) {
+ Extent->Length = (ULONG)( DirtyLba +
+ RemainLength -
+ DirtyStart );
+ ASSERT(Extent->Length <= Length);
+ RemainLength = 0;
+ } else {
+ Extent->Length = (ULONG)(DirtyLength + DirtyLba - DirtyStart);
+ RemainLength = (DirtyStart + RemainLength) -
+ (DirtyLba + DirtyLength);
+ ASSERT(RemainLength <= (LONGLONG)Length);
+ ASSERT(Extent->Length <= Length);
+ }
+
+ ASSERT(Extent->Length >= SECTOR_SIZE);
+ DirtyLba = DirtyStart + DirtyLength;
+
+ if (List) {
+ List->Next = Extent;
+ List = Extent;
+ } else {
+ Chain = List = Extent;
+ }
+
+ } else {
+
+ if (RemainLength > SECTOR_SIZE) {
+ DirtyLba = DirtyStart + SECTOR_SIZE;
+ RemainLength -= SECTOR_SIZE;
+ } else {
+ RemainLength = 0;
+ }
+ }
+ }
+
+ if (Chain) {
+ Status = Ext2ReadWriteBlocks(IrpContext,
+ Vcb,
+ Chain,
+ Length );
+ Irp = IrpContext->Irp;
+
+ if (NT_SUCCESS(Status)) {
+ for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
+ Ext2RemoveVcbExtent(Vcb, Extent->Lba, Extent->Length);
+ }
+ }
+
+ if (!Irp) {
+ _SEH2_LEAVE;
+ }
+
+ } else {
+
+ Irp->IoStatus.Information = Length;
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ } else {
+
+ Length &= ~((ULONG)SECTOR_SIZE - 1);
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoWriteAccess );
+
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ BlockArray.Irp = NULL;
+ BlockArray.Lba = ByteOffset.QuadPart;
+ BlockArray.Offset = 0;
+ BlockArray.Length = Length;
+ BlockArray.Next = NULL;
+
+ Status = Ext2ReadWriteBlocks(IrpContext,
+ Vcb,
+ &BlockArray,
+ Length );
+
+ if (NT_SUCCESS(Status)) {
+ Irp->IoStatus.Information = Length;
+ }
+
+ Irp = IrpContext->Irp;
+ if (!Irp) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ } _SEH2_FINALLY {
+
+ if (MainResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->MainResource);
+ }
+
+ if (!IrpContext->ExceptionInProgress) {
+
+ if (Irp) {
+
+ if (Status == STATUS_PENDING) {
+
+ if (!bDeferred) {
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoReadAccess );
+
+ if (NT_SUCCESS(Status)) {
+ Status = Ext2QueueRequest(IrpContext);
+ } else {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ }
+
+ } else {
+
+ if (NT_SUCCESS(Status)) {
+
+ if (SynchronousIo && !PagingIo) {
+ FileObject->CurrentByteOffset.QuadPart =
+ ByteOffset.QuadPart + Irp->IoStatus.Information;
+ }
+
+ if (!PagingIo) {
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ }
+ }
+
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+
+ } else {
+
+ Ext2FreeIrpContext(IrpContext);
+ }
+ }
+
+ if (Chain) {
+ Ext2DestroyExtentChain(Chain);
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+NTSTATUS
+Ext2WriteInode (
+ IN PEXT2_IRP_CONTEXT IrpContext,
+ IN PEXT2_VCB Vcb,
+ IN PEXT2_MCB Mcb,
+ IN ULONGLONG Offset,
+ IN PVOID Buffer,
+ IN ULONG Size,
+ IN BOOLEAN bDirectIo,
+ OUT PULONG BytesWritten
+)
+{
+ PEXT2_EXTENT Chain = NULL;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ _SEH2_TRY {
+
+ if (BytesWritten) {
+ *BytesWritten = 0;
+ }
+
+ Status = Ext2BuildExtents (
+ IrpContext,
+ Vcb,
+ Mcb,
+ Offset,
+ Size,
+ IsMcbDirectory(Mcb) ? FALSE : TRUE,
+ &Chain
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ if (Chain == NULL) {
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if (bDirectIo) {
+
+ ASSERT(IrpContext != NULL);
+
+ //
+ // We assume the offset is aligned.
+ //
+
+ Status = Ext2ReadWriteBlocks(
+ IrpContext,
+ Vcb,
+ Chain,
+ Size
+ );
+
+ } else {
+
+ PEXT2_EXTENT Extent;
+ for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
+
+ if ( !Ext2SaveBuffer(
+ IrpContext,
+ Vcb,
+ Extent->Lba,
+ Extent->Length,
+ (PVOID)((PUCHAR)Buffer + Extent->Offset)
+ )) {
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
+
+ DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n"));
+ Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
+ }
+
+ Status = STATUS_SUCCESS;
+ }
+
+ } _SEH2_FINALLY {
+
+ if (Chain) {
+ Ext2DestroyExtentChain(Chain);
+ }
+
+ if (NT_SUCCESS(Status) && BytesWritten) {
+ *BytesWritten = Size;
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+NTSTATUS
+Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ PEXT2_VCB Vcb;
+ PEXT2_FCB Fcb;
+ PEXT2_CCB Ccb;
+ PFILE_OBJECT FileObject;
+
+ PDEVICE_OBJECT DeviceObject;
+
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+ PUCHAR Buffer;
+
+ LARGE_INTEGER ByteOffset;
+ ULONG ReturnedLength = 0;
+ ULONG Length;
+
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ BOOLEAN OpPostIrp = FALSE;
+ BOOLEAN PagingIo = FALSE;
+ BOOLEAN Nocache = FALSE;
+ BOOLEAN SynchronousIo = FALSE;
+
+ BOOLEAN RecursiveWriteThrough = FALSE;
+ BOOLEAN MainResourceAcquired = FALSE;
+ BOOLEAN PagingIoResourceAcquired = FALSE;
+
+ BOOLEAN bDeferred = FALSE;
+#ifndef __REACTOS__
+ BOOLEAN UpdateFileValidSize = FALSE;
+#endif
+ BOOLEAN FileSizesChanged = FALSE;
+ BOOLEAN rc;
+
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+ ASSERT(Vcb != NULL);
+ ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
+ (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
+
+ FileObject = IrpContext->FileObject;
+ Fcb = (PEXT2_FCB) FileObject->FsContext;
+ Ccb = (PEXT2_CCB) FileObject->FsContext2;
+ ASSERT(Fcb);
+ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+
+ Irp = IrpContext->Irp;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ Length = IoStackLocation->Parameters.Write.Length;
+ ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
+
+ PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
+ Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
+ SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
+
+ if (PagingIo) {
+ ASSERT(Nocache);
+ }
+
+ DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n",
+ &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
+
+ if (IsSpecialFile(Fcb)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ if (IsFileDeleted(Fcb->Mcb) ||
+ (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) {
+ Status = STATUS_FILE_DELETED;
+ _SEH2_LEAVE;
+ }
+
+ if (Length == 0) {
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ if (Nocache && ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
+ (Length & (SECTOR_SIZE - 1))) ) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
+ ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+
+ if (!Nocache) {
+
+ BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+ BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+ BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+
+ if ( !CcCanIWrite(
+ FileObject,
+ Length,
+ (bWait && bQueue),
+ bAgain ) ) {
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoReadAccess);
+
+ if (NT_SUCCESS(Status)) {
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+ CcDeferWrite( FileObject,
+ (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
+ IrpContext,
+ Irp,
+ Length,
+ bAgain );
+ bDeferred = TRUE;
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ }
+ }
+
+ if (IsWritingToEof(ByteOffset)) {
+ ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
+ }
+
+ if (IsDirectory(Fcb) && !PagingIo) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) {
+
+ PIRP TopIrp;
+
+ TopIrp = IoGetTopLevelIrp();
+
+ if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG &&
+ NodeType(TopIrp) == IO_TYPE_IRP) {
+
+ PIO_STACK_LOCATION IrpStack;
+
+ IrpStack = IoGetCurrentIrpStackLocation(TopIrp);
+
+ if ((IrpStack->MajorFunction == IRP_MJ_WRITE) &&
+ (IrpStack->FileObject->FsContext == FileObject->FsContext) &&
+ !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) {
+
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
+ RecursiveWriteThrough = TRUE;
+ }
+ }
+ }
+
+ if (PagingIo) {
+
+ if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ PagingIoResourceAcquired = TRUE;
+
+ if ( (ByteOffset.QuadPart + Length) > Fcb->Header.AllocationSize.QuadPart) {
+
+ if ( ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
+
+ Status = STATUS_END_OF_FILE;
+ Irp->IoStatus.Information = 0;
+ _SEH2_LEAVE;
+
+ } else {
+
+ Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
+ }
+ }
+
+ } else {
+
+ if (IsDirectory(Fcb)) {
+ _SEH2_LEAVE;
+ }
+
+ if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ MainResourceAcquired = TRUE;
+
+ //
+ // Do flushing for such cases
+ //
+ if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL) {
+
+ ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+ CcFlushCache( &(Fcb->SectionObject),
+ &ByteOffset,
+ CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
+ &(Irp->IoStatus));
+ ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+
+ if (!NT_SUCCESS(Irp->IoStatus.Status)) {
+ Status = Irp->IoStatus.Status;
+ _SEH2_LEAVE;
+ }
+
+ ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+ CcPurgeCacheSection( &(Fcb->SectionObject),
+ &(ByteOffset),
+ CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
+ FALSE );
+ }
+
+ if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) {
+ Status = STATUS_FILE_LOCK_CONFLICT;
+ _SEH2_LEAVE;
+ }
+
+ if (Ccb != NULL) {
+ Status = FsRtlCheckOplock( &Fcb->Oplock,
+ Irp,
+ IrpContext,
+ Ext2OplockComplete,
+ Ext2LockIrp );
+
+ if (Status != STATUS_SUCCESS) {
+ OpPostIrp = TRUE;
+ _SEH2_LEAVE;
+ }
+
+ //
+ // Set the flag indicating if Fast I/O is possible
+ //
+
+ Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
+ }
+
+ //
+ // Extend the inode size when the i/o is beyond the file end ?
+ //
+
+ if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {
+
+ LARGE_INTEGER AllocationSize, Last;
+
+ if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) {
+ Status = STATUS_PENDING;
+ _SEH2_LEAVE;
+ }
+ PagingIoResourceAcquired = TRUE;
+
+ /* let this irp wait, since it has to be synchronous */
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+
+ Last.QuadPart = Fcb->Header.AllocationSize.QuadPart;
+ AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
+ AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
+ (ULONGLONG)AllocationSize.QuadPart,
+ (ULONGLONG)BLOCK_SIZE);
+
+ /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks
+ for indirect files, otherwise we might get gabage data in holes */
+ IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION;
+ Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize);
+ IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
+ if (AllocationSize.QuadPart > Last.QuadPart) {
+ Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
+ SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE);
+ }
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ PagingIoResourceAcquired = FALSE;
+
+ if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
+ if (NT_SUCCESS(Status)) {
+ DbgBreak();
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ _SEH2_LEAVE;
+ }
+
+ if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) {
+ Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
+ }
+
+ Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length;
+ Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
+
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
+ FileSizesChanged = TRUE;
+
+ if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
+ !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
+ SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+ Ext2SaveSuper(IrpContext, Vcb);
+ }
+
+ DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n",
+ &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
+ Fcb->Header.AllocationSize.QuadPart));
+ }
+ }
+
+ ReturnedLength = Length;
+
+ if (!Nocache) {
+
+ if (FileObject->PrivateCacheMap == NULL) {
+ CcInitializeCacheMap(
+ FileObject,
+ (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
+ FALSE,
+ &Ext2Global->CacheManagerCallbacks,
+ Fcb );
+
+ CcSetReadAheadGranularity(
+ FileObject,
+ READ_AHEAD_GRANULARITY );
+ }
+
+ if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
+
+ CcPrepareMdlWrite(
+ FileObject,
+ &ByteOffset,
+ Length,
+ &Irp->MdlAddress,
+ &Irp->IoStatus );
+
+ Status = Irp->IoStatus.Status;
+
+ } else {
+
+ Buffer = Ext2GetUserBuffer(Irp);
+ if (Buffer == NULL) {
+ DbgBreak();
+ Status = STATUS_INVALID_USER_BUFFER;
+ _SEH2_LEAVE;
+ }
+
+ if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
+
+ /* let this irp wait, since it has to be synchronous */
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+
+ rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
+ &Fcb->Header.ValidDataLength, &ByteOffset);
+ if (!rc) {
+ Status = STATUS_PENDING;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) {
+ if (Ext2CanIWait() ||
+ !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) {
+ Status = STATUS_PENDING;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+ }
+
+ if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
+
+ if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
+ Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+ } else {
+ if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
+ Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
+ }
+
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ FileSizesChanged = TRUE;
+ }
+
+ Status = STATUS_SUCCESS;
+ }
+
+ if (NT_SUCCESS(Status)) {
+ Irp->IoStatus.Information = Length;
+ if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
+ DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n"));
+ Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject);
+ }
+ }
+
+ } else {
+
+ if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
+ if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
+ if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
+
+ /* let this irp wait, since it has to be synchronous */
+ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+ rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
+ &Fcb->Header.ValidDataLength,
+ &ByteOffset);
+ if (!rc) {
+ Status = STATUS_PENDING;
+ DbgBreak();
+ _SEH2_LEAVE;
+ }
+ }
+ }
+ }
+
+ Status = Ext2LockUserBuffer(
+ IrpContext->Irp,
+ Length,
+ IoReadAccess );
+
+ if (!NT_SUCCESS(Status)) {
+ _SEH2_LEAVE;
+ }
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = ReturnedLength;
+
+ Status = Ext2WriteInode(
+ IrpContext,
+ Vcb,
+ Fcb->Mcb,
+ (ULONGLONG)(ByteOffset.QuadPart),
+ NULL,
+ ReturnedLength,
+ TRUE,
+ &Length
+ );
+
+ Irp = IrpContext->Irp;
+
+ if (NT_SUCCESS(Status) && !PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
+
+ if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
+
+ FileSizesChanged = TRUE;
+
+ if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
+ Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+ } else {
+ if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
+ Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
+ }
+
+ if (CcIsFileCached(FileObject)) {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+ }
+
+ DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n",
+ &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
+ Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length));
+ }
+ }
+ }
+
+ if (FileSizesChanged) {
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
+ Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb,
+ FILE_NOTIFY_CHANGE_SIZE,
+ FILE_ACTION_MODIFIED );
+ }
+
+ } _SEH2_FINALLY {
+
+ /*
+ * in case we got excpetions, we need revert MajorFunction
+ * back to IRP_MJ_WRITE. The reason we do this, if to tell
+ * Ext2ExpandFile to allocate unwritten extent or don't add
+ * new blocks for indirect files.
+ */
+ if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION)
+ IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
+
+ if (Irp) {
+ if (PagingIoResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ }
+
+ if (MainResourceAcquired) {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+ }
+
+ if (!OpPostIrp && !IrpContext->ExceptionInProgress) {
+
+ if (Irp) {
+
+ if (Status == STATUS_PENDING ||
+ Status == STATUS_CANT_WAIT ) {
+
+ if (!bDeferred) {
+ Status = Ext2QueueRequest(IrpContext);
+ }
+
+ } else {
+
+ if (NT_SUCCESS(Status) && !PagingIo) {
+
+ if (SynchronousIo) {
+ FileObject->CurrentByteOffset.QuadPart =
+ ByteOffset.QuadPart + Irp->IoStatus.Information;
+ }
+
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+ SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+ }
+
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } else {
+ Ext2FreeIrpContext(IrpContext);
+ }
+ }
+ } _SEH2_END;
+
+ DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d "
+ "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n",
+ &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength,
+ Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart,
+ Fcb->Inode->i_size, Status));
+
+ return Status;
+}
+
+NTSTATUS
+Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PFILE_OBJECT FileObject;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext);
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ FileObject = IrpContext->FileObject;
+
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
+ Irp->MdlAddress = NULL;
+ Status = STATUS_SUCCESS;
+
+ } _SEH2_FINALLY {
+
+ if (!IrpContext->ExceptionInProgress) {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+
+NTSTATUS
+Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext)
+{
+ NTSTATUS Status;
+ PEXT2_FCBVCB FcbOrVcb;
+ PDEVICE_OBJECT DeviceObject;
+ PFILE_OBJECT FileObject;
+ PEXT2_VCB Vcb;
+ BOOLEAN bCompleteRequest = TRUE;
+
+ ASSERT(IrpContext);
+
+ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
+ (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
+
+ _SEH2_TRY {
+
+ if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
+
+ Status = Ext2WriteComplete(IrpContext);
+ bCompleteRequest = FALSE;
+
+ } else {
+
+ DeviceObject = IrpContext->DeviceObject;
+ if (IsExt2FsDevice(DeviceObject)) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+ FileObject = IrpContext->FileObject;
+
+ Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+
+ if (Vcb->Identifier.Type != EXT2VCB ||
+ Vcb->Identifier.Size != sizeof(EXT2_VCB) ) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ if (IsVcbReadOnly(Vcb)) {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ _SEH2_LEAVE;
+ }
+
+ if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
+ Vcb->LockFile != FileObject ) {
+ Status = STATUS_ACCESS_DENIED;
+ _SEH2_LEAVE;
+ }
+
+ FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
+
+ if (FcbOrVcb->Identifier.Type == EXT2VCB) {
+
+ Status = Ext2WriteVolume(IrpContext);
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ }
+ bCompleteRequest = FALSE;
+
+ } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
+
+ if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
+ Status = STATUS_TOO_LATE;
+ _SEH2_LEAVE;
+ }
+
+ Status = Ext2WriteFile(IrpContext);
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ }
+
+ bCompleteRequest = FALSE;
+ } else {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ } _SEH2_FINALLY {
+
+ if (bCompleteRequest) {
+ Ext2CompleteIrpContext(IrpContext, Status);
+ }
+ } _SEH2_END;
+
+ return Status;
}
+++ /dev/null
-
-include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers
- inc)
-
-list(APPEND SOURCE
- src/init.c
- src/ext3/generic.c
- src/ext3/htree.c
- src/ext3/indirect.c
- src/ext3/recover.c
- src/ext4/ext4_bh.c
- src/ext4/ext4_extents.c
- src/ext4/ext4_jbd2.c
- src/ext4/extents.c
- src/jbd/recovery.c
- src/jbd/replay.c
- src/jbd/revoke.c
- src/nls/nls_ascii.c
- src/nls/nls_base.c
- src/nls/nls_cp437.c
- src/nls/nls_cp737.c
- src/nls/nls_cp775.c
- src/nls/nls_cp850.c
- src/nls/nls_cp852.c
- src/nls/nls_cp855.c
- src/nls/nls_cp857.c
- src/nls/nls_cp860.c
- src/nls/nls_cp861.c
- src/nls/nls_cp862.c
- src/nls/nls_cp863.c
- src/nls/nls_cp864.c
- src/nls/nls_cp865.c
- src/nls/nls_cp866.c
- src/nls/nls_cp869.c
- src/nls/nls_cp874.c
- src/nls/nls_cp932.c
- src/nls/nls_cp936.c
- src/nls/nls_cp949.c
- src/nls/nls_cp950.c
- src/nls/nls_cp1250.c
- src/nls/nls_cp1251.c
- src/nls/nls_cp1255.c
- src/nls/nls_euc-jp.c
- src/nls/nls_iso8859-1.c
- src/nls/nls_iso8859-2.c
- src/nls/nls_iso8859-3.c
- src/nls/nls_iso8859-4.c
- src/nls/nls_iso8859-5.c
- src/nls/nls_iso8859-6.c
- src/nls/nls_iso8859-7.c
- src/nls/nls_iso8859-9.c
- src/nls/nls_iso8859-13.c
- src/nls/nls_iso8859-14.c
- src/nls/nls_iso8859-15.c
- src/nls/nls_koi8-r.c
- src/nls/nls_koi8-ru.c
- src/nls/nls_koi8-u.c
- src/nls/nls_utf8.c
- src/block.c
- src/cleanup.c
- src/close.c
- src/cmcb.c
- src/create.c
- src/debug.c
- src/devctl.c
- src/dirctl.c
- src/dispatch.c
- src/except.c
- src/fastio.c
- src/fileinfo.c
- src/flush.c
- src/fsctl.c
- src/linux.c
- src/lock.c
- src/memory.c
- src/misc.c
- src/nls.c
- src/pnp.c
- src/rbtree.c
- src/read.c
- src/shutdown.c
- src/volinfo.c
- src/write.c
- inc/ext2fs.h)
-
-add_library(ext2fs SHARED ${SOURCE} ext2fs.rc)
-
-if(NOT MSVC)
- add_target_compile_flags(ext2fs "-Wno-pointer-sign -Wno-unused-function")
- if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
- replace_compile_flags("-Werror" " ")
- add_target_compile_flags(ext2fs "-Wno-unused-but-set-variable -Wno-unused-variable -Wno-missing-braces")
- endif()
-else()
- #disable warnings: "unreferenced local variable", "initialized, but not used variable", "benign include"
- replace_compile_flags("/we\"4189\"" " ")
- add_target_compile_flags(ext2fs "/wd\"4189\" /wd\"4142\" /wd\"4101\"")
-endif()
-
-target_link_libraries(ext2fs memcmp ${PSEH_LIB})
-add_definitions(-D__KERNEL__ -D_X86_)
-set_module_type(ext2fs kernelmodedriver)
-add_importlibs(ext2fs ntoskrnl hal)
-add_pch(ext2fs inc/ext2fs.h SOURCE)
-add_cd_file(TARGET ext2fs DESTINATION reactos/system32/drivers NO_CAB FOR all)
+++ /dev/null
-#define REACTOS_VERSION_DLL
-#define REACTOS_STR_FILE_DESCRIPTION "Linux ext2 IFS Driver"
-#define REACTOS_STR_INTERNAL_NAME "ext2fs"
-#define REACTOS_STR_ORIGINAL_FILENAME "ext2fs.sys"
-#include <reactos/version.rc>
+++ /dev/null
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by ext2fsd.rc
-//
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 104
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1000
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: cleanup.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-NTSTATUS
-Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS Status = STATUS_SUCCESS;
- PEXT2_VCB Vcb;
- PFILE_OBJECT FileObject;
- PEXT2_FCB Fcb;
- PEXT2_CCB Ccb;
- PIRP Irp;
- PEXT2_MCB Mcb;
-
-
- BOOLEAN VcbResourceAcquired = FALSE;
- BOOLEAN FcbResourceAcquired = FALSE;
- BOOLEAN FcbPagingIoResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext != NULL);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- Irp = IrpContext->Irp;
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- if (!IsVcbInited(Vcb)) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- FileObject = IrpContext->FileObject;
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
- Fcb->Identifier.Type != EXT2FCB)) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
- Mcb = Fcb->Mcb;
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
-
- if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- VcbResourceAcquired =
- ExAcquireResourceExclusiveLite(
- &Vcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
- );
-
- if (Fcb->Identifier.Type == EXT2VCB) {
-
- if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
- Vcb->LockFile == FileObject ){
-
- ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
- Vcb->LockFile = NULL;
- Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
- }
-
- if (Ccb) {
- Ext2DerefXcb(&Vcb->OpenHandleCount);
- Ext2DerefXcb(&Vcb->OpenVolumeCount);
- }
-
- IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
-
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
- if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
- IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
- !IsVcbReadOnly(Vcb) ) {
- Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
- }
- _SEH2_LEAVE;
- }
-
- if (Ccb == NULL) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if (IsDirectory(Fcb)) {
- if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
- SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
-
- FsRtlNotifyFullChangeDirectory(
- Vcb->NotifySync,
- &Vcb->NotifyList,
- Ccb,
- NULL,
- FALSE,
- FALSE,
- 0,
- NULL,
- NULL,
- NULL );
- }
-
- FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
-
- }
-
- ExReleaseResourceLite(&Vcb->MainResource);
- VcbResourceAcquired = FALSE;
-
- FcbResourceAcquired =
- ExAcquireResourceExclusiveLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
- );
-
- ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
- (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
-
- Ext2DerefXcb(&Vcb->OpenHandleCount);
- Ext2DerefXcb(&Fcb->OpenHandleCount);
-
- if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
- Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
- }
-
- if (IsDirectory(Fcb)) {
-
- ext3_release_dir(Fcb->Inode, &Ccb->filp);
-
- } else {
-
- if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
- !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
-
- LARGE_INTEGER SysTime;
- KeQuerySystemTime(&SysTime);
-
- Fcb->Inode->i_atime =
- Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
- Fcb->Mcb->LastAccessTime =
- Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
-
- Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
-
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Fcb->Mcb,
- FILE_NOTIFY_CHANGE_ATTRIBUTES |
- FILE_NOTIFY_CHANGE_LAST_WRITE |
- FILE_NOTIFY_CHANGE_LAST_ACCESS,
- FILE_ACTION_MODIFIED );
- }
-
- FsRtlCheckOplock( &Fcb->Oplock,
- Irp,
- IrpContext,
- NULL,
- NULL );
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
-
- if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
- Fcb->NonCachedOpenCount--;
- }
-
- if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
- SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
- }
-
- //
- // Drop any byte range locks this process may have on the file.
- //
-
- FsRtlFastUnlockAll(
- &Fcb->FileLockAnchor,
- FileObject,
- IoGetRequestorProcess(Irp),
- NULL );
-
- //
- // If there are no byte range locks owned by other processes on the
- // file the fast I/O read/write functions doesn't have to check for
- // locks so we set IsFastIoPossible to FastIoIsPossible again.
- //
- if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
- if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
-#if EXT2_DEBUG
- DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
- Ext2GetCurrentProcessName(),
- "FastIoIsPossible",
- &Fcb->Mcb->FullName
- ));
-#endif
-
- Fcb->Header.IsFastIoPossible = FastIoIsPossible;
- }
- }
-
- if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
- FCB_ALLOC_IN_SETINFO) ){
-
- if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
- if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
- if (!INODE_HAS_EXTENT(Fcb->Inode)) {
- #if EXT2_PRE_ALLOCATION_SUPPORT
- CcZeroData(FileObject, &Fcb->Header.ValidDataLength,
- &Fcb->Header.AllocationSize, TRUE);
- #endif
- }
- }
- }
-
- if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
-
- LARGE_INTEGER Size;
-
- ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
- FcbPagingIoResourceAcquired = TRUE;
-
- Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
- (ULONGLONG)Fcb->Mcb->Inode.i_size,
- (ULONGLONG)BLOCK_SIZE);
- if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
-
- Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
- Fcb->Header.AllocationSize = Size;
- Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
- if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
- Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject,
- (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
- }
- ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- FcbPagingIoResourceAcquired = FALSE;
- }
- }
- }
-
- if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
-
- if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {
-
- //
- // Ext2DeleteFile will acquire these lock inside
- //
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- FcbResourceAcquired = FALSE;
- }
-
- //
- // this file is to be deleted ...
- //
- if (Ccb->SymLink) {
- Mcb = Ccb->SymLink;
- FileObject->DeletePending = FALSE;
- }
-
- Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
-
- if (NT_SUCCESS(Status)) {
- if (IsMcbDirectory(Mcb)) {
- Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- FILE_ACTION_REMOVED );
- } else {
- Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- FILE_ACTION_REMOVED );
- }
- }
-
- //
- // re-acquire the main resource lock
- //
-
- FcbResourceAcquired =
- ExAcquireResourceExclusiveLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
- );
-
- SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject,
- (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
- }
- }
-
- if (!IsDirectory(Fcb)) {
-
- if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
- (Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) &&
- (Fcb->SectionObject.DataSectionObject != NULL)) {
-
- if (!IsVcbReadOnly(Vcb)) {
- CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
- ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
- }
-
- if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
- ExReleaseResourceLite(&(Fcb->PagingIoResource));
- }
-
- CcPurgeCacheSection( &Fcb->SectionObject,
- NULL,
- 0,
- FALSE );
- }
-
- CcUninitializeCacheMap(FileObject, NULL, NULL);
- }
-
- IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
-
- DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
- Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
-
- Status = STATUS_SUCCESS;
-
- if (FileObject) {
- SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
- }
-
- } _SEH2_FINALLY {
-
- if (FcbPagingIoResourceAcquired) {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- }
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
- if (Status == STATUS_PENDING) {
- Ext2QueueRequest(IrpContext);
- } else {
- IrpContext->Irp->IoStatus.Status = Status;
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: close.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, Ext2QueueCloseRequest)
-#pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
-#endif
-
-NTSTATUS
-Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS Status = STATUS_SUCCESS;
- PEXT2_VCB Vcb = NULL;
- BOOLEAN VcbResourceAcquired = FALSE;
- PFILE_OBJECT FileObject;
- PEXT2_FCB Fcb;
- BOOLEAN FcbResourceAcquired = FALSE;
- PEXT2_CCB Ccb;
- BOOLEAN bDeleteVcb = FALSE;
- BOOLEAN bBeingClosed = FALSE;
- BOOLEAN bSkipLeave = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext != NULL);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_SUCCESS;
- Vcb = NULL;
- _SEH2_LEAVE;
- }
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- if (!ExAcquireResourceExclusiveLite(
- &Vcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
- Vcb->OpenHandleCount, Vcb->ReferenceCount));
-
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- VcbResourceAcquired = TRUE;
-
- bSkipLeave = TRUE;
- if (IsFlagOn(Vcb->Flags, VCB_BEING_CLOSED)) {
- bBeingClosed = TRUE;
- } else {
- SetLongFlag(Vcb->Flags, VCB_BEING_CLOSED);
- bBeingClosed = FALSE;
- }
-
- if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
-
- FileObject = NULL;
- Fcb = IrpContext->Fcb;
- Ccb = IrpContext->Ccb;
-
- } else {
-
- FileObject = IrpContext->FileObject;
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (!Fcb) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
- ASSERT(Fcb != NULL);
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- }
-
- DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n",
- bBeingClosed, Vcb, Vcb->ReferenceCount));
-
- if (Fcb->Identifier.Type == EXT2VCB) {
-
- if (Ccb) {
-
- Ext2DerefXcb(&Vcb->ReferenceCount);
- Ext2FreeCcb(Vcb, Ccb);
-
- if (FileObject) {
- FileObject->FsContext2 = Ccb = NULL;
- }
- }
-
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if ( Fcb->Identifier.Type != EXT2FCB ||
- Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
- _SEH2_LEAVE;
- }
-
- if (!ExAcquireResourceExclusiveLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- FcbResourceAcquired = TRUE;
-
- Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
-
- if (!Ccb) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
- (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
-
- if (IsFlagOn(Fcb->Flags, FCB_STATE_BUSY)) {
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY);
- DEBUG(DL_WRN, ( "Ext2Close: busy bit set: %wZ\n", &Fcb->Mcb->FullName ));
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
- Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
-
- if (Ccb) {
-
- Ext2FreeCcb(Vcb, Ccb);
-
- if (FileObject) {
- FileObject->FsContext2 = Ccb = NULL;
- }
- }
-
- if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) {
-
- //
- // Remove Fcb from Vcb->FcbList ...
- //
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- FcbResourceAcquired = FALSE;
- }
-
- Ext2FreeFcb(Fcb);
-
- if (FileObject) {
- FileObject->FsContext = Fcb = NULL;
- }
- }
-
- Ext2DerefXcb(&Vcb->ReferenceCount);
- Status = STATUS_SUCCESS;
-
- } _SEH2_FINALLY {
-
- if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) {
- /* for Ext2Fsd driver open/close, Vcb is NULL */
- if ((!bBeingClosed) && (Vcb->ReferenceCount == 0)&&
- (!IsMounted(Vcb) || IsDispending(Vcb))) {
- bDeleteVcb = TRUE;
- }
- }
-
- if (bSkipLeave && !bBeingClosed) {
- ClearFlag(Vcb->Flags, VCB_BEING_CLOSED);
- }
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
-
- if (Status == STATUS_PENDING) {
-
- Ext2QueueCloseRequest(IrpContext);
-
- } else {
-
- Ext2CompleteIrpContext(IrpContext, Status);
-
- if (bDeleteVcb) {
-
- PVPB Vpb = Vcb->Vpb;
- DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n",
- Vcb, Vpb));
-
- Ext2CheckDismount(IrpContext, Vcb, FALSE);
- }
- }
- }
- } _SEH2_END;
-
- return Status;
-}
-
-VOID
-Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
-
- if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
- Ext2Sleep(500); /* 0.5 sec*/
- } else {
- Ext2Sleep(50); /* 0.05 sec*/
- }
-
- } else {
-
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
-
- IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
- IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
- }
-
- ExInitializeWorkItem(
- &IrpContext->WorkQueueItem,
- Ext2DeQueueCloseRequest,
- IrpContext);
-
- ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
-}
-
-VOID NTAPI
-Ext2DeQueueCloseRequest (IN PVOID Context)
-{
- PEXT2_IRP_CONTEXT IrpContext;
-
- IrpContext = (PEXT2_IRP_CONTEXT) Context;
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- _SEH2_TRY {
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
- Ext2Close(IrpContext);
-
- } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
-
- Ext2ExceptionHandler(IrpContext);
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-}
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: create.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS *****************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, Ext2IsNameValid)
-#pragma alloc_text(PAGE, Ext2FollowLink)
-#pragma alloc_text(PAGE, Ext2IsSpecialSystemFile)
-#pragma alloc_text(PAGE, Ext2LookupFile)
-#pragma alloc_text(PAGE, Ext2ScanDir)
-#pragma alloc_text(PAGE, Ext2CreateFile)
-#pragma alloc_text(PAGE, Ext2CreateVolume)
-#pragma alloc_text(PAGE, Ext2Create)
-#pragma alloc_text(PAGE, Ext2CreateInode)
-#pragma alloc_text(PAGE, Ext2SupersedeOrOverWriteFile)
-#endif
-
-
-BOOLEAN
-Ext2IsNameValid(PUNICODE_STRING FileName)
-{
- USHORT i = 0;
- PUSHORT pName = (PUSHORT) FileName->Buffer;
-
- if (FileName == NULL) {
- return FALSE;
- }
-
- while (i < (FileName->Length / sizeof(WCHAR))) {
-
- if (pName[i] == 0) {
- break;
- }
-
- if (pName[i] == L'|' || pName[i] == L':' ||
- pName[i] == L'/' || pName[i] == L'*' ||
- pName[i] == L'?' || pName[i] == L'\"' ||
- pName[i] == L'<' || pName[i] == L'>' ) {
-
- return FALSE;
- }
-
- i++;
- }
-
- return TRUE;
-}
-
-
-NTSTATUS
-Ext2FollowLink (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PEXT2_MCB Parent,
- IN PEXT2_MCB Mcb,
- IN USHORT Linkdep
-)
-{
- NTSTATUS Status = STATUS_LINK_FAILED;
-
- UNICODE_STRING UniName;
- OEM_STRING OemName;
- BOOLEAN bOemBuffer = FALSE;
-
- PEXT2_MCB Target = NULL;
-
- USHORT i;
-
- _SEH2_TRY {
-
- RtlZeroMemory(&UniName, sizeof(UNICODE_STRING));
- RtlZeroMemory(&OemName, sizeof(OEM_STRING));
-
- /* exit if we jump into a possible symlink forever loop */
- if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS ||
- IoGetRemainingStackSize() < 1024) {
- _SEH2_LEAVE;
- }
-
- /* read the symlink target path */
- if (Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
-
- OemName.Buffer = (PUCHAR) (&Mcb->Inode.i_block[0]);
- OemName.Length = (USHORT)Mcb->Inode.i_size;
- OemName.MaximumLength = OemName.Length + 1;
-
- } else {
-
- OemName.Length = (USHORT)Mcb->Inode.i_size;
- OemName.MaximumLength = OemName.Length + 1;
- OemName.Buffer = Ext2AllocatePool(PagedPool,
- OemName.MaximumLength,
- 'NL2E');
- if (OemName.Buffer == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
- bOemBuffer = TRUE;
- RtlZeroMemory(OemName.Buffer, OemName.MaximumLength);
-
- Status = Ext2ReadInode(
- IrpContext,
- Vcb,
- Mcb,
- (ULONGLONG)0,
- OemName.Buffer,
- (ULONG)(Mcb->Inode.i_size),
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
- }
-
- /* convert Linux slash to Windows backslash */
- for (i=0; i < OemName.Length; i++) {
- if (OemName.Buffer[i] == '/') {
- OemName.Buffer[i] = '\\';
- }
- }
-
- /* convert oem string to unicode string */
- UniName.MaximumLength = (USHORT)Ext2OEMToUnicodeSize(Vcb, &OemName);
- if (UniName.MaximumLength <= 0) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
-
- UniName.MaximumLength += 2;
- UniName.Buffer = Ext2AllocatePool(PagedPool,
- UniName.MaximumLength,
- 'NL2E');
- if (UniName.Buffer == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
- RtlZeroMemory(UniName.Buffer, UniName.MaximumLength);
- Status = Ext2OEMToUnicode(Vcb, &UniName, &OemName);
- if (!NT_SUCCESS(Status)) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
-
- /* search the real target */
- Status = Ext2LookupFile(
- IrpContext,
- Vcb,
- &UniName,
- Parent,
- &Target,
- Linkdep
- );
- if (Target == NULL) {
- Status = STATUS_LINK_FAILED;
- }
-
- if (Target == NULL /* link target doesn't exist */ ||
- Target == Mcb /* symlink points to itself */ ||
- IsMcbSpecialFile(Target) /* target not resolved*/ ||
- IsFileDeleted(Target) /* target deleted */ ) {
-
- if (Target) {
- ASSERT(Target->Refercount > 0);
- Ext2DerefMcb(Target);
- }
- ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
- SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
- Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
- Mcb->Target = NULL;
-
- } else if (IsMcbSymLink(Target)) {
-
- ASSERT(Target->Refercount > 0);
- ASSERT(Target->Target != NULL);
- Ext2ReferMcb(Target->Target);
- Mcb->Target = Target->Target;
- Ext2DerefMcb(Target);
- ASSERT(!IsMcbSymLink(Target->Target));
- SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
- ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
- ASSERT(Mcb->Target->Refercount > 0);
- Mcb->FileAttr = Target->FileAttr;
-
- } else {
-
- Mcb->Target = Target;
- SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
- ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
- ASSERT(Mcb->Target->Refercount > 0);
- Mcb->FileAttr = Target->FileAttr;
- }
-
- } _SEH2_FINALLY {
-
- if (bOemBuffer) {
- Ext2FreePool(OemName.Buffer, 'NL2E');
- }
-
- if (UniName.Buffer) {
- Ext2FreePool(UniName.Buffer, 'NL2E');
- }
- } _SEH2_END;
-
- return Status;
-}
-
-BOOLEAN
-Ext2IsSpecialSystemFile(
- IN PUNICODE_STRING FileName,
- IN BOOLEAN bDirectory
-)
-{
- PWSTR SpecialFileList[] = {
- L"pagefile.sys",
- L"swapfile.sys",
- L"hiberfil.sys",
- NULL
- };
-
- PWSTR SpecialDirList[] = {
- L"Recycled",
- L"RECYCLER",
- L"$RECYCLE.BIN",
- NULL
- };
-
- PWSTR entryName;
- ULONG length;
- int i;
-
- for (i = 0; TRUE; i++) {
-
- if (bDirectory) {
- entryName = SpecialDirList[i];
- } else {
- entryName = SpecialFileList[i];
- }
-
- if (NULL == entryName) {
- break;
- }
-
- length = wcslen(entryName) * sizeof(WCHAR);
- if (FileName->Length == length) {
- if ( 0 == _wcsnicmp( entryName,
- FileName->Buffer,
- length / sizeof(WCHAR) )) {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-NTSTATUS
-Ext2LookupFile (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PUNICODE_STRING FullName,
- IN PEXT2_MCB Parent,
- OUT PEXT2_MCB * Ext2Mcb,
- IN USHORT Linkdep
-)
-{
- NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
- UNICODE_STRING FileName;
- PEXT2_MCB Mcb = NULL;
- struct dentry *de = NULL;
-
- USHORT i = 0, End;
- ULONG Inode;
-
- BOOLEAN bParent = FALSE;
- BOOLEAN bDirectory = FALSE;
- BOOLEAN LockAcquired = FALSE;
-
- _SEH2_TRY {
-
- ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
- LockAcquired = TRUE;
-
- *Ext2Mcb = NULL;
-
- DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName));
-
- /* check names and parameters */
- if (FullName->Buffer[0] == L'\\') {
- Parent = Vcb->McbTree;
- } else if (Parent) {
- bParent = TRUE;
- } else {
- Parent = Vcb->McbTree;
- }
-
- /* make sure the parent is NULL */
- if (!IsMcbDirectory(Parent)) {
- Status = STATUS_NOT_A_DIRECTORY;
- _SEH2_LEAVE;
- }
-
- /* use symlink's target as parent directory */
- if (IsMcbSymLink(Parent)) {
- Parent = Parent->Target;
- ASSERT(!IsMcbSymLink(Parent));
- if (IsFileDeleted(Parent)) {
- Status = STATUS_NOT_A_DIRECTORY;
- _SEH2_LEAVE;
- }
- }
-
- if (NULL == Parent) {
- Status = STATUS_NOT_A_DIRECTORY;
- _SEH2_LEAVE;
- }
-
- /* default is the parent Mcb*/
- Ext2ReferMcb(Parent);
- Mcb = Parent;
-
- /* is empty file name or root node */
- End = FullName->Length/sizeof(WCHAR);
- if ( (End == 0) || (End == 1 &&
- FullName->Buffer[0] == L'\\')) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- /* is a directory expected ? */
- if (FullName->Buffer[End - 1] == L'\\') {
- bDirectory = TRUE;
- }
-
- /* loop with every sub name */
- while (i < End) {
-
- USHORT Start = 0;
-
- /* zero the prefix '\' */
- while (i < End && FullName->Buffer[i] == L'\\') i++;
- Start = i;
-
- /* zero the suffix '\' */
- while (i < End && (FullName->Buffer[i] != L'\\')) i++;
-
- if (i > Start) {
-
- FileName = *FullName;
- FileName.Buffer += Start;
- FileName.Length = (USHORT)((i - Start) * 2);
-
- /* make sure the parent is NULL */
- if (!IsMcbDirectory(Parent)) {
- Status = STATUS_NOT_A_DIRECTORY;
- Ext2DerefMcb(Parent);
- break;
- }
-
- if (IsMcbSymLink(Parent)) {
- if (IsFileDeleted(Parent->Target)) {
- Status = STATUS_NOT_A_DIRECTORY;
- Ext2DerefMcb(Parent);
- break;
- } else {
- Ext2ReferMcb(Parent->Target);
- Ext2DerefMcb(Parent);
- Parent = Parent->Target;
- }
- }
-
- /* search cached Mcb nodes */
- Mcb = Ext2SearchMcbWithoutLock(Parent, &FileName);
-
- if (Mcb) {
-
- /* derefer the parent Mcb */
- Ext2DerefMcb(Parent);
- Status = STATUS_SUCCESS;
- Parent = Mcb;
-
- if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) &&
- (Mcb->Refercount == 1)) {
-
- ASSERT(Mcb->Target);
- ASSERT(Mcb->Target->Refercount > 0);
- Ext2DerefMcb(Mcb->Target);
- Mcb->Target = NULL;
- ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
- SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
- Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
- }
-
- } else {
-
- /* need create new Mcb node */
-
- /* is a valid ext2 name */
- if (!Ext2IsNameValid(&FileName)) {
- Status = STATUS_OBJECT_NAME_INVALID;
- Ext2DerefMcb(Parent);
- break;
- }
-
- /* seach the disk */
- de = NULL;
- Status = Ext2ScanDir (
- IrpContext,
- Vcb,
- Parent,
- &FileName,
- &Inode,
- &de);
-
- if (NT_SUCCESS(Status)) {
-
- /* check it's real parent */
- ASSERT (!IsMcbSymLink(Parent));
-
- /* allocate Mcb ... */
- Mcb = Ext2AllocateMcb(Vcb, &FileName, &Parent->FullName, 0);
- if (!Mcb) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- Ext2DerefMcb(Parent);
- break;
- }
- Mcb->de = de;
- Mcb->de->d_inode = &Mcb->Inode;
- Mcb->Inode.i_ino = Inode;
- Mcb->Inode.i_sb = &Vcb->sb;
- de = NULL;
-
- /* load inode information */
- if (!Ext2LoadInode(Vcb, &Mcb->Inode)) {
- Status = STATUS_CANT_WAIT;
- Ext2DerefMcb(Parent);
- Ext2FreeMcb(Vcb, Mcb);
- break;
- }
-
- /* set inode attribute */
- if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
- SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
- }
-
- if (S_ISDIR(Mcb->Inode.i_mode)) {
- SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
- } else {
- SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
- if (!S_ISREG(Mcb->Inode.i_mode) &&
- !S_ISLNK(Mcb->Inode.i_mode)) {
- SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
- }
- }
-
- /* process special files under root directory */
- if (IsMcbRoot(Parent)) {
- /* set hidden and system attributes for
- Recycled / RECYCLER / pagefile.sys */
- BOOLEAN IsDirectory = IsMcbDirectory(Mcb);
- if (Ext2IsSpecialSystemFile(&Mcb->ShortName, IsDirectory)) {
- SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_HIDDEN);
- SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_SYSTEM);
- }
- }
-
- Mcb->CreationTime = Ext2NtTime(Mcb->Inode.i_ctime);
- Mcb->LastAccessTime = Ext2NtTime(Mcb->Inode.i_atime);
- Mcb->LastWriteTime = Ext2NtTime(Mcb->Inode.i_mtime);
- Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime);
-
- /* process symlink */
- if (S_ISLNK(Mcb->Inode.i_mode)) {
- Ext2FollowLink( IrpContext,
- Vcb,
- Parent,
- Mcb,
- Linkdep+1
- );
- }
-
- /* add reference ... */
- Ext2ReferMcb(Mcb);
-
- /* add Mcb to it's parent tree*/
- Ext2InsertMcb(Vcb, Parent, Mcb);
-
- /* it's safe to deref Parent Mcb */
- Ext2DerefMcb(Parent);
-
- /* linking this Mcb*/
- Ext2LinkTailMcb(Vcb, Mcb);
-
- /* set parent to preare re-scan */
- Parent = Mcb;
-
- } else {
-
- /* derefernce it's parent */
- Ext2DerefMcb(Parent);
- break;
- }
- }
-
- } else {
-
- /* there seems too many \ or / */
- /* Mcb should be already set to Parent */
- ASSERT(Mcb == Parent);
- Status = STATUS_SUCCESS;
- break;
- }
- }
-
- } _SEH2_FINALLY {
-
- if (de) {
- Ext2FreeEntry(de);
- }
-
- if (NT_SUCCESS(Status)) {
- if (bDirectory) {
- if (IsMcbDirectory(Mcb)) {
- *Ext2Mcb = Mcb;
- } else {
- Ext2DerefMcb(Mcb);
- Status = STATUS_NOT_A_DIRECTORY;
- }
- } else {
- *Ext2Mcb = Mcb;
- }
- }
-
- if (LockAcquired) {
- ExReleaseResourceLite(&Vcb->McbLock);
- }
- } _SEH2_END;
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2ScanDir (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PEXT2_MCB Parent,
- IN PUNICODE_STRING FileName,
- OUT PULONG Inode,
- OUT struct dentry **dentry
-)
-{
- struct ext3_dir_entry_2 *dir_entry = NULL;
- struct buffer_head *bh = NULL;
- struct dentry *de = NULL;
-
- NTSTATUS Status = STATUS_NO_SUCH_FILE;
-
- DEBUG(DL_RES, ("Ext2ScanDir: %wZ\\%wZ\n", &Parent->FullName, FileName));
-
- _SEH2_TRY {
-
- /* grab parent's reference first */
- Ext2ReferMcb(Parent);
-
- /* bad request ! Can a man be pregnant ? Maybe:) */
- if (!IsMcbDirectory(Parent)) {
- Status = STATUS_NOT_A_DIRECTORY;
- _SEH2_LEAVE;
- }
-
- /* parent is a symlink ? */
- if IsMcbSymLink(Parent) {
- if (Parent->Target) {
- Ext2ReferMcb(Parent->Target);
- Ext2DerefMcb(Parent);
- Parent = Parent->Target;
- ASSERT(!IsMcbSymLink(Parent));
- } else {
- DbgBreak();
- Status = STATUS_NOT_A_DIRECTORY;
- _SEH2_LEAVE;
- }
- }
-
- de = Ext2BuildEntry(Vcb, Parent, FileName);
- if (!de) {
- DEBUG(DL_ERR, ( "Ex2ScanDir: failed to allocate dentry.\n"));
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
-
- bh = ext3_find_entry(IrpContext, de, &dir_entry);
- if (dir_entry) {
- Status = STATUS_SUCCESS;
- *Inode = dir_entry->inode;
- *dentry = de;
- }
-
- } _SEH2_FINALLY {
-
- Ext2DerefMcb(Parent);
-
- if (bh)
- brelse(bh);
-
- if (!NT_SUCCESS(Status)) {
- if (de)
- Ext2FreeEntry(de);
- }
- } _SEH2_END;
-
- return Status;
-}
-
-NTSTATUS Ext2AddDotEntries(struct ext2_icb *icb, struct inode *dir,
- struct inode *inode)
-{
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
- ext3_lblk_t block = 0;
- int rc = 0;
-
- bh = ext3_append(icb, inode, &block, &rc);
- if (!bh) {
- goto errorout;
- }
-
- de = (struct ext3_dir_entry_2 *) bh->b_data;
- de->inode = cpu_to_le32(inode->i_ino);
- de->name_len = 1;
- de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
- strcpy (de->name, ".");
- ext3_set_de_type(inode->i_sb, de, S_IFDIR);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
- de->inode = cpu_to_le32(dir->i_ino);
- de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
- de->name_len = 2;
- strcpy (de->name, "..");
- ext3_set_de_type(inode->i_sb, de, S_IFDIR);
- inode->i_nlink = 2;
- set_buffer_dirty(bh);
- ext3_mark_inode_dirty(icb, inode);
-
-errorout:
- if (bh)
- brelse (bh);
-
- return Ext2WinntError(rc);
-}
-
-NTSTATUS
-Ext2CreateFile(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PBOOLEAN OpPostIrp
-)
-{
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PIO_STACK_LOCATION IrpSp;
- PEXT2_FCB Fcb = NULL;
- PEXT2_MCB Mcb = NULL;
- PEXT2_MCB SymLink = NULL;
- PEXT2_CCB Ccb = NULL;
-
- PEXT2_FCB ParentFcb = NULL;
- PEXT2_MCB ParentMcb = NULL;
-
- UNICODE_STRING FileName;
- PIRP Irp;
-
- ULONG Options;
- ULONG CreateDisposition;
-
- BOOLEAN bParentFcbCreated = FALSE;
-
-#ifndef __REACTOS__
- BOOLEAN bDir = FALSE;
-#endif
- BOOLEAN bFcbAllocated = FALSE;
- BOOLEAN bCreated = FALSE;
- BOOLEAN bMainResourceAcquired = FALSE;
-
- BOOLEAN OpenDirectory;
- BOOLEAN OpenTargetDirectory;
- BOOLEAN CreateDirectory;
- BOOLEAN SequentialOnly;
- BOOLEAN NoIntermediateBuffering;
- BOOLEAN IsPagingFile;
- BOOLEAN DirectoryFile;
- BOOLEAN NonDirectoryFile;
- BOOLEAN NoEaKnowledge;
- BOOLEAN DeleteOnClose;
- BOOLEAN TemporaryFile;
- BOOLEAN CaseSensitive;
-
- ACCESS_MASK DesiredAccess;
- ULONG ShareAccess;
-
- RtlZeroMemory(&FileName, sizeof(UNICODE_STRING));
-
- Irp = IrpContext->Irp;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- Options = IrpSp->Parameters.Create.Options;
-
- DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
- OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
-
- NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
- SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
- NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
- NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
- DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
-
- CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
-
- TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
- FILE_ATTRIBUTE_TEMPORARY );
-
- CreateDisposition = (Options >> 24) & 0x000000ff;
-
- IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
-
- CreateDirectory = (BOOLEAN)(DirectoryFile &&
- ((CreateDisposition == FILE_CREATE) ||
- (CreateDisposition == FILE_OPEN_IF)));
-
- OpenDirectory = (BOOLEAN)(DirectoryFile &&
- ((CreateDisposition == FILE_OPEN) ||
- (CreateDisposition == FILE_OPEN_IF)));
-
- DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
- ShareAccess = IrpSp->Parameters.Create.ShareAccess;
-
- *OpPostIrp = FALSE;
-
- _SEH2_TRY {
-
- FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
- FileName.Length = IrpSp->FileObject->FileName.Length;
-
- if (IrpSp->FileObject->RelatedFileObject) {
- ParentFcb = (PEXT2_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
- }
-
- if (ParentFcb) {
- ParentMcb = ParentFcb->Mcb;
- SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
- Ext2ReferMcb(ParentMcb);
- }
-
- if (FileName.Length == 0) {
-
- if (ParentFcb) {
- Mcb = ParentFcb->Mcb;
- Ext2ReferMcb(Mcb);
- Status = STATUS_SUCCESS;
- goto McbExisting;
- } else {
- DbgBreak();
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
- }
-
- FileName.Buffer = Ext2AllocatePool(
- PagedPool,
- FileName.MaximumLength,
- EXT2_FNAME_MAGIC
- );
-
- if (!FileName.Buffer) {
- DEBUG(DL_ERR, ( "Ex2CreateFile: failed to allocate FileName.\n"));
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
-
- INC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
-
- RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
- RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
-
- if (ParentFcb && FileName.Buffer[0] == L'\\') {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- if ((FileName.Length > sizeof(WCHAR)) &&
- (FileName.Buffer[1] == L'\\') &&
- (FileName.Buffer[0] == L'\\')) {
-
- FileName.Length -= sizeof(WCHAR);
-
- RtlMoveMemory( &FileName.Buffer[0],
- &FileName.Buffer[1],
- FileName.Length );
-
- //
- // Bad Name if there are still beginning backslashes.
- //
-
- if ((FileName.Length > sizeof(WCHAR)) &&
- (FileName.Buffer[1] == L'\\') &&
- (FileName.Buffer[0] == L'\\')) {
-
- Status = STATUS_OBJECT_NAME_INVALID;
- _SEH2_LEAVE;
- }
- }
-
- if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID)) {
- Status = STATUS_NOT_IMPLEMENTED;
- _SEH2_LEAVE;
- }
-
- DEBUG(DL_INF, ( "Ext2CreateFile: %wZ Paging=%d Option: %xh:"
- "Dir=%d NonDir=%d OpenTarget=%d NC=%d DeleteOnClose=%d\n",
- &FileName, IsPagingFile, IrpSp->Parameters.Create.Options,
- DirectoryFile, NonDirectoryFile, OpenTargetDirectory,
- NoIntermediateBuffering, DeleteOnClose ));
-
- DEBUG(DL_RES, ("Ext2CreateFile: Lookup 1st: %wZ at %S\n",
- &FileName, ParentMcb ? ParentMcb->FullName.Buffer : L" "));
- Status = Ext2LookupFile(
- IrpContext,
- Vcb,
- &FileName,
- ParentMcb,
- &Mcb,
- 0 );
-McbExisting:
-
- if (!NT_SUCCESS(Status)) {
-
- UNICODE_STRING PathName;
- UNICODE_STRING RealName;
- UNICODE_STRING RemainName;
-
-#ifndef __REACTOS__
- LONG i = 0;
-#endif
- PathName = FileName;
- Mcb = NULL;
-
- if (PathName.Buffer[PathName.Length/2 - 1] == L'\\') {
- if (DirectoryFile) {
- PathName.Length -=2;
- PathName.Buffer[PathName.Length/2] = 0;
- } else {
- DirectoryFile = TRUE;
- }
- }
-
- if (!ParentMcb) {
- if (PathName.Buffer[0] != L'\\') {
- Status = STATUS_OBJECT_PATH_NOT_FOUND;
- _SEH2_LEAVE;
- } else {
- ParentMcb = Vcb->McbTree;
- Ext2ReferMcb(ParentMcb);
- }
- }
-
-Dissecting:
-
- FsRtlDissectName(PathName, &RealName, &RemainName);
-
- if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
- (RealName.Length >= 256 * sizeof(WCHAR))) {
- Status = STATUS_OBJECT_NAME_INVALID;
- _SEH2_LEAVE;
- }
-
- if (RemainName.Length != 0) {
-
- PEXT2_MCB RetMcb = NULL;
-
- DEBUG(DL_RES, ("Ext2CreateFile: Lookup 2nd: %wZ\\%wZ\n",
- &ParentMcb->FullName, &RealName));
-
- Status = Ext2LookupFile (
- IrpContext,
- Vcb,
- &RealName,
- ParentMcb,
- &RetMcb,
- 0);
-
- /* quit name resolving loop */
- if (!NT_SUCCESS(Status)) {
- if (Status == STATUS_NO_SUCH_FILE && RemainName.Length != 0) {
- Status = STATUS_OBJECT_PATH_NOT_FOUND;
- }
- _SEH2_LEAVE;
- }
-
- /* deref ParentMcb */
- Ext2DerefMcb(ParentMcb);
-
- /* RetMcb is already refered */
- ParentMcb = RetMcb;
- PathName = RemainName;
-
- /* symlink must use it's target */
- if (IsMcbSymLink(ParentMcb)) {
- Ext2ReferMcb(ParentMcb->Target);
- Ext2DerefMcb(ParentMcb);
- ParentMcb = ParentMcb->Target;
- ASSERT(!IsMcbSymLink(ParentMcb));
- }
-
- goto Dissecting;
- }
-
- /* is name valid */
- if ( FsRtlDoesNameContainWildCards(&RealName) ||
- !Ext2IsNameValid(&RealName)) {
- Status = STATUS_OBJECT_NAME_INVALID;
- _SEH2_LEAVE;
- }
-
- /* clear BUSY bit from original ParentFcb */
- if (ParentFcb) {
- ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
- }
-
- /* get the ParentFcb, allocate it if needed ... */
- ParentFcb = ParentMcb->Fcb;
- if (!ParentFcb) {
- ParentFcb = Ext2AllocateFcb(Vcb, ParentMcb);
- if (!ParentFcb) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
- bParentFcbCreated = TRUE;
- Ext2ReferXcb(&ParentFcb->ReferenceCount);
- }
- SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
-
- // We need to create a new one ?
- if ((CreateDisposition == FILE_CREATE ) ||
- (CreateDisposition == FILE_SUPERSEDE) ||
- (CreateDisposition == FILE_OPEN_IF) ||
- (CreateDisposition == FILE_OVERWRITE_IF)) {
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
-
- if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(ParentFcb->Mcb->Inode.i_mode)) {
- Status = STATUS_ACCESS_DENIED;
- _SEH2_LEAVE;
- }
-
- if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
- IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
- Vcb->Vpb->RealDevice );
- SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
- Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
- }
-
- if (DirectoryFile) {
- if (TemporaryFile) {
- DbgBreak();
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
- }
-
- if (!ParentFcb) {
- Status = STATUS_OBJECT_PATH_NOT_FOUND;
- _SEH2_LEAVE;
- }
-
- /* allocate inode and construct entry for this file */
- Status = Ext2CreateInode(
- IrpContext,
- Vcb,
- ParentFcb,
- DirectoryFile ? EXT2_FT_DIR : EXT2_FT_REG_FILE,
- IrpSp->Parameters.Create.FileAttributes,
- &RealName
- );
-
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- bCreated = TRUE;
- DEBUG(DL_RES, ("Ext2CreateFile: Confirm creation: %wZ\\%wZ\n",
- &ParentMcb->FullName, &RealName));
-
- Irp->IoStatus.Information = FILE_CREATED;
- Status = Ext2LookupFile (
- IrpContext,
- Vcb,
- &RealName,
- ParentMcb,
- &Mcb,
- 0);
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- }
-
- } else if (OpenTargetDirectory) {
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
-
- if (!ParentFcb) {
- Status = STATUS_OBJECT_PATH_NOT_FOUND;
- _SEH2_LEAVE;
- }
-
- RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
- IrpSp->FileObject->FileName.MaximumLength);
- IrpSp->FileObject->FileName.Length = RealName.Length;
-
- RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
- RealName.Buffer,
- RealName.Length );
-
- Fcb = ParentFcb;
- Mcb = Fcb->Mcb;
- Ext2ReferMcb(Mcb);
-
- Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
- Status = STATUS_SUCCESS;
-
- } else {
-
- Status = STATUS_OBJECT_NAME_NOT_FOUND;
- _SEH2_LEAVE;
- }
-
- } else { // File / Dir already exists.
-
- /* here already get Mcb referred */
- if (OpenTargetDirectory) {
-
- UNICODE_STRING RealName = FileName;
- USHORT i = 0;
-
- while (RealName.Buffer[RealName.Length/2 - 1] == L'\\') {
- RealName.Length -= sizeof(WCHAR);
- RealName.Buffer[RealName.Length/2] = 0;
- }
- i = RealName.Length/2;
- while (i > 0 && RealName.Buffer[i - 1] != L'\\')
- i--;
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- Ext2DerefMcb(Mcb);
- _SEH2_LEAVE;
- }
-
- Irp->IoStatus.Information = FILE_EXISTS;
- Status = STATUS_SUCCESS;
-
- RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
- IrpSp->FileObject->FileName.MaximumLength);
- IrpSp->FileObject->FileName.Length = RealName.Length - i * sizeof(WCHAR);
- RtlCopyMemory( IrpSp->FileObject->FileName.Buffer, &RealName.Buffer[i],
- IrpSp->FileObject->FileName.Length );
-
- // use's it's parent since it's open-target operation
- Ext2ReferMcb(Mcb->Parent);
- Ext2DerefMcb(Mcb);
- Mcb = Mcb->Parent;
-
- goto Openit;
- }
-
- // We can not create if one exists
- if (CreateDisposition == FILE_CREATE) {
- Irp->IoStatus.Information = FILE_EXISTS;
- Status = STATUS_OBJECT_NAME_COLLISION;
- Ext2DerefMcb(Mcb);
- _SEH2_LEAVE;
- }
-
- /* directory forbits us to do the followings ... */
- if (IsMcbDirectory(Mcb)) {
-
- if ((CreateDisposition != FILE_OPEN) &&
- (CreateDisposition != FILE_OPEN_IF)) {
-
- Status = STATUS_OBJECT_NAME_COLLISION;
- Ext2DerefMcb(Mcb);
- _SEH2_LEAVE;
- }
-
- if (NonDirectoryFile) {
- Status = STATUS_FILE_IS_A_DIRECTORY;
- Ext2DerefMcb(Mcb);
- _SEH2_LEAVE;
- }
-
- if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
-
- if (OpenTargetDirectory) {
- DbgBreak();
- Status = STATUS_INVALID_PARAMETER;
- Ext2DerefMcb(Mcb);
- _SEH2_LEAVE;
- }
- }
-
- } else {
-
- if (DirectoryFile) {
- Status = STATUS_NOT_A_DIRECTORY;;
- Ext2DerefMcb(Mcb);
- _SEH2_LEAVE;
- }
- }
-
- Irp->IoStatus.Information = FILE_OPENED;
- }
-
-Openit:
- /* Mcb should already be referred and symlink is too */
- if (Mcb) {
-
- ASSERT(Mcb->Refercount > 0);
-
- /* refer it's target if it's a symlink, so both refered */
- if (IsMcbSymLink(Mcb)) {
- if (IsFileDeleted(Mcb->Target)) {
- DbgBreak();
- SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
- ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
- Ext2DerefMcb(Mcb->Target);
- Mcb->Target = NULL;
- } else {
- SymLink = Mcb;
- Mcb = Mcb->Target;
- Ext2ReferMcb(Mcb);
- ASSERT (!IsMcbSymLink(Mcb));
- }
- }
-
- // Check readonly flag
- if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
- if (BooleanFlagOn(DesiredAccess, FILE_WRITE_DATA | FILE_APPEND_DATA |
- FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) {
- Status = STATUS_ACCESS_DENIED;
- _SEH2_LEAVE;
- } else if (IsFlagOn(Options, FILE_DELETE_ON_CLOSE )) {
- Status = STATUS_CANNOT_DELETE;
- _SEH2_LEAVE;
- }
- }
-
- Fcb = Mcb->Fcb;
- if (Fcb == NULL) {
-
- /* allocate Fcb for this file */
- Fcb = Ext2AllocateFcb (Vcb, Mcb);
- if (Fcb) {
- bFcbAllocated = TRUE;
- } else {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- } else {
- if (IsPagingFile) {
- Status = STATUS_SHARING_VIOLATION;
- Fcb = NULL;
- }
- }
-
- /* Now it's safe to defer Mcb */
- Ext2DerefMcb(Mcb);
- }
-
- if (Fcb) {
-
- /* grab Fcb's reference first to avoid the race between
- Ext2Close (it could free the Fcb we are accessing) */
- Ext2ReferXcb(&Fcb->ReferenceCount);
-
- ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
- bMainResourceAcquired = TRUE;
-
- /* Open target directory ? */
- if (NULL == Mcb) {
- DbgBreak();
- Mcb = Fcb->Mcb;
- }
-
- /* check Mcb reference */
- ASSERT(Fcb->Mcb->Refercount > 0);
-
- /* file delted ? */
- if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) {
- Status = STATUS_FILE_DELETED;
- _SEH2_LEAVE;
- }
-
- if (DeleteOnClose && NULL == SymLink) {
- Status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
- }
-
- /* check access and oplock access for opened files */
- if (!bFcbAllocated && !IsDirectory(Fcb)) {
-
- /* whether there's batch oplock grabed on the file */
- if (FsRtlCurrentBatchOplock(&Fcb->Oplock)) {
-
- Irp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
-
- /* break the batch lock if the sharing check fails */
- Status = FsRtlCheckOplock( &Fcb->Oplock,
- IrpContext->Irp,
- IrpContext,
- Ext2OplockComplete,
- Ext2LockIrp );
-
- if ( Status != STATUS_SUCCESS &&
- Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
- *OpPostIrp = TRUE;
- _SEH2_LEAVE;
- }
- }
- }
-
- if (bCreated) {
-
- //
- // This file is just created.
- //
-
- if (DirectoryFile) {
-
- Status = Ext2AddDotEntries(IrpContext, &ParentMcb->Inode, &Mcb->Inode);
- if (!NT_SUCCESS(Status)) {
- Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
- _SEH2_LEAVE;
- }
-
- } else {
-
- if ((LONGLONG)ext3_free_blocks_count(SUPER_BLOCK) <=
- Ext2TotalBlocks(Vcb, &Irp->Overlay.AllocationSize, NULL)) {
- DbgBreak();
- Status = STATUS_DISK_FULL;
- _SEH2_LEAVE;
- }
-
- /* disable data blocks allocation */
-#if 0
- Fcb->Header.AllocationSize.QuadPart =
- Irp->Overlay.AllocationSize.QuadPart;
-
- if (Fcb->Header.AllocationSize.QuadPart > 0) {
- Status = Ext2ExpandFile(IrpContext,
- Vcb,
- Fcb->Mcb,
- &(Fcb->Header.AllocationSize)
- );
- SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
- if (!NT_SUCCESS(Status)) {
- Fcb->Header.AllocationSize.QuadPart = 0;
- Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb,
- &Fcb->Header.AllocationSize);
- _SEH2_LEAVE;
- }
- }
-#endif
- }
-
- } else {
-
- //
- // This file alreayd exists.
- //
-
- if (DeleteOnClose) {
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
-
- if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
-
- IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
- Vcb->Vpb->RealDevice );
-
- SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
-
- Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
- }
-
- } else {
-
- //
- // Just to Open file (Open/OverWrite ...)
- //
-
- if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
- FO_NO_INTERMEDIATE_BUFFERING))) {
- Fcb->Header.IsFastIoPossible = FastIoIsPossible;
-
- if (Fcb->SectionObject.DataSectionObject != NULL) {
-
- if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) {
-
- if (!IsVcbReadOnly(Vcb)) {
- CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
- ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
- }
-
- CcPurgeCacheSection(&Fcb->SectionObject,
- NULL,
- 0,
- FALSE );
- }
- }
- }
- }
- }
-
- if (!IsDirectory(Fcb)) {
-
- if (!IsVcbReadOnly(Vcb)) {
- if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) {
- DesiredAccess |= DELETE;
- } else if (((CreateDisposition == FILE_OVERWRITE) ||
- (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
- DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
- FILE_WRITE_ATTRIBUTES );
- }
- }
-
- if (!bFcbAllocated) {
-
- //
- // check the oplock state of the file
- //
- Status = FsRtlCheckOplock( &Fcb->Oplock,
- IrpContext->Irp,
- IrpContext,
- Ext2OplockComplete,
- Ext2LockIrp );
-
- if ( Status != STATUS_SUCCESS &&
- Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
- *OpPostIrp = TRUE;
- _SEH2_LEAVE;
- }
- }
- }
-
- if (Fcb->OpenHandleCount > 0) {
-
- /* check the shrae access conflicts */
- Status = IoCheckShareAccess( DesiredAccess,
- ShareAccess,
- IrpSp->FileObject,
- &(Fcb->ShareAccess),
- TRUE );
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- } else {
-
- /* set share access rights */
- IoSetShareAccess( DesiredAccess,
- ShareAccess,
- IrpSp->FileObject,
- &(Fcb->ShareAccess) );
- }
-
- Ccb = Ext2AllocateCcb(SymLink);
- if (!Ccb) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- if (DeleteOnClose)
- SetLongFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
-
- if (SymLink)
- Ccb->filp.f_dentry = SymLink->de;
- else
- Ccb->filp.f_dentry = Fcb->Mcb->de;
-
- Ccb->filp.f_version = Fcb->Mcb->Inode.i_version;
- Ext2ReferXcb(&Fcb->OpenHandleCount);
- Ext2ReferXcb(&Fcb->ReferenceCount);
-
- if (!IsDirectory(Fcb)) {
- if (NoIntermediateBuffering) {
- Fcb->NonCachedOpenCount++;
- SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
- } else {
- SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
- }
- }
-
- Ext2ReferXcb(&Vcb->OpenHandleCount);
- Ext2ReferXcb(&Vcb->ReferenceCount);
-
- IrpSp->FileObject->FsContext = (void*) Fcb;
- IrpSp->FileObject->FsContext2 = (void*) Ccb;
- IrpSp->FileObject->PrivateCacheMap = NULL;
- IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
-
- DEBUG(DL_INF, ( "Ext2CreateFile: %wZ OpenCount=%u ReferCount=%u NonCachedCount=%u\n",
- &Fcb->Mcb->FullName, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount));
-
- Status = STATUS_SUCCESS;
-
- if (bCreated) {
-
- if (IsDirectory(Fcb)) {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Fcb->Mcb,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- FILE_ACTION_ADDED );
- } else {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Fcb->Mcb,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- FILE_ACTION_ADDED );
- }
-
- } else if (!IsDirectory(Fcb)) {
-
- if ( DeleteOnClose ||
- IsFlagOn(DesiredAccess, FILE_WRITE_DATA) ||
- (CreateDisposition == FILE_OVERWRITE) ||
- (CreateDisposition == FILE_OVERWRITE_IF)) {
- if (!MmFlushImageSection( &Fcb->SectionObject,
- MmFlushForWrite )) {
-
- Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
- STATUS_SHARING_VIOLATION;
- _SEH2_LEAVE;
- }
- }
-
- if ((CreateDisposition == FILE_SUPERSEDE) ||
- (CreateDisposition == FILE_OVERWRITE) ||
- (CreateDisposition == FILE_OVERWRITE_IF)) {
-
- if (IsDirectory(Fcb)) {
- Status = STATUS_FILE_IS_A_DIRECTORY;
- _SEH2_LEAVE;
- }
-
- if (SymLink != NULL) {
- DbgBreak();
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
-
- if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
-
- IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
- Vcb->Vpb->RealDevice );
- SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
- Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
- }
-
- Status = Ext2SupersedeOrOverWriteFile(
- IrpContext,
- IrpSp->FileObject,
- Vcb,
- Fcb,
- &Irp->Overlay.AllocationSize,
- CreateDisposition );
-
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Fcb->Mcb,
- FILE_NOTIFY_CHANGE_LAST_WRITE |
- FILE_NOTIFY_CHANGE_ATTRIBUTES |
- FILE_NOTIFY_CHANGE_SIZE,
- FILE_ACTION_MODIFIED );
-
-
- if (CreateDisposition == FILE_SUPERSEDE) {
- Irp->IoStatus.Information = FILE_SUPERSEDED;
- } else {
- Irp->IoStatus.Information = FILE_OVERWRITTEN;
- }
- }
- }
-
- } else {
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- } _SEH2_FINALLY {
-
-
- if (ParentMcb) {
- Ext2DerefMcb(ParentMcb);
- }
-
- /* cleanup Fcb and Ccb, Mcb if necessary */
- if (!NT_SUCCESS(Status)) {
-
- if (Ccb != NULL) {
-
- DbgBreak();
-
- ASSERT(Fcb != NULL);
- ASSERT(Fcb->Mcb != NULL);
-
- DEBUG(DL_ERR, ("Ext2CreateFile: failed to create %wZ status = %xh\n",
- &Fcb->Mcb->FullName, Status));
-
- Ext2DerefXcb(&Fcb->OpenHandleCount);
- Ext2DerefXcb(&Fcb->ReferenceCount);
-
- if (!IsDirectory(Fcb)) {
- if (NoIntermediateBuffering) {
- Fcb->NonCachedOpenCount--;
- } else {
- ClearFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
- }
- }
-
- Ext2DerefXcb(&Vcb->OpenHandleCount);
- Ext2DerefXcb(&Vcb->ReferenceCount);
-
- IoRemoveShareAccess(IrpSp->FileObject, &Fcb->ShareAccess);
-
- IrpSp->FileObject->FsContext = NULL;
- IrpSp->FileObject->FsContext2 = NULL;
- IrpSp->FileObject->PrivateCacheMap = NULL;
- IrpSp->FileObject->SectionObjectPointer = NULL;
-
- Ext2FreeCcb(Vcb, Ccb);
- }
- }
-
- if (Fcb && Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
-
- if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
-
- LARGE_INTEGER Size;
- ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
- _SEH2_TRY {
- Size.QuadPart = 0;
- Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
- } _SEH2_FINALLY {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- } _SEH2_END;
- }
-
- if (bCreated) {
- Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
- }
-
- Ext2FreeFcb(Fcb);
- Fcb = NULL;
- bMainResourceAcquired = FALSE;
- }
-
- if (bMainResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- /* free file name buffer */
- if (FileName.Buffer) {
- DEC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
- Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC);
- }
-
- /* dereference parent Fcb, free it if it goes to zero */
- if (ParentFcb) {
- ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
- if (bParentFcbCreated) {
- if (Ext2DerefXcb(&ParentFcb->ReferenceCount) == 0) {
- Ext2FreeFcb(ParentFcb);
- }
- }
- }
-
- /* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer
- it already. It fails, we need release the refer to let it freed */
- if (SymLink) {
- Ext2DerefMcb(SymLink);
- }
- } _SEH2_END;
-
- return Status;
-}
-
-NTSTATUS
-Ext2CreateVolume(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
-{
- PIO_STACK_LOCATION IrpSp;
- PIRP Irp;
- PEXT2_CCB Ccb;
-
- NTSTATUS Status;
-
- ACCESS_MASK DesiredAccess;
- ULONG ShareAccess;
-
- ULONG Options;
- BOOLEAN DirectoryFile;
- BOOLEAN OpenTargetDirectory;
-
- ULONG CreateDisposition;
-
- Irp = IrpContext->Irp;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- Options = IrpSp->Parameters.Create.Options;
-
- DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
- OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
-
- CreateDisposition = (Options >> 24) & 0x000000ff;
-
- DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
- ShareAccess = IrpSp->Parameters.Create.ShareAccess;
-
- if (DirectoryFile) {
- return STATUS_NOT_A_DIRECTORY;
- }
-
- if (OpenTargetDirectory) {
- DbgBreak();
- return STATUS_INVALID_PARAMETER;
- }
-
- if ( (CreateDisposition != FILE_OPEN) &&
- (CreateDisposition != FILE_OPEN_IF) ) {
- return STATUS_ACCESS_DENIED;
- }
-
- if ( !FlagOn(ShareAccess, FILE_SHARE_READ) &&
- Vcb->OpenVolumeCount != 0 ) {
- return STATUS_SHARING_VIOLATION;
- }
-
- Ccb = Ext2AllocateCcb(NULL);
- if (Ccb == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto errorout;
- }
-
- Status = STATUS_SUCCESS;
-
- if (Vcb->OpenVolumeCount > 0) {
- Status = IoCheckShareAccess( DesiredAccess, ShareAccess,
- IrpSp->FileObject,
- &(Vcb->ShareAccess), TRUE);
-
- if (!NT_SUCCESS(Status)) {
- goto errorout;
- }
- } else {
- IoSetShareAccess( DesiredAccess, ShareAccess,
- IrpSp->FileObject,
- &(Vcb->ShareAccess) );
- }
-
-
- if (Vcb->OpenVolumeCount == 0 &&
- !IsFlagOn(ShareAccess, FILE_SHARE_READ) &&
- !IsFlagOn(ShareAccess, FILE_SHARE_WRITE) ){
-
- if (!IsVcbReadOnly(Vcb)) {
- Ext2FlushFiles(IrpContext, Vcb, FALSE);
- Ext2FlushVolume(IrpContext, Vcb, FALSE);
- }
-
- SetLongFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
- Vcb->LockFile = IrpSp->FileObject;
- } else {
- if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA) ) {
- if (!IsVcbReadOnly(Vcb)) {
- Ext2FlushFiles(IrpContext, Vcb, FALSE);
- Ext2FlushVolume(IrpContext, Vcb, FALSE);
- }
- }
- }
-
- IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
- IrpSp->FileObject->FsContext = Vcb;
- IrpSp->FileObject->FsContext2 = Ccb;
- IrpSp->FileObject->Vpb = Vcb->Vpb;
-
- Ext2ReferXcb(&Vcb->ReferenceCount);
- Ext2ReferXcb(&Vcb->OpenHandleCount);
- Ext2ReferXcb(&Vcb->OpenVolumeCount);
-
- Irp->IoStatus.Information = FILE_OPENED;
-
-errorout:
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- PIRP Irp;
- PIO_STACK_LOCATION IrpSp;
- PEXT2_VCB Vcb = 0;
- NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
- PEXT2_FCBVCB Xcb = NULL;
- BOOLEAN PostIrp = FALSE;
- BOOLEAN VcbResourceAcquired = FALSE;
-
- DeviceObject = IrpContext->DeviceObject;
- Irp = IrpContext->Irp;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- Xcb = (PEXT2_FCBVCB) (IrpSp->FileObject->FsContext);
-
- if (IsExt2FsDevice(DeviceObject)) {
-
- DEBUG(DL_INF, ( "Ext2Create: Create on main device object.\n"));
-
- Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = FILE_OPENED;
-
- Ext2CompleteIrpContext(IrpContext, Status);
-
- return Status;
- }
-
- _SEH2_TRY {
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb->Identifier.Type == EXT2VCB);
- IrpSp->FileObject->Vpb = Vcb->Vpb;
-
- if (!IsMounted(Vcb)) {
- DbgBreak();
- if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
- Status = STATUS_NO_SUCH_DEVICE;
- } else {
- Status = STATUS_VOLUME_DISMOUNTED;
- }
- _SEH2_LEAVE;
- }
-
- if (!ExAcquireResourceExclusiveLite(
- &Vcb->MainResource, TRUE)) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- VcbResourceAcquired = TRUE;
-
- Ext2VerifyVcb(IrpContext, Vcb);
-
- if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
- Status = STATUS_ACCESS_DENIED;
- if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
- Status = STATUS_VOLUME_DISMOUNTED;
- }
- _SEH2_LEAVE;
- }
-
- if ( ((IrpSp->FileObject->FileName.Length == 0) &&
- (IrpSp->FileObject->RelatedFileObject == NULL)) ||
- (Xcb && Xcb->Identifier.Type == EXT2VCB) ) {
- Status = Ext2CreateVolume(IrpContext, Vcb);
- } else {
-
- Status = Ext2CreateFile(IrpContext, Vcb, &PostIrp);
- }
-
- } _SEH2_FINALLY {
-
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress && !PostIrp) {
- if ( Status == STATUS_PENDING ||
- Status == STATUS_CANT_WAIT) {
- Status = Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
-
-NTSTATUS
-Ext2CreateInode(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PEXT2_FCB Parent,
- ULONG Type,
- ULONG FileAttr,
- PUNICODE_STRING FileName)
-{
- NTSTATUS Status;
- ULONG iGrp;
- ULONG iNo;
- struct inode Inode = { 0 };
- struct dentry *Dentry = NULL;
-
- LARGE_INTEGER SysTime;
-
- iGrp = (Parent->Inode->i_ino - 1) / BLOCKS_PER_GROUP;
-
- DEBUG(DL_INF, ("Ext2CreateInode: %S in %S(Inode=%xh)\n",
- FileName->Buffer,
- Parent->Mcb->ShortName.Buffer,
- Parent->Inode->i_ino));
-
- Status = Ext2NewInode(IrpContext, Vcb, iGrp, Type, &iNo);
- if (!NT_SUCCESS(Status)) {
- goto errorout;
- }
-
- KeQuerySystemTime(&SysTime);
- Ext2ClearInode(IrpContext, Vcb, iNo);
- Inode.i_sb = &Vcb->sb;
- Inode.i_ino = iNo;
- Inode.i_ctime = Inode.i_mtime =
- Inode.i_atime = Ext2LinuxTime(SysTime);
- Inode.i_uid = Parent->Inode->i_uid;
- Inode.i_gid = Parent->Inode->i_gid;
- Inode.i_generation = Parent->Inode->i_generation;
- Inode.i_mode = S_IPERMISSION_MASK &
- Parent->Inode->i_mode;
- if (Type == EXT2_FT_DIR) {
- Inode.i_mode |= S_IFDIR;
- } else if (Type == EXT2_FT_REG_FILE) {
- Inode.i_mode &= S_IFATTR;
- Inode.i_mode |= S_IFREG;
- } else {
- DbgBreak();
- }
-
- /* Force using extent */
- if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
- Inode.i_flags |= EXT2_EXTENTS_FL;
- }
-
- /* add new entry to its parent */
- Status = Ext2AddEntry(
- IrpContext,
- Vcb,
- Parent,
- &Inode,
- FileName,
- &Dentry
- );
-
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- Ext2FreeInode(IrpContext, Vcb, iNo, Type);
- goto errorout;
- }
-
- DEBUG(DL_INF, ("Ext2CreateInode: New Inode = %xh (Type=%xh)\n",
- Inode.i_ino, Type));
-
-errorout:
-
- if (Dentry)
- Ext2FreeEntry(Dentry);
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2SupersedeOrOverWriteFile(
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PFILE_OBJECT FileObject,
- IN PEXT2_VCB Vcb,
- IN PEXT2_FCB Fcb,
- IN PLARGE_INTEGER AllocationSize,
- IN ULONG Disposition
-)
-{
- LARGE_INTEGER CurrentTime;
- LARGE_INTEGER Size;
-
- KeQuerySystemTime(&CurrentTime);
-
- Size.QuadPart = 0;
- if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(Size))) {
- return STATUS_USER_MAPPED_FILE;
- }
-
- /* purge all file cache and shrink cache windows size */
- CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
- Fcb->Header.AllocationSize.QuadPart =
- Fcb->Header.FileSize.QuadPart =
- Fcb->Header.ValidDataLength.QuadPart = 0;
- CcSetFileSizes(FileObject,
- (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
-
- Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
- (ULONGLONG)AllocationSize->QuadPart,
- (ULONGLONG)BLOCK_SIZE);
-
- if ((loff_t)Size.QuadPart > Fcb->Inode->i_size) {
- Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &Size);
- } else {
- Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
- }
-
- Fcb->Header.AllocationSize = Size;
- if (Fcb->Header.AllocationSize.QuadPart > 0) {
- SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
- CcSetFileSizes(FileObject,
- (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
- }
-
- /* remove all extent mappings */
- DEBUG(DL_EXT, ("Ext2SuperSede ...: %wZ\n", &Fcb->Mcb->FullName));
- Fcb->Inode->i_size = 0;
-
- if (Disposition == FILE_SUPERSEDE) {
- Fcb->Inode->i_ctime = Ext2LinuxTime(CurrentTime);
- }
- Fcb->Inode->i_atime =
- Fcb->Inode->i_mtime = Ext2LinuxTime(CurrentTime);
- Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
-
- return STATUS_SUCCESS;
-}
+++ /dev/null
-//Microsoft Developer Studio generated resource script.
-//
-#include "../inc/resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#define APSTUDIO_HIDDEN_SYMBOLS
-#include "windows.h"
-#undef APSTUDIO_HIDDEN_SYMBOLS
-/* REACTOS FIXME */
-/* #include "ntverp.h" */
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-/* UTF-8 */
-#pragma code_page(65001)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "..\\inc\\resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
- "#include ""windows.h""\r\n"
- "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
- "#include ""ntverp.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,6,2,0
- PRODUCTVERSION 0,6,2,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x29L
-#else
- FILEFLAGS 0x28L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x3L
- FILESUBTYPE 0x7L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "Comments", "Ext2 File System Driver\0"
- VALUE "CompanyName", "Purayidathil\0"
- VALUE "FileDescription", "Ext2 File System Driver\0"
- VALUE "FileVersion", "0, 6, 2, 0\0"
- VALUE "InternalName", "ext2fs.sys\0"
- VALUE "LegalCopyright", "Copyright © 2015 Matt Wu\0"
- VALUE "LegalTrademarks", " - \0"
- VALUE "OriginalFilename", "ext2fs.sys\0"
- VALUE "PrivateBuild", " - \0"
- VALUE "ProductName", "Ext2 File System Driver for Windows\0"
- VALUE "ProductVersion", "0, 6, 2, 0\0"
- VALUE "SpecialBuild", " - \0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // !_MAC
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: fastio.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-
-#pragma alloc_text(PAGE, Ext2FastIoRead)
-#pragma alloc_text(PAGE, Ext2FastIoWrite)
-#pragma alloc_text(PAGE, Ext2FastIoCheckIfPossible)
-#pragma alloc_text(PAGE, Ext2FastIoQueryBasicInfo)
-#pragma alloc_text(PAGE, Ext2FastIoQueryStandardInfo)
-#pragma alloc_text(PAGE, Ext2FastIoQueryNetworkOpenInfo)
-#pragma alloc_text(PAGE, Ext2FastIoLock)
-#pragma alloc_text(PAGE, Ext2FastIoUnlockSingle)
-#pragma alloc_text(PAGE, Ext2FastIoUnlockAll)
-#pragma alloc_text(PAGE, Ext2FastIoUnlockAll)
-#endif
-
-FAST_IO_POSSIBLE
-Ext2IsFastIoPossible(
- IN PEXT2_FCB Fcb
-)
-{
- FAST_IO_POSSIBLE IsPossible = FastIoIsNotPossible;
-
- if (!Fcb || !FsRtlOplockIsFastIoPossible(&Fcb->Oplock))
- return IsPossible;
-
- IsPossible = FastIoIsQuestionable;
-
- if (!FsRtlAreThereCurrentFileLocks(&Fcb->FileLockAnchor)) {
- if (!IsVcbReadOnly(Fcb->Vcb) && !FlagOn(Fcb->Vcb->Flags, VCB_VOLUME_LOCKED)) {
- IsPossible = FastIoIsPossible;
- }
- }
-
- return IsPossible;
-}
-
-
-BOOLEAN NTAPI
-Ext2FastIoCheckIfPossible (
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- IN BOOLEAN CheckForReadOperation,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject
-)
-{
- BOOLEAN bPossible = FastIoIsNotPossible;
- PEXT2_FCB Fcb;
- PEXT2_CCB Ccb;
- LARGE_INTEGER lLength;
-
- lLength.QuadPart = Length;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsDirectory(Fcb)) {
- _SEH2_LEAVE;
- }
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- if (Ccb == NULL) {
- _SEH2_LEAVE;
- }
-
- if (CheckForReadOperation) {
-
- bPossible = FsRtlFastCheckLockForRead(
- &Fcb->FileLockAnchor,
- FileOffset,
- &lLength,
- LockKey,
- FileObject,
- PsGetCurrentProcess());
-
- } else {
-
- if (!IsVcbReadOnly(Fcb->Vcb)) {
- bPossible = FsRtlFastCheckLockForWrite(
- &Fcb->FileLockAnchor,
- FileOffset,
- &lLength,
- LockKey,
- FileObject,
- PsGetCurrentProcess());
- }
- }
-
-#if EXT2_DEBUG
- DEBUG(DL_INF, ("Ext2FastIIOCheckPossible: %s %s %wZ\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_CHECK_IF_POSSIBLE",
- &Fcb->Mcb->FullName
- ));
-
- DEBUG(DL_INF, (
- "Ext2FastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n",
- FileOffset->QuadPart,
- Length,
- LockKey,
- (CheckForReadOperation ? "CheckForReadOperation:" :
- "CheckForWriteOperation:"),
- (bPossible ? "Succeeded" : "Failed")));
-#endif
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- bPossible = FastIoIsNotPossible;
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
- return bPossible;
-}
-
-
-BOOLEAN NTAPI
-Ext2FastIoRead (IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- OUT PVOID Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
- PEXT2_FCB Fcb;
- BOOLEAN Status = FALSE;
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL) {
- return FALSE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- Status = FsRtlCopyRead (
- FileObject, FileOffset, Length, Wait,
- LockKey, Buffer, IoStatus, DeviceObject);
-
- DEBUG(DL_IO, ("Ext2FastIoRead: %wZ Offset: %I64xh Length: %xh Key: %u Status: %d\n",
- &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status));
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoWrite (
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- OUT PVOID Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
- PEXT2_FCB Fcb = NULL;
- BOOLEAN Status = FALSE;
- BOOLEAN Locked = FALSE;
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL)
- return FALSE;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsVcbReadOnly(Fcb->Vcb)) {
- _SEH2_LEAVE;
- }
-
- ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
- Locked = TRUE;
-
- if (IsWritingToEof(*FileOffset) ||
- Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart ||
- Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
- Status = FALSE;
- } else {
- ExReleaseResourceLite(&Fcb->MainResource);
- Locked = FALSE;
- Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
- LockKey, Buffer, IoStatus, DeviceObject);
- }
-
- } _SEH2_FINALLY {
-
- if (Locked) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
- DEBUG(DL_IO, ("Ext2FastIoWrite: %wZ Offset: %I64xh Length: %xh Key: %xh Status=%d\n",
- &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status));
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoQueryBasicInfo (
- IN PFILE_OBJECT FileObject,
- IN BOOLEAN Wait,
- OUT PFILE_BASIC_INFORMATION Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
- PEXT2_FCB Fcb = NULL;
- BOOLEAN Status = FALSE;
- BOOLEAN FcbMainResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "Ext2FastIoQueryBasicInfo: %s %s %wZ\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_QUERY_BASIC_INFO",
- &Fcb->Mcb->FullName
- ));
-#endif
- if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
- if (!ExAcquireResourceSharedLite(
- &Fcb->MainResource,
- Wait)) {
- _SEH2_LEAVE;
- }
- FcbMainResourceAcquired = TRUE;
- }
-
- RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
-
- /*
- typedef struct _FILE_BASIC_INFORMATION {
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- ULONG FileAttributes;
- } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
- */
-
- if (IsRoot(Fcb)) {
- Buffer->CreationTime = Buffer->LastAccessTime =
- Buffer->LastWriteTime = Buffer->ChangeTime = Ext2NtTime(0);
- } else {
- Buffer->CreationTime = Fcb->Mcb->CreationTime;
- Buffer->LastAccessTime = Fcb->Mcb->LastAccessTime;
- Buffer->LastWriteTime = Fcb->Mcb->LastWriteTime;
- Buffer->ChangeTime = Fcb->Mcb->ChangeTime;
- }
-
- Buffer->FileAttributes = Fcb->Mcb->FileAttr;
- if (Buffer->FileAttributes == 0) {
- Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- }
-
- IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
- IoStatus->Status = STATUS_SUCCESS;
-
- Status = TRUE;
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- IoStatus->Status = _SEH2_GetExceptionCode();
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- if (FcbMainResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
-#if EXT2_DEBUG
-
- if (Status == FALSE) {
-
- DEBUG(DL_ERR, ("Ext2FastIoQueryBasicInfo: %s %s Status: FALSE ***\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_QUERY_BASIC_INFO"));
-
- } else if (IoStatus->Status != STATUS_SUCCESS) {
-
- DEBUG(DL_ERR, (
- "Ext2FastIoQueryBasicInfo: %s %s Status: %#x ***\n",
- Ext2FastIoQueryBasicInfo,
- "FASTIO_QUERY_BASIC_INFO",
- IoStatus->Status
- ));
- }
-#endif
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoQueryStandardInfo (
- IN PFILE_OBJECT FileObject,
- IN BOOLEAN Wait,
- OUT PFILE_STANDARD_INFORMATION Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject
-)
-{
-
- BOOLEAN Status = FALSE;
- PEXT2_VCB Vcb;
- PEXT2_FCB Fcb;
- BOOLEAN FcbMainResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "Ext2FastIoQueryStandardInfo: %s %s %wZ\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_QUERY_STANDARD_INFO",
- &Fcb->Mcb->FullName ));
-#endif
- Vcb = Fcb->Vcb;
-
- if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
- if (!ExAcquireResourceSharedLite(
- &Fcb->MainResource,
- Wait )) {
- _SEH2_LEAVE;
- }
- FcbMainResourceAcquired = TRUE;
- }
-
- RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
-
- /*
- typedef struct _FILE_STANDARD_INFORMATION {
- LARGE_INTEGER AllocationSize;
- LARGE_INTEGER EndOfFile;
- ULONG NumberOfLinks;
- BOOLEAN DeletePending;
- BOOLEAN Directory;
- } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
- */
-
- Buffer->NumberOfLinks = Fcb->Inode->i_nlink;
- Buffer->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
-
- if (IsDirectory(Fcb)) {
- Buffer->Directory = IsDirectory(Fcb);
- Buffer->AllocationSize.QuadPart = 0;
- Buffer->EndOfFile.QuadPart = 0;
- } else {
- Buffer->Directory = FALSE;
- Buffer->AllocationSize = Fcb->Header.AllocationSize;
- Buffer->EndOfFile = Fcb->Header.FileSize;
- }
-
- IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
- IoStatus->Status = STATUS_SUCCESS;
-#if EXT2_DEBUG
- DEBUG(DL_INF, ( "Ext2FastIoQueryStandInfo: AllocatieonSize = %I64xh FileSize = %I64xh\n",
- Buffer->AllocationSize.QuadPart, Buffer->EndOfFile.QuadPart));
-#endif
- Status = TRUE;
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- IoStatus->Status = _SEH2_GetExceptionCode();
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- if (FcbMainResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
-#if EXT2_DEBUG
- if (Status == FALSE) {
- DEBUG(DL_INF, (
- "Ext2FastIoQueryStandardInfo: %s %s Status: FALSE ***\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_QUERY_STANDARD_INFO" ));
- } else if (IoStatus->Status != STATUS_SUCCESS) {
- DEBUG(DL_INF, (
- "Ext2FastIoQueryStandardInfo: %s %s Status: %#x ***\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_QUERY_STANDARD_INFO",
- IoStatus->Status ));
- }
-#endif
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoLock (
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN PLARGE_INTEGER Length,
- IN PEPROCESS Process,
- IN ULONG Key,
- IN BOOLEAN FailImmediately,
- IN BOOLEAN ExclusiveLock,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject
-)
-{
- BOOLEAN Status = FALSE;
- PEXT2_FCB Fcb;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsDirectory(Fcb)) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "Ext2FastIoLock: %s %s %wZ\n",
- Ext2GetCurrentProcessName(),
- "FASTIO_LOCK",
- &Fcb->Mcb->FullName ));
-
- DEBUG(DL_INF, (
- "Ext2FastIoLock: Offset: %I64xh Length: %I64xh Key: %u %s%s\n",
- FileOffset->QuadPart,
- Length->QuadPart,
- Key,
- (FailImmediately ? "FailImmediately " : ""),
- (ExclusiveLock ? "ExclusiveLock " : "") ));
-#endif
-
- if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
- _SEH2_LEAVE;
- }
-
- Status = FsRtlFastLock(
- &Fcb->FileLockAnchor,
- FileObject,
- FileOffset,
- Length,
- Process,
- Key,
- FailImmediately,
- ExclusiveLock,
- IoStatus,
- NULL,
- FALSE);
-
- if (Status) {
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
- }
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- IoStatus->Status = _SEH2_GetExceptionCode();
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
-#if EXT2_DEBUG
- if (Status == FALSE) {
- DEBUG(DL_ERR, (
- "Ext2FastIoLock: %s %s *** Status: FALSE ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_LOCK"
- ));
- } else if (IoStatus->Status != STATUS_SUCCESS) {
- DEBUG(DL_ERR, (
- "Ext2FastIoLock: %s %s *** Status: %s (%#x) ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_LOCK",
- Ext2NtStatusToString(IoStatus->Status),
- IoStatus->Status
- ));
- }
-#endif
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoUnlockSingle (
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN PLARGE_INTEGER Length,
- IN PEPROCESS Process,
- IN ULONG Key,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject
-)
-{
- BOOLEAN Status = FALSE;
- PEXT2_FCB Fcb;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsDirectory(Fcb)) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "Ext2FastIoUnlockSingle: %s %s %wZ\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_SINGLE",
- &Fcb->Mcb->FullName ));
-
- DEBUG(DL_INF, (
- "Ext2FastIoUnlockSingle: Offset: %I64xh Length: %I64xh Key: %u\n",
- FileOffset->QuadPart,
- Length->QuadPart,
- Key ));
-#endif
-
- if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
- _SEH2_LEAVE;
- }
-
- IoStatus->Status = FsRtlFastUnlockSingle(
- &Fcb->FileLockAnchor,
- FileObject,
- FileOffset,
- Length,
- Process,
- Key,
- NULL,
- FALSE);
-
- IoStatus->Information = 0;
- Status = TRUE;
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- IoStatus->Status = _SEH2_GetExceptionCode();
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
-#if EXT2_DEBUG
- if (Status == FALSE) {
-
- DEBUG(DL_ERR, (
- "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_SINGLE" ));
- } else if (IoStatus->Status != STATUS_SUCCESS) {
- DEBUG(DL_ERR, (
- "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_SINGLE",
- Ext2NtStatusToString(IoStatus->Status),
- IoStatus->Status ));
- }
-#endif
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoUnlockAll (
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN Status = FALSE;
- PEXT2_FCB Fcb;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsDirectory(Fcb)) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "Ext2FastIoUnlockSingle: %s %s %wZ\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_ALL",
- &Fcb->Mcb->FullName
- ));
-#endif
-
- if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
- _SEH2_LEAVE;
- }
-
- IoStatus->Status = FsRtlFastUnlockAll(
- &Fcb->FileLockAnchor,
- FileObject,
- Process,
- NULL );
-
- IoStatus->Information = 0;
- Status = TRUE;
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- IoStatus->Status = _SEH2_GetExceptionCode();
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
-#if EXT2_DEBUG
- if (Status == FALSE) {
-
- DEBUG(DL_ERR, (
- "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_ALL"
- ));
- } else if (IoStatus->Status != STATUS_SUCCESS) {
- DEBUG(DL_ERR, (
- "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_ALL",
- Ext2NtStatusToString(IoStatus->Status),
- IoStatus->Status
- ));
- }
-#endif
-
- return Status;
-}
-
-BOOLEAN NTAPI
-Ext2FastIoUnlockAllByKey (
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process,
- IN ULONG Key,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject
-)
-{
- BOOLEAN Status = FALSE;
- PEXT2_FCB Fcb;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- _SEH2_TRY {
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsDirectory(Fcb)) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "Ext2FastIoUnlockAllByKey: %s %s %wZ\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_ALL_BY_KEY",
- &Fcb->Mcb->FullName
- ));
-
- DEBUG(DL_INF, (
- "Ext2FastIoUnlockAllByKey: Key: %u\n",
- Key
- ));
-#endif
-
- if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
- _SEH2_LEAVE;
- }
-
- IoStatus->Status = FsRtlFastUnlockAllByKey(
- &Fcb->FileLockAnchor,
- FileObject,
- Process,
- Key,
- NULL
- );
-
- IoStatus->Information = 0;
- Status = TRUE;
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
-
- } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
- IoStatus->Status = _SEH2_GetExceptionCode();
- } _SEH2_END;
-
- } _SEH2_FINALLY {
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
-#if EXT2_DEBUG
- if (Status == FALSE) {
-
- DEBUG(DL_ERR, (
- "Ext2FastIoUnlockAllByKey: %s %s *** Status: FALSE ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_ALL_BY_KEY"
- ));
- } else if (IoStatus->Status != STATUS_SUCCESS) {
-
- DEBUG(DL_ERR, (
- "Ext2FastIoUnlockAllByKey: %s %s *** Status: %s (%#x) ***\n",
- (PUCHAR) Process + ProcessNameOffset,
- "FASTIO_UNLOCK_ALL_BY_KEY",
- Ext2NtStatusToString(IoStatus->Status),
- IoStatus->Status
- ));
- }
-#endif
-
- return Status;
-}
-
-
-BOOLEAN NTAPI
-Ext2FastIoQueryNetworkOpenInfo (
- IN PFILE_OBJECT FileObject,
- IN BOOLEAN Wait,
- IN OUT PFILE_NETWORK_OPEN_INFORMATION PFNOI,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject
-)
-{
- BOOLEAN bResult = FALSE;
-
- PEXT2_FCB Fcb = NULL;
-
- BOOLEAN FcbResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- FsRtlEnterFileSystem();
-
- if (IsExt2FsDevice(DeviceObject)) {
- IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- DbgBreak();
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
-#if EXT2_DEBUG
- DEBUG(DL_INF, (
- "%-31s %wZ\n",
- "FASTIO_QUERY_NETWORK_OPEN_INFO",
- &Fcb->Mcb->FullName
- ));
-#endif
-
- if (FileObject->FsContext2) {
- _SEH2_LEAVE;
- }
-
- if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
-
- if (!ExAcquireResourceSharedLite(
- &Fcb->MainResource,
- Wait
- )) {
- _SEH2_LEAVE;
- }
-
- FcbResourceAcquired = TRUE;
- }
-
- if (IsDirectory(Fcb)) {
- PFNOI->AllocationSize.QuadPart = 0;
- PFNOI->EndOfFile.QuadPart = 0;
- } else {
- PFNOI->AllocationSize = Fcb->Header.AllocationSize;
- PFNOI->EndOfFile = Fcb->Header.FileSize;
- }
-
- PFNOI->FileAttributes = Fcb->Mcb->FileAttr;
- if (PFNOI->FileAttributes == 0) {
- PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- }
-
- if (IsRoot(Fcb)) {
- PFNOI->CreationTime =
- PFNOI->LastAccessTime =
- PFNOI->LastWriteTime =
- PFNOI->ChangeTime = Ext2NtTime(0);
- } else {
- PFNOI->CreationTime = Fcb->Mcb->CreationTime;
- PFNOI->LastAccessTime = Fcb->Mcb->LastAccessTime;
- PFNOI->LastWriteTime = Fcb->Mcb->LastWriteTime;
- PFNOI->ChangeTime = Fcb->Mcb->ChangeTime;
- }
-
- bResult = TRUE;
-
- IoStatus->Status = STATUS_SUCCESS;
- IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION);
-
- } _SEH2_FINALLY {
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- FsRtlExitFileSystem();
- } _SEH2_END;
-
- return bResult;
-}
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: fileinfo.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-#include <linux/ext4.h>
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, Ext2QueryFileInformation)
-#pragma alloc_text(PAGE, Ext2SetFileInformation)
-#pragma alloc_text(PAGE, Ext2ExpandFile)
-#pragma alloc_text(PAGE, Ext2TruncateFile)
-#pragma alloc_text(PAGE, Ext2SetDispositionInfo)
-#pragma alloc_text(PAGE, Ext2SetRenameInfo)
-#pragma alloc_text(PAGE, Ext2DeleteFile)
-#endif
-
-NTSTATUS
-Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PFILE_OBJECT FileObject;
- PEXT2_VCB Vcb;
- PEXT2_FCB Fcb;
- PEXT2_MCB Mcb;
- PEXT2_CCB Ccb;
- PIRP Irp;
- PIO_STACK_LOCATION IoStackLocation;
- FILE_INFORMATION_CLASS FileInformationClass;
- ULONG Length;
- PVOID Buffer;
- BOOLEAN FcbResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext != NULL);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
-
- //
- // This request is not allowed on the main device object
- //
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- FileObject = IrpContext->FileObject;
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- if (Fcb == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- //
- // This request is not allowed on volumes
- //
- if (Fcb->Identifier.Type == EXT2VCB) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- if (!((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)))) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- Vcb = Fcb->Vcb;
-
- {
- if (!ExAcquireResourceSharedLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
- )) {
-
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- FcbResourceAcquired = TRUE;
- }
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- ASSERT(Ccb != NULL);
- ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
- (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
- Mcb = Ccb->SymLink;
- if (!Mcb)
- Mcb = Fcb->Mcb;
-
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
- FileInformationClass =
- IoStackLocation->Parameters.QueryFile.FileInformationClass;
-
- Length = IoStackLocation->Parameters.QueryFile.Length;
- Buffer = Irp->AssociatedIrp.SystemBuffer;
- RtlZeroMemory(Buffer, Length);
-
- switch (FileInformationClass) {
-
- case FileBasicInformation:
- {
- PFILE_BASIC_INFORMATION FileBasicInformation;
-
- if (Length < sizeof(FILE_BASIC_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FileBasicInformation = (PFILE_BASIC_INFORMATION) Buffer;
-
- FileBasicInformation->CreationTime = Mcb->CreationTime;
- FileBasicInformation->LastAccessTime = Mcb->LastAccessTime;
- FileBasicInformation->LastWriteTime = Mcb->LastWriteTime;
- FileBasicInformation->ChangeTime = Mcb->ChangeTime;
-
- FileBasicInformation->FileAttributes = Mcb->FileAttr;
- if (IsLinkInvalid(Mcb)) {
- ClearFlag(FileBasicInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
- }
- if (FileBasicInformation->FileAttributes == 0) {
- FileBasicInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- }
-
- Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileStandardInformation:
- {
- PFILE_STANDARD_INFORMATION FSI;
-
- if (Length < sizeof(FILE_STANDARD_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FSI = (PFILE_STANDARD_INFORMATION) Buffer;
-
- FSI->NumberOfLinks = Mcb->Inode.i_nlink;
-
- if (IsVcbReadOnly(Fcb->Vcb))
- FSI->DeletePending = FALSE;
- else
- FSI->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
-
- if (IsLinkInvalid(Mcb)) {
- FSI->Directory = FALSE;
- FSI->AllocationSize.QuadPart = 0;
- FSI->EndOfFile.QuadPart = 0;
- } else if (IsMcbDirectory(Mcb)) {
- FSI->Directory = TRUE;
- FSI->AllocationSize.QuadPart = 0;
- FSI->EndOfFile.QuadPart = 0;
- } else {
- FSI->Directory = FALSE;
- FSI->AllocationSize = Fcb->Header.AllocationSize;
- FSI->EndOfFile = Fcb->Header.FileSize;
- }
-
- Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileInternalInformation:
- {
- PFILE_INTERNAL_INFORMATION FileInternalInformation;
-
- if (Length < sizeof(FILE_INTERNAL_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FileInternalInformation = (PFILE_INTERNAL_INFORMATION) Buffer;
-
- /* we use the inode number as the internal index */
- FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Mcb->Inode.i_ino;
-
- Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
-
- case FileEaInformation:
- {
- PFILE_EA_INFORMATION FileEaInformation;
-
- if (Length < sizeof(FILE_EA_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FileEaInformation = (PFILE_EA_INFORMATION) Buffer;
-
- // Romfs doesn't have any extended attributes
- FileEaInformation->EaSize = 0;
-
- Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileNameInformation:
- {
- PFILE_NAME_INFORMATION FileNameInformation;
- ULONG BytesToCopy = 0;
-
- if (Length < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) +
- Mcb->FullName.Length) {
- BytesToCopy = Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
- Status = STATUS_BUFFER_OVERFLOW;
- } else {
- BytesToCopy = Mcb->FullName.Length;
- Status = STATUS_SUCCESS;
- }
-
- FileNameInformation = (PFILE_NAME_INFORMATION) Buffer;
- FileNameInformation->FileNameLength = Mcb->FullName.Length;
-
- RtlCopyMemory(
- FileNameInformation->FileName,
- Mcb->FullName.Buffer,
- BytesToCopy );
-
- Irp->IoStatus.Information = BytesToCopy +
- + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
- }
- break;
-
- case FilePositionInformation:
- {
- PFILE_POSITION_INFORMATION FilePositionInformation;
-
- if (Length < sizeof(FILE_POSITION_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
- FilePositionInformation->CurrentByteOffset =
- FileObject->CurrentByteOffset;
-
- Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileAllInformation:
- {
- PFILE_ALL_INFORMATION FileAllInformation;
- PFILE_BASIC_INFORMATION FileBasicInformation;
- PFILE_STANDARD_INFORMATION FSI;
- PFILE_INTERNAL_INFORMATION FileInternalInformation;
- PFILE_EA_INFORMATION FileEaInformation;
- PFILE_POSITION_INFORMATION FilePositionInformation;
- PFILE_NAME_INFORMATION FileNameInformation;
-
- if (Length < sizeof(FILE_ALL_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FileAllInformation = (PFILE_ALL_INFORMATION) Buffer;
-
- FileBasicInformation =
- &FileAllInformation->BasicInformation;
-
- FSI =
- &FileAllInformation->StandardInformation;
-
- FileInternalInformation =
- &FileAllInformation->InternalInformation;
-
- FileEaInformation =
- &FileAllInformation->EaInformation;
-
- FilePositionInformation =
- &FileAllInformation->PositionInformation;
-
- FileNameInformation =
- &FileAllInformation->NameInformation;
-
- FileBasicInformation->CreationTime = Mcb->CreationTime;
- FileBasicInformation->LastAccessTime = Mcb->LastAccessTime;
- FileBasicInformation->LastWriteTime = Mcb->LastWriteTime;
- FileBasicInformation->ChangeTime = Mcb->ChangeTime;
-
- FileBasicInformation->FileAttributes = Mcb->FileAttr;
- if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target)) {
- ClearFlag(FileBasicInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
- }
- if (FileBasicInformation->FileAttributes == 0) {
- FileBasicInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- }
-
- FSI->NumberOfLinks = Mcb->Inode.i_nlink;
-
- if (IsVcbReadOnly(Fcb->Vcb))
- FSI->DeletePending = FALSE;
- else
- FSI->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
-
- if (IsLinkInvalid(Mcb)) {
- FSI->Directory = FALSE;
- FSI->AllocationSize.QuadPart = 0;
- FSI->EndOfFile.QuadPart = 0;
- } else if (IsDirectory(Fcb)) {
- FSI->Directory = TRUE;
- FSI->AllocationSize.QuadPart = 0;
- FSI->EndOfFile.QuadPart = 0;
- } else {
- FSI->Directory = FALSE;
- FSI->AllocationSize = Fcb->Header.AllocationSize;
- FSI->EndOfFile = Fcb->Header.FileSize;
- }
-
- // The "inode number"
- FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Mcb->Inode.i_ino;
-
- // Romfs doesn't have any extended attributes
- FileEaInformation->EaSize = 0;
-
- FilePositionInformation->CurrentByteOffset =
- FileObject->CurrentByteOffset;
-
- FileNameInformation->FileNameLength = Mcb->ShortName.Length;
-
- if (Length < sizeof(FILE_ALL_INFORMATION) +
- Mcb->ShortName.Length - sizeof(WCHAR)) {
- Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
- Status = STATUS_BUFFER_OVERFLOW;
- RtlCopyMemory(
- FileNameInformation->FileName,
- Mcb->ShortName.Buffer,
- Length - FIELD_OFFSET(FILE_ALL_INFORMATION,
- NameInformation.FileName)
- );
- _SEH2_LEAVE;
- }
-
- RtlCopyMemory(
- FileNameInformation->FileName,
- Mcb->ShortName.Buffer,
- Mcb->ShortName.Length
- );
-
- Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
- Mcb->ShortName.Length - sizeof(WCHAR);
-#if 0
- sizeof(FILE_ACCESS_INFORMATION) -
- sizeof(FILE_MODE_INFORMATION) -
- sizeof(FILE_ALIGNMENT_INFORMATION);
-#endif
-
- Status = STATUS_SUCCESS;
- }
- break;
-
- /*
- case FileAlternateNameInformation:
- {
- // TODO: Handle FileAlternateNameInformation
-
- // Here we would like to use RtlGenerate8dot3Name but I don't
- // know how to use the argument PGENERATE_NAME_CONTEXT
- }
- */
-
- case FileNetworkOpenInformation:
- {
- PFILE_NETWORK_OPEN_INFORMATION PFNOI;
-
- if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- PFNOI = (PFILE_NETWORK_OPEN_INFORMATION) Buffer;
-
- PFNOI->FileAttributes = Mcb->FileAttr;
- if (IsLinkInvalid(Mcb)) {
- ClearFlag(PFNOI->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
- PFNOI->AllocationSize.QuadPart = 0;
- PFNOI->EndOfFile.QuadPart = 0;
- } else if (IsDirectory(Fcb)) {
- PFNOI->AllocationSize.QuadPart = 0;
- PFNOI->EndOfFile.QuadPart = 0;
- } else {
- PFNOI->AllocationSize = Fcb->Header.AllocationSize;
- PFNOI->EndOfFile = Fcb->Header.FileSize;
- }
-
- if (PFNOI->FileAttributes == 0) {
- PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- }
-
- PFNOI->CreationTime = Mcb->CreationTime;
- PFNOI->LastAccessTime = Mcb->LastAccessTime;
- PFNOI->LastWriteTime = Mcb->LastWriteTime;
- PFNOI->ChangeTime = Mcb->ChangeTime;
-
-
- Irp->IoStatus.Information =
- sizeof(FILE_NETWORK_OPEN_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
-#if (_WIN32_WINNT >= 0x0500)
-
- case FileAttributeTagInformation:
- {
- PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
-
- if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
- FATI->FileAttributes = Mcb->FileAttr;
- if (IsLinkInvalid(Mcb)) {
- ClearFlag(FATI->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
- }
- if (FATI->FileAttributes == 0) {
- FATI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
- }
- FATI->ReparseTag = IO_REPARSE_TAG_RESERVED_ZERO;
- Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-#endif // (_WIN32_WINNT >= 0x0500)
-
- case FileStreamInformation:
- Status = STATUS_INVALID_PARAMETER;
- break;
-
- default:
- DEBUG(DL_WRN, ( "Ext2QueryInformation: invalid class: %d\n",
- FileInformationClass));
- Status = STATUS_INVALID_PARAMETER; /* STATUS_INVALID_INFO_CLASS; */
- break;
- }
-
- } _SEH2_FINALLY {
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
- if (Status == STATUS_PENDING ||
- Status == STATUS_CANT_WAIT) {
- Status = Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PEXT2_VCB Vcb;
- PFILE_OBJECT FileObject;
- PEXT2_FCB Fcb;
- PEXT2_CCB Ccb;
- PEXT2_MCB Mcb;
- PIRP Irp;
- PIO_STACK_LOCATION IoStackLocation;
- FILE_INFORMATION_CLASS FileInformationClass;
-
- ULONG NotifyFilter = 0;
-
- ULONG Length;
- PVOID Buffer;
-
- BOOLEAN VcbMainResourceAcquired = FALSE;
- BOOLEAN FcbMainResourceAcquired = FALSE;
- BOOLEAN FcbPagingIoResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext != NULL);
-
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
- DeviceObject = IrpContext->DeviceObject;
-
- //
- // This request is not allowed on the main device object
- //
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- /* check io stack location of irp stack */
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
- FileInformationClass =
- IoStackLocation->Parameters.SetFile.FileInformationClass;
- Length = IoStackLocation->Parameters.SetFile.Length;
- Buffer = Irp->AssociatedIrp.SystemBuffer;
-
- /* check Vcb */
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
- if (!IsMounted(Vcb)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- /* we need grab Vcb in case it's a rename operation */
- if (FileInformationClass == FileRenameInformation) {
- if (!ExAcquireResourceExclusiveLite(
- &Vcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- VcbMainResourceAcquired = TRUE;
- }
-
- if (IsVcbReadOnly(Vcb)) {
- if (FileInformationClass != FilePositionInformation) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
- }
-
- if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
- Status = STATUS_ACCESS_DENIED;
- _SEH2_LEAVE;
- }
-
- FileObject = IrpContext->FileObject;
- Fcb = (PEXT2_FCB) FileObject->FsContext;
-
- // This request is issued to volumes, just return success
- if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) {
- Status = STATUS_FILE_DELETED;
- _SEH2_LEAVE;
- }
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- ASSERT(Ccb != NULL);
- ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
- (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
- Mcb = Ccb->SymLink;
- if (Mcb) {
- if (IsFlagOn(Mcb->Flags, MCB_FILE_DELETED)) {
- Status = STATUS_FILE_DELETED;
- _SEH2_LEAVE;
- }
- } else {
- Mcb = Fcb->Mcb;
- }
-
- if ( !IsDirectory(Fcb) && !FlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
- ((FileInformationClass == FileEndOfFileInformation) ||
- (FileInformationClass == FileValidDataLengthInformation) ||
- (FileInformationClass == FileAllocationInformation))) {
-
- Status = FsRtlCheckOplock( &Fcb->Oplock,
- Irp,
- IrpContext,
- NULL,
- NULL );
-
- if (Status != STATUS_SUCCESS) {
- _SEH2_LEAVE;
- }
-
- //
- // Set the flag indicating if Fast I/O is possible
- //
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
- }
-
- /* for renaming, we must not get any Fcb locks here, function
- Ext2SetRenameInfo will get Dcb resource exclusively. */
- if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
- FileInformationClass != FileRenameInformation) {
-
- if (!ExAcquireResourceExclusiveLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- FcbMainResourceAcquired = TRUE;
-
- if ( FileInformationClass == FileAllocationInformation ||
- FileInformationClass == FileEndOfFileInformation ||
- FileInformationClass == FileValidDataLengthInformation) {
-
- if (!ExAcquireResourceExclusiveLite(
- &Fcb->PagingIoResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- DbgBreak();
- _SEH2_LEAVE;
- }
- FcbPagingIoResourceAcquired = TRUE;
- }
- }
-
- switch (FileInformationClass) {
-
- case FileBasicInformation:
- {
- PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION) Buffer;
- struct inode *Inode = &Mcb->Inode;
-
- if (FBI->CreationTime.QuadPart != 0 && FBI->CreationTime.QuadPart != -1) {
- Inode->i_ctime = Ext2LinuxTime(FBI->CreationTime);
- Mcb->CreationTime = Ext2NtTime(Inode->i_ctime);
- NotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
- }
-
- if (FBI->LastAccessTime.QuadPart != 0 && FBI->LastAccessTime.QuadPart != -1) {
- Inode->i_atime = Ext2LinuxTime(FBI->LastAccessTime);
- Mcb->LastAccessTime = Ext2NtTime(Inode->i_atime);
- NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
- }
-
- if (FBI->LastWriteTime.QuadPart != 0 && FBI->LastWriteTime.QuadPart != -1) {
- Inode->i_mtime = Ext2LinuxTime(FBI->LastWriteTime);
- Mcb->LastWriteTime = Ext2NtTime(Inode->i_mtime);
- NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
- SetFlag(Ccb->Flags, CCB_LAST_WRITE_UPDATED);
- }
-
- if (FBI->ChangeTime.QuadPart !=0 && FBI->ChangeTime.QuadPart != -1) {
- Mcb->ChangeTime = FBI->ChangeTime;
- }
-
- if (FBI->FileAttributes != 0) {
-
- BOOLEAN bIsDirectory = IsDirectory(Fcb);
- NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
-
- if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) {
- Ext2SetOwnerReadOnly(Inode->i_mode);
- } else {
- Ext2SetOwnerWritable(Inode->i_mode);
- }
-
- if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
- SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
- } else {
- ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
- }
-
- Mcb->FileAttr = FBI->FileAttributes;
- if (bIsDirectory) {
- SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
- ClearFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
- }
- }
-
- if (NotifyFilter != 0) {
- if (Ext2SaveInode(IrpContext, Vcb, Inode)) {
- Status = STATUS_SUCCESS;
- }
- }
-
- ClearFlag(NotifyFilter, FILE_NOTIFY_CHANGE_LAST_ACCESS);
- Status = STATUS_SUCCESS;
- }
-
- break;
-
- case FileAllocationInformation:
- {
- PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
- LARGE_INTEGER AllocationSize;
-
- if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- } else {
- Status = STATUS_SUCCESS;
- }
-
- /* set Mcb to it's target */
- if (IsMcbSymLink(Mcb)) {
- ASSERT(Fcb->Mcb == Mcb->Target);
- }
- Mcb = Fcb->Mcb;
-
- /* get user specified allocationsize aligned with BLOCK_SIZE */
- AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
- (ULONGLONG)FAI->AllocationSize.QuadPart,
- (ULONGLONG)BLOCK_SIZE);
-
- if (AllocationSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) {
-
- Status = Ext2ExpandFile(IrpContext, Vcb, Mcb, &AllocationSize);
- Fcb->Header.AllocationSize = AllocationSize;
- NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
- SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_SETINFO);
-
- } else if (AllocationSize.QuadPart < Fcb->Header.AllocationSize.QuadPart) {
-
- if (MmCanFileBeTruncated(&(Fcb->SectionObject), &AllocationSize)) {
-
- /* truncate file blocks */
- Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &AllocationSize);
-
- if (NT_SUCCESS(Status)) {
- ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
- }
-
- NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
- Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
- if (Mcb->Inode.i_size > (loff_t)AllocationSize.QuadPart) {
- Mcb->Inode.i_size = AllocationSize.QuadPart;
- }
- Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
- if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) {
- Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
- }
-
- } else {
-
- Status = STATUS_USER_MAPPED_FILE;
- DbgBreak();
- _SEH2_LEAVE;
- }
- }
-
- if (NotifyFilter) {
-
- SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
- SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
- Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
- }
-
- DEBUG(DL_IO, ("Ext2SetInformation: %wZ NewSize=%I64xh AllocationSize=%I64xh "
- "FileSize=%I64xh VDL=%I64xh i_size=%I64xh status = %xh\n",
- &Fcb->Mcb->ShortName, AllocationSize.QuadPart,
- Fcb->Header.AllocationSize.QuadPart,
- Fcb->Header.FileSize.QuadPart, Fcb->Header.ValidDataLength.QuadPart,
- Mcb->Inode.i_size, Status));
- }
-
- break;
-
- case FileEndOfFileInformation:
- {
- PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
- LARGE_INTEGER NewSize, OldSize, EndOfFile;
-
- if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- } else {
- Status = STATUS_SUCCESS;
- }
-
- /* set Mcb to it's target */
- if (IsMcbSymLink(Mcb)) {
- ASSERT(Fcb->Mcb == Mcb->Target);
- }
- Mcb = Fcb->Mcb;
-
- OldSize = Fcb->Header.AllocationSize;
- EndOfFile = FEOFI->EndOfFile;
-
- if (IoStackLocation->Parameters.SetFile.AdvanceOnly) {
-
- if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
- _SEH2_LEAVE;
- }
-
- if (EndOfFile.QuadPart > Fcb->Header.FileSize.QuadPart) {
- EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
- }
-
- if (EndOfFile.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
- Fcb->Header.ValidDataLength.QuadPart = EndOfFile.QuadPart;
- NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
- }
-
- _SEH2_LEAVE;
- }
-
- NewSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
- EndOfFile.QuadPart, BLOCK_SIZE);
-
- if (NewSize.QuadPart > OldSize.QuadPart) {
-
- Fcb->Header.AllocationSize = NewSize;
- Status = Ext2ExpandFile(
- IrpContext,
- Vcb,
- Mcb,
- &(Fcb->Header.AllocationSize)
- );
- NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
- SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_SETINFO);
-
-
- } else if (NewSize.QuadPart == OldSize.QuadPart) {
-
- /* we are luck ;) */
- Status = STATUS_SUCCESS;
-
- } else {
-
- /* don't truncate file data since it's still being written */
- if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_WRITE)) {
-
- Status = STATUS_SUCCESS;
-
- } else {
-
- if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &NewSize)) {
- Status = STATUS_USER_MAPPED_FILE;
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- /* truncate file blocks */
- Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &NewSize);
-
- /* restore original file size */
- if (NT_SUCCESS(Status)) {
- ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
- }
-
- /* update file allocateion size */
- Fcb->Header.AllocationSize.QuadPart = NewSize.QuadPart;
-
- ASSERT((loff_t)NewSize.QuadPart >= Mcb->Inode.i_size);
- if ((loff_t)Fcb->Header.FileSize.QuadPart < Mcb->Inode.i_size) {
- Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
- }
- if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) {
- Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
- }
-
- SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
- SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
- }
-
- NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
- }
-
- if (NT_SUCCESS(Status)) {
-
- Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size = EndOfFile.QuadPart;
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
-
- if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
- !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
- SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
- Ext2SaveSuper(IrpContext, Vcb);
- }
-
- SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
- SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
- NotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
- }
-
-
- Ext2SaveInode( IrpContext, Vcb, &Mcb->Inode);
-
- DEBUG(DL_IO, ("Ext2SetInformation: FileEndOfFileInformation %wZ EndofFile=%I64xh "
- "AllocatieonSize=%I64xh FileSize=%I64xh VDL=%I64xh i_size=%I64xh status = %xh\n",
- &Fcb->Mcb->ShortName, EndOfFile.QuadPart, Fcb->Header.AllocationSize.QuadPart,
- Fcb->Header.FileSize.QuadPart, Fcb->Header.ValidDataLength.QuadPart,
- Mcb->Inode.i_size, Status));
- }
-
- break;
-
- case FileValidDataLengthInformation:
- {
- PFILE_VALID_DATA_LENGTH_INFORMATION FVDL = (PFILE_VALID_DATA_LENGTH_INFORMATION) Buffer;
- LARGE_INTEGER NewVDL;
-
- if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- } else {
- Status = STATUS_SUCCESS;
- }
-
- NewVDL = FVDL->ValidDataLength;
- if ((NewVDL.QuadPart < Fcb->Header.ValidDataLength.QuadPart)) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
- if (NewVDL.QuadPart > Fcb->Header.FileSize.QuadPart)
- NewVDL = Fcb->Header.FileSize;
-
- if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer,
- &NewVDL)) {
- Status = STATUS_USER_MAPPED_FILE;
- _SEH2_LEAVE;
- }
-
- Fcb->Header.ValidDataLength = NewVDL;
- FileObject->Flags |= FO_FILE_MODIFIED;
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
- }
-
- break;
-
- case FileDispositionInformation:
- {
- PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
-
- Status = Ext2SetDispositionInfo(IrpContext, Vcb, Fcb, Ccb, FDI->DeleteFile);
-
- DEBUG(DL_INF, ( "Ext2SetInformation: SetDispositionInformation: DeleteFile=%d %wZ status = %xh\n",
- FDI->DeleteFile, &Mcb->ShortName, Status));
- }
-
- break;
-
- case FileRenameInformation:
- {
- Status = Ext2SetRenameInfo(IrpContext, Vcb, Fcb, Ccb);
- }
-
- break;
-
- //
- // This is the only set file information request supported on read
- // only file systems
- //
- case FilePositionInformation:
- {
- PFILE_POSITION_INFORMATION FilePositionInformation;
-
- if (Length < sizeof(FILE_POSITION_INFORMATION)) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
-
- if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
- (FilePositionInformation->CurrentByteOffset.LowPart &
- DeviceObject->AlignmentRequirement) ) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- FileObject->CurrentByteOffset =
- FilePositionInformation->CurrentByteOffset;
-
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- break;
-
- case FileLinkInformation:
-
- Status = STATUS_INVALID_DEVICE_REQUEST;
- break;
-
- default:
- DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n",
- FileInformationClass));
- Status = STATUS_INVALID_PARAMETER;/* STATUS_INVALID_INFO_CLASS; */
- }
-
- } _SEH2_FINALLY {
-
- if (FcbPagingIoResourceAcquired) {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- }
-
- if (NT_SUCCESS(Status) && (NotifyFilter != 0)) {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Mcb,
- NotifyFilter,
- FILE_ACTION_MODIFIED );
-
- }
-
- if (FcbMainResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- if (VcbMainResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
- if (Status == STATUS_PENDING ||
- Status == STATUS_CANT_WAIT ) {
- DbgBreak();
- Status = Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
-
-ULONG
-Ext2TotalBlocks(
- PEXT2_VCB Vcb,
- PLARGE_INTEGER Size,
- PULONG pMeta
-)
-{
- ULONG Blocks, Meta =0, Remain;
-
- Blocks = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
- if (Blocks <= EXT2_NDIR_BLOCKS)
- goto errorout;
- Blocks -= EXT2_NDIR_BLOCKS;
-
- Meta += 1;
- if (Blocks <= Vcb->max_blocks_per_layer[1]) {
- goto errorout;
- }
- Blocks -= Vcb->max_blocks_per_layer[1];
-
-level2:
-
- if (Blocks <= Vcb->max_blocks_per_layer[2]) {
- Meta += 1 + ((Blocks + BLOCK_SIZE/4 - 1) >> (BLOCK_BITS - 2));
- goto errorout;
- }
- Meta += 1 + BLOCK_SIZE/4;
- Blocks -= Vcb->max_blocks_per_layer[2];
-
- if (Blocks > Vcb->max_blocks_per_layer[3]) {
- Blocks = Vcb->max_blocks_per_layer[3];
- }
-
- ASSERT(Vcb->max_blocks_per_layer[2]);
- Remain = Blocks % Vcb->max_blocks_per_layer[2];
- Blocks = Blocks / Vcb->max_blocks_per_layer[2];
- Meta += 1 + Blocks * (1 + BLOCK_SIZE/4);
- if (Remain) {
- Blocks = Remain;
- goto level2;
- }
-
-errorout:
-
- if (pMeta)
- *pMeta = Meta;
- Blocks = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
- return (Blocks + Meta);
-}
-
-NTSTATUS
-Ext2BlockMap(
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PEXT2_MCB Mcb,
- IN ULONG Index,
- IN BOOLEAN bAlloc,
- OUT PULONG pBlock,
- OUT PULONG Number
-)
-{
- NTSTATUS status;
-
- if (INODE_HAS_EXTENT(&Mcb->Inode)) {
- status = Ext2MapExtent(IrpContext, Vcb, Mcb, Index,
- bAlloc, pBlock, Number );
- } else {
- status = Ext2MapIndirect(IrpContext, Vcb, Mcb, Index,
- bAlloc, pBlock, Number );
- }
-
- return status;
-}
-
-
-NTSTATUS
-Ext2ExpandFile(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PEXT2_MCB Mcb,
- PLARGE_INTEGER Size
-)
-{
- NTSTATUS status = STATUS_SUCCESS;
- ULONG Start = 0;
- ULONG End = 0;
-
- Start = (ULONG)((Mcb->Inode.i_size + BLOCK_SIZE - 1) >> BLOCK_BITS);
- End = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
-
- /* it's a truncate operation, not expanding */
- if (Start >= End) {
- Size->QuadPart = ((LONGLONG) Start) << BLOCK_BITS;
- return STATUS_SUCCESS;
- }
-
- /* ignore special files */
- if (IsMcbSpecialFile(Mcb)) {
- return STATUS_INVALID_DEVICE_REQUEST;
- }
-
- /* expandind file extents */
- if (INODE_HAS_EXTENT(&Mcb->Inode)) {
-
- status = Ext2ExpandExtent(IrpContext, Vcb, Mcb, Start, End, Size);
-
- } else {
-
- BOOLEAN do_expand;
-
-#if EXT2_PRE_ALLOCATION_SUPPORT
- do_expand = TRUE;
-#else
- do_expand = (IrpContext->MajorFunction == IRP_MJ_WRITE) ||
- IsMcbDirectory(Mcb);
-#endif
- if (!do_expand)
- goto errorout;
-
- status = Ext2ExpandIndirect(IrpContext, Vcb, Mcb, Start, End, Size);
- }
-
-errorout:
- return status;
-}
-
-
-NTSTATUS
-Ext2TruncateFile(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PEXT2_MCB Mcb,
- PLARGE_INTEGER Size
-)
-{
- NTSTATUS status = STATUS_SUCCESS;
-
- if (INODE_HAS_EXTENT(&Mcb->Inode)) {
- status = Ext2TruncateExtent(IrpContext, Vcb, Mcb, Size);
- } else {
- status = Ext2TruncateIndirect(IrpContext, Vcb, Mcb, Size);
- }
-
- /* check and clear data/meta mcb extents */
- if (Size->QuadPart == 0) {
-
- /* check and remove all data extents */
- if (Ext2ListExtents(&Mcb->Extents)) {
- DbgBreak();
- }
- Ext2ClearAllExtents(&Mcb->Extents);
- /* check and remove all meta extents */
- if (Ext2ListExtents(&Mcb->MetaExts)) {
- DbgBreak();
- }
- Ext2ClearAllExtents(&Mcb->MetaExts);
- ClearLongFlag(Mcb->Flags, MCB_ZONE_INITED);
- }
-
- return status;
-}
-
-NTSTATUS
-Ext2IsFileRemovable(
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PEXT2_FCB Fcb,
- IN PEXT2_CCB Ccb
-)
-{
- PEXT2_MCB Mcb = Fcb->Mcb;
-
- if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
- return STATUS_CANNOT_DELETE;
- }
-
- if (IsMcbDirectory(Mcb)) {
- if (!Ext2IsDirectoryEmpty(IrpContext, Vcb, Mcb)) {
- return STATUS_DIRECTORY_NOT_EMPTY;
- }
- }
-
- if (!MmFlushImageSection(&Fcb->SectionObject,
- MmFlushForDelete )) {
- return STATUS_CANNOT_DELETE;
- }
-
- if (IsMcbDirectory(Mcb)) {
- FsRtlNotifyFullChangeDirectory(
- Vcb->NotifySync,
- &Vcb->NotifyList,
- Ccb,
- NULL,
- FALSE,
- FALSE,
- 0,
- NULL,
- NULL,
- NULL
- );
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-Ext2SetDispositionInfo(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PEXT2_FCB Fcb,
- PEXT2_CCB Ccb,
- BOOLEAN bDelete
-)
-{
- PIRP Irp = IrpContext->Irp;
- PIO_STACK_LOCATION IrpSp;
- NTSTATUS status = STATUS_SUCCESS;
- PEXT2_MCB Mcb = Fcb->Mcb;
-
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- DEBUG(DL_INF, ( "Ext2SetDispositionInfo: bDelete=%x\n", bDelete));
-
- if (bDelete) {
-
- DEBUG(DL_INF, ( "Ext2SetDispositionInformation: Removing %wZ.\n",
- &Mcb->FullName));
-
- /* always allow deleting on symlinks */
- if (Ccb->SymLink == NULL) {
- status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
- }
-
- if (NT_SUCCESS(status)) {
- SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
- IrpSp->FileObject->DeletePending = TRUE;
- }
-
- } else {
-
- ClearLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
- IrpSp->FileObject->DeletePending = FALSE;
- }
-
- return status;
-}
-
-NTSTATUS
-Ext2SetRenameInfo(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PEXT2_FCB Fcb,
- PEXT2_CCB Ccb
-)
-{
- PEXT2_MCB Mcb = Fcb->Mcb;
-
- PEXT2_FCB TargetDcb = NULL; /* Dcb of target directory */
- PEXT2_MCB TargetMcb = NULL;
- PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */
- PEXT2_MCB ParentMcb = NULL;
-
- PEXT2_FCB ExistingFcb = NULL; /* Target file Fcb if it exists*/
- PEXT2_MCB ExistingMcb = NULL;
-
- UNICODE_STRING FileName;
-
- NTSTATUS Status;
-
- PIRP Irp;
- PIO_STACK_LOCATION IrpSp;
-
- PFILE_OBJECT FileObject;
- PFILE_OBJECT TargetObject;
-
- struct dentry *NewEntry = NULL;
-
- BOOLEAN ReplaceIfExists;
- BOOLEAN bMove = FALSE;
- BOOLEAN bTargetRemoved = FALSE;
-
- BOOLEAN bNewTargetDcb = FALSE;
- BOOLEAN bNewParentDcb = FALSE;
-
- PFILE_RENAME_INFORMATION FRI;
-
- if (Ccb->SymLink) {
- Mcb = Ccb->SymLink;
- }
-
- if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
- Status = STATUS_INVALID_PARAMETER;
- goto errorout;
- }
-
- Irp = IrpContext->Irp;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- FileObject = IrpSp->FileObject;
- TargetObject = IrpSp->Parameters.SetFile.FileObject;
- ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
-
- FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
-
- if (TargetObject == NULL) {
-
- UNICODE_STRING NewName;
-
- NewName.Buffer = FRI->FileName;
- NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
-
- while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') {
- NewName.Buffer[NewName.Length/2 - 1] = 0;
- NewName.Length -= 2;
- }
-
- while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') {
- NewName.Length -= 2;
- }
-
- NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
- NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
-
- FileName = NewName;
-
- TargetMcb = Mcb->Parent;
- if (IsMcbSymLink(TargetMcb)) {
- TargetMcb = TargetMcb->Target;
- ASSERT(!IsMcbSymLink(TargetMcb));
- }
-
- if (TargetMcb == NULL || FileName.Length >= EXT2_NAME_LEN*2) {
- Status = STATUS_OBJECT_NAME_INVALID;
- goto errorout;
- }
-
- } else {
-
- TargetDcb = (PEXT2_FCB)(TargetObject->FsContext);
-
- if (!TargetDcb || TargetDcb->Vcb != Vcb) {
-
- DbgBreak();
-
- Status = STATUS_INVALID_PARAMETER;
- goto errorout;
- }
-
- TargetMcb = TargetDcb->Mcb;
- FileName = TargetObject->FileName;
- }
-
- if (FsRtlDoesNameContainWildCards(&FileName)) {
- Status = STATUS_OBJECT_NAME_INVALID;
- goto errorout;
- }
-
- if (TargetMcb->Inode.i_ino == Mcb->Parent->Inode.i_ino) {
- if (FsRtlAreNamesEqual( &FileName,
- &(Mcb->ShortName),
- FALSE,
- NULL )) {
- Status = STATUS_SUCCESS;
- goto errorout;
- }
- } else {
- bMove = TRUE;
- }
-
- TargetDcb = TargetMcb->Fcb;
- if (TargetDcb == NULL) {
- TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
- if (TargetDcb) {
- Ext2ReferXcb(&TargetDcb->ReferenceCount);
- bNewTargetDcb = TRUE;
- }
- }
- if (TargetDcb) {
- SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
- }
-
- ParentMcb = Mcb->Parent;
- ParentDcb = ParentMcb->Fcb;
-
- if ((TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino)) {
-
- if (ParentDcb == NULL) {
- ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
- if (ParentDcb) {
- Ext2ReferXcb(&ParentDcb->ReferenceCount);
- bNewParentDcb = TRUE;
- }
- }
- if (ParentDcb) {
- SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
- }
- }
-
- if (!TargetDcb || !ParentDcb) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto errorout;
- }
-
- DEBUG(DL_RES, ("Ext2SetRenameInfo: rename %wZ to %wZ\\%wZ\n",
- &Mcb->FullName, &TargetMcb->FullName, &FileName));
-
- Status = Ext2LookupFile(
- IrpContext,
- Vcb,
- &FileName,
- TargetMcb,
- &ExistingMcb,
- 0
- );
-
- if (NT_SUCCESS(Status) && ExistingMcb != Mcb) {
-
- if (!ReplaceIfExists) {
-
- Status = STATUS_OBJECT_NAME_COLLISION;
- DEBUG(DL_RES, ("Ext2SetRenameInfo: Target file %wZ exists\n",
- &ExistingMcb->FullName));
- goto errorout;
-
- } else {
-
- if ( (ExistingFcb = ExistingMcb->Fcb) && !IsMcbSymLink(ExistingMcb) ) {
-
- Status = Ext2IsFileRemovable(IrpContext, Vcb, ExistingFcb, Ccb);
- if (!NT_SUCCESS(Status)) {
- DEBUG(DL_REN, ("Ext2SetRenameInfo: Target file %wZ cannot be removed.\n",
- &ExistingMcb->FullName));
- goto errorout;
- }
- }
-
- Status = Ext2DeleteFile(IrpContext, Vcb, ExistingFcb, ExistingMcb);
- if (!NT_SUCCESS(Status)) {
- DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to delete %wZ with status: %xh.\n",
- &FileName, Status));
-
- goto errorout;
- }
-
- bTargetRemoved = TRUE;
- }
- }
-
- /* remove directory entry of old name */
- Status = Ext2RemoveEntry(IrpContext, Vcb, ParentDcb, Mcb);
- if (!NT_SUCCESS(Status)) {
- DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to remove entry %wZ with status %xh.\n",
- &Mcb->FullName, Status));
- DbgBreak();
- goto errorout;
- }
-
- /* add new entry for new target name */
- Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, &NewEntry);
- if (!NT_SUCCESS(Status)) {
- DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to add entry for %wZ with status: %xh.\n",
- &FileName, Status));
- Ext2AddEntry(IrpContext, Vcb, ParentDcb, &Mcb->Inode, &Mcb->ShortName, &NewEntry);
- goto errorout;
- }
-
- /* correct the inode number in .. entry */
- if (IsMcbDirectory(Mcb)) {
- Status = Ext2SetParentEntry(
- IrpContext, Vcb, Fcb,
- ParentMcb->Inode.i_ino,
- TargetMcb->Inode.i_ino );
- if (!NT_SUCCESS(Status)) {
- DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to set parent refer of %wZ with %xh.\n",
- &Mcb->FullName, Status));
- DbgBreak();
- goto errorout;
- }
- }
-
- /* Update current dentry from the newly created one. We need keep the original
- dentry to assure children's links are valid if current entry is a directory */
- if (Mcb->de) {
- char *np = Mcb->de->d_name.name;
- *(Mcb->de) = *NewEntry;
- NewEntry->d_name.name = np;
- }
-
- if (bTargetRemoved) {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- ExistingMcb,
- (IsMcbDirectory(ExistingMcb) ?
- FILE_NOTIFY_CHANGE_DIR_NAME :
- FILE_NOTIFY_CHANGE_FILE_NAME ),
- FILE_ACTION_REMOVED);
- }
-
- if (NT_SUCCESS(Status)) {
-
- if (bMove) {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Mcb,
- (IsDirectory(Fcb) ?
- FILE_NOTIFY_CHANGE_DIR_NAME :
- FILE_NOTIFY_CHANGE_FILE_NAME ),
- FILE_ACTION_REMOVED);
-
- } else {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Mcb,
- (IsDirectory(Fcb) ?
- FILE_NOTIFY_CHANGE_DIR_NAME :
- FILE_NOTIFY_CHANGE_FILE_NAME ),
- FILE_ACTION_RENAMED_OLD_NAME);
-
- }
-
- if (TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino) {
- Ext2RemoveMcb(Vcb, Mcb);
- Ext2InsertMcb(Vcb, TargetMcb, Mcb);
- }
-
- if (!Ext2BuildName( &Mcb->ShortName,
- &FileName, NULL )) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto errorout;
- }
-
- if (!Ext2BuildName( &Mcb->FullName,
- &FileName,
- &TargetMcb->FullName)) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto errorout;
- }
-
- if (bMove) {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Mcb,
- (IsDirectory(Fcb) ?
- FILE_NOTIFY_CHANGE_DIR_NAME :
- FILE_NOTIFY_CHANGE_FILE_NAME ),
- FILE_ACTION_ADDED);
- } else {
- Ext2NotifyReportChange(
- IrpContext,
- Vcb,
- Mcb,
- (IsDirectory(Fcb) ?
- FILE_NOTIFY_CHANGE_DIR_NAME :
- FILE_NOTIFY_CHANGE_FILE_NAME ),
- FILE_ACTION_RENAMED_NEW_NAME );
-
- }
- }
-
-errorout:
-
- if (NewEntry)
- Ext2FreeEntry(NewEntry);
-
- if (TargetDcb) {
- if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) {
- ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
- }
- ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
- }
-
- if (bNewTargetDcb) {
- ASSERT(TargetDcb != NULL);
- if (Ext2DerefXcb(&TargetDcb->ReferenceCount) == 0) {
- Ext2FreeFcb(TargetDcb);
- TargetDcb = NULL;
- } else {
- DEBUG(DL_RES, ( "Ext2SetRenameInfo: TargetDcb is resued by other threads.\n"));
- }
- }
-
- if (bNewParentDcb) {
- ASSERT(ParentDcb != NULL);
- if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) {
- Ext2FreeFcb(ParentDcb);
- ParentDcb = NULL;
- } else {
- DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n"));
- }
- }
-
- if (ExistingMcb)
- Ext2DerefMcb(ExistingMcb);
-
- return Status;
-}
-
-ULONG
-Ext2InodeType(PEXT2_MCB Mcb)
-{
- if (IsMcbSymLink(Mcb)) {
- return EXT2_FT_SYMLINK;
- }
-
- if (IsMcbDirectory(Mcb)) {
- return EXT2_FT_DIR;
- }
-
- return EXT2_FT_REG_FILE;
-}
-
-NTSTATUS
-Ext2DeleteFile(
- PEXT2_IRP_CONTEXT IrpContext,
- PEXT2_VCB Vcb,
- PEXT2_FCB Fcb,
- PEXT2_MCB Mcb
-)
-{
- PEXT2_FCB Dcb = NULL;
-
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
- BOOLEAN VcbResourceAcquired = FALSE;
- BOOLEAN FcbPagingIoAcquired = FALSE;
- BOOLEAN FcbResourceAcquired = FALSE;
- BOOLEAN DcbResourceAcquired = FALSE;
-
- LARGE_INTEGER Size;
- LARGE_INTEGER SysTime;
-
- BOOLEAN bNewDcb = FALSE;
-
- DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n",
- &Mcb->FullName, Mcb->Inode.i_ino));
-
- if (IsFlagOn(Mcb->Flags, MCB_FILE_DELETED)) {
- return STATUS_SUCCESS;
- }
-
- if (!IsMcbSymLink(Mcb) && IsMcbDirectory(Mcb)) {
- if (!Ext2IsDirectoryEmpty(IrpContext, Vcb, Mcb)) {
- return STATUS_DIRECTORY_NOT_EMPTY;
- }
- }
-
-
- _SEH2_TRY {
-
- Ext2ReferMcb(Mcb);
-
- ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
- VcbResourceAcquired = TRUE;
-
- if (!(Dcb = Mcb->Parent->Fcb)) {
- Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent);
- if (Dcb) {
- Ext2ReferXcb(&Dcb->ReferenceCount);
- bNewDcb = TRUE;
- }
- }
-
- if (Dcb) {
- SetLongFlag(Dcb->Flags, FCB_STATE_BUSY);
- DcbResourceAcquired =
- ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
-
- /* remove it's entry form it's parent */
- Status = Ext2RemoveEntry(IrpContext, Vcb, Dcb, Mcb);
- }
-
- if (NT_SUCCESS(Status)) {
-
- SetFlag(Mcb->Flags, MCB_FILE_DELETED);
- Ext2RemoveMcb(Vcb, Mcb);
-
- if (Fcb) {
- FcbResourceAcquired =
- ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
-
- FcbPagingIoAcquired =
- ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
- }
-
- if (DcbResourceAcquired) {
- ExReleaseResourceLite(&Dcb->MainResource);
- DcbResourceAcquired = FALSE;
- }
-
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- VcbResourceAcquired = FALSE;
- }
-
- if (IsMcbSymLink(Mcb)) {
- if (Mcb->Inode.i_nlink > 0) {
- Status = STATUS_CANNOT_DELETE;
- _SEH2_LEAVE;
- }
- } else if (!IsMcbDirectory(Mcb)) {
- if (Mcb->Inode.i_nlink > 0) {
- _SEH2_LEAVE;
- }
- } else {
- if (Mcb->Inode.i_nlink >= 2) {
- _SEH2_LEAVE;
- }
- }
-
- if (S_ISLNK(Mcb->Inode.i_mode)) {
-
- /* for symlink, we should do differenctly */
- if (Mcb->Inode.i_size > EXT2_LINKLEN_IN_INODE) {
- Size.QuadPart = (LONGLONG)0;
- Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &Size);
- }
-
- } else {
-
- /* truncate file size */
- Size.QuadPart = (LONGLONG)0;
- Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &Size);
-
- /* check file offset mappings */
- DEBUG(DL_EXT, ("Ext2DeleteFile ...: %wZ\n", &Mcb->FullName));
-
- if (Fcb) {
- Fcb->Header.AllocationSize.QuadPart = Size.QuadPart;
- if (Fcb->Header.FileSize.QuadPart > Size.QuadPart) {
- Fcb->Header.FileSize.QuadPart = Size.QuadPart;
- Fcb->Mcb->Inode.i_size = Size.QuadPart;
- }
- if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) {
- Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
- }
- } else if (Mcb) {
- /* Update the inode's data length . It should be ZERO if succeeds. */
- if (Mcb->Inode.i_size > (loff_t)Size.QuadPart) {
- Mcb->Inode.i_size = Size.QuadPart;
- }
- }
- }
-
- /* set delete time and free the inode */
- KeQuerySystemTime(&SysTime);
- Mcb->Inode.i_nlink = 0;
- Mcb->Inode.i_dtime = Ext2LinuxTime(SysTime);
- Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
- Ext2FreeInode(IrpContext, Vcb, Mcb->Inode.i_ino, Ext2InodeType(Mcb));
- }
-
- } _SEH2_FINALLY {
-
- if (FcbPagingIoAcquired) {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- }
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- if (DcbResourceAcquired) {
- ExReleaseResourceLite(&Dcb->MainResource);
- }
-
- if (Dcb) {
- ClearLongFlag(Dcb->Flags, FCB_STATE_BUSY);
- if (bNewDcb) {
- if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) {
- Ext2FreeFcb(Dcb);
- } else {
- DEBUG(DL_ERR, ( "Ext2DeleteFile: Dcb %wZ used by other threads.\n",
- &Mcb->FullName ));
- }
- }
- }
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- Ext2DerefMcb(Mcb);
- } _SEH2_END;
-
- DEBUG(DL_INF, ( "Ext2DeleteFile: %wZ Succeed... EXT2SB->S_FREE_BLOCKS = %I64xh .\n",
- &Mcb->FullName, ext3_free_blocks_count(SUPER_BLOCK)));
-
- return Status;
-}
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: flush.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-
-NTSTATUS NTAPI
-Ext2FlushCompletionRoutine (
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID Context )
-
-{
- if (Irp->PendingReturned)
- IoMarkIrpPending( Irp );
-
-
- if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-Ext2FlushFiles(
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN BOOLEAN bShutDown
-)
-{
- IO_STATUS_BLOCK IoStatus;
-
- PEXT2_FCB Fcb;
- PLIST_ENTRY ListEntry;
-
- if (IsVcbReadOnly(Vcb)) {
- return STATUS_SUCCESS;
- }
-
- IoStatus.Status = STATUS_SUCCESS;
-
- DEBUG(DL_INF, ( "Flushing Files ...\n"));
-
- // Flush all Fcbs in Vcb list queue.
- for (ListEntry = Vcb->FcbList.Flink;
- ListEntry != &Vcb->FcbList;
- ListEntry = ListEntry->Flink ) {
-
- Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
- ExAcquireResourceExclusiveLite(
- &Fcb->MainResource, TRUE);
- IoStatus.Status = Ext2FlushFile(IrpContext, Fcb, NULL);
- ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- return IoStatus.Status;
-}
-
-NTSTATUS
-Ext2FlushVolume (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN BOOLEAN bShutDown
-)
-{
- IO_STATUS_BLOCK IoStatus;
-
- DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
-
- ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Vcb->PagingIoResource);
-
- CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
-
- return IoStatus.Status;
-}
-
-NTSTATUS
-Ext2FlushFile (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_FCB Fcb,
- IN PEXT2_CCB Ccb
-)
-{
- IO_STATUS_BLOCK IoStatus;
-
- ASSERT(Fcb != NULL);
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- /* update timestamp and achieve attribute */
- if (Ccb != NULL) {
-
- if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
-
- LARGE_INTEGER SysTime;
- KeQuerySystemTime(&SysTime);
-
- Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
- Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
- Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
- }
- }
-
- if (IsDirectory(Fcb)) {
- return STATUS_SUCCESS;
- }
-
- DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
- Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
-
- CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
- ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
-
- return IoStatus.Status;
-}
-
-NTSTATUS
-Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status = STATUS_SUCCESS;
-
- PIRP Irp = NULL;
- PIO_STACK_LOCATION IrpSp = NULL;
-
- PEXT2_VCB Vcb = NULL;
- PEXT2_FCB Fcb = NULL;
- PEXT2_FCBVCB FcbOrVcb = NULL;
- PEXT2_CCB Ccb = NULL;
- PFILE_OBJECT FileObject = NULL;
-
- PDEVICE_OBJECT DeviceObject = NULL;
-
- BOOLEAN MainResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
-
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
-
- //
- // This request is not allowed on the main device object
- //
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- ASSERT(IsMounted(Vcb));
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- Irp = IrpContext->Irp;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- FileObject = IrpContext->FileObject;
- FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
- ASSERT(FcbOrVcb != NULL);
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- if (Ccb == NULL) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- MainResourceAcquired =
- ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
-
- ASSERT(MainResourceAcquired);
- DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
- FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
-
- if (FcbOrVcb->Identifier.Type == EXT2VCB) {
-
- Ext2VerifyVcb(IrpContext, Vcb);
- Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
- if (NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
-
- if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
- ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
- }
-
- } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
-
- Fcb = (PEXT2_FCB)(FcbOrVcb);
-
- Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
- if (NT_SUCCESS(Status)) {
- if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
- Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
- ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
- }
- }
- }
-
- DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
- FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
-
-
- } _SEH2_FINALLY {
-
- if (MainResourceAcquired) {
- ExReleaseResourceLite(&FcbOrVcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
-
- if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
-
- // Call the disk driver to flush the physial media.
- NTSTATUS DriverStatus;
- PIO_STACK_LOCATION NextIrpSp;
-
- NextIrpSp = IoGetNextIrpStackLocation(Irp);
-
- *NextIrpSp = *IrpSp;
-
- IoSetCompletionRoutine( Irp,
- Ext2FlushCompletionRoutine,
- NULL,
- TRUE,
- TRUE,
- TRUE );
-
- DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
-
- Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
- Status : DriverStatus;
-
- IrpContext->Irp = Irp = NULL;
- }
-
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } _SEH2_END;
-
- return Status;
-}
\ No newline at end of file
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: misc.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, Ext2Sleep)
-#endif
-
-ULONG
-Ext2Log2(ULONG Value)
-{
- ULONG Order = 0;
-
- ASSERT(Value > 0);
-
- while (Value) {
- Order++;
- Value >>= 1;
- }
-
- return (Order - 1);
-}
-
-LARGE_INTEGER
-Ext2NtTime (IN ULONG i_time)
-{
- LARGE_INTEGER SysTime;
-
- SysTime.QuadPart = 0;
- RtlSecondsSince1970ToTime(i_time, &SysTime);
-
- return SysTime;
-}
-
-ULONG
-Ext2LinuxTime (IN LARGE_INTEGER SysTime)
-{
- ULONG Ext2Time = 0;
-
- if (!RtlTimeToSecondsSince1970(&SysTime, &Ext2Time)) {
- LARGE_INTEGER NtTime;
- KeQuerySystemTime(&NtTime);
- RtlTimeToSecondsSince1970(&NtTime, &Ext2Time);
- }
-
- return Ext2Time;
-}
-
-
-ULONG
-Ext2MbsToUnicode(
- struct nls_table * PageTable,
- IN OUT PUNICODE_STRING Unicode,
- IN PANSI_STRING Mbs )
-{
- ULONG Length = 0;
- int i, mbc = 0;
- WCHAR uc;
-
- /* Count the length of the resulting Unicode. */
- for (i = 0; i < Mbs->Length; i += mbc) {
-
- mbc = PageTable->char2uni(
- (PUCHAR)&(Mbs->Buffer[i]),
- Mbs->Length - i,
- &uc
- );
-
- if (mbc <= 0) {
-
- /* invalid character. */
- if (mbc == 0 && Length > 0) {
- break;
- }
- return 0;
- }
-
- Length += 2;
- }
-
- if (Unicode) {
- if (Unicode->MaximumLength < Length) {
-
- DbgBreak();
- return 0;
- }
-
- Unicode->Length = 0;
- mbc = 0;
-
- for (i = 0; i < Mbs->Length; i += mbc) {
-
- mbc = PageTable->char2uni(
- (PUCHAR)&(Mbs->Buffer[i]),
- Mbs->Length - i,
- &uc
- );
- Unicode->Buffer[Unicode->Length/2] = uc;
- Unicode->Length += 2;
- }
- }
-
- return Length;
-}
-
-ULONG
-Ext2UnicodeToMbs (
- struct nls_table * PageTable,
- IN OUT PANSI_STRING Mbs,
- IN PUNICODE_STRING Unicode)
-{
- ULONG Length = 0;
- UCHAR mbs[0x10];
- int i, mbc;
-
- /* Count the length of the resulting mbc-8. */
- for (i = 0; i < (Unicode->Length / 2); i++) {
-
- RtlZeroMemory(mbs, 0x10);
- mbc = PageTable->uni2char(
- Unicode->Buffer[i],
- mbs,
- 0x10
- );
-
- if (mbc <= 0) {
-
- /* Invalid character. */
- return 0;
- }
-
- Length += mbc;
- }
-
- if (Mbs) {
-
- if (Mbs->MaximumLength < Length) {
-
- DbgBreak();
- return 0;
- }
-
- Mbs->Length = 0;
-
- for (i = 0; i < (Unicode->Length / 2); i++) {
-
- mbc = PageTable->uni2char(
- Unicode->Buffer[i],
- mbs,
- 0x10
- );
-
- RtlCopyMemory(
- (PUCHAR)&(Mbs->Buffer[Mbs->Length]),
- &mbs[0],
- mbc
- );
-
- Mbs->Length += (USHORT)mbc;
- }
- }
-
- return Length;
-}
-
-
-ULONG
-Ext2OEMToUnicodeSize(
- IN PEXT2_VCB Vcb,
- IN PANSI_STRING Oem
-)
-{
- ULONG Length = 0;
-
- if (Vcb->Codepage.PageTable) {
- Length = Ext2MbsToUnicode(Vcb->Codepage.PageTable, NULL, Oem);
- if (Length > 0) {
- goto errorout;
- }
- }
-
- Length = RtlOemStringToCountedUnicodeSize(Oem);
-
-errorout:
-
- return Length;
-}
-
-
-NTSTATUS
-Ext2OEMToUnicode(
- IN PEXT2_VCB Vcb,
- IN OUT PUNICODE_STRING Unicode,
- IN POEM_STRING Oem
-)
-{
- NTSTATUS Status;
-
-
- if (Vcb->Codepage.PageTable) {
- Status = Ext2MbsToUnicode(Vcb->Codepage.PageTable,
- Unicode, Oem);
-
- if (Status >0 && Status == Unicode->Length) {
- Status = STATUS_SUCCESS;
- goto errorout;
- }
- }
-
- Status = RtlOemStringToUnicodeString(
- Unicode, Oem, FALSE );
-
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- goto errorout;
- }
-
-errorout:
-
- return Status;
-}
-
-ULONG
-Ext2UnicodeToOEMSize(
- IN PEXT2_VCB Vcb,
- IN PUNICODE_STRING Unicode
-)
-{
- ULONG Length = 0;
-
- if (Vcb->Codepage.PageTable) {
- Length = Ext2UnicodeToMbs(Vcb->Codepage.PageTable,
- NULL, Unicode);
- if (Length > 0) {
- return Length;
- }
-
- DbgBreak();
- }
-
- return RtlxUnicodeStringToOemSize(Unicode);
-}
-
-
-NTSTATUS
-Ext2UnicodeToOEM (
- IN PEXT2_VCB Vcb,
- IN OUT POEM_STRING Oem,
- IN PUNICODE_STRING Unicode)
-{
- NTSTATUS Status;
-
- if (Vcb->Codepage.PageTable) {
-
- Status = Ext2UnicodeToMbs(Vcb->Codepage.PageTable,
- Oem, Unicode);
- if (Status > 0 && Status == Oem->Length) {
- Status = STATUS_SUCCESS;
- } else {
- Status = STATUS_UNSUCCESSFUL;
- DbgBreak();
- }
-
- goto errorout;
- }
-
- Status = RtlUnicodeStringToOemString(
- Oem, Unicode, FALSE );
-
- if (!NT_SUCCESS(Status))
- {
- DbgBreak();
- goto errorout;
- }
-
-errorout:
-
- return Status;
-}
-
-VOID
-Ext2Sleep(ULONG ms)
-{
- LARGE_INTEGER Timeout;
- Timeout.QuadPart = (LONGLONG)ms*1000*(-10); /* ms/1000 sec*/
- KeDelayExecutionThread(KernelMode, TRUE, &Timeout);
-}
-
-int Ext2LinuxError (NTSTATUS Status)
-{
- switch (Status) {
- case STATUS_ACCESS_DENIED:
- return (-EACCES);
-
- case STATUS_ACCESS_VIOLATION:
- return (-EFAULT);
-
- case STATUS_BUFFER_TOO_SMALL:
- return (-ETOOSMALL);
-
- case STATUS_INVALID_PARAMETER:
- return (-EINVAL);
-
- case STATUS_NOT_IMPLEMENTED:
- case STATUS_NOT_SUPPORTED:
- return (-EOPNOTSUPP);
-
- case STATUS_INVALID_ADDRESS:
- case STATUS_INVALID_ADDRESS_COMPONENT:
- return (-EADDRNOTAVAIL);
-
- case STATUS_NO_SUCH_DEVICE:
- case STATUS_NO_SUCH_FILE:
- case STATUS_OBJECT_NAME_NOT_FOUND:
- case STATUS_OBJECT_PATH_NOT_FOUND:
- case STATUS_NETWORK_BUSY:
- case STATUS_INVALID_NETWORK_RESPONSE:
- case STATUS_UNEXPECTED_NETWORK_ERROR:
- return (-ENETDOWN);
-
- case STATUS_BAD_NETWORK_PATH:
- case STATUS_NETWORK_UNREACHABLE:
- case STATUS_PROTOCOL_UNREACHABLE:
- return (-ENETUNREACH);
-
- case STATUS_LOCAL_DISCONNECT:
- case STATUS_TRANSACTION_ABORTED:
- case STATUS_CONNECTION_ABORTED:
- return (-ECONNABORTED);
-
- case STATUS_REMOTE_DISCONNECT:
- case STATUS_LINK_FAILED:
- case STATUS_CONNECTION_DISCONNECTED:
- case STATUS_CONNECTION_RESET:
- case STATUS_PORT_UNREACHABLE:
- return (-ECONNRESET);
-
- case STATUS_INSUFFICIENT_RESOURCES:
- return (-ENOMEM);
-
- case STATUS_PAGEFILE_QUOTA:
- case STATUS_NO_MEMORY:
- case STATUS_CONFLICTING_ADDRESSES:
- case STATUS_QUOTA_EXCEEDED:
- case STATUS_TOO_MANY_PAGING_FILES:
- case STATUS_WORKING_SET_QUOTA:
- case STATUS_COMMITMENT_LIMIT:
- case STATUS_TOO_MANY_ADDRESSES:
- case STATUS_REMOTE_RESOURCES:
- return (-ENOBUFS);
-
- case STATUS_INVALID_CONNECTION:
- return (-ENOTCONN);
-
- case STATUS_PIPE_DISCONNECTED:
- return (-ESHUTDOWN);
-
- case STATUS_TIMEOUT:
- case STATUS_IO_TIMEOUT:
- case STATUS_LINK_TIMEOUT:
- return (-ETIMEDOUT);
-
- case STATUS_REMOTE_NOT_LISTENING:
- case STATUS_CONNECTION_REFUSED:
- return (-ECONNREFUSED);
-
- case STATUS_HOST_UNREACHABLE:
- return (-EHOSTUNREACH);
-
- case STATUS_PENDING:
- case STATUS_DEVICE_NOT_READY:
- return (-EAGAIN);
-
- case STATUS_CANCELLED:
- case STATUS_REQUEST_ABORTED:
- return (-EINTR);
-
- case STATUS_BUFFER_OVERFLOW:
- case STATUS_INVALID_BUFFER_SIZE:
- return (-EMSGSIZE);
-
- case STATUS_ADDRESS_ALREADY_EXISTS:
- return (-EADDRINUSE);
- }
-
- if (NT_SUCCESS (Status))
- return 0;
-
- return (-EINVAL);
-}
-
-NTSTATUS Ext2WinntError(int rc)
-{
- switch (rc) {
-
- case 0:
- return STATUS_SUCCESS;
-
- case -EPERM:
- case -EACCES:
- return STATUS_ACCESS_DENIED;
-
- case -ENOENT:
- return STATUS_OBJECT_NAME_NOT_FOUND;
-
- case -EFAULT:
- return STATUS_ACCESS_VIOLATION;
-
- case -ETOOSMALL:
- return STATUS_BUFFER_TOO_SMALL;
-
- case -EBADMSG:
- case -EBADF:
- case -EINVAL:
- case -EFBIG:
- return STATUS_INVALID_PARAMETER;
-
- case -EBUSY:
- return STATUS_DEVICE_BUSY;
-
- case -ENOSYS:
- return STATUS_NOT_IMPLEMENTED;
-
- case -ENOSPC:
- return STATUS_DISK_FULL;
-
- case -EOPNOTSUPP:
- return STATUS_NOT_SUPPORTED;
-
- case -EDEADLK:
- return STATUS_POSSIBLE_DEADLOCK;
-
- case -EEXIST:
- return STATUS_OBJECT_NAME_COLLISION;
-
- case -EIO:
- return STATUS_UNEXPECTED_IO_ERROR;
-
- case -ENOTDIR:
- return STATUS_NOT_A_DIRECTORY;
-
- case -EISDIR:
- return STATUS_FILE_IS_A_DIRECTORY;
-
- case -ENOTEMPTY:
- return STATUS_DIRECTORY_NOT_EMPTY;
-
- case -ENODEV:
- return STATUS_NO_SUCH_DEVICE;
-
- case -ENXIO:
- return STATUS_INVALID_ADDRESS;
-
- case -EADDRNOTAVAIL:
- return STATUS_INVALID_ADDRESS;
-
- case -ENETDOWN:
- return STATUS_UNEXPECTED_NETWORK_ERROR;
-
- case -ENETUNREACH:
- return STATUS_NETWORK_UNREACHABLE;
-
- case -ECONNABORTED:
- return STATUS_CONNECTION_ABORTED;
-
- case -ECONNRESET:
- return STATUS_CONNECTION_RESET;
-
- case -ENOMEM:
- return STATUS_INSUFFICIENT_RESOURCES;
-
- case -ENOBUFS:
- return STATUS_NO_MEMORY;
-
- case -ENOTCONN:
- return STATUS_INVALID_CONNECTION;
-
- case -ESHUTDOWN:
- return STATUS_CONNECTION_DISCONNECTED;
-
- case -ETIMEDOUT:
- return STATUS_TIMEOUT;
-
- case -ECONNREFUSED:
- return STATUS_CONNECTION_REFUSED;
-
- case -EHOSTUNREACH:
- return STATUS_HOST_UNREACHABLE;
-
- case -EAGAIN:
- return STATUS_DEVICE_NOT_READY;
-
- case -EINTR:
- return STATUS_CANCELLED;
-
- case -EMSGSIZE:
- return STATUS_INVALID_BUFFER_SIZE;
-
- case -EADDRINUSE:
- return STATUS_ADDRESS_ALREADY_EXISTS;
- }
-
- return STATUS_UNSUCCESSFUL;
-}
-
-BOOLEAN Ext2IsDot(PUNICODE_STRING name)
-{
- return (name->Length == 2 && name->Buffer[0] == L'.');
-}
-
-BOOLEAN Ext2IsDotDot(PUNICODE_STRING name)
-{
- return (name->Length == 4 && name->Buffer[0] == L'.' &&
- name->Buffer[1] == L'.');
-}
\ No newline at end of file
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: read.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-NTSTATUS
-Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext);
-
-NTSTATUS
-Ext2ReadFile (IN PEXT2_IRP_CONTEXT IrpContext);
-
-NTSTATUS
-Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext);
-
-/* FUNCTIONS *************************************************************/
-
-NTSTATUS
-Ext2CompleteIrpContext (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN NTSTATUS Status )
-{
- PIRP Irp = NULL;
- BOOLEAN bPrint;
-
- Irp = IrpContext->Irp;
-
- if (Irp != NULL) {
-
- if (NT_ERROR(Status)) {
- Irp->IoStatus.Information = 0;
- }
-
- Irp->IoStatus.Status = Status;
- bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
-
- Ext2CompleteRequest(
- Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)?
- IO_DISK_INCREMENT : IO_NO_INCREMENT) );
-
- IrpContext->Irp = NULL;
- }
-
- Ext2FreeIrpContext(IrpContext);
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
- PEXT2_VCB Vcb;
- PEXT2_CCB Ccb;
- PEXT2_FCBVCB FcbOrVcb;
- PFILE_OBJECT FileObject;
-
- PDEVICE_OBJECT DeviceObject;
-
- PIRP Irp = NULL;
- PIO_STACK_LOCATION IoStackLocation;
-
- ULONG Length;
- LARGE_INTEGER ByteOffset;
-
- BOOLEAN PagingIo;
- BOOLEAN Nocache;
- BOOLEAN SynchronousIo;
- BOOLEAN MainResourceAcquired = FALSE;
-
- PUCHAR Buffer = NULL;
- EXT2_EXTENT BlockArray;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- FileObject = IrpContext->FileObject;
- FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
- ASSERT(FcbOrVcb);
-
- if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
-
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- Irp = IrpContext->Irp;
- Irp->IoStatus.Information = 0;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
-
- Length = IoStackLocation->Parameters.Read.Length;
- ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
-
- PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
- Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
- SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
-
- if (PagingIo) {
- ASSERT(Nocache);
- }
-
- if (Length == 0) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
- ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- if (ByteOffset.QuadPart >=
- Vcb->PartitionInformation.PartitionLength.QuadPart ) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_END_OF_FILE;
- _SEH2_LEAVE;
- }
-
- if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
- Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
- }
-
- /*
- * User direct volume access
- */
-
- if (Ccb != NULL && !PagingIo) {
-
- if (!ExAcquireResourceExclusiveLite(
- &Vcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- MainResourceAcquired = TRUE;
-
- if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {
-
- if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
- Ext2FlushVolume(IrpContext, Vcb, FALSE);
- }
-
- SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
- }
-
- ExReleaseResourceLite(&Vcb->MainResource);
- MainResourceAcquired = FALSE;
-
- /* will do Nocache i/o */
- }
-
- /*
- * I/O to volume StreamObject
- */
-
- if (!Nocache) {
-
- if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
-
- CcMdlRead(
- Vcb->Volume,
- &ByteOffset,
- Length,
- &Irp->MdlAddress,
- &Irp->IoStatus );
-
- Status = Irp->IoStatus.Status;
-
- } else {
-
- Buffer = Ext2GetUserBuffer(Irp);
- if (Buffer == NULL) {
- DbgBreak();
- Status = STATUS_INVALID_USER_BUFFER;
- _SEH2_LEAVE;
- }
-
- if (!CcCopyRead(
- Vcb->Volume,
- &ByteOffset,
- Length,
- Ext2CanIWait(),
- Buffer,
- &Irp->IoStatus )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- Status = Irp->IoStatus.Status;
- }
-
- } else {
-
- Length &= ~((ULONG)SECTOR_SIZE - 1);
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoWriteAccess );
-
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- BlockArray.Irp = NULL;
- BlockArray.Lba = ByteOffset.QuadPart;
- BlockArray.Offset = 0;
- BlockArray.Length = Length;
- BlockArray.Next = NULL;
-
- Status = Ext2ReadWriteBlocks(IrpContext,
- Vcb,
- &BlockArray,
- Length );
-
- Irp = IrpContext->Irp;
- if (!Irp) {
- _SEH2_LEAVE;
- }
- }
-
- } _SEH2_FINALLY {
-
- if (MainResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
-
- if (Irp) {
-
- if (Status == STATUS_PENDING &&
- !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) {
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoWriteAccess );
-
- if (NT_SUCCESS(Status)) {
- Status = Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
-
- } else {
-
- if (NT_SUCCESS(Status)) {
-
- if (!PagingIo) {
-
- if (SynchronousIo) {
-
- FileObject->CurrentByteOffset.QuadPart =
- ByteOffset.QuadPart + Irp->IoStatus.Information;
- }
-
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
- }
- }
-
- Ext2CompleteIrpContext(IrpContext, Status);;
- }
-
- } else {
- Ext2FreeIrpContext(IrpContext);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
-
-
-#define SafeZeroMemory(AT,BYTE_COUNT) { \
- _SEH2_TRY { \
- if (AT) \
- RtlZeroMemory((AT), (BYTE_COUNT)); \
- } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
- Ext2RaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \
- } _SEH2_END; \
-}
-
-NTSTATUS
-Ext2ReadInode (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PEXT2_MCB Mcb,
- IN ULONGLONG Offset,
- IN PVOID Buffer,
- IN ULONG Size,
- IN BOOLEAN bDirectIo,
- OUT PULONG BytesRead
-)
-{
- PEXT2_EXTENT Chain = NULL;
- PEXT2_EXTENT Extent = NULL, Prev = NULL;
-
- IO_STATUS_BLOCK IoStatus;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- ULONG RealSize ;
-
- if (BytesRead) {
- *BytesRead = 0;
- }
-
- _SEH2_TRY {
-
- Ext2ReferMcb(Mcb);
-
- ASSERT((Mcb->Identifier.Type == EXT2MCB) &&
- (Mcb->Identifier.Size == sizeof(EXT2_MCB)));
-
- if ((Mcb->Identifier.Type != EXT2MCB) ||
- (Mcb->Identifier.Size != sizeof(EXT2_MCB))) {
- _SEH2_LEAVE;
- }
-
- if (Buffer == NULL && IrpContext != NULL)
- Buffer = Ext2GetUserBuffer(IrpContext->Irp);
-
-
- /* handle fast symlinks */
- if (S_ISLNK(Mcb->Inode.i_mode) &&
- Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
-
- PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]);
-
- if (!Buffer) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
-
- if (Offset < EXT2_LINKLEN_IN_INODE) {
- if ((ULONG)Offset + Size >= EXT2_LINKLEN_IN_INODE)
- Size = EXT2_LINKLEN_IN_INODE - (ULONG)Offset - 1;
- RtlCopyMemory(Buffer, Data + (ULONG)Offset, Size);
- Status = STATUS_SUCCESS;
- } else {
- Status = STATUS_END_OF_FILE;
- }
- _SEH2_LEAVE;
- }
-
- //
- // Build the scatterred block ranges to be read
- //
-
- if (bDirectIo) {
- RealSize = CEILING_ALIGNED(ULONG, Size, SECTOR_SIZE - 1);
- } else {
- RealSize = Size;
- }
-
- Status = Ext2BuildExtents(
- IrpContext,
- Vcb,
- Mcb,
- Offset,
- RealSize,
- FALSE,
- &Chain
- );
-
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- if (Chain == NULL) {
- SafeZeroMemory((PCHAR)Buffer, Size);
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- /* for sparse file, we need zero the gaps */
- for (Extent = Chain; Buffer != NULL && Extent != NULL; Extent = Extent->Next) {
- if (NULL == Prev) {
- ASSERT(Extent == Chain);
- if (Extent->Offset) {
- SafeZeroMemory((PCHAR)Buffer, Extent->Offset);
- }
- } else if (Extent->Offset > (Prev->Offset + Prev->Length)) {
- SafeZeroMemory((PCHAR)Buffer + Prev->Offset + Prev->Length,
- Extent->Offset - Prev->Offset - Prev->Length);
- }
- if (NULL == Extent->Next) {
- if (Extent->Offset + Extent->Length < Size) {
- SafeZeroMemory((PCHAR)Buffer + Extent->Offset + Extent->Length,
- Size - Extent->Offset - Extent->Length);
- }
- }
- Prev = Extent;
- }
-
- if (bDirectIo) {
-
- ASSERT(IrpContext != NULL);
-
- // Offset should be SECTOR_SIZE aligned ...
- Status = Ext2ReadWriteBlocks(
- IrpContext,
- Vcb,
- Chain,
- Size
- );
- } else {
-
- for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
-
- if (!CcCopyRead(
- Vcb->Volume,
- (PLARGE_INTEGER)(&(Extent->Lba)),
- Extent->Length,
- PIN_WAIT,
- (PVOID)((PUCHAR)Buffer + Extent->Offset),
- &IoStatus
- )) {
- Status = STATUS_CANT_WAIT;
- } else {
- Status = IoStatus.Status;
- }
-
- if (!NT_SUCCESS(Status)) {
- break;
- }
- }
- }
-
- } _SEH2_FINALLY {
-
- if (Chain) {
- Ext2DestroyExtentChain(Chain);
- }
-
- Ext2DerefMcb(Mcb);
- } _SEH2_END;
-
- if (NT_SUCCESS(Status)) {
- if (BytesRead)
- *BytesRead = Size;
- }
-
- return Status;
-}
-
-NTSTATUS
-Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
- PEXT2_VCB Vcb;
- PEXT2_FCB Fcb;
- PEXT2_CCB Ccb;
- PFILE_OBJECT FileObject;
-
- PDEVICE_OBJECT DeviceObject;
-
- PIRP Irp;
- PIO_STACK_LOCATION IoStackLocation;
-
- ULONG Length;
- ULONG ReturnedLength = 0;
- LARGE_INTEGER ByteOffset;
-
- BOOLEAN OpPostIrp = FALSE;
- BOOLEAN PagingIo;
- BOOLEAN Nocache;
- BOOLEAN SynchronousIo;
- BOOLEAN MainResourceAcquired = FALSE;
- BOOLEAN PagingIoResourceAcquired = FALSE;
-
- PUCHAR Buffer;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- FileObject = IrpContext->FileObject;
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- ASSERT(Fcb);
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
-
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
-
- Length = IoStackLocation->Parameters.Read.Length;
- ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
-
- PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
- Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
- SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
-
- if (PagingIo) {
- ASSERT(Nocache);
- }
-
- DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
- &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
-
- if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ||
- IsFileDeleted(Fcb->Mcb)) {
- Status = STATUS_FILE_DELETED;
- _SEH2_LEAVE;
- }
-
- if (Length == 0) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if (Nocache &&
- (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
- Length & (SECTOR_SIZE - 1))) {
- Status = STATUS_INVALID_PARAMETER;
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
- ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
- Status = STATUS_PENDING;
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- if (!PagingIo && Nocache && (FileObject->SectionObjectPointer->DataSectionObject != NULL)) {
- CcFlushCache( FileObject->SectionObjectPointer,
- &ByteOffset,
- Length,
- &Irp->IoStatus );
-
- if (!NT_SUCCESS(Irp->IoStatus.Status)) {
- _SEH2_LEAVE;
- }
- }
-
- ReturnedLength = Length;
-
- if (PagingIo) {
-
- if (!ExAcquireResourceSharedLite(
- &Fcb->PagingIoResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- PagingIoResourceAcquired = TRUE;
-
- } else {
-
- if (Nocache) {
-
- if (!ExAcquireResourceExclusiveLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- MainResourceAcquired = TRUE;
-
- } else {
-
- if (!ExAcquireResourceSharedLite(
- &Fcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- MainResourceAcquired = TRUE;
- }
-
- if (!FsRtlCheckLockForReadAccess(
- &Fcb->FileLockAnchor,
- Irp )) {
- Status = STATUS_FILE_LOCK_CONFLICT;
- _SEH2_LEAVE;
- }
- }
-
- if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.FileSize.QuadPart) {
- if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_END_OF_FILE;
- _SEH2_LEAVE;
- }
- ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
- }
-
-
- if (!IsDirectory(Fcb) && Ccb != NULL) {
- Status = FsRtlCheckOplock( &Fcb->Oplock,
- Irp,
- IrpContext,
- Ext2OplockComplete,
- Ext2LockIrp );
-
- if (Status != STATUS_SUCCESS) {
- OpPostIrp = TRUE;
- _SEH2_LEAVE;
- }
-
- //
- // Set the flag indicating if Fast I/O is possible
- //
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
- }
-
- if (!Nocache) {
-
- if (IsDirectory(Fcb)) {
- _SEH2_LEAVE;
- }
-
- if (FileObject->PrivateCacheMap == NULL) {
- CcInitializeCacheMap(
- FileObject,
- (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
- FALSE,
- &Ext2Global->CacheManagerCallbacks,
- Fcb );
- CcSetReadAheadGranularity(
- FileObject,
- READ_AHEAD_GRANULARITY );
- }
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
- CcMdlRead(
- FileObject,
- (&ByteOffset),
- ReturnedLength,
- &Irp->MdlAddress,
- &Irp->IoStatus );
-
- Status = Irp->IoStatus.Status;
-
- } else {
-
- Buffer = Ext2GetUserBuffer(Irp);
- if (Buffer == NULL) {
- Status = STATUS_INVALID_USER_BUFFER;
- DbgBreak();
- _SEH2_LEAVE;
- }
-
- if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength,
- Ext2CanIWait(), Buffer, &Irp->IoStatus)) {
-
- if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset,
- ReturnedLength, TRUE,
- Buffer, &Irp->IoStatus)) {
- Status = STATUS_PENDING;
- DbgBreak();
- _SEH2_LEAVE;
- }
- }
- Status = Irp->IoStatus.Status;
- }
-
- } else {
-
- ULONG BytesRead = ReturnedLength;
- PUCHAR SystemVA = Ext2GetUserBuffer(IrpContext->Irp);
-
- if (ByteOffset.QuadPart + BytesRead > Fcb->Header.ValidDataLength.QuadPart) {
-
- if (ByteOffset.QuadPart >= Fcb->Header.ValidDataLength.QuadPart) {
- if (SystemVA) {
- SafeZeroMemory(SystemVA, Length);
- }
- Irp->IoStatus.Information = ReturnedLength;
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- } else {
- BytesRead = (ULONG)(Fcb->Header.ValidDataLength.QuadPart - ByteOffset.QuadPart);
- if (SystemVA) {
- SafeZeroMemory(SystemVA + BytesRead, Length - BytesRead);
- }
- }
- }
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- BytesRead,
- IoReadAccess );
-
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- Status = Ext2ReadInode(
- IrpContext,
- Vcb,
- Fcb->Mcb,
- ByteOffset.QuadPart,
- NULL,
- BytesRead,
- TRUE,
- NULL );
-
- /* we need re-queue this request in case STATUS_CANT_WAIT
- and fail it in other failure cases */
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- /* pended by low level device */
- if (Status == STATUS_PENDING) {
- IrpContext->Irp = Irp = NULL;
- _SEH2_LEAVE;
- }
-
- Irp = IrpContext->Irp;
- ASSERT(Irp);
- Status = Irp->IoStatus.Status;
-
- if (!NT_SUCCESS(Status)) {
- Ext2NormalizeAndRaiseStatus(IrpContext, Status);
- }
- }
-
- Irp->IoStatus.Information = ReturnedLength;
-
- } _SEH2_FINALLY {
-
- if (Irp) {
- if (PagingIoResourceAcquired) {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- }
-
- if (MainResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
- }
-
- if (!OpPostIrp && !IrpContext->ExceptionInProgress) {
-
- if (Irp) {
- if ( Status == STATUS_PENDING ||
- Status == STATUS_CANT_WAIT) {
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoWriteAccess );
-
- if (NT_SUCCESS(Status)) {
- Status = Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } else {
- if (NT_SUCCESS(Status)) {
- if (!PagingIo) {
- if (SynchronousIo) {
- FileObject->CurrentByteOffset.QuadPart =
- ByteOffset.QuadPart + Irp->IoStatus.Information;
- }
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
- }
- }
-
- Ext2CompleteIrpContext(IrpContext, Status);
- }
-
- } else {
-
- Ext2FreeIrpContext(IrpContext);
- }
- }
- } _SEH2_END;
-
- DEBUG(DL_IO, ("Ext2ReadFile: %wZ fetch at Off=%I64xh Len=%xh Paging=%xh Nocache=%xh Returned=%xh Status=%xh\n",
- &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache, ReturnedLength, Status));
- return Status;
-
-}
-
-NTSTATUS
-Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PFILE_OBJECT FileObject;
- PIRP Irp;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- FileObject = IrpContext->FileObject;
- Irp = IrpContext->Irp;
-
- CcMdlReadComplete(FileObject, Irp->MdlAddress);
- Irp->MdlAddress = NULL;
- Status = STATUS_SUCCESS;
-
- } _SEH2_FINALLY {
-
- if (!IrpContext->ExceptionInProgress) {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } _SEH2_END;
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status;
- PEXT2_VCB Vcb;
- PEXT2_FCBVCB FcbOrVcb;
- PDEVICE_OBJECT DeviceObject;
- PFILE_OBJECT FileObject;
- BOOLEAN bCompleteRequest;
-
- ASSERT(IrpContext);
-
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- _SEH2_TRY {
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
-
- Status = Ext2ReadComplete(IrpContext);
- bCompleteRequest = FALSE;
-
- } else {
-
- DeviceObject = IrpContext->DeviceObject;
-
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- bCompleteRequest = TRUE;
- _SEH2_LEAVE;
- }
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- if (Vcb->Identifier.Type != EXT2VCB ||
- Vcb->Identifier.Size != sizeof(EXT2_VCB) ) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- bCompleteRequest = TRUE;
-
- _SEH2_LEAVE;
- }
-
- FileObject = IrpContext->FileObject;
-
- if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
- Vcb->LockFile != FileObject ) {
- Status = STATUS_ACCESS_DENIED;
- _SEH2_LEAVE;
- }
-
- FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
-
- if (FcbOrVcb->Identifier.Type == EXT2VCB) {
-
- Status = Ext2ReadVolume(IrpContext);
- bCompleteRequest = FALSE;
-
- } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
-
- if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
- Status = STATUS_TOO_LATE;
- bCompleteRequest = TRUE;
- _SEH2_LEAVE;
- }
-
- Status = Ext2ReadFile(IrpContext);
- bCompleteRequest = FALSE;
- } else {
- DEBUG(DL_ERR, ( "Ext2Read: Inavlid FileObject (Vcb or Fcb corrupted)\n"));
- DbgBreak();
-
- Status = STATUS_INVALID_PARAMETER;
- bCompleteRequest = TRUE;
- }
- }
-
- } _SEH2_FINALLY {
- if (bCompleteRequest) {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } _SEH2_END;
-
- return Status;
-}
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: shutdown.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, Ext2ShutDown)
-#endif
-
-NTSTATUS
-Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status;
-
- PIRP Irp;
-
- PEXT2_VCB Vcb;
- PLIST_ENTRY ListEntry;
-
- BOOLEAN GlobalResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- Status = STATUS_SUCCESS;
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- Irp = IrpContext->Irp;
-
- if (!ExAcquireResourceExclusiveLite(
- &Ext2Global->Resource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- GlobalResourceAcquired = TRUE;
-
- for (ListEntry = Ext2Global->VcbList.Flink;
- ListEntry != &(Ext2Global->VcbList);
- ListEntry = ListEntry->Flink ) {
-
- Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
-
- if (ExAcquireResourceExclusiveLite(
- &Vcb->MainResource,
- TRUE )) {
-
- if (IsMounted(Vcb)) {
-
- /* update mount count */
- Vcb->SuperBlock->s_mnt_count++;
- if (Vcb->SuperBlock->s_mnt_count >
- Vcb->SuperBlock->s_max_mnt_count ) {
- Vcb->SuperBlock->s_mnt_count =
- Vcb->SuperBlock->s_max_mnt_count;
- }
- Ext2SaveSuper(IrpContext, Vcb);
-
- /* flush dirty cache for all files */
- Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- }
-
- /* flush volume stream's cache to disk */
- Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);
-
- if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
- DbgBreak();
- }
-
- /* send shutdown request to underlying disk */
- Ext2DiskShutDown(Vcb);
- }
-
- ExReleaseResourceLite(&Vcb->MainResource);
- }
- }
-
- /*
- IoUnregisterFileSystem(Ext2Global->DiskdevObject);
- IoUnregisterFileSystem(Ext2Global->CdromdevObject);
- */
-
- } _SEH2_FINALLY {
-
- if (GlobalResourceAcquired) {
- ExReleaseResourceLite(&Ext2Global->Resource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
- if (Status == STATUS_PENDING) {
- Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
\ No newline at end of file
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: volinfo.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-/* DEFINITIONS *************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
-#pragma alloc_text(PAGE, Ext2SetVolumeInformation)
-#endif
-
-
-NTSTATUS
-Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PEXT2_VCB Vcb;
- PIRP Irp;
- PIO_STACK_LOCATION IoStackLocation;
- FS_INFORMATION_CLASS FsInformationClass;
- ULONG Length;
- PVOID Buffer;
- BOOLEAN VcbResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext != NULL);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
-
- //
- // This request is not allowed on the main device object
- //
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- if (!IsMounted(Vcb)) {
- Status = STATUS_VOLUME_DISMOUNTED;
- _SEH2_LEAVE;
- }
-
- if (!ExAcquireResourceSharedLite(
- &Vcb->MainResource,
- IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
- )) {
-
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- VcbResourceAcquired = TRUE;
-
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
- FsInformationClass =
- IoStackLocation->Parameters.QueryVolume.FsInformationClass;
-
- Length = IoStackLocation->Parameters.QueryVolume.Length;
- Buffer = Irp->AssociatedIrp.SystemBuffer;
-
- RtlZeroMemory(Buffer, Length);
-
- switch (FsInformationClass) {
-
- case FileFsVolumeInformation:
- {
- PFILE_FS_VOLUME_INFORMATION FsVolInfo;
- ULONG VolumeLabelLength;
- ULONG RequiredLength;
-
- if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer;
- FsVolInfo->VolumeCreationTime.QuadPart = 0;
- FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
- VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
- FsVolInfo->VolumeLabelLength = VolumeLabelLength;
- /* We don't support ObjectId */
- FsVolInfo->SupportsObjects = FALSE;
-
- RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
- + VolumeLabelLength - sizeof(WCHAR);
-
- if (Length < RequiredLength) {
- Irp->IoStatus.Information =
- sizeof(FILE_FS_VOLUME_INFORMATION);
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
-
- Irp->IoStatus.Information = RequiredLength;
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileFsSizeInformation:
- {
- PFILE_FS_SIZE_INFORMATION FsSizeInfo;
-
- if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer;
- FsSizeInfo->TotalAllocationUnits.QuadPart =
- ext3_blocks_count(SUPER_BLOCK);
- FsSizeInfo->AvailableAllocationUnits.QuadPart =
- ext3_free_blocks_count(SUPER_BLOCK);
- FsSizeInfo->SectorsPerAllocationUnit =
- Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
- FsSizeInfo->BytesPerSector =
- Vcb->DiskGeometry.BytesPerSector;
-
- Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileFsDeviceInformation:
- {
- PFILE_FS_DEVICE_INFORMATION FsDevInfo;
-
- if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer;
- FsDevInfo->DeviceType =
- Vcb->TargetDeviceObject->DeviceType;
-
- if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) {
- DbgBreak();
- }
-
- FsDevInfo->Characteristics =
- Vcb->TargetDeviceObject->Characteristics;
-
- if (IsVcbReadOnly(Vcb)) {
- SetFlag( FsDevInfo->Characteristics,
- FILE_READ_ONLY_DEVICE );
- }
-
- Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
- case FileFsAttributeInformation:
- {
- PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
- ULONG RequiredLength;
-
- if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- FsAttrInfo =
- (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
- FsAttrInfo->FileSystemAttributes =
- FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
- if (IsVcbReadOnly(Vcb)) {
- FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
- }
- FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN;
- FsAttrInfo->FileSystemNameLength = 8;
-
- RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
- 8 - sizeof(WCHAR);
-
- if (Length < RequiredLength) {
- Irp->IoStatus.Information =
- sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
- RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10);
- } else if (Vcb->IsExt3fs) {
- RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10);
- } else {
- RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10);
- }
-
- Irp->IoStatus.Information = RequiredLength;
- Status = STATUS_SUCCESS;
- }
- break;
-
-#if (_WIN32_WINNT >= 0x0500)
-
- case FileFsFullSizeInformation:
- {
- PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
-
- if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) {
- Status = STATUS_BUFFER_OVERFLOW;
- _SEH2_LEAVE;
- }
-
- PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer;
-
- /*
- typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
- LARGE_INTEGER TotalAllocationUnits;
- LARGE_INTEGER CallerAvailableAllocationUnits;
- LARGE_INTEGER ActualAvailableAllocationUnits;
- ULONG SectorsPerAllocationUnit;
- ULONG BytesPerSector;
- } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
- */
-
- {
- PFFFSI->TotalAllocationUnits.QuadPart =
- ext3_blocks_count(SUPER_BLOCK);
-
- PFFFSI->CallerAvailableAllocationUnits.QuadPart =
- ext3_free_blocks_count(SUPER_BLOCK);
-
- /* - Vcb->SuperBlock->s_r_blocks_count; */
- PFFFSI->ActualAvailableAllocationUnits.QuadPart =
- ext3_free_blocks_count(SUPER_BLOCK);
- }
-
- PFFFSI->SectorsPerAllocationUnit =
- Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
-
- PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
-
- Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
- Status = STATUS_SUCCESS;
- }
- break;
-
-#endif // (_WIN32_WINNT >= 0x0500)
-
- default:
- Status = STATUS_INVALID_INFO_CLASS;
- break;
- }
-
- } _SEH2_FINALLY {
-
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
- if (Status == STATUS_PENDING) {
- Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
-
-NTSTATUS
-Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PEXT2_VCB Vcb;
- PIRP Irp;
- PIO_STACK_LOCATION IoStackLocation;
- FS_INFORMATION_CLASS FsInformationClass;
- BOOLEAN VcbResourceAcquired = FALSE;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext != NULL);
-
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
-
- //
- // This request is not allowed on the main device object
- //
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
- ASSERT(IsMounted(Vcb));
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
-
- if (!ExAcquireResourceExclusiveLite(
- &Vcb->MainResource, TRUE)) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- VcbResourceAcquired = TRUE;
-
- Ext2VerifyVcb(IrpContext, Vcb);
-
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
-
- //Notes: SetVolume is not defined in ntddk.h of win2k ddk,
- // But it's same to QueryVolume ....
- FsInformationClass =
- IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
-
- switch (FsInformationClass) {
-
- case FileFsLabelInformation:
- {
- PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
- ULONG VolLabelLen;
- UNICODE_STRING LabelName ;
-
- OEM_STRING OemName;
-
- VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
- VolLabelLen = VolLabelInfo->VolumeLabelLength;
-
- if (VolLabelLen > (16 * sizeof(WCHAR))) {
- Status = STATUS_INVALID_VOLUME_LABEL;
- _SEH2_LEAVE;
- }
-
- RtlCopyMemory( Vcb->Vpb->VolumeLabel,
- VolLabelInfo->VolumeLabel,
- VolLabelLen );
-
- RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16);
- LabelName.Buffer = VolLabelInfo->VolumeLabel;
- LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
- LabelName.Length = (USHORT)VolLabelLen;
-
- OemName.Buffer = SUPER_BLOCK->s_volume_name;
- OemName.Length = 0;
- OemName.MaximumLength = 16;
-
- Ext2UnicodeToOEM(Vcb, &OemName, &LabelName);
- Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen;
-
- if (Ext2SaveSuper(IrpContext, Vcb)) {
- Status = STATUS_SUCCESS;
- }
-
- Irp->IoStatus.Information = 0;
- }
- break;
-
- default:
- Status = STATUS_INVALID_INFO_CLASS;
- }
-
- } _SEH2_FINALLY {
-
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
- if (Status == STATUS_PENDING) {
- Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
- } _SEH2_END;
-
- return Status;
-}
\ No newline at end of file
+++ /dev/null
-/*
- * COPYRIGHT: See COPYRIGHT.TXT
- * PROJECT: Ext2 File System Driver for WinNT/2K/XP
- * FILE: write.c
- * PROGRAMMER: Matt Wu <mattwu@163.com>
- * HOMEPAGE: http://www.ext2fsd.com
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "ext2fs.h"
-
-/* GLOBALS ***************************************************************/
-
-extern PEXT2_GLOBAL Ext2Global;
-
-#define DL_FLP DL_DBG
-
-/* DEFINITIONS *************************************************************/
-
-#define EXT2_FLPFLUSH_MAGIC 'FF2E'
-
-typedef struct _EXT2_FLPFLUSH_CONTEXT {
-
- PEXT2_VCB Vcb;
- PEXT2_FCB Fcb;
- PFILE_OBJECT FileObject;
-
- KDPC Dpc;
- KTIMER Timer;
- WORK_QUEUE_ITEM Item;
-
-} EXT2_FLPFLUSH_CONTEXT, *PEXT2_FLPFLUSH_CONTEXT;
-
-VOID NTAPI
-Ext2FloppyFlush(IN PVOID Parameter);
-
-VOID NTAPI
-Ext2FloppyFlushDpc (
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2);
-
-
-NTSTATUS
-Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext);
-
-NTSTATUS
-Ext2WriteFile (IN PEXT2_IRP_CONTEXT IrpContext);
-
-NTSTATUS
-Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext);
-
-VOID
-Ext2DeferWrite(IN PEXT2_IRP_CONTEXT, PIRP Irp);
-
-
-/* FUNCTIONS *************************************************************/
-
-VOID NTAPI
-Ext2FloppyFlush(IN PVOID Parameter)
-{
- PEXT2_FLPFLUSH_CONTEXT Context;
- PFILE_OBJECT FileObject;
- PEXT2_FCB Fcb;
- PEXT2_VCB Vcb;
-
- Context = (PEXT2_FLPFLUSH_CONTEXT) Parameter;
- FileObject = Context->FileObject;
- Fcb = Context->Fcb;
- Vcb = Context->Vcb;
-
- DEBUG(DL_FLP, ("Ext2FloppyFlushing ...\n"));
-
- IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
-
- if (FileObject) {
- ASSERT(Fcb == (PEXT2_FCB)FileObject->FsContext);
-
- ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Fcb->PagingIoResource);
-
- CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);
-
- ObDereferenceObject(FileObject);
- }
-
- if (Vcb) {
- ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Vcb->PagingIoResource);
-
- CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
- }
-
- IoSetTopLevelIrp(NULL);
- Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC);
-}
-
-VOID NTAPI
-Ext2FloppyFlushDpc (
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2
-)
-{
- PEXT2_FLPFLUSH_CONTEXT Context;
-
- Context = (PEXT2_FLPFLUSH_CONTEXT) DeferredContext;
-
- DEBUG(DL_FLP, ("Ext2FloppyFlushDpc is to be started...\n"));
-
- ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
-}
-
-VOID
-Ext2StartFloppyFlushDpc (
- PEXT2_VCB Vcb,
- PEXT2_FCB Fcb,
- PFILE_OBJECT FileObject )
-{
- LARGE_INTEGER OneSecond;
- PEXT2_FLPFLUSH_CONTEXT Context;
-
- ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK));
-
- Context = Ext2AllocatePool(
- NonPagedPool,
- sizeof(EXT2_FLPFLUSH_CONTEXT),
- EXT2_FLPFLUSH_MAGIC
- );
-
- if (!Context) {
- DEBUG(DL_ERR, ( "Ex2StartFloppy...: failed to allocate Context\n"));
- DbgBreak();
- return;
- }
-
- KeInitializeTimer(&Context->Timer);
-
- KeInitializeDpc( &Context->Dpc,
- Ext2FloppyFlushDpc,
- Context );
-
- ExInitializeWorkItem( &Context->Item,
- Ext2FloppyFlush,
- Context );
-
- Context->Vcb = Vcb;
- Context->Fcb = Fcb;
- Context->FileObject = FileObject;
-
- if (FileObject) {
- ObReferenceObject(FileObject);
- }
-
- OneSecond.QuadPart = (LONGLONG)-1*1000*1000*10;
- KeSetTimer( &Context->Timer,
- OneSecond,
- &Context->Dpc );
-}
-
-BOOLEAN
-Ext2ZeroData (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER Start,
- IN PLARGE_INTEGER End
- )
-{
- PEXT2_FCB Fcb;
- PBCB Bcb;
- PVOID Ptr;
- ULONG Size;
-#ifndef __REACTOS__
- BOOLEAN rc = TRUE;
-#endif
- ASSERT (End && Start && End->QuadPart > Start->QuadPart);
- Fcb = (PEXT2_FCB) FileObject->FsContext;
-
- /* skip data zero if we've already tracked unwritten part */
- if (0 == ( End->LowPart & (BLOCK_SIZE -1)) &&
- 0 == (Start->LowPart & (BLOCK_SIZE -1))) {
-
- if (INODE_HAS_EXTENT(Fcb->Inode)) {
- return TRUE;
- } else {
-#if !EXT2_PRE_ALLOCATION_SUPPORT
- return TRUE;
-#endif
- }
- }
-
- /* clear data in range [Start, End) */
- return CcZeroData(FileObject, Start, End, Ext2CanIWait());
-}
-
-VOID
-Ext2DeferWrite(IN PEXT2_IRP_CONTEXT IrpContext, PIRP Irp)
-{
- ASSERT(IrpContext->Irp == Irp);
-
- Ext2QueueRequest(IrpContext);
-}
-
-
-NTSTATUS
-Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
- PEXT2_VCB Vcb;
- PEXT2_CCB Ccb;
- PEXT2_FCBVCB FcbOrVcb;
- PFILE_OBJECT FileObject;
-
- PDEVICE_OBJECT DeviceObject;
-
- PIRP Irp = NULL;
- PIO_STACK_LOCATION IoStackLocation;
-
- ULONG Length;
- LARGE_INTEGER ByteOffset;
-
- BOOLEAN PagingIo = FALSE;
- BOOLEAN Nocache = FALSE;
- BOOLEAN SynchronousIo = FALSE;
- BOOLEAN MainResourceAcquired = FALSE;
-
- BOOLEAN bDeferred = FALSE;
-
- PUCHAR Buffer = NULL;
- PEXT2_EXTENT Chain = NULL;
- EXT2_EXTENT BlockArray;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- FileObject = IrpContext->FileObject;
- FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
- ASSERT(FcbOrVcb);
-
- if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
-
- Length = IoStackLocation->Parameters.Write.Length;
- ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
-
- PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
- Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
- SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
-
- if (PagingIo) {
- ASSERT(Nocache);
- }
-
- DEBUG(DL_INF, ("Ext2WriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
- ByteOffset.QuadPart, Length, PagingIo, Nocache));
-
- if (Length == 0) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if (Nocache &&
- (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
- Length & (SECTOR_SIZE - 1))) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
- ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- if (ByteOffset.QuadPart >=
- Vcb->PartitionInformation.PartitionLength.QuadPart ) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_END_OF_FILE;
- _SEH2_LEAVE;
- }
-
- if (!Nocache) {
-
- BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
- BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
- BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
-
- if ( !CcCanIWrite(
- FileObject,
- Length,
- (bWait && bQueue),
- bAgain ) ) {
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoReadAccess);
- if (NT_SUCCESS(Status)) {
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
- CcDeferWrite( FileObject,
- (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
- IrpContext,
- Irp,
- Length,
- bAgain );
-
- bDeferred = TRUE;
- Status = STATUS_PENDING;
-
- _SEH2_LEAVE;
- }
- }
- }
-
- /*
- * User direct volume access
- */
-
- if (Ccb != NULL && !PagingIo) {
-
- if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {
-
- if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
- Status = Ext2PurgeVolume( Vcb, TRUE);
- }
-
- SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
- }
-
- if (!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) {
- if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
- Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
- }
- }
-
- } else if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) {
-
- ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
- MainResourceAcquired = TRUE;
-
- ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Vcb->PagingIoResource);
-
- CcFlushCache( &(Vcb->SectionObject),
- &ByteOffset,
- Length,
- &(Irp->IoStatus));
-
- if (!NT_SUCCESS(Irp->IoStatus.Status)) {
- Status = Irp->IoStatus.Status;
- _SEH2_LEAVE;
- }
-
- ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Vcb->PagingIoResource);
-
- CcPurgeCacheSection( &(Vcb->SectionObject),
- (PLARGE_INTEGER)&(ByteOffset),
- Length,
- FALSE );
-
- ExReleaseResourceLite(&Vcb->MainResource);
- MainResourceAcquired = FALSE;
- }
-
- if ( (ByteOffset.QuadPart + Length) > Vcb->Header.FileSize.QuadPart) {
- Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
- }
-
- if (!Nocache) {
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
-
- CcPrepareMdlWrite (
- Vcb->Volume,
- &ByteOffset,
- Length,
- &Irp->MdlAddress,
- &Irp->IoStatus );
-
- Status = Irp->IoStatus.Status;
-
- } else {
-
- Buffer = Ext2GetUserBuffer(Irp);
- if (Buffer == NULL) {
- DbgBreak();
-
- Status = STATUS_INVALID_USER_BUFFER;
- _SEH2_LEAVE;
- }
-
- if (!CcCopyWrite( Vcb->Volume,
- (PLARGE_INTEGER)(&ByteOffset),
- Length,
- TRUE,
- Buffer )) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- Status = Irp->IoStatus.Status;
- Ext2AddVcbExtent(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
- }
-
- if (NT_SUCCESS(Status)) {
- Irp->IoStatus.Information = Length;
- }
-
- } else if (PagingIo) {
-
- LONGLONG DirtyStart;
- LONGLONG DirtyLba;
- LONGLONG DirtyLength;
- LONGLONG RemainLength;
-
- PEXT2_EXTENT Extent = NULL;
- PEXT2_EXTENT List = NULL;
-
- Length &= ~((ULONG)SECTOR_SIZE - 1);
-
- Status = Ext2LockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- DirtyLba = ByteOffset.QuadPart;
- RemainLength = (LONGLONG) Length;
-
- ASSERT(Length >= SECTOR_SIZE);
-
- while (RemainLength > 0) {
-
- DirtyStart = DirtyLba;
- ASSERT(DirtyStart >= ByteOffset.QuadPart);
- ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
-
- if (Ext2LookupVcbExtent(Vcb, DirtyStart, &DirtyLba, &DirtyLength)) {
-
- if (DirtyLba == -1) {
-
- DirtyLba = DirtyStart + DirtyLength;
- if (ByteOffset.QuadPart + Length > DirtyLba) {
- RemainLength = ByteOffset.QuadPart + Length - DirtyLba;
- ASSERT(DirtyStart >= ByteOffset.QuadPart);
- ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
- } else {
- RemainLength = 0;
- }
- continue;
- }
-
- ASSERT(DirtyLba <= DirtyStart);
- Extent = Ext2AllocateExtent();
-
- if (!Extent) {
- DEBUG(DL_ERR, ( "Ex2WriteVolume: failed to allocate Extent\n"));
- Status = STATUS_INSUFFICIENT_RESOURCES;
- _SEH2_LEAVE;
- }
-
- Extent->Irp = NULL;
- Extent->Lba = DirtyLba;
- Extent->Offset = (ULONG)( DirtyStart + Length -
- RemainLength - DirtyLba );
- ASSERT(Extent->Offset <= Length);
-
- if (DirtyLba + DirtyLength >= DirtyStart + RemainLength) {
- Extent->Length = (ULONG)( DirtyLba +
- RemainLength -
- DirtyStart );
- ASSERT(Extent->Length <= Length);
- RemainLength = 0;
- } else {
- Extent->Length = (ULONG)(DirtyLength + DirtyLba - DirtyStart);
- RemainLength = (DirtyStart + RemainLength) -
- (DirtyLba + DirtyLength);
- ASSERT(RemainLength <= (LONGLONG)Length);
- ASSERT(Extent->Length <= Length);
- }
-
- ASSERT(Extent->Length >= SECTOR_SIZE);
- DirtyLba = DirtyStart + DirtyLength;
-
- if (List) {
- List->Next = Extent;
- List = Extent;
- } else {
- Chain = List = Extent;
- }
-
- } else {
-
- if (RemainLength > SECTOR_SIZE) {
- DirtyLba = DirtyStart + SECTOR_SIZE;
- RemainLength -= SECTOR_SIZE;
- } else {
- RemainLength = 0;
- }
- }
- }
-
- if (Chain) {
- Status = Ext2ReadWriteBlocks(IrpContext,
- Vcb,
- Chain,
- Length );
- Irp = IrpContext->Irp;
-
- if (NT_SUCCESS(Status)) {
- for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
- Ext2RemoveVcbExtent(Vcb, Extent->Lba, Extent->Length);
- }
- }
-
- if (!Irp) {
- _SEH2_LEAVE;
- }
-
- } else {
-
- Irp->IoStatus.Information = Length;
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- } else {
-
- Length &= ~((ULONG)SECTOR_SIZE - 1);
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoWriteAccess );
-
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- BlockArray.Irp = NULL;
- BlockArray.Lba = ByteOffset.QuadPart;
- BlockArray.Offset = 0;
- BlockArray.Length = Length;
- BlockArray.Next = NULL;
-
- Status = Ext2ReadWriteBlocks(IrpContext,
- Vcb,
- &BlockArray,
- Length );
-
- if (NT_SUCCESS(Status)) {
- Irp->IoStatus.Information = Length;
- }
-
- Irp = IrpContext->Irp;
- if (!Irp) {
- _SEH2_LEAVE;
- }
- }
-
- } _SEH2_FINALLY {
-
- if (MainResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- }
-
- if (!IrpContext->ExceptionInProgress) {
-
- if (Irp) {
-
- if (Status == STATUS_PENDING) {
-
- if (!bDeferred) {
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoReadAccess );
-
- if (NT_SUCCESS(Status)) {
- Status = Ext2QueueRequest(IrpContext);
- } else {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- }
-
- } else {
-
- if (NT_SUCCESS(Status)) {
-
- if (SynchronousIo && !PagingIo) {
- FileObject->CurrentByteOffset.QuadPart =
- ByteOffset.QuadPart + Irp->IoStatus.Information;
- }
-
- if (!PagingIo) {
- SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
- }
- }
-
- Ext2CompleteIrpContext(IrpContext, Status);
- }
-
- } else {
-
- Ext2FreeIrpContext(IrpContext);
- }
- }
-
- if (Chain) {
- Ext2DestroyExtentChain(Chain);
- }
- } _SEH2_END;
-
- return Status;
-}
-
-NTSTATUS
-Ext2WriteInode (
- IN PEXT2_IRP_CONTEXT IrpContext,
- IN PEXT2_VCB Vcb,
- IN PEXT2_MCB Mcb,
- IN ULONGLONG Offset,
- IN PVOID Buffer,
- IN ULONG Size,
- IN BOOLEAN bDirectIo,
- OUT PULONG BytesWritten
-)
-{
- PEXT2_EXTENT Chain = NULL;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
- _SEH2_TRY {
-
- if (BytesWritten) {
- *BytesWritten = 0;
- }
-
- Status = Ext2BuildExtents (
- IrpContext,
- Vcb,
- Mcb,
- Offset,
- Size,
- IsMcbDirectory(Mcb) ? FALSE : TRUE,
- &Chain
- );
-
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- if (Chain == NULL) {
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if (bDirectIo) {
-
- ASSERT(IrpContext != NULL);
-
- //
- // We assume the offset is aligned.
- //
-
- Status = Ext2ReadWriteBlocks(
- IrpContext,
- Vcb,
- Chain,
- Size
- );
-
- } else {
-
- PEXT2_EXTENT Extent;
- for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
-
- if ( !Ext2SaveBuffer(
- IrpContext,
- Vcb,
- Extent->Lba,
- Extent->Length,
- (PVOID)((PUCHAR)Buffer + Extent->Offset)
- )) {
- _SEH2_LEAVE;
- }
- }
-
- if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
-
- DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n"));
- Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
- }
-
- Status = STATUS_SUCCESS;
- }
-
- } _SEH2_FINALLY {
-
- if (Chain) {
- Ext2DestroyExtentChain(Chain);
- }
-
- if (NT_SUCCESS(Status) && BytesWritten) {
- *BytesWritten = Size;
- }
- } _SEH2_END;
-
- return Status;
-}
-
-NTSTATUS
-Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
-{
- PEXT2_VCB Vcb;
- PEXT2_FCB Fcb;
- PEXT2_CCB Ccb;
- PFILE_OBJECT FileObject;
-
- PDEVICE_OBJECT DeviceObject;
-
- PIRP Irp;
- PIO_STACK_LOCATION IoStackLocation;
- PUCHAR Buffer;
-
- LARGE_INTEGER ByteOffset;
- ULONG ReturnedLength = 0;
- ULONG Length;
-
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
- BOOLEAN OpPostIrp = FALSE;
- BOOLEAN PagingIo = FALSE;
- BOOLEAN Nocache = FALSE;
- BOOLEAN SynchronousIo = FALSE;
-
- BOOLEAN RecursiveWriteThrough = FALSE;
- BOOLEAN MainResourceAcquired = FALSE;
- BOOLEAN PagingIoResourceAcquired = FALSE;
-
- BOOLEAN bDeferred = FALSE;
-#ifndef __REACTOS__
- BOOLEAN UpdateFileValidSize = FALSE;
-#endif
- BOOLEAN FileSizesChanged = FALSE;
- BOOLEAN rc;
-
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- DeviceObject = IrpContext->DeviceObject;
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
- ASSERT(Vcb != NULL);
- ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
- (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
-
- FileObject = IrpContext->FileObject;
- Fcb = (PEXT2_FCB) FileObject->FsContext;
- Ccb = (PEXT2_CCB) FileObject->FsContext2;
- ASSERT(Fcb);
- ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
- (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
-
- Irp = IrpContext->Irp;
- IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
-
- Length = IoStackLocation->Parameters.Write.Length;
- ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
-
- PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
- Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
- SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
-
- if (PagingIo) {
- ASSERT(Nocache);
- }
-
- DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n",
- &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
-
- if (IsSpecialFile(Fcb)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- if (IsFileDeleted(Fcb->Mcb) ||
- (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) {
- Status = STATUS_FILE_DELETED;
- _SEH2_LEAVE;
- }
-
- if (Length == 0) {
- Irp->IoStatus.Information = 0;
- Status = STATUS_SUCCESS;
- _SEH2_LEAVE;
- }
-
- if (Nocache && ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
- (Length & (SECTOR_SIZE - 1))) ) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
- ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
-
- if (!Nocache) {
-
- BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
- BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
- BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
-
- if ( !CcCanIWrite(
- FileObject,
- Length,
- (bWait && bQueue),
- bAgain ) ) {
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoReadAccess);
-
- if (NT_SUCCESS(Status)) {
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
- CcDeferWrite( FileObject,
- (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
- IrpContext,
- Irp,
- Length,
- bAgain );
- bDeferred = TRUE;
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- }
- }
-
- if (IsWritingToEof(ByteOffset)) {
- ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
- }
-
- if (IsDirectory(Fcb) && !PagingIo) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
-
- if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) {
-
- PIRP TopIrp;
-
- TopIrp = IoGetTopLevelIrp();
-
- if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG &&
- NodeType(TopIrp) == IO_TYPE_IRP) {
-
- PIO_STACK_LOCATION IrpStack;
-
- IrpStack = IoGetCurrentIrpStackLocation(TopIrp);
-
- if ((IrpStack->MajorFunction == IRP_MJ_WRITE) &&
- (IrpStack->FileObject->FsContext == FileObject->FsContext) &&
- !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) {
-
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
- RecursiveWriteThrough = TRUE;
- }
- }
- }
-
- if (PagingIo) {
-
- if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- PagingIoResourceAcquired = TRUE;
-
- if ( (ByteOffset.QuadPart + Length) > Fcb->Header.AllocationSize.QuadPart) {
-
- if ( ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
-
- Status = STATUS_END_OF_FILE;
- Irp->IoStatus.Information = 0;
- _SEH2_LEAVE;
-
- } else {
-
- Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
- }
- }
-
- } else {
-
- if (IsDirectory(Fcb)) {
- _SEH2_LEAVE;
- }
-
- if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- MainResourceAcquired = TRUE;
-
- //
- // Do flushing for such cases
- //
- if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL) {
-
- ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Fcb->PagingIoResource);
-
- CcFlushCache( &(Fcb->SectionObject),
- &ByteOffset,
- CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
- &(Irp->IoStatus));
- ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
-
- if (!NT_SUCCESS(Irp->IoStatus.Status)) {
- Status = Irp->IoStatus.Status;
- _SEH2_LEAVE;
- }
-
- ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
- ExReleaseResourceLite(&Fcb->PagingIoResource);
-
- CcPurgeCacheSection( &(Fcb->SectionObject),
- &(ByteOffset),
- CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
- FALSE );
- }
-
- if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) {
- Status = STATUS_FILE_LOCK_CONFLICT;
- _SEH2_LEAVE;
- }
-
- if (Ccb != NULL) {
- Status = FsRtlCheckOplock( &Fcb->Oplock,
- Irp,
- IrpContext,
- Ext2OplockComplete,
- Ext2LockIrp );
-
- if (Status != STATUS_SUCCESS) {
- OpPostIrp = TRUE;
- _SEH2_LEAVE;
- }
-
- //
- // Set the flag indicating if Fast I/O is possible
- //
-
- Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
- }
-
- //
- // Extend the inode size when the i/o is beyond the file end ?
- //
-
- if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {
-
- LARGE_INTEGER AllocationSize, Last;
-
- if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) {
- Status = STATUS_PENDING;
- _SEH2_LEAVE;
- }
- PagingIoResourceAcquired = TRUE;
-
- /* let this irp wait, since it has to be synchronous */
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
-
- Last.QuadPart = Fcb->Header.AllocationSize.QuadPart;
- AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
- AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
- (ULONGLONG)AllocationSize.QuadPart,
- (ULONGLONG)BLOCK_SIZE);
-
- /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks
- for indirect files, otherwise we might get gabage data in holes */
- IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION;
- Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize);
- IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
- if (AllocationSize.QuadPart > Last.QuadPart) {
- Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
- SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE);
- }
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- PagingIoResourceAcquired = FALSE;
-
- if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
- if (NT_SUCCESS(Status)) {
- DbgBreak();
- Status = STATUS_UNSUCCESSFUL;
- }
- _SEH2_LEAVE;
- }
-
- if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) {
- Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
- }
-
- Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length;
- Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
-
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
-
- FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
- FileSizesChanged = TRUE;
-
- if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
- !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
- SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
- Ext2SaveSuper(IrpContext, Vcb);
- }
-
- DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n",
- &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
- Fcb->Header.AllocationSize.QuadPart));
- }
- }
-
- ReturnedLength = Length;
-
- if (!Nocache) {
-
- if (FileObject->PrivateCacheMap == NULL) {
- CcInitializeCacheMap(
- FileObject,
- (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
- FALSE,
- &Ext2Global->CacheManagerCallbacks,
- Fcb );
-
- CcSetReadAheadGranularity(
- FileObject,
- READ_AHEAD_GRANULARITY );
- }
-
- if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
-
- CcPrepareMdlWrite(
- FileObject,
- &ByteOffset,
- Length,
- &Irp->MdlAddress,
- &Irp->IoStatus );
-
- Status = Irp->IoStatus.Status;
-
- } else {
-
- Buffer = Ext2GetUserBuffer(Irp);
- if (Buffer == NULL) {
- DbgBreak();
- Status = STATUS_INVALID_USER_BUFFER;
- _SEH2_LEAVE;
- }
-
- if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
-
- /* let this irp wait, since it has to be synchronous */
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
-
- rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
- &Fcb->Header.ValidDataLength, &ByteOffset);
- if (!rc) {
- Status = STATUS_PENDING;
- DbgBreak();
- _SEH2_LEAVE;
- }
- }
-
- if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) {
- if (Ext2CanIWait() ||
- !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) {
- Status = STATUS_PENDING;
- DbgBreak();
- _SEH2_LEAVE;
- }
- }
-
- if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
-
- if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
- Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
- } else {
- if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
- Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
- }
-
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- FileSizesChanged = TRUE;
- }
-
- Status = STATUS_SUCCESS;
- }
-
- if (NT_SUCCESS(Status)) {
- Irp->IoStatus.Information = Length;
- if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
- DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n"));
- Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject);
- }
- }
-
- } else {
-
- if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
- if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
- if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
-
- /* let this irp wait, since it has to be synchronous */
- SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
- rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
- &Fcb->Header.ValidDataLength,
- &ByteOffset);
- if (!rc) {
- Status = STATUS_PENDING;
- DbgBreak();
- _SEH2_LEAVE;
- }
- }
- }
- }
-
- Status = Ext2LockUserBuffer(
- IrpContext->Irp,
- Length,
- IoReadAccess );
-
- if (!NT_SUCCESS(Status)) {
- _SEH2_LEAVE;
- }
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = ReturnedLength;
-
- Status = Ext2WriteInode(
- IrpContext,
- Vcb,
- Fcb->Mcb,
- (ULONGLONG)(ByteOffset.QuadPart),
- NULL,
- ReturnedLength,
- TRUE,
- &Length
- );
-
- Irp = IrpContext->Irp;
-
- if (NT_SUCCESS(Status) && !PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
-
- if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
-
- FileSizesChanged = TRUE;
-
- if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
- Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
- } else {
- if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
- Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
- }
-
- if (CcIsFileCached(FileObject)) {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
- }
-
- DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n",
- &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
- Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length));
- }
- }
- }
-
- if (FileSizesChanged) {
- FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
- Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb,
- FILE_NOTIFY_CHANGE_SIZE,
- FILE_ACTION_MODIFIED );
- }
-
- } _SEH2_FINALLY {
-
- /*
- * in case we got excpetions, we need revert MajorFunction
- * back to IRP_MJ_WRITE. The reason we do this, if to tell
- * Ext2ExpandFile to allocate unwritten extent or don't add
- * new blocks for indirect files.
- */
- if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION)
- IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
-
- if (Irp) {
- if (PagingIoResourceAcquired) {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- }
-
- if (MainResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- }
- }
-
- if (!OpPostIrp && !IrpContext->ExceptionInProgress) {
-
- if (Irp) {
-
- if (Status == STATUS_PENDING ||
- Status == STATUS_CANT_WAIT ) {
-
- if (!bDeferred) {
- Status = Ext2QueueRequest(IrpContext);
- }
-
- } else {
-
- if (NT_SUCCESS(Status) && !PagingIo) {
-
- if (SynchronousIo) {
- FileObject->CurrentByteOffset.QuadPart =
- ByteOffset.QuadPart + Irp->IoStatus.Information;
- }
-
- SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
- SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
- }
-
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } else {
- Ext2FreeIrpContext(IrpContext);
- }
- }
- } _SEH2_END;
-
- DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d "
- "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n",
- &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength,
- Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart,
- Fcb->Inode->i_size, Status));
-
- return Status;
-}
-
-NTSTATUS
-Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PFILE_OBJECT FileObject;
- PIRP Irp;
- PIO_STACK_LOCATION IrpSp;
-
- _SEH2_TRY {
-
- ASSERT(IrpContext);
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- FileObject = IrpContext->FileObject;
-
- Irp = IrpContext->Irp;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
- Irp->MdlAddress = NULL;
- Status = STATUS_SUCCESS;
-
- } _SEH2_FINALLY {
-
- if (!IrpContext->ExceptionInProgress) {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } _SEH2_END;
-
- return Status;
-}
-
-
-NTSTATUS
-Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext)
-{
- NTSTATUS Status;
- PEXT2_FCBVCB FcbOrVcb;
- PDEVICE_OBJECT DeviceObject;
- PFILE_OBJECT FileObject;
- PEXT2_VCB Vcb;
- BOOLEAN bCompleteRequest = TRUE;
-
- ASSERT(IrpContext);
-
- ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
- (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
-
- _SEH2_TRY {
-
- if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
-
- Status = Ext2WriteComplete(IrpContext);
- bCompleteRequest = FALSE;
-
- } else {
-
- DeviceObject = IrpContext->DeviceObject;
- if (IsExt2FsDevice(DeviceObject)) {
- Status = STATUS_INVALID_DEVICE_REQUEST;
- _SEH2_LEAVE;
- }
- FileObject = IrpContext->FileObject;
-
- Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
-
- if (Vcb->Identifier.Type != EXT2VCB ||
- Vcb->Identifier.Size != sizeof(EXT2_VCB) ) {
- Status = STATUS_INVALID_PARAMETER;
- _SEH2_LEAVE;
- }
-
- if (IsVcbReadOnly(Vcb)) {
- Status = STATUS_MEDIA_WRITE_PROTECTED;
- _SEH2_LEAVE;
- }
-
- if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
- Vcb->LockFile != FileObject ) {
- Status = STATUS_ACCESS_DENIED;
- _SEH2_LEAVE;
- }
-
- FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
-
- if (FcbOrVcb->Identifier.Type == EXT2VCB) {
-
- Status = Ext2WriteVolume(IrpContext);
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- }
- bCompleteRequest = FALSE;
-
- } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
-
- if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
- Status = STATUS_TOO_LATE;
- _SEH2_LEAVE;
- }
-
- Status = Ext2WriteFile(IrpContext);
- if (!NT_SUCCESS(Status)) {
- DbgBreak();
- }
-
- bCompleteRequest = FALSE;
- } else {
- Status = STATUS_INVALID_PARAMETER;
- }
- }
-
- } _SEH2_FINALLY {
-
- if (bCompleteRequest) {
- Ext2CompleteIrpContext(IrpContext, Status);
- }
- } _SEH2_END;
-
- return Status;
-}