From: Pierre Schweitzer Date: Sat, 17 Oct 2015 22:35:20 +0000 (+0000) Subject: [EXT2] X-Git-Tag: ReactOS-0.4.0~479 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=b9b583fd2234d81eb50f9edd6598b9e0b44fc47a [EXT2] [EXT2_NEW] Get rid of old ext2 driver and use new one svn path=/trunk/; revision=69576 --- diff --git a/reactos/drivers/filesystems/CMakeLists.txt b/reactos/drivers/filesystems/CMakeLists.txt index 1df81cc4582..4a89a8e90d1 100644 --- a/reactos/drivers/filesystems/CMakeLists.txt +++ b/reactos/drivers/filesystems/CMakeLists.txt @@ -1,7 +1,6 @@ add_subdirectory(cdfs) add_subdirectory(ext2) -#add_subdirectory(ext2_new) add_subdirectory(fastfat) #add_subdirectory(fastfat_new) add_subdirectory(fs_rec) @@ -10,3 +9,4 @@ add_subdirectory(mup) add_subdirectory(npfs) add_subdirectory(ntfs) add_subdirectory(udfs) +add_subdirectory(registryfs) diff --git a/reactos/drivers/filesystems/ext2/CMakeLists.txt b/reactos/drivers/filesystems/ext2/CMakeLists.txt index 8e1f9529efe..f02de3cfa03 100644 --- a/reactos/drivers/filesystems/ext2/CMakeLists.txt +++ b/reactos/drivers/filesystems/ext2/CMakeLists.txt @@ -1,35 +1,105 @@ -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) diff --git a/reactos/drivers/filesystems/ext2_new/ext2fs_reg.inf b/reactos/drivers/filesystems/ext2/ext2fs_reg.inf similarity index 100% rename from reactos/drivers/filesystems/ext2_new/ext2fs_reg.inf rename to reactos/drivers/filesystems/ext2/ext2fs_reg.inf diff --git a/reactos/drivers/filesystems/ext2_new/inc/asm/page.h b/reactos/drivers/filesystems/ext2/inc/asm/page.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/asm/page.h rename to reactos/drivers/filesystems/ext2/inc/asm/page.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/asm/semaphore.h b/reactos/drivers/filesystems/ext2/inc/asm/semaphore.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/asm/semaphore.h rename to reactos/drivers/filesystems/ext2/inc/asm/semaphore.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/asm/uaccess.h b/reactos/drivers/filesystems/ext2/inc/asm/uaccess.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/asm/uaccess.h rename to reactos/drivers/filesystems/ext2/inc/asm/uaccess.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/common.h b/reactos/drivers/filesystems/ext2/inc/common.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/common.h rename to reactos/drivers/filesystems/ext2/inc/common.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/ext2fs.h b/reactos/drivers/filesystems/ext2/inc/ext2fs.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/ext2fs.h rename to reactos/drivers/filesystems/ext2/inc/ext2fs.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/atomic.h b/reactos/drivers/filesystems/ext2/inc/linux/atomic.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/atomic.h rename to reactos/drivers/filesystems/ext2/inc/linux/atomic.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/bit_spinlock.h b/reactos/drivers/filesystems/ext2/inc/linux/bit_spinlock.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/bit_spinlock.h rename to reactos/drivers/filesystems/ext2/inc/linux/bit_spinlock.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/bitops.h b/reactos/drivers/filesystems/ext2/inc/linux/bitops.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/bitops.h rename to reactos/drivers/filesystems/ext2/inc/linux/bitops.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/buffer_head.h b/reactos/drivers/filesystems/ext2/inc/linux/buffer_head.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/buffer_head.h rename to reactos/drivers/filesystems/ext2/inc/linux/buffer_head.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/config.h b/reactos/drivers/filesystems/ext2/inc/linux/config.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/config.h rename to reactos/drivers/filesystems/ext2/inc/linux/config.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/debugfs.h b/reactos/drivers/filesystems/ext2/inc/linux/debugfs.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/debugfs.h rename to reactos/drivers/filesystems/ext2/inc/linux/debugfs.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/errno.h b/reactos/drivers/filesystems/ext2/inc/linux/errno.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/errno.h rename to reactos/drivers/filesystems/ext2/inc/linux/errno.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext2_fs.h b/reactos/drivers/filesystems/ext2/inc/linux/ext2_fs.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext2_fs.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext2_fs.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext3_fs.h b/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext3_fs.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext3_fs.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext3_fs_i.h b/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_i.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext3_fs_i.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_i.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext3_fs_sb.h b/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_sb.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext3_fs_sb.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_sb.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext3_jbd.h b/reactos/drivers/filesystems/ext2/inc/linux/ext3_jbd.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext3_jbd.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext3_jbd.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext4.h b/reactos/drivers/filesystems/ext2/inc/linux/ext4.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext4.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext4.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext4_ext.h b/reactos/drivers/filesystems/ext2/inc/linux/ext4_ext.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext4_ext.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext4_ext.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/ext4_jbd2.h b/reactos/drivers/filesystems/ext2/inc/linux/ext4_jbd2.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/ext4_jbd2.h rename to reactos/drivers/filesystems/ext2/inc/linux/ext4_jbd2.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/freezer.h b/reactos/drivers/filesystems/ext2/inc/linux/freezer.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/freezer.h rename to reactos/drivers/filesystems/ext2/inc/linux/freezer.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/fs.h b/reactos/drivers/filesystems/ext2/inc/linux/fs.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/fs.h rename to reactos/drivers/filesystems/ext2/inc/linux/fs.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/group.h b/reactos/drivers/filesystems/ext2/inc/linux/group.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/group.h rename to reactos/drivers/filesystems/ext2/inc/linux/group.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/highmem.h b/reactos/drivers/filesystems/ext2/inc/linux/highmem.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/highmem.h rename to reactos/drivers/filesystems/ext2/inc/linux/highmem.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/init.h b/reactos/drivers/filesystems/ext2/inc/linux/init.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/init.h rename to reactos/drivers/filesystems/ext2/inc/linux/init.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/jbd.h b/reactos/drivers/filesystems/ext2/inc/linux/jbd.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/jbd.h rename to reactos/drivers/filesystems/ext2/inc/linux/jbd.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/journal-head.h b/reactos/drivers/filesystems/ext2/inc/linux/journal-head.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/journal-head.h rename to reactos/drivers/filesystems/ext2/inc/linux/journal-head.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/kernel.h b/reactos/drivers/filesystems/ext2/inc/linux/kernel.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/kernel.h rename to reactos/drivers/filesystems/ext2/inc/linux/kernel.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/kthread.h b/reactos/drivers/filesystems/ext2/inc/linux/kthread.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/kthread.h rename to reactos/drivers/filesystems/ext2/inc/linux/kthread.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/list.h b/reactos/drivers/filesystems/ext2/inc/linux/list.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/list.h rename to reactos/drivers/filesystems/ext2/inc/linux/list.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/lockdep.h b/reactos/drivers/filesystems/ext2/inc/linux/lockdep.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/lockdep.h rename to reactos/drivers/filesystems/ext2/inc/linux/lockdep.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/log2.h b/reactos/drivers/filesystems/ext2/inc/linux/log2.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/log2.h rename to reactos/drivers/filesystems/ext2/inc/linux/log2.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/magic.h b/reactos/drivers/filesystems/ext2/inc/linux/magic.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/magic.h rename to reactos/drivers/filesystems/ext2/inc/linux/magic.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/mm.h b/reactos/drivers/filesystems/ext2/inc/linux/mm.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/mm.h rename to reactos/drivers/filesystems/ext2/inc/linux/mm.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/module.h b/reactos/drivers/filesystems/ext2/inc/linux/module.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/module.h rename to reactos/drivers/filesystems/ext2/inc/linux/module.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/mutex.h b/reactos/drivers/filesystems/ext2/inc/linux/mutex.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/mutex.h rename to reactos/drivers/filesystems/ext2/inc/linux/mutex.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/nls.h b/reactos/drivers/filesystems/ext2/inc/linux/nls.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/nls.h rename to reactos/drivers/filesystems/ext2/inc/linux/nls.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/pagemap.h b/reactos/drivers/filesystems/ext2/inc/linux/pagemap.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/pagemap.h rename to reactos/drivers/filesystems/ext2/inc/linux/pagemap.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/poison.h b/reactos/drivers/filesystems/ext2/inc/linux/poison.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/poison.h rename to reactos/drivers/filesystems/ext2/inc/linux/poison.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/proc_fs.h b/reactos/drivers/filesystems/ext2/inc/linux/proc_fs.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/proc_fs.h rename to reactos/drivers/filesystems/ext2/inc/linux/proc_fs.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/rbtree.h b/reactos/drivers/filesystems/ext2/inc/linux/rbtree.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/rbtree.h rename to reactos/drivers/filesystems/ext2/inc/linux/rbtree.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/sched.h b/reactos/drivers/filesystems/ext2/inc/linux/sched.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/sched.h rename to reactos/drivers/filesystems/ext2/inc/linux/sched.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/slab.h b/reactos/drivers/filesystems/ext2/inc/linux/slab.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/slab.h rename to reactos/drivers/filesystems/ext2/inc/linux/slab.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/spinlock.h b/reactos/drivers/filesystems/ext2/inc/linux/spinlock.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/spinlock.h rename to reactos/drivers/filesystems/ext2/inc/linux/spinlock.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/stddef.h b/reactos/drivers/filesystems/ext2/inc/linux/stddef.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/stddef.h rename to reactos/drivers/filesystems/ext2/inc/linux/stddef.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/string.h b/reactos/drivers/filesystems/ext2/inc/linux/string.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/string.h rename to reactos/drivers/filesystems/ext2/inc/linux/string.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/time.h b/reactos/drivers/filesystems/ext2/inc/linux/time.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/time.h rename to reactos/drivers/filesystems/ext2/inc/linux/time.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/timer.h b/reactos/drivers/filesystems/ext2/inc/linux/timer.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/timer.h rename to reactos/drivers/filesystems/ext2/inc/linux/timer.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/types.h b/reactos/drivers/filesystems/ext2/inc/linux/types.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/types.h rename to reactos/drivers/filesystems/ext2/inc/linux/types.h diff --git a/reactos/drivers/filesystems/ext2_new/inc/linux/version.h b/reactos/drivers/filesystems/ext2/inc/linux/version.h similarity index 100% rename from reactos/drivers/filesystems/ext2_new/inc/linux/version.h rename to reactos/drivers/filesystems/ext2/inc/linux/version.h diff --git a/reactos/drivers/filesystems/ext2/inc/resource.h b/reactos/drivers/filesystems/ext2/inc/resource.h index 9c490bf5b6c..f3308974ab2 100644 --- a/reactos/drivers/filesystems/ext2/inc/resource.h +++ b/reactos/drivers/filesystems/ext2/inc/resource.h @@ -1,14 +1,13 @@ //{{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 diff --git a/reactos/drivers/filesystems/ext2_new/src/block.c b/reactos/drivers/filesystems/ext2/src/block.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/block.c rename to reactos/drivers/filesystems/ext2/src/block.c diff --git a/reactos/drivers/filesystems/ext2/src/cleanup.c b/reactos/drivers/filesystems/ext2/src/cleanup.c index d5d33c5f528..2c04b8d75e0 100644 --- a/reactos/drivers/filesystems/ext2/src/cleanup.c +++ b/reactos/drivers/filesystems/ext2/src/cleanup.c @@ -1,398 +1,389 @@ -/************************************************************************* -* -* 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 + * 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; } diff --git a/reactos/drivers/filesystems/ext2/src/close.c b/reactos/drivers/filesystems/ext2/src/close.c index 1674bf0e533..de2d6875744 100644 --- a/reactos/drivers/filesystems/ext2/src/close.c +++ b/reactos/drivers/filesystems/ext2/src/close.c @@ -1,515 +1,282 @@ -/************************************************************************* -* -* 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 + * 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; } diff --git a/reactos/drivers/filesystems/ext2_new/src/cmcb.c b/reactos/drivers/filesystems/ext2/src/cmcb.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/cmcb.c rename to reactos/drivers/filesystems/ext2/src/cmcb.c diff --git a/reactos/drivers/filesystems/ext2/src/create.c b/reactos/drivers/filesystems/ext2/src/create.c index 13aeafddb68..43703eaae89 100644 --- a/reactos/drivers/filesystems/ext2/src/create.c +++ b/reactos/drivers/filesystems/ext2/src/create.c @@ -1,1675 +1,1977 @@ -/************************************************************************* -* -* 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 + * 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; } diff --git a/reactos/drivers/filesystems/ext2_new/src/debug.c b/reactos/drivers/filesystems/ext2/src/debug.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/debug.c rename to reactos/drivers/filesystems/ext2/src/debug.c diff --git a/reactos/drivers/filesystems/ext2_new/src/devctl.c b/reactos/drivers/filesystems/ext2/src/devctl.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/devctl.c rename to reactos/drivers/filesystems/ext2/src/devctl.c diff --git a/reactos/drivers/filesystems/ext2_new/src/dirctl.c b/reactos/drivers/filesystems/ext2/src/dirctl.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/dirctl.c rename to reactos/drivers/filesystems/ext2/src/dirctl.c diff --git a/reactos/drivers/filesystems/ext2_new/src/dispatch.c b/reactos/drivers/filesystems/ext2/src/dispatch.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/dispatch.c rename to reactos/drivers/filesystems/ext2/src/dispatch.c diff --git a/reactos/drivers/filesystems/ext2_new/src/except.c b/reactos/drivers/filesystems/ext2/src/except.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/except.c rename to reactos/drivers/filesystems/ext2/src/except.c diff --git a/reactos/drivers/filesystems/ext2/src/ext2.rc b/reactos/drivers/filesystems/ext2/src/ext2.rc index 916f599e785..3e53be1f80e 100644 --- a/reactos/drivers/filesystems/ext2/src/ext2.rc +++ b/reactos/drivers/filesystems/ext2/src/ext2.rc @@ -62,8 +62,8 @@ END // 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 @@ -81,14 +81,14 @@ BEGIN 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/ext3/generic.c b/reactos/drivers/filesystems/ext2/src/ext3/generic.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext3/generic.c rename to reactos/drivers/filesystems/ext2/src/ext3/generic.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext3/htree.c b/reactos/drivers/filesystems/ext2/src/ext3/htree.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext3/htree.c rename to reactos/drivers/filesystems/ext2/src/ext3/htree.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext3/indirect.c b/reactos/drivers/filesystems/ext2/src/ext3/indirect.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext3/indirect.c rename to reactos/drivers/filesystems/ext2/src/ext3/indirect.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext3/recover.c b/reactos/drivers/filesystems/ext2/src/ext3/recover.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext3/recover.c rename to reactos/drivers/filesystems/ext2/src/ext3/recover.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext4/ext4_bh.c b/reactos/drivers/filesystems/ext2/src/ext4/ext4_bh.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext4/ext4_bh.c rename to reactos/drivers/filesystems/ext2/src/ext4/ext4_bh.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext4/ext4_extents.c b/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext4/ext4_extents.c rename to reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext4/ext4_jbd2.c b/reactos/drivers/filesystems/ext2/src/ext4/ext4_jbd2.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext4/ext4_jbd2.c rename to reactos/drivers/filesystems/ext2/src/ext4/ext4_jbd2.c diff --git a/reactos/drivers/filesystems/ext2_new/src/ext4/extents.c b/reactos/drivers/filesystems/ext2/src/ext4/extents.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/ext4/extents.c rename to reactos/drivers/filesystems/ext2/src/ext4/extents.c diff --git a/reactos/drivers/filesystems/ext2/src/fastio.c b/reactos/drivers/filesystems/ext2/src/fastio.c index 5c616761ad0..b339a262243 100644 --- a/reactos/drivers/filesystems/ext2/src/fastio.c +++ b/reactos/drivers/filesystems/ext2/src/fastio.c @@ -1,1703 +1,980 @@ -/************************************************************************* -* -* 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 + * 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 diff --git a/reactos/drivers/filesystems/ext2/src/fileinfo.c b/reactos/drivers/filesystems/ext2/src/fileinfo.c index 143c80929fc..3588b47b20a 100644 --- a/reactos/drivers/filesystems/ext2/src/fileinfo.c +++ b/reactos/drivers/filesystems/ext2/src/fileinfo.c @@ -1,1122 +1,1849 @@ -/************************************************************************* -* -* 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 + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" +#include + +/* 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; } diff --git a/reactos/drivers/filesystems/ext2/src/flush.c b/reactos/drivers/filesystems/ext2/src/flush.c index 9ca5294900b..136cf26974d 100644 --- a/reactos/drivers/filesystems/ext2/src/flush.c +++ b/reactos/drivers/filesystems/ext2/src/flush.c @@ -1,346 +1,268 @@ -/************************************************************************* -* -* 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 + * 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/fsctl.c b/reactos/drivers/filesystems/ext2/src/fsctl.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/fsctl.c rename to reactos/drivers/filesystems/ext2/src/fsctl.c diff --git a/reactos/drivers/filesystems/ext2_new/src/init.c b/reactos/drivers/filesystems/ext2/src/init.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/init.c rename to reactos/drivers/filesystems/ext2/src/init.c diff --git a/reactos/drivers/filesystems/ext2_new/src/jbd/recovery.c b/reactos/drivers/filesystems/ext2/src/jbd/recovery.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/jbd/recovery.c rename to reactos/drivers/filesystems/ext2/src/jbd/recovery.c diff --git a/reactos/drivers/filesystems/ext2_new/src/jbd/replay.c b/reactos/drivers/filesystems/ext2/src/jbd/replay.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/jbd/replay.c rename to reactos/drivers/filesystems/ext2/src/jbd/replay.c diff --git a/reactos/drivers/filesystems/ext2_new/src/jbd/revoke.c b/reactos/drivers/filesystems/ext2/src/jbd/revoke.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/jbd/revoke.c rename to reactos/drivers/filesystems/ext2/src/jbd/revoke.c diff --git a/reactos/drivers/filesystems/ext2_new/src/linux.c b/reactos/drivers/filesystems/ext2/src/linux.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/linux.c rename to reactos/drivers/filesystems/ext2/src/linux.c diff --git a/reactos/drivers/filesystems/ext2_new/src/lock.c b/reactos/drivers/filesystems/ext2/src/lock.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/lock.c rename to reactos/drivers/filesystems/ext2/src/lock.c diff --git a/reactos/drivers/filesystems/ext2_new/src/memory.c b/reactos/drivers/filesystems/ext2/src/memory.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/memory.c rename to reactos/drivers/filesystems/ext2/src/memory.c diff --git a/reactos/drivers/filesystems/ext2/src/misc.c b/reactos/drivers/filesystems/ext2/src/misc.c index d09998ac4cb..1fbbc34cb59 100644 --- a/reactos/drivers/filesystems/ext2/src/misc.c +++ b/reactos/drivers/filesystems/ext2/src/misc.c @@ -1,2121 +1,530 @@ -/************************************************************************* -* -* 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 + * 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/nls.c b/reactos/drivers/filesystems/ext2/src/nls.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls.c rename to reactos/drivers/filesystems/ext2/src/nls.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_ascii.c b/reactos/drivers/filesystems/ext2/src/nls/nls_ascii.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_ascii.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_ascii.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_base.c b/reactos/drivers/filesystems/ext2/src/nls/nls_base.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_base.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_base.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp1250.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp1250.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp1250.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp1250.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp1251.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp1251.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp1251.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp1251.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp1255.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp1255.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp1255.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp1255.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp437.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp437.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp437.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp437.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp737.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp737.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp737.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp737.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp775.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp775.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp775.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp775.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp850.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp850.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp850.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp850.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp852.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp852.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp852.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp852.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp855.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp855.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp855.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp855.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp857.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp857.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp857.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp857.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp860.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp860.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp860.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp860.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp861.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp861.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp861.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp861.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp862.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp862.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp862.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp862.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp863.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp863.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp863.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp863.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp864.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp864.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp864.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp864.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp865.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp865.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp865.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp865.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp866.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp866.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp866.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp866.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp869.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp869.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp869.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp869.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp874.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp874.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp874.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp874.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp932.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp932.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp932.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp932.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp936.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp936.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp936.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp936.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp949.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp949.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp949.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp949.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_cp950.c b/reactos/drivers/filesystems/ext2/src/nls/nls_cp950.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_cp950.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_cp950.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_euc-jp.c b/reactos/drivers/filesystems/ext2/src/nls/nls_euc-jp.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_euc-jp.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_euc-jp.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-1.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-1.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-1.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-1.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-13.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-13.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-13.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-13.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-14.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-14.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-14.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-14.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-15.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-15.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-15.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-15.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-2.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-2.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-2.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-2.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-3.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-3.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-3.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-3.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-4.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-4.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-4.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-4.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-5.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-5.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-5.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-5.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-6.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-6.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-6.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-6.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-7.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-7.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-7.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-7.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-9.c b/reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-9.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_iso8859-9.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_iso8859-9.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_koi8-r.c b/reactos/drivers/filesystems/ext2/src/nls/nls_koi8-r.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_koi8-r.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_koi8-r.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_koi8-ru.c b/reactos/drivers/filesystems/ext2/src/nls/nls_koi8-ru.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_koi8-ru.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_koi8-ru.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_koi8-u.c b/reactos/drivers/filesystems/ext2/src/nls/nls_koi8-u.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_koi8-u.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_koi8-u.c diff --git a/reactos/drivers/filesystems/ext2_new/src/nls/nls_utf8.c b/reactos/drivers/filesystems/ext2/src/nls/nls_utf8.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/nls/nls_utf8.c rename to reactos/drivers/filesystems/ext2/src/nls/nls_utf8.c diff --git a/reactos/drivers/filesystems/ext2_new/src/pnp.c b/reactos/drivers/filesystems/ext2/src/pnp.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/pnp.c rename to reactos/drivers/filesystems/ext2/src/pnp.c diff --git a/reactos/drivers/filesystems/ext2_new/src/rbtree.c b/reactos/drivers/filesystems/ext2/src/rbtree.c similarity index 100% rename from reactos/drivers/filesystems/ext2_new/src/rbtree.c rename to reactos/drivers/filesystems/ext2/src/rbtree.c diff --git a/reactos/drivers/filesystems/ext2/src/read.c b/reactos/drivers/filesystems/ext2/src/read.c index 3c7d70b4c7a..b78c754b16a 100644 --- a/reactos/drivers/filesystems/ext2/src/read.c +++ b/reactos/drivers/filesystems/ext2/src/read.c @@ -1,1468 +1,930 @@ -/************************************************************************* -* -* 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 + * 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; } diff --git a/reactos/drivers/filesystems/ext2/src/shutdown.c b/reactos/drivers/filesystems/ext2/src/shutdown.c index 0c234a1c7ad..1e3564a2636 100644 --- a/reactos/drivers/filesystems/ext2/src/shutdown.c +++ b/reactos/drivers/filesystems/ext2/src/shutdown.c @@ -1,208 +1,118 @@ -/************************************************************************* -* -* 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 + * 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 diff --git a/reactos/drivers/filesystems/ext2/src/volinfo.c b/reactos/drivers/filesystems/ext2/src/volinfo.c index 32661d14a9c..895da8fc4c8 100644 --- a/reactos/drivers/filesystems/ext2/src/volinfo.c +++ b/reactos/drivers/filesystems/ext2/src/volinfo.c @@ -1,338 +1,408 @@ -/************************************************************************* -* -* 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 + * 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 diff --git a/reactos/drivers/filesystems/ext2/src/write.c b/reactos/drivers/filesystems/ext2/src/write.c index f72c0ecc02f..fe50d349486 100644 --- a/reactos/drivers/filesystems/ext2/src/write.c +++ b/reactos/drivers/filesystems/ext2/src/write.c @@ -1,1481 +1,1396 @@ -/************************************************************************* -* -* 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 + * 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; } diff --git a/reactos/drivers/filesystems/ext2_new/CMakeLists.txt b/reactos/drivers/filesystems/ext2_new/CMakeLists.txt deleted file mode 100644 index f02de3cfa03..00000000000 --- a/reactos/drivers/filesystems/ext2_new/CMakeLists.txt +++ /dev/null @@ -1,105 +0,0 @@ - -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) diff --git a/reactos/drivers/filesystems/ext2_new/ext2fs.rc b/reactos/drivers/filesystems/ext2_new/ext2fs.rc deleted file mode 100644 index 5988979293a..00000000000 --- a/reactos/drivers/filesystems/ext2_new/ext2fs.rc +++ /dev/null @@ -1,5 +0,0 @@ -#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 diff --git a/reactos/drivers/filesystems/ext2_new/inc/resource.h b/reactos/drivers/filesystems/ext2_new/inc/resource.h deleted file mode 100644 index f3308974ab2..00000000000 --- a/reactos/drivers/filesystems/ext2_new/inc/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{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 diff --git a/reactos/drivers/filesystems/ext2_new/src/cleanup.c b/reactos/drivers/filesystems/ext2_new/src/cleanup.c deleted file mode 100644 index 2c04b8d75e0..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/cleanup.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: cleanup.c - * PROGRAMMER: Matt Wu - * 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; -} diff --git a/reactos/drivers/filesystems/ext2_new/src/close.c b/reactos/drivers/filesystems/ext2_new/src/close.c deleted file mode 100644 index de2d6875744..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/close.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: close.c - * PROGRAMMER: Matt Wu - * 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; -} diff --git a/reactos/drivers/filesystems/ext2_new/src/create.c b/reactos/drivers/filesystems/ext2_new/src/create.c deleted file mode 100644 index 43703eaae89..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/create.c +++ /dev/null @@ -1,1977 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: create.c - * PROGRAMMER: Matt Wu - * 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; -} diff --git a/reactos/drivers/filesystems/ext2_new/src/ext2.rc b/reactos/drivers/filesystems/ext2_new/src/ext2.rc deleted file mode 100644 index 3e53be1f80e..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/ext2.rc +++ /dev/null @@ -1,117 +0,0 @@ -//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 - diff --git a/reactos/drivers/filesystems/ext2_new/src/fastio.c b/reactos/drivers/filesystems/ext2_new/src/fastio.c deleted file mode 100644 index b339a262243..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/fastio.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: fastio.c - * PROGRAMMER: Matt Wu - * 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; -} diff --git a/reactos/drivers/filesystems/ext2_new/src/fileinfo.c b/reactos/drivers/filesystems/ext2_new/src/fileinfo.c deleted file mode 100644 index 3588b47b20a..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/fileinfo.c +++ /dev/null @@ -1,1849 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: fileinfo.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" -#include - -/* 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; -} diff --git a/reactos/drivers/filesystems/ext2_new/src/flush.c b/reactos/drivers/filesystems/ext2_new/src/flush.c deleted file mode 100644 index 136cf26974d..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/flush.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: flush.c - * PROGRAMMER: Matt Wu - * 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/misc.c b/reactos/drivers/filesystems/ext2_new/src/misc.c deleted file mode 100644 index 1fbbc34cb59..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/misc.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: misc.c - * PROGRAMMER: Matt Wu - * 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/read.c b/reactos/drivers/filesystems/ext2_new/src/read.c deleted file mode 100644 index b78c754b16a..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/read.c +++ /dev/null @@ -1,930 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: read.c - * PROGRAMMER: Matt Wu - * 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; -} diff --git a/reactos/drivers/filesystems/ext2_new/src/shutdown.c b/reactos/drivers/filesystems/ext2_new/src/shutdown.c deleted file mode 100644 index 1e3564a2636..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/shutdown.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: shutdown.c - * PROGRAMMER: Matt Wu - * 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/volinfo.c b/reactos/drivers/filesystems/ext2_new/src/volinfo.c deleted file mode 100644 index 895da8fc4c8..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/volinfo.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: volinfo.c - * PROGRAMMER: Matt Wu - * 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 diff --git a/reactos/drivers/filesystems/ext2_new/src/write.c b/reactos/drivers/filesystems/ext2_new/src/write.c deleted file mode 100644 index fe50d349486..00000000000 --- a/reactos/drivers/filesystems/ext2_new/src/write.c +++ /dev/null @@ -1,1396 +0,0 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: write.c - * PROGRAMMER: Matt Wu - * 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; -}