From 4fb9ddefa70006ffb5e09ab8631b73b53c05528b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=20Brant=C3=A9n?= Date: Tue, 21 Jul 2020 01:12:02 +0200 Subject: [PATCH] converted some files from UNIX to DOS line endings --- Ext4Fsd/DIRS | 2 +- Ext4Fsd/access.c | 108 +- Ext4Fsd/block.c | 1518 ++++---- Ext4Fsd/cleanup.c | 798 ++-- Ext4Fsd/close.c | 494 +-- Ext4Fsd/cmcb.c | 276 +- Ext4Fsd/debug.c | 5410 +++++++++++++------------- Ext4Fsd/devctl.c | 1624 ++++---- Ext4Fsd/dirctl.c | 2548 ++++++------ Ext4Fsd/dispatch.c | 708 ++-- Ext4Fsd/ea.c | 1208 +++--- Ext4Fsd/except.c | 546 +-- Ext4Fsd/ext3/indirect.c | 2318 +++++------ Ext4Fsd/ext4/ext4_bh.c | 136 +- Ext4Fsd/ext4/extents.c | 488 +-- Ext4Fsd/fastio.c | 2250 +++++------ Ext4Fsd/fileinfo.c | 4178 ++++++++++---------- Ext4Fsd/flush.c | 552 +-- Ext4Fsd/include/common.h | 522 +-- Ext4Fsd/include/linux/atomic.h | 308 +- Ext4Fsd/include/linux/bit_spinlock.h | 190 +- Ext4Fsd/include/linux/bitops.h | 560 +-- Ext4Fsd/include/linux/config.h | 12 +- Ext4Fsd/include/linux/errno.h | 294 +- Ext4Fsd/include/linux/ext4_ext.h | 514 +-- Ext4Fsd/include/linux/ext4_jbd2.h | 130 +- Ext4Fsd/include/linux/ext4_xattr.h | 410 +- Ext4Fsd/include/linux/fs.h | 320 +- Ext4Fsd/include/linux/group.h | 58 +- Ext4Fsd/include/linux/journal-head.h | 184 +- Ext4Fsd/include/linux/list.h | 510 +-- Ext4Fsd/include/linux/log2.h | 280 +- Ext4Fsd/include/linux/module.h | 2430 ++++++------ Ext4Fsd/include/linux/rbtree.h | 322 +- Ext4Fsd/include/linux/stddef.h | 26 +- Ext4Fsd/include/resource.h | 30 +- Ext4Fsd/lock.c | 250 +- Ext4Fsd/misc.c | 1064 ++--- Ext4Fsd/nls.c | 462 +-- Ext4Fsd/pnp.c | 792 ++-- Ext4Fsd/rbtree.c | 830 ++-- Ext4Fsd/read.c | 1890 ++++----- Ext4Fsd/shutdown.c | 234 +- Ext4Fsd/volinfo.c | 816 ++-- Ext4Fsd/write.c | 2846 +++++++------- 45 files changed, 20723 insertions(+), 20723 deletions(-) diff --git a/Ext4Fsd/DIRS b/Ext4Fsd/DIRS index c9e0cbd..e911af4 100644 --- a/Ext4Fsd/DIRS +++ b/Ext4Fsd/DIRS @@ -1 +1 @@ -DIRS = nls ext3 ext4 jbd2 sys +DIRS = nls ext3 ext4 jbd2 sys diff --git a/Ext4Fsd/access.c b/Ext4Fsd/access.c index 03ec404..bfec162 100644 --- a/Ext4Fsd/access.c +++ b/Ext4Fsd/access.c @@ -1,54 +1,54 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: access.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt) -{ - int granted = 0; - - uid_t uid = Vcb->uid; - gid_t gid = Vcb->gid; - - if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { - uid = Vcb->euid; - gid = Vcb->egid; - } - - if (!uid || uid == in->i_uid) { - /* grant all access for inode owner or root */ - granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; - } else if (gid == in->i_gid) { - if (Ext2IsGroupReadOnly(in->i_mode)) - granted = Ext2FileCanRead | Ext2FileCanExecute; - else if (Ext2IsGroupWritable(in->i_mode)) - granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; - } else { - if (Ext2IsOtherReadOnly(in->i_mode)) - granted = Ext2FileCanRead | Ext2FileCanExecute; - else if (Ext2IsOtherWritable(in->i_mode)) - granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; - - } - - return IsFlagOn(granted, attempt); -} - -int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt) -{ - return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt); -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: access.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt) +{ + int granted = 0; + + uid_t uid = Vcb->uid; + gid_t gid = Vcb->gid; + + if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { + uid = Vcb->euid; + gid = Vcb->egid; + } + + if (!uid || uid == in->i_uid) { + /* grant all access for inode owner or root */ + granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; + } else if (gid == in->i_gid) { + if (Ext2IsGroupReadOnly(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanExecute; + else if (Ext2IsGroupWritable(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; + } else { + if (Ext2IsOtherReadOnly(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanExecute; + else if (Ext2IsOtherWritable(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; + + } + + return IsFlagOn(granted, attempt); +} + +int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt) +{ + return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt); +} diff --git a/Ext4Fsd/block.c b/Ext4Fsd/block.c index b5666a6..b301375 100644 --- a/Ext4Fsd/block.c +++ b/Ext4Fsd/block.c @@ -1,759 +1,759 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: block.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -NTSTATUS -Ext2ReadWriteBlockSyncCompletionRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context ); - -NTSTATUS -Ext2ReadWriteBlockAsyncCompletionRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context ); - - -NTSTATUS -Ext2MediaEjectControlCompletion ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Contxt ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Ext2LockUserBuffer) -#pragma alloc_text(PAGE, Ext2ReadSync) -#pragma alloc_text(PAGE, Ext2ReadDisk) -#pragma alloc_text(PAGE, Ext2DiskIoControl) -#pragma alloc_text(PAGE, Ext2MediaEjectControl) -#pragma alloc_text(PAGE, Ext2DiskShutDown) -#endif - - -/* FUNCTIONS ***************************************************************/ - -PMDL -Ext2CreateMdl ( - IN PVOID Buffer, - IN ULONG Length, - IN LOCK_OPERATION op -) -{ - NTSTATUS Status; - PMDL Mdl = NULL; - - ASSERT (Buffer != NULL); - Mdl = IoAllocateMdl (Buffer, Length, FALSE, FALSE, NULL); - if (Mdl == NULL) { - Status = STATUS_INSUFFICIENT_RESOURCES; - } else { - __try { - if (MmIsNonPagedSystemAddressValid(Buffer)) { - MmBuildMdlForNonPagedPool(Mdl); - } else { - MmProbeAndLockPages(Mdl, KernelMode, op); - } - Status = STATUS_SUCCESS; - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoFreeMdl (Mdl); - Mdl = NULL; - DbgBreak(); - Status = STATUS_INVALID_USER_BUFFER; - } - } - return Mdl; -} - - -VOID -Ext2DestroyMdl (IN PMDL Mdl) -{ - ASSERT (Mdl != NULL); - while (Mdl) { - PMDL Next; - Next = Mdl->Next; - Mdl->Next = NULL; - if (IsFlagOn(Mdl->MdlFlags, MDL_PAGES_LOCKED)) { - MmUnlockPages (Mdl); - } - IoFreeMdl (Mdl); - Mdl = Next; - } -} - -NTSTATUS -Ext2LockUserBuffer (IN PIRP Irp, - IN ULONG Length, - IN LOCK_OPERATION Operation) -{ - NTSTATUS Status; - ASSERT(Irp != NULL); - - if (Irp->MdlAddress != NULL) { - return STATUS_SUCCESS; - } - - IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp); - if (Irp->MdlAddress == NULL) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - __try { - - MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); - Status = STATUS_SUCCESS; - - } __except (EXCEPTION_EXECUTE_HANDLER) { - - DbgBreak(); - IoFreeMdl(Irp->MdlAddress); - Irp->MdlAddress = NULL; - Status = STATUS_INVALID_USER_BUFFER; - } - - return Status; -} - -PVOID -Ext2GetUserBuffer (IN PIRP Irp ) -{ - ASSERT(Irp != NULL); - - if (Irp->MdlAddress) { - -#if (_WIN32_WINNT >= 0x0500) - return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); -#else - return MmGetSystemAddressForMdl(Irp->MdlAddress); -#endif - } else { - - return Irp->UserBuffer; - } -} - -NTSTATUS -Ext2ReadWriteBlockSyncCompletionRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context ) -{ - PEXT2_RW_CONTEXT pContext = (PEXT2_RW_CONTEXT)Context; - - if (Irp != pContext->MasterIrp) { - - if (!NT_SUCCESS(Irp->IoStatus.Status)) { - pContext->MasterIrp->IoStatus = Irp->IoStatus; - } - - IoFreeMdl(Irp->MdlAddress); - IoFreeIrp(Irp ); - } - - if (InterlockedDecrement(&pContext->Blocks) == 0) { - - pContext->MasterIrp->IoStatus.Information = 0; - if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) { - - pContext->MasterIrp->IoStatus.Information = - pContext->Length; - } - - KeSetEvent(&pContext->Event, 0, FALSE); - } - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -Ext2ReadWriteBlockAsyncCompletionRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context -) -{ - PEXT2_RW_CONTEXT pContext = (PEXT2_RW_CONTEXT)Context; - PIO_STACK_LOCATION iosp; - - ASSERT(FALSE == pContext->Wait); - - if (Irp != pContext->MasterIrp && !NT_SUCCESS(Irp->IoStatus.Status)) { - pContext->MasterIrp->IoStatus = Irp->IoStatus; - } - - if (InterlockedDecrement(&pContext->Blocks) == 0) { - - if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) { - - /* set written bytes to status information */ - pContext->MasterIrp->IoStatus.Information = pContext->Length; - - if (pContext->FileObject != NULL && !IsFlagOn(pContext->MasterIrp->Flags, IRP_PAGING_IO)) { - - /* modify FileObject flags, skip this for volume direct access */ - SetFlag( pContext->FileObject->Flags, - IsFlagOn(pContext->Flags, EXT2_RW_CONTEXT_WRITE) ? - FO_FILE_MODIFIED : FO_FILE_FAST_IO_READ); - - /* update Current Byteoffset */ - if (IsFlagOn(pContext->FileObject->Flags, FO_SYNCHRONOUS_IO)) { - iosp = IoGetCurrentIrpStackLocation(pContext->MasterIrp); - pContext->FileObject->CurrentByteOffset.QuadPart = - iosp->Parameters.Read.ByteOffset.QuadPart + pContext->Length; - } - } - - } else { - - pContext->MasterIrp->IoStatus.Information = 0; - } - - /* release the locked resource acquired by the caller */ - if (pContext->Resource) { - ExReleaseResourceForThread(pContext->Resource, pContext->ThreadId); - } - - Ext2FreePool(pContext, EXT2_RWC_MAGIC); - DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); - } - - return STATUS_SUCCESS; -} - -NTSTATUS -Ext2ReadWriteBlocks( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_EXTENT Chain, - IN ULONG Length - ) -{ - PIRP Irp; - PIRP MasterIrp = IrpContext->Irp; - PIO_STACK_LOCATION IrpSp; - PMDL Mdl; - PEXT2_RW_CONTEXT pContext = NULL; - PEXT2_EXTENT Extent; - KEVENT Wait; - NTSTATUS Status = STATUS_SUCCESS; - BOOLEAN bMasterCompleted = FALSE; - BOOLEAN bBugCheck = FALSE; - - ASSERT(MasterIrp); - - __try { - - pContext = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_RW_CONTEXT), EXT2_RWC_MAGIC); - - if (!pContext) { - DEBUG(DL_ERR, ( "Ex2ReadWriteBlocks: failed to allocate pContext.\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - INC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); - RtlZeroMemory(pContext, sizeof(EXT2_RW_CONTEXT)); - pContext->Wait = Ext2CanIWait(); - pContext->MasterIrp = MasterIrp; - pContext->Length = Length; - - if (IrpContext->MajorFunction == IRP_MJ_WRITE) { - SetFlag(pContext->Flags, EXT2_RW_CONTEXT_WRITE); - } - - if (pContext->Wait) { - - KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE); - - } else if (IrpContext->Fcb->Identifier.Type == EXT2FCB) { - - if (IsFlagOn(MasterIrp->Flags, IRP_PAGING_IO)) { - pContext->Resource = &IrpContext->Fcb->PagingIoResource; - } else { - pContext->Resource = &IrpContext->Fcb->MainResource; - } - - pContext->FileObject = IrpContext->FileObject; - pContext->ThreadId = ExGetCurrentResourceThread(); - } - - - if (NULL == Chain->Next && 0 == Chain->Offset) { - - /* we get only 1 extent to dispatch, then don't bother allocating new irps */ - - /* setup the Stack location to do a read from the disk driver. */ - IrpSp = IoGetNextIrpStackLocation(MasterIrp); - IrpSp->MajorFunction = IrpContext->MajorFunction; - IrpSp->Parameters.Read.Length = Chain->Length; - IrpSp->Parameters.Read.ByteOffset.QuadPart = Chain->Lba; - if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { - SetFlag(IrpSp->Flags, SL_WRITE_THROUGH); - } - if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { - SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); - } - - IoSetCompletionRoutine( - MasterIrp, - Ext2CanIWait() ? - Ext2ReadWriteBlockSyncCompletionRoutine : - Ext2ReadWriteBlockAsyncCompletionRoutine, - (PVOID) pContext, - TRUE, - TRUE, - TRUE ); - - /* intialize context block */ - Chain->Irp = MasterIrp; - pContext->Blocks = 1; - - } else { - - for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { - - Irp = IoMakeAssociatedIrp( - MasterIrp, - (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) ); - - if (!Irp) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer + - Extent->Offset, - Extent->Length, - FALSE, - FALSE, - Irp ); - - if (!Mdl) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - IoBuildPartialMdl( MasterIrp->MdlAddress, - Mdl, - (PCHAR)MasterIrp->UserBuffer+Extent->Offset, - Extent->Length ); - - IoSetNextIrpStackLocation(Irp); - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - IrpSp->MajorFunction = IrpContext->MajorFunction; - IrpSp->Parameters.Read.Length = Extent->Length; - IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; - - IoSetCompletionRoutine( - Irp, - Ext2CanIWait() ? - Ext2ReadWriteBlockSyncCompletionRoutine : - Ext2ReadWriteBlockAsyncCompletionRoutine, - (PVOID) pContext, - TRUE, - TRUE, - TRUE ); - - IrpSp = IoGetNextIrpStackLocation(Irp); - - IrpSp->MajorFunction = IrpContext->MajorFunction; - IrpSp->Parameters.Read.Length =Extent->Length; - IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; - - /* set write through flag */ - if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { - SetFlag( IrpSp->Flags, SL_WRITE_THROUGH ); - } - - /* set verify flag */ - if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { - SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); - } - - Extent->Irp = Irp; - pContext->Blocks += 1; - } - - MasterIrp->AssociatedIrp.IrpCount = pContext->Blocks; - if (Ext2CanIWait()) { - MasterIrp->AssociatedIrp.IrpCount += 1; - } - } - if (!Ext2CanIWait()) { - /* mark MasterIrp pending */ - IoMarkIrpPending(pContext->MasterIrp); - } - - bBugCheck = TRUE; - - for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { - Status = IoCallDriver ( Vcb->TargetDeviceObject, - Extent->Irp); - Extent->Irp = NULL; - } - - if (Ext2CanIWait()) { - KeWaitForSingleObject( &(pContext->Event), - Executive, KernelMode, FALSE, NULL ); - KeClearEvent( &(pContext->Event) ); - } else { - bMasterCompleted = TRUE; - } - - } __finally { - - for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { - if (Extent->Irp != NULL ) { - if (Extent->Irp->MdlAddress != NULL) { - IoFreeMdl(Extent->Irp->MdlAddress ); - } - IoFreeIrp(Extent->Irp); - } - } - - if (IrpContext->ExceptionInProgress) { - - if (bBugCheck) { - Ext2BugCheck(EXT2_BUGCHK_BLOCK, 0, 0, 0); - } - - } else { - - if (Ext2CanIWait()) { - if (MasterIrp) { - Status = MasterIrp->IoStatus.Status; - } - if (pContext) { - Ext2FreePool(pContext, EXT2_RWC_MAGIC); - DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); - } - } else { - if (bMasterCompleted) { - IrpContext->Irp = NULL; - Status = STATUS_PENDING; - } - } - } - } - - return Status; -} - -NTSTATUS -Ext2ReadSync( - IN PEXT2_VCB Vcb, - IN ULONGLONG Offset, - IN ULONG Length, - OUT PVOID Buffer, - BOOLEAN bVerify -) -{ - PKEVENT Event = NULL; - - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; - - - ASSERT(Vcb != NULL); - ASSERT(Vcb->TargetDeviceObject != NULL); - ASSERT(Buffer != NULL); - - __try { - - Event = Ext2AllocatePool(NonPagedPool, sizeof(KEVENT), 'EK2E'); - - if (NULL == Event) { - DEBUG(DL_ERR, ( "Ex2ReadSync: failed to allocate Event.\n")); - __leave; - } - - INC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); - - KeInitializeEvent(Event, NotificationEvent, FALSE); - - Irp = IoBuildSynchronousFsdRequest( - IRP_MJ_READ, - Vcb->TargetDeviceObject, - Buffer, - Length, - (PLARGE_INTEGER)(&Offset), - Event, - &IoStatus - ); - - if (!Irp) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - if (bVerify) { - SetFlag( IoGetNextIrpStackLocation(Irp)->Flags, - SL_OVERRIDE_VERIFY_VOLUME ); - } - - Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); - - if (Status == STATUS_PENDING) { - KeWaitForSingleObject( - Event, - Suspended, - KernelMode, - FALSE, - NULL - ); - - Status = IoStatus.Status; - } - - } __finally { - - if (Event) { - Ext2FreePool(Event, 'EK2E'); - DEC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); - } - } - - return Status; -} - - -NTSTATUS -Ext2ReadDisk( - IN PEXT2_VCB Vcb, - IN ULONGLONG Offset, - IN ULONG Size, - IN PVOID Buffer, - IN BOOLEAN bVerify ) -{ - NTSTATUS Status; - PUCHAR Buf; - ULONG Length; - ULONGLONG Lba; - - Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1)); - Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) & - (~((ULONG)SECTOR_SIZE - 1)); - - Buf = Ext2AllocatePool(PagedPool, Length, EXT2_DATA_MAGIC); - if (!Buf) { - DEBUG(DL_ERR, ( "Ext2ReadDisk: failed to allocate Buffer.\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - - goto errorout; - } - INC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length); - - Status = Ext2ReadSync( Vcb, - Lba, - Length, - Buf, - FALSE ); - - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ("Ext2ReadDisk: disk i/o error: %xh.\n", Status)); - goto errorout; - } - - RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size); - -errorout: - - if (Buf) { - Ext2FreePool(Buf, EXT2_DATA_MAGIC); - DEC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length); - } - - return Status; -} - - -NTSTATUS -Ext2DiskIoControl ( - IN PDEVICE_OBJECT DeviceObject, - IN ULONG IoctlCode, - IN PVOID InputBuffer, - IN ULONG InputBufferSize, - IN OUT PVOID OutputBuffer, - IN OUT PULONG OutputBufferSize) -{ - ULONG OutBufferSize = 0; - KEVENT Event; - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status; - - ASSERT(DeviceObject != NULL); - - if (OutputBufferSize) - { - OutBufferSize = *OutputBufferSize; - } - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - - Irp = IoBuildDeviceIoControlRequest( - IoctlCode, - DeviceObject, - InputBuffer, - InputBufferSize, - OutputBuffer, - OutBufferSize, - FALSE, - &Event, - &IoStatus - ); - - if (Irp == NULL) { - DEBUG(DL_ERR, ( "Ext2DiskIoControl: failed to build Irp!\n")); - return STATUS_INSUFFICIENT_RESOURCES; - } - - Status = IoCallDriver(DeviceObject, Irp); - - if (Status == STATUS_PENDING) { - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - Status = IoStatus.Status; - } - - if (OutputBufferSize) { - *OutputBufferSize = (ULONG)(IoStatus.Information); - } - - return Status; -} - - -NTSTATUS -Ext2MediaEjectControlCompletion ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Contxt -) -{ - PKEVENT Event = (PKEVENT)Contxt; - - KeSetEvent( Event, 0, FALSE ); - - UNREFERENCED_PARAMETER( DeviceObject ); - - return STATUS_SUCCESS; -} - -VOID -Ext2MediaEjectControl ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN BOOLEAN bPrevent -) -{ - PIRP Irp; - KEVENT Event; - NTSTATUS Status; - PREVENT_MEDIA_REMOVAL Prevent; - IO_STATUS_BLOCK IoStatus; - - - ExAcquireResourceExclusiveLite( - &Vcb->MainResource, - TRUE ); - - if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED)) { - if (bPrevent) { - SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); - } else { - ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); - } - } - - ExReleaseResourceLite(&Vcb->MainResource); - - Prevent.PreventMediaRemoval = bPrevent; - - KeInitializeEvent( &Event, NotificationEvent, FALSE ); - - Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_MEDIA_REMOVAL, - Vcb->TargetDeviceObject, - &Prevent, - sizeof(PREVENT_MEDIA_REMOVAL), - NULL, - 0, - FALSE, - NULL, - &IoStatus ); - - if (Irp != NULL) { - IoSetCompletionRoutine( Irp, - Ext2MediaEjectControlCompletion, - &Event, - TRUE, - TRUE, - TRUE ); - - Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); - - if (Status == STATUS_PENDING) { - Status = KeWaitForSingleObject( &Event, - Executive, - KernelMode, - FALSE, - NULL ); - } - } -} - - -NTSTATUS -Ext2DiskShutDown(PEXT2_VCB Vcb) -{ - PIRP Irp; - KEVENT Event; - - NTSTATUS Status; - IO_STATUS_BLOCK IoStatus; - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, - Vcb->TargetDeviceObject, - NULL, - 0, - NULL, - &Event, - &IoStatus); - - if (Irp) { - Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); - - if (Status == STATUS_PENDING) { - KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - NULL); - - Status = IoStatus.Status; - } - } else { - Status = IoStatus.Status; - } - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: block.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +NTSTATUS +Ext2ReadWriteBlockSyncCompletionRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context ); + +NTSTATUS +Ext2ReadWriteBlockAsyncCompletionRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context ); + + +NTSTATUS +Ext2MediaEjectControlCompletion ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, Ext2LockUserBuffer) +#pragma alloc_text(PAGE, Ext2ReadSync) +#pragma alloc_text(PAGE, Ext2ReadDisk) +#pragma alloc_text(PAGE, Ext2DiskIoControl) +#pragma alloc_text(PAGE, Ext2MediaEjectControl) +#pragma alloc_text(PAGE, Ext2DiskShutDown) +#endif + + +/* FUNCTIONS ***************************************************************/ + +PMDL +Ext2CreateMdl ( + IN PVOID Buffer, + IN ULONG Length, + IN LOCK_OPERATION op +) +{ + NTSTATUS Status; + PMDL Mdl = NULL; + + ASSERT (Buffer != NULL); + Mdl = IoAllocateMdl (Buffer, Length, FALSE, FALSE, NULL); + if (Mdl == NULL) { + Status = STATUS_INSUFFICIENT_RESOURCES; + } else { + __try { + if (MmIsNonPagedSystemAddressValid(Buffer)) { + MmBuildMdlForNonPagedPool(Mdl); + } else { + MmProbeAndLockPages(Mdl, KernelMode, op); + } + Status = STATUS_SUCCESS; + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoFreeMdl (Mdl); + Mdl = NULL; + DbgBreak(); + Status = STATUS_INVALID_USER_BUFFER; + } + } + return Mdl; +} + + +VOID +Ext2DestroyMdl (IN PMDL Mdl) +{ + ASSERT (Mdl != NULL); + while (Mdl) { + PMDL Next; + Next = Mdl->Next; + Mdl->Next = NULL; + if (IsFlagOn(Mdl->MdlFlags, MDL_PAGES_LOCKED)) { + MmUnlockPages (Mdl); + } + IoFreeMdl (Mdl); + Mdl = Next; + } +} + +NTSTATUS +Ext2LockUserBuffer (IN PIRP Irp, + IN ULONG Length, + IN LOCK_OPERATION Operation) +{ + NTSTATUS Status; + ASSERT(Irp != NULL); + + if (Irp->MdlAddress != NULL) { + return STATUS_SUCCESS; + } + + IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp); + if (Irp->MdlAddress == NULL) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + __try { + + MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); + Status = STATUS_SUCCESS; + + } __except (EXCEPTION_EXECUTE_HANDLER) { + + DbgBreak(); + IoFreeMdl(Irp->MdlAddress); + Irp->MdlAddress = NULL; + Status = STATUS_INVALID_USER_BUFFER; + } + + return Status; +} + +PVOID +Ext2GetUserBuffer (IN PIRP Irp ) +{ + ASSERT(Irp != NULL); + + if (Irp->MdlAddress) { + +#if (_WIN32_WINNT >= 0x0500) + return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); +#else + return MmGetSystemAddressForMdl(Irp->MdlAddress); +#endif + } else { + + return Irp->UserBuffer; + } +} + +NTSTATUS +Ext2ReadWriteBlockSyncCompletionRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context ) +{ + PEXT2_RW_CONTEXT pContext = (PEXT2_RW_CONTEXT)Context; + + if (Irp != pContext->MasterIrp) { + + if (!NT_SUCCESS(Irp->IoStatus.Status)) { + pContext->MasterIrp->IoStatus = Irp->IoStatus; + } + + IoFreeMdl(Irp->MdlAddress); + IoFreeIrp(Irp ); + } + + if (InterlockedDecrement(&pContext->Blocks) == 0) { + + pContext->MasterIrp->IoStatus.Information = 0; + if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) { + + pContext->MasterIrp->IoStatus.Information = + pContext->Length; + } + + KeSetEvent(&pContext->Event, 0, FALSE); + } + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +Ext2ReadWriteBlockAsyncCompletionRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context +) +{ + PEXT2_RW_CONTEXT pContext = (PEXT2_RW_CONTEXT)Context; + PIO_STACK_LOCATION iosp; + + ASSERT(FALSE == pContext->Wait); + + if (Irp != pContext->MasterIrp && !NT_SUCCESS(Irp->IoStatus.Status)) { + pContext->MasterIrp->IoStatus = Irp->IoStatus; + } + + if (InterlockedDecrement(&pContext->Blocks) == 0) { + + if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) { + + /* set written bytes to status information */ + pContext->MasterIrp->IoStatus.Information = pContext->Length; + + if (pContext->FileObject != NULL && !IsFlagOn(pContext->MasterIrp->Flags, IRP_PAGING_IO)) { + + /* modify FileObject flags, skip this for volume direct access */ + SetFlag( pContext->FileObject->Flags, + IsFlagOn(pContext->Flags, EXT2_RW_CONTEXT_WRITE) ? + FO_FILE_MODIFIED : FO_FILE_FAST_IO_READ); + + /* update Current Byteoffset */ + if (IsFlagOn(pContext->FileObject->Flags, FO_SYNCHRONOUS_IO)) { + iosp = IoGetCurrentIrpStackLocation(pContext->MasterIrp); + pContext->FileObject->CurrentByteOffset.QuadPart = + iosp->Parameters.Read.ByteOffset.QuadPart + pContext->Length; + } + } + + } else { + + pContext->MasterIrp->IoStatus.Information = 0; + } + + /* release the locked resource acquired by the caller */ + if (pContext->Resource) { + ExReleaseResourceForThread(pContext->Resource, pContext->ThreadId); + } + + Ext2FreePool(pContext, EXT2_RWC_MAGIC); + DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); + } + + return STATUS_SUCCESS; +} + +NTSTATUS +Ext2ReadWriteBlocks( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_EXTENT Chain, + IN ULONG Length + ) +{ + PIRP Irp; + PIRP MasterIrp = IrpContext->Irp; + PIO_STACK_LOCATION IrpSp; + PMDL Mdl; + PEXT2_RW_CONTEXT pContext = NULL; + PEXT2_EXTENT Extent; + KEVENT Wait; + NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN bMasterCompleted = FALSE; + BOOLEAN bBugCheck = FALSE; + + ASSERT(MasterIrp); + + __try { + + pContext = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_RW_CONTEXT), EXT2_RWC_MAGIC); + + if (!pContext) { + DEBUG(DL_ERR, ( "Ex2ReadWriteBlocks: failed to allocate pContext.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + INC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); + RtlZeroMemory(pContext, sizeof(EXT2_RW_CONTEXT)); + pContext->Wait = Ext2CanIWait(); + pContext->MasterIrp = MasterIrp; + pContext->Length = Length; + + if (IrpContext->MajorFunction == IRP_MJ_WRITE) { + SetFlag(pContext->Flags, EXT2_RW_CONTEXT_WRITE); + } + + if (pContext->Wait) { + + KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE); + + } else if (IrpContext->Fcb->Identifier.Type == EXT2FCB) { + + if (IsFlagOn(MasterIrp->Flags, IRP_PAGING_IO)) { + pContext->Resource = &IrpContext->Fcb->PagingIoResource; + } else { + pContext->Resource = &IrpContext->Fcb->MainResource; + } + + pContext->FileObject = IrpContext->FileObject; + pContext->ThreadId = ExGetCurrentResourceThread(); + } + + + if (NULL == Chain->Next && 0 == Chain->Offset) { + + /* we get only 1 extent to dispatch, then don't bother allocating new irps */ + + /* setup the Stack location to do a read from the disk driver. */ + IrpSp = IoGetNextIrpStackLocation(MasterIrp); + IrpSp->MajorFunction = IrpContext->MajorFunction; + IrpSp->Parameters.Read.Length = Chain->Length; + IrpSp->Parameters.Read.ByteOffset.QuadPart = Chain->Lba; + if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { + SetFlag(IrpSp->Flags, SL_WRITE_THROUGH); + } + if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { + SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); + } + + IoSetCompletionRoutine( + MasterIrp, + Ext2CanIWait() ? + Ext2ReadWriteBlockSyncCompletionRoutine : + Ext2ReadWriteBlockAsyncCompletionRoutine, + (PVOID) pContext, + TRUE, + TRUE, + TRUE ); + + /* intialize context block */ + Chain->Irp = MasterIrp; + pContext->Blocks = 1; + + } else { + + for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { + + Irp = IoMakeAssociatedIrp( + MasterIrp, + (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) ); + + if (!Irp) { + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer + + Extent->Offset, + Extent->Length, + FALSE, + FALSE, + Irp ); + + if (!Mdl) { + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + IoBuildPartialMdl( MasterIrp->MdlAddress, + Mdl, + (PCHAR)MasterIrp->UserBuffer+Extent->Offset, + Extent->Length ); + + IoSetNextIrpStackLocation(Irp); + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + IrpSp->MajorFunction = IrpContext->MajorFunction; + IrpSp->Parameters.Read.Length = Extent->Length; + IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; + + IoSetCompletionRoutine( + Irp, + Ext2CanIWait() ? + Ext2ReadWriteBlockSyncCompletionRoutine : + Ext2ReadWriteBlockAsyncCompletionRoutine, + (PVOID) pContext, + TRUE, + TRUE, + TRUE ); + + IrpSp = IoGetNextIrpStackLocation(Irp); + + IrpSp->MajorFunction = IrpContext->MajorFunction; + IrpSp->Parameters.Read.Length =Extent->Length; + IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; + + /* set write through flag */ + if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { + SetFlag( IrpSp->Flags, SL_WRITE_THROUGH ); + } + + /* set verify flag */ + if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { + SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); + } + + Extent->Irp = Irp; + pContext->Blocks += 1; + } + + MasterIrp->AssociatedIrp.IrpCount = pContext->Blocks; + if (Ext2CanIWait()) { + MasterIrp->AssociatedIrp.IrpCount += 1; + } + } + if (!Ext2CanIWait()) { + /* mark MasterIrp pending */ + IoMarkIrpPending(pContext->MasterIrp); + } + + bBugCheck = TRUE; + + for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { + Status = IoCallDriver ( Vcb->TargetDeviceObject, + Extent->Irp); + Extent->Irp = NULL; + } + + if (Ext2CanIWait()) { + KeWaitForSingleObject( &(pContext->Event), + Executive, KernelMode, FALSE, NULL ); + KeClearEvent( &(pContext->Event) ); + } else { + bMasterCompleted = TRUE; + } + + } __finally { + + for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { + if (Extent->Irp != NULL ) { + if (Extent->Irp->MdlAddress != NULL) { + IoFreeMdl(Extent->Irp->MdlAddress ); + } + IoFreeIrp(Extent->Irp); + } + } + + if (IrpContext->ExceptionInProgress) { + + if (bBugCheck) { + Ext2BugCheck(EXT2_BUGCHK_BLOCK, 0, 0, 0); + } + + } else { + + if (Ext2CanIWait()) { + if (MasterIrp) { + Status = MasterIrp->IoStatus.Status; + } + if (pContext) { + Ext2FreePool(pContext, EXT2_RWC_MAGIC); + DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); + } + } else { + if (bMasterCompleted) { + IrpContext->Irp = NULL; + Status = STATUS_PENDING; + } + } + } + } + + return Status; +} + +NTSTATUS +Ext2ReadSync( + IN PEXT2_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Length, + OUT PVOID Buffer, + BOOLEAN bVerify +) +{ + PKEVENT Event = NULL; + + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; + + + ASSERT(Vcb != NULL); + ASSERT(Vcb->TargetDeviceObject != NULL); + ASSERT(Buffer != NULL); + + __try { + + Event = Ext2AllocatePool(NonPagedPool, sizeof(KEVENT), 'EK2E'); + + if (NULL == Event) { + DEBUG(DL_ERR, ( "Ex2ReadSync: failed to allocate Event.\n")); + __leave; + } + + INC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); + + KeInitializeEvent(Event, NotificationEvent, FALSE); + + Irp = IoBuildSynchronousFsdRequest( + IRP_MJ_READ, + Vcb->TargetDeviceObject, + Buffer, + Length, + (PLARGE_INTEGER)(&Offset), + Event, + &IoStatus + ); + + if (!Irp) { + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + if (bVerify) { + SetFlag( IoGetNextIrpStackLocation(Irp)->Flags, + SL_OVERRIDE_VERIFY_VOLUME ); + } + + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + if (Status == STATUS_PENDING) { + KeWaitForSingleObject( + Event, + Suspended, + KernelMode, + FALSE, + NULL + ); + + Status = IoStatus.Status; + } + + } __finally { + + if (Event) { + Ext2FreePool(Event, 'EK2E'); + DEC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); + } + } + + return Status; +} + + +NTSTATUS +Ext2ReadDisk( + IN PEXT2_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Size, + IN PVOID Buffer, + IN BOOLEAN bVerify ) +{ + NTSTATUS Status; + PUCHAR Buf; + ULONG Length; + ULONGLONG Lba; + + Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1)); + Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) & + (~((ULONG)SECTOR_SIZE - 1)); + + Buf = Ext2AllocatePool(PagedPool, Length, EXT2_DATA_MAGIC); + if (!Buf) { + DEBUG(DL_ERR, ( "Ext2ReadDisk: failed to allocate Buffer.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + + goto errorout; + } + INC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length); + + Status = Ext2ReadSync( Vcb, + Lba, + Length, + Buf, + FALSE ); + + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ("Ext2ReadDisk: disk i/o error: %xh.\n", Status)); + goto errorout; + } + + RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size); + +errorout: + + if (Buf) { + Ext2FreePool(Buf, EXT2_DATA_MAGIC); + DEC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length); + } + + return Status; +} + + +NTSTATUS +Ext2DiskIoControl ( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG IoctlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize) +{ + ULONG OutBufferSize = 0; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + ASSERT(DeviceObject != NULL); + + if (OutputBufferSize) + { + OutBufferSize = *OutputBufferSize; + } + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildDeviceIoControlRequest( + IoctlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutBufferSize, + FALSE, + &Event, + &IoStatus + ); + + if (Irp == NULL) { + DEBUG(DL_ERR, ( "Ext2DiskIoControl: failed to build Irp!\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = IoCallDriver(DeviceObject, Irp); + + if (Status == STATUS_PENDING) { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + if (OutputBufferSize) { + *OutputBufferSize = (ULONG)(IoStatus.Information); + } + + return Status; +} + + +NTSTATUS +Ext2MediaEjectControlCompletion ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt +) +{ + PKEVENT Event = (PKEVENT)Contxt; + + KeSetEvent( Event, 0, FALSE ); + + UNREFERENCED_PARAMETER( DeviceObject ); + + return STATUS_SUCCESS; +} + +VOID +Ext2MediaEjectControl ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN BOOLEAN bPrevent +) +{ + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + PREVENT_MEDIA_REMOVAL Prevent; + IO_STATUS_BLOCK IoStatus; + + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE ); + + if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED)) { + if (bPrevent) { + SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); + } else { + ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); + } + } + + ExReleaseResourceLite(&Vcb->MainResource); + + Prevent.PreventMediaRemoval = bPrevent; + + KeInitializeEvent( &Event, NotificationEvent, FALSE ); + + Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_MEDIA_REMOVAL, + Vcb->TargetDeviceObject, + &Prevent, + sizeof(PREVENT_MEDIA_REMOVAL), + NULL, + 0, + FALSE, + NULL, + &IoStatus ); + + if (Irp != NULL) { + IoSetCompletionRoutine( Irp, + Ext2MediaEjectControlCompletion, + &Event, + TRUE, + TRUE, + TRUE ); + + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + if (Status == STATUS_PENDING) { + Status = KeWaitForSingleObject( &Event, + Executive, + KernelMode, + FALSE, + NULL ); + } + } +} + + +NTSTATUS +Ext2DiskShutDown(PEXT2_VCB Vcb) +{ + PIRP Irp; + KEVENT Event; + + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, + Vcb->TargetDeviceObject, + NULL, + 0, + NULL, + &Event, + &IoStatus); + + if (Irp) { + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + if (Status == STATUS_PENDING) { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + + Status = IoStatus.Status; + } + } else { + Status = IoStatus.Status; + } + + return Status; +} diff --git a/Ext4Fsd/cleanup.c b/Ext4Fsd/cleanup.c index 1d49d58..87540f4 100644 --- a/Ext4Fsd/cleanup.c +++ b/Ext4Fsd/cleanup.c @@ -1,399 +1,399 @@ -/* - * 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 = NULL; - PFILE_OBJECT FileObject; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PIRP Irp = NULL; - PEXT2_MCB Mcb = NULL; - - - BOOLEAN VcbResourceAcquired = FALSE; - BOOLEAN FcbResourceAcquired = FALSE; - BOOLEAN FcbPagingIoResourceAcquired = FALSE; - BOOLEAN SymLinkDelete = FALSE; - - __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; - __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; - __leave; - } - - FileObject = IrpContext->FileObject; - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (!Fcb || (Fcb->Identifier.Type != EXT2VCB && - Fcb->Identifier.Type != EXT2FCB)) { - Status = STATUS_SUCCESS; - __leave; - } - Mcb = Fcb->Mcb; - Ccb = (PEXT2_CCB) FileObject->FsContext2; - - if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { - Status = STATUS_SUCCESS; - __leave; - } - - if (Fcb->Identifier.Type == EXT2VCB) { - - ExAcquireResourceExclusiveLite( - &Vcb->MainResource, TRUE); - VcbResourceAcquired = TRUE; - - 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; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - FcbResourceAcquired = - ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - TRUE - ); - - 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); - } - __leave; - } - - if (Ccb == NULL) { - Status = STATUS_SUCCESS; - __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); - } - - 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)) { - if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { - SymLinkDelete = TRUE; - } else { - 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 - __try { - CcZeroData( FileObject, - &Fcb->Header.ValidDataLength, - &Fcb->Header.AllocationSize, - TRUE); - } __except (EXCEPTION_EXECUTE_HANDLER) { - DbgBreak(); - } - #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; - } - } - } - - IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); - - if (!IsDirectory(Fcb)) { - - if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && - (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) && - (Fcb->SectionObject.DataSectionObject != NULL)) { - - if (!IsVcbReadOnly(Vcb)) { - CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); - ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); - } - - /* purge cache if all remaining openings are non-cached */ - if (Fcb->NonCachedOpenCount > 0 || - IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { - if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { - ExReleaseResourceLite(&(Fcb->PagingIoResource)); - } - - /* CcPurge could generate recursive IRP_MJ_CLOSE request */ - CcPurgeCacheSection( &Fcb->SectionObject, - NULL, - 0, - FALSE ); - } - } - - CcUninitializeCacheMap(FileObject, NULL, NULL); - } - - if (SymLinkDelete || - (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) && - Fcb->OpenHandleCount == 0) ) { - - // - // 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, - TRUE - ); - if (!SymLinkDelete) { - SetFlag(FileObject->Flags, FO_FILE_MODIFIED); - if (CcIsFileCached(FileObject)) { - CcSetFileSizes(FileObject, - (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); - } - } - } - - 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); - } - - } __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); - } - } - } - - return Status; -} +/* + * 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 = NULL; + PFILE_OBJECT FileObject; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; + PEXT2_MCB Mcb = NULL; + + + BOOLEAN VcbResourceAcquired = FALSE; + BOOLEAN FcbResourceAcquired = FALSE; + BOOLEAN FcbPagingIoResourceAcquired = FALSE; + BOOLEAN SymLinkDelete = FALSE; + + __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; + __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; + __leave; + } + + FileObject = IrpContext->FileObject; + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (!Fcb || (Fcb->Identifier.Type != EXT2VCB && + Fcb->Identifier.Type != EXT2FCB)) { + Status = STATUS_SUCCESS; + __leave; + } + Mcb = Fcb->Mcb; + Ccb = (PEXT2_CCB) FileObject->FsContext2; + + if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { + Status = STATUS_SUCCESS; + __leave; + } + + if (Fcb->Identifier.Type == EXT2VCB) { + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + VcbResourceAcquired = TRUE; + + 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; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + FcbResourceAcquired = + ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + TRUE + ); + + 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); + } + __leave; + } + + if (Ccb == NULL) { + Status = STATUS_SUCCESS; + __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); + } + + 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)) { + if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { + SymLinkDelete = TRUE; + } else { + 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 + __try { + CcZeroData( FileObject, + &Fcb->Header.ValidDataLength, + &Fcb->Header.AllocationSize, + TRUE); + } __except (EXCEPTION_EXECUTE_HANDLER) { + DbgBreak(); + } + #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; + } + } + } + + IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); + + if (!IsDirectory(Fcb)) { + + if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && + (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) && + (Fcb->SectionObject.DataSectionObject != NULL)) { + + if (!IsVcbReadOnly(Vcb)) { + CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); + ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); + } + + /* purge cache if all remaining openings are non-cached */ + if (Fcb->NonCachedOpenCount > 0 || + IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { + if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { + ExReleaseResourceLite(&(Fcb->PagingIoResource)); + } + + /* CcPurge could generate recursive IRP_MJ_CLOSE request */ + CcPurgeCacheSection( &Fcb->SectionObject, + NULL, + 0, + FALSE ); + } + } + + CcUninitializeCacheMap(FileObject, NULL, NULL); + } + + if (SymLinkDelete || + (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) && + Fcb->OpenHandleCount == 0) ) { + + // + // 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, + TRUE + ); + if (!SymLinkDelete) { + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + if (CcIsFileCached(FileObject)) { + CcSetFileSizes(FileObject, + (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); + } + } + } + + 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); + } + + } __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); + } + } + } + + return Status; +} diff --git a/Ext4Fsd/close.c b/Ext4Fsd/close.c index 7a3b410..fbc677a 100644 --- a/Ext4Fsd/close.c +++ b/Ext4Fsd/close.c @@ -1,247 +1,247 @@ -/* - * 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; - PFILE_OBJECT FileObject; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - - BOOLEAN VcbResourceAcquired = FALSE; - BOOLEAN FcbResourceAcquired = FALSE; - BOOLEAN FcbDerefDeferred = FALSE; - - __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; - __leave; - } - - Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; - ASSERT(Vcb != NULL); - ASSERT((Vcb->Identifier.Type == EXT2VCB) && - (Vcb->Identifier.Size == sizeof(EXT2_VCB))); - - 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; - __leave; - } - ASSERT(Fcb != NULL); - Ccb = (PEXT2_CCB) FileObject->FsContext2; - } - - DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n", - Vcb, Vcb->ReferenceCount)); - - /* - * WARNING: don't release Vcb resource lock here. - * - * CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE - * which would cause revrese order of lock acquirision: - * 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock - * 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock - */ - - if (Fcb->Identifier.Type == EXT2VCB) { - - if (!ExAcquireResourceExclusiveLite( - &Vcb->MainResource, - TRUE )) { - DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", - Vcb->OpenHandleCount, Vcb->ReferenceCount)); - Status = STATUS_PENDING; - __leave; - } - VcbResourceAcquired = TRUE; - - if (Ccb) { - - Ext2DerefXcb(&Vcb->ReferenceCount); - Ext2FreeCcb(Vcb, Ccb); - - if (FileObject) { - FileObject->FsContext2 = Ccb = NULL; - } - } - - Status = STATUS_SUCCESS; - __leave; - } - - if ( Fcb->Identifier.Type != EXT2FCB || - Fcb->Identifier.Size != sizeof(EXT2_FCB)) { - __leave; - } - - if (!ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - TRUE )) { - Status = STATUS_PENDING; - __leave; - } - FcbResourceAcquired = TRUE; - - Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; - - if (Ccb == NULL || - Ccb->Identifier.Type != EXT2CCB || - Ccb->Identifier.Size != sizeof(EXT2_CCB)) { - Status = STATUS_SUCCESS; - __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 )); - - Ext2FreeCcb(Vcb, Ccb); - if (FileObject) { - FileObject->FsContext2 = Ccb = NULL; - } - - /* only deref fcb, Ext2ReleaseFcb might lead deadlock */ - FcbDerefDeferred = TRUE; - if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) || - NULL == Fcb->Mcb || - IsFileDeleted(Fcb->Mcb)) { - Fcb->TsDrop.QuadPart = 0; - } else { - KeQuerySystemTime(&Fcb->TsDrop); - } - Ext2DerefXcb(&Vcb->ReferenceCount); - - if (FileObject) { - FileObject->FsContext = NULL; - } - - Status = STATUS_SUCCESS; - - } __finally { - - if (FcbResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (VcbResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - - if (!IrpContext->ExceptionInProgress) { - - if (Status == STATUS_PENDING) { - - Ext2QueueCloseRequest(IrpContext); - - } else { - - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - if (FcbDerefDeferred) - Ext2DerefXcb(&Fcb->ReferenceCount); - } - - 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 -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))); - - __try { - - __try { - - FsRtlEnterFileSystem(); - Ext2Close(IrpContext); - - } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { - - Ext2ExceptionHandler(IrpContext); - } - - } __finally { - - FsRtlExitFileSystem(); - } -} +/* + * 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; + PFILE_OBJECT FileObject; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + + BOOLEAN VcbResourceAcquired = FALSE; + BOOLEAN FcbResourceAcquired = FALSE; + BOOLEAN FcbDerefDeferred = FALSE; + + __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; + __leave; + } + + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + ASSERT(Vcb != NULL); + ASSERT((Vcb->Identifier.Type == EXT2VCB) && + (Vcb->Identifier.Size == sizeof(EXT2_VCB))); + + 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; + __leave; + } + ASSERT(Fcb != NULL); + Ccb = (PEXT2_CCB) FileObject->FsContext2; + } + + DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n", + Vcb, Vcb->ReferenceCount)); + + /* + * WARNING: don't release Vcb resource lock here. + * + * CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE + * which would cause revrese order of lock acquirision: + * 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock + * 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock + */ + + if (Fcb->Identifier.Type == EXT2VCB) { + + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE )) { + DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", + Vcb->OpenHandleCount, Vcb->ReferenceCount)); + Status = STATUS_PENDING; + __leave; + } + VcbResourceAcquired = TRUE; + + if (Ccb) { + + Ext2DerefXcb(&Vcb->ReferenceCount); + Ext2FreeCcb(Vcb, Ccb); + + if (FileObject) { + FileObject->FsContext2 = Ccb = NULL; + } + } + + Status = STATUS_SUCCESS; + __leave; + } + + if ( Fcb->Identifier.Type != EXT2FCB || + Fcb->Identifier.Size != sizeof(EXT2_FCB)) { + __leave; + } + + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + TRUE )) { + Status = STATUS_PENDING; + __leave; + } + FcbResourceAcquired = TRUE; + + Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; + + if (Ccb == NULL || + Ccb->Identifier.Type != EXT2CCB || + Ccb->Identifier.Size != sizeof(EXT2_CCB)) { + Status = STATUS_SUCCESS; + __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 )); + + Ext2FreeCcb(Vcb, Ccb); + if (FileObject) { + FileObject->FsContext2 = Ccb = NULL; + } + + /* only deref fcb, Ext2ReleaseFcb might lead deadlock */ + FcbDerefDeferred = TRUE; + if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) || + NULL == Fcb->Mcb || + IsFileDeleted(Fcb->Mcb)) { + Fcb->TsDrop.QuadPart = 0; + } else { + KeQuerySystemTime(&Fcb->TsDrop); + } + Ext2DerefXcb(&Vcb->ReferenceCount); + + if (FileObject) { + FileObject->FsContext = NULL; + } + + Status = STATUS_SUCCESS; + + } __finally { + + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (VcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + } + + if (!IrpContext->ExceptionInProgress) { + + if (Status == STATUS_PENDING) { + + Ext2QueueCloseRequest(IrpContext); + + } else { + + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + if (FcbDerefDeferred) + Ext2DerefXcb(&Fcb->ReferenceCount); + } + + 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 +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))); + + __try { + + __try { + + FsRtlEnterFileSystem(); + Ext2Close(IrpContext); + + } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { + + Ext2ExceptionHandler(IrpContext); + } + + } __finally { + + FsRtlExitFileSystem(); + } +} diff --git a/Ext4Fsd/cmcb.c b/Ext4Fsd/cmcb.c index c689990..54d6cd2 100644 --- a/Ext4Fsd/cmcb.c +++ b/Ext4Fsd/cmcb.c @@ -1,138 +1,138 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: cmcb.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -#define CMCB_DEBUG_LEVEL DL_NVR - -BOOLEAN -Ext2AcquireForLazyWrite ( - IN PVOID Context, - IN BOOLEAN Wait) -{ - // - // On a readonly filesystem this function still has to exist but it - // doesn't need to do anything. - - PEXT2_FCB Fcb; - - Fcb = (PEXT2_FCB) Context; - ASSERT(Fcb != NULL); - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); -#if EXT2_DEBUG - DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForLazyWrite: %s %s Fcb=%p\n", - Ext2GetCurrentProcessName(), "ACQUIRE_FOR_LAZY_WRITE", Fcb)); -#endif - if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) { - return FALSE; - } - - ASSERT(Fcb->LazyWriterThread == NULL); - Fcb->LazyWriterThread = PsGetCurrentThread(); - - ASSERT(IoGetTopLevelIrp() == NULL); - IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); - - return TRUE; -} - -VOID -Ext2ReleaseFromLazyWrite (IN PVOID Context) -{ - // - // On a readonly filesystem this function still has to exist but it - // doesn't need to do anything. - PEXT2_FCB Fcb = (PEXT2_FCB) Context; - - ASSERT(Fcb != NULL); - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); -#if EXT2_DEBUG - DEBUG(CMCB_DEBUG_LEVEL, ( "Ext2ReleaseFromLazyWrite: %s %s Fcb=%p\n", - Ext2GetCurrentProcessName(), "RELEASE_FROM_LAZY_WRITE", Fcb)); -#endif - ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread()); - Fcb->LazyWriterThread = NULL; - - ExReleaseResourceLite(Fcb->Header.Resource); - - ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); - IoSetTopLevelIrp( NULL ); -} - -BOOLEAN -Ext2AcquireForReadAhead (IN PVOID Context, - IN BOOLEAN Wait) -{ - PEXT2_FCB Fcb = (PEXT2_FCB) Context; - - ASSERT(Fcb != NULL); - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForReadAhead: i=%xh Fcb=%p\n", - Fcb->Mcb->Inode.i_ino, Fcb)); - - if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) - return FALSE; - ASSERT(IoGetTopLevelIrp() == NULL); - IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); - - return TRUE; -} - -VOID -Ext2ReleaseFromReadAhead (IN PVOID Context) -{ - PEXT2_FCB Fcb = (PEXT2_FCB) Context; - - ASSERT(Fcb != NULL); - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFromReadAhead: i=%xh Fcb=%p\n", - Fcb->Mcb->Inode.i_ino, Fcb)); - - IoSetTopLevelIrp(NULL); - ExReleaseResourceLite(Fcb->Header.Resource); -} - -BOOLEAN -Ext2NoOpAcquire ( - IN PVOID Fcb, - IN BOOLEAN Wait -) -{ - ASSERT(IoGetTopLevelIrp() == NULL); - IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); - return TRUE; -} - -VOID -Ext2NoOpRelease ( - IN PVOID Fcb -) -{ - ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); - IoSetTopLevelIrp( NULL ); - - return; -} - +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: cmcb.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +#define CMCB_DEBUG_LEVEL DL_NVR + +BOOLEAN +Ext2AcquireForLazyWrite ( + IN PVOID Context, + IN BOOLEAN Wait) +{ + // + // On a readonly filesystem this function still has to exist but it + // doesn't need to do anything. + + PEXT2_FCB Fcb; + + Fcb = (PEXT2_FCB) Context; + ASSERT(Fcb != NULL); + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); +#if EXT2_DEBUG + DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForLazyWrite: %s %s Fcb=%p\n", + Ext2GetCurrentProcessName(), "ACQUIRE_FOR_LAZY_WRITE", Fcb)); +#endif + if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) { + return FALSE; + } + + ASSERT(Fcb->LazyWriterThread == NULL); + Fcb->LazyWriterThread = PsGetCurrentThread(); + + ASSERT(IoGetTopLevelIrp() == NULL); + IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + return TRUE; +} + +VOID +Ext2ReleaseFromLazyWrite (IN PVOID Context) +{ + // + // On a readonly filesystem this function still has to exist but it + // doesn't need to do anything. + PEXT2_FCB Fcb = (PEXT2_FCB) Context; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); +#if EXT2_DEBUG + DEBUG(CMCB_DEBUG_LEVEL, ( "Ext2ReleaseFromLazyWrite: %s %s Fcb=%p\n", + Ext2GetCurrentProcessName(), "RELEASE_FROM_LAZY_WRITE", Fcb)); +#endif + ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread()); + Fcb->LazyWriterThread = NULL; + + ExReleaseResourceLite(Fcb->Header.Resource); + + ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + IoSetTopLevelIrp( NULL ); +} + +BOOLEAN +Ext2AcquireForReadAhead (IN PVOID Context, + IN BOOLEAN Wait) +{ + PEXT2_FCB Fcb = (PEXT2_FCB) Context; + + ASSERT(Fcb != NULL); + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForReadAhead: i=%xh Fcb=%p\n", + Fcb->Mcb->Inode.i_ino, Fcb)); + + if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) + return FALSE; + ASSERT(IoGetTopLevelIrp() == NULL); + IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + return TRUE; +} + +VOID +Ext2ReleaseFromReadAhead (IN PVOID Context) +{ + PEXT2_FCB Fcb = (PEXT2_FCB) Context; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFromReadAhead: i=%xh Fcb=%p\n", + Fcb->Mcb->Inode.i_ino, Fcb)); + + IoSetTopLevelIrp(NULL); + ExReleaseResourceLite(Fcb->Header.Resource); +} + +BOOLEAN +Ext2NoOpAcquire ( + IN PVOID Fcb, + IN BOOLEAN Wait +) +{ + ASSERT(IoGetTopLevelIrp() == NULL); + IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + return TRUE; +} + +VOID +Ext2NoOpRelease ( + IN PVOID Fcb +) +{ + ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + IoSetTopLevelIrp( NULL ); + + return; +} + diff --git a/Ext4Fsd/debug.c b/Ext4Fsd/debug.c index 54eed8b..2f7eb53 100644 --- a/Ext4Fsd/debug.c +++ b/Ext4Fsd/debug.c @@ -1,2705 +1,2705 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: Debug.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES **************************************************************/ - -#include "stdarg.h" -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -#if EXT2_DEBUG - -#define SYSTEM_PROCESS_NAME "System" - -extern PEXT2_GLOBAL Ext2Global; - -ULONG DebugFilter = DL_DEFAULT; - -ULONG ProcessNameOffset = 0; - -/* DEFINITIONS ***********************************************************/ - - -/* Static Definitions ****************************************************/ - -static PUCHAR IrpMjStrings[] = { - "IRP_MJ_CREATE", - "IRP_MJ_CREATE_NAMED_PIPE", - "IRP_MJ_CLOSE", - "IRP_MJ_READ", - "IRP_MJ_WRITE", - "IRP_MJ_QUERY_INFORMATION", - "IRP_MJ_SET_INFORMATION", - "IRP_MJ_QUERY_EA", - "IRP_MJ_SET_EA", - "IRP_MJ_FLUSH_BUFFERS", - "IRP_MJ_QUERY_VOLUME_INFORMATION", - "IRP_MJ_SET_VOLUME_INFORMATION", - "IRP_MJ_DIRECTORY_CONTROL", - "IRP_MJ_FILE_SYSTEM_CONTROL", - "IRP_MJ_DEVICE_CONTROL", - "IRP_MJ_INTERNAL_DEVICE_CONTROL", - "IRP_MJ_SHUTDOWN", - "IRP_MJ_LOCK_CONTROL", - "IRP_MJ_CLEANUP", - "IRP_MJ_CREATE_MAILSLOT", - "IRP_MJ_QUERY_SECURITY", - "IRP_MJ_SET_SECURITY", - "IRP_MJ_POWER", - "IRP_MJ_SYSTEM_CONTROL", - "IRP_MJ_DEVICE_CHANGE", - "IRP_MJ_QUERY_QUOTA", - "IRP_MJ_SET_QUOTA", - "IRP_MJ_PNP" -}; - -static PUCHAR FileInformationClassStrings[] = { - "Unknown FileInformationClass 0", - "FileDirectoryInformation", - "FileFullDirectoryInformation", - "FileBothDirectoryInformation", - "FileBasicInformation", - "FileStandardInformation", - "FileInternalInformation", - "FileEaInformation", - "FileAccessInformation", - "FileNameInformation", - "FileRenameInformation", - "FileLinkInformation", - "FileNamesInformation", - "FileDispositionInformation", - "FilePositionInformation", - "FileFullEaInformation", - "FileModeInformation", - "FileAlignmentInformation", - "FileAllInformation", - "FileAllocationInformation", - "FileEndOfFileInformation", - "FileAlternateNameInformation", - "FileStreamInformation", - "FilePipeInformation", - "FilePipeLocalInformation", - "FilePipeRemoteInformation", - "FileMailslotQueryInformation", - "FileMailslotSetInformation", - "FileCompressionInformation", - "FileObjectIdInformation", - "FileCompletionInformation", - "FileMoveClusterInformation", - "FileQuotaInformation", - "FileReparsePointInformation", - "FileNetworkOpenInformation", - "FileAttributeTagInformation", - "FileTrackingInformation" -}; - -static PUCHAR FsInformationClassStrings[] = { - "Unknown FsInformationClass 0", - "FileFsVolumeInformation", - "FileFsLabelInformation", - "FileFsSizeInformation", - "FileFsDeviceInformation", - "FileFsAttributeInformation", - "FileFsControlInformation", - "FileFsFullSizeInformation", - "FileFsObjectIdInformation" -}; - -/* - * Ext2Printf - * This function is variable-argument, level-sensitive debug print routine. - * If the specified debug level for the print statement is lower or equal - * to the current debug level, the message will be printed. - * - * Arguments: - * DebugMessage - Variable argument ascii c string - * - * Return Value: - * N/A - * - * NOTES: - * N/A - */ - -#define DBG_BUF_LEN 0x100 -VOID -Ext2Printf( - PCHAR DebugMessage, - ... -) -{ - va_list ap; - LARGE_INTEGER CurrentTime; - TIME_FIELDS TimeFields; - CHAR Buffer[DBG_BUF_LEN]; - ULONG i; - - RtlZeroMemory(Buffer, DBG_BUF_LEN); - va_start(ap, DebugMessage); - - KeQuerySystemTime( &CurrentTime); - RtlTimeToTimeFields(&CurrentTime, &TimeFields); - _vsnprintf(&Buffer[0], DBG_BUF_LEN, DebugMessage, ap); - - DbgPrint(DRIVER_NAME":~%d: %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s", - KeGetCurrentProcessorNumber(), - TimeFields.Hour, TimeFields.Minute, - TimeFields.Second, TimeFields.Milliseconds, - PsGetCurrentThread(), Buffer); - - va_end(ap); -} - -VOID -Ext2NiPrintf( - PCHAR DebugMessage, - ... -) -{ - va_list ap; - LARGE_INTEGER CurrentTime; - TIME_FIELDS TimeFields; - CHAR Buffer[0x100]; - ULONG i; - - va_start(ap, DebugMessage); - - KeQuerySystemTime( &CurrentTime); - RtlTimeToTimeFields(&CurrentTime, &TimeFields); - _vsnprintf(&Buffer[0], 0x100, DebugMessage, ap); - - DbgPrint(DRIVER_NAME":~%d: %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s", - KeGetCurrentProcessorNumber(), - TimeFields.Hour, TimeFields.Minute, - TimeFields.Second, TimeFields.Milliseconds, - PsGetCurrentThread(), Buffer); - - va_end(ap); - -} // Ext2NiPrintf() - -ULONG -Ext2GetProcessNameOffset ( VOID ) -{ - PEPROCESS Process; - ULONG i; - - Process = PsGetCurrentProcess(); - - for (i = 0; i < PAGE_SIZE; i++) { - if (!strncmp( - SYSTEM_PROCESS_NAME, - (PCHAR) Process + i, - strlen(SYSTEM_PROCESS_NAME) - )) { - - return i; - } - } - - DEBUG(DL_ERR, ( ": *** FsdGetProcessNameOffset failed ***\n")); - - return 0; -} - - -VOID -Ext2DbgPrintCall (IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp ) -{ - PIO_STACK_LOCATION IoStackLocation; - PFILE_OBJECT FileObject; - PWCHAR FileName; - PEXT2_FCB Fcb; - FILE_INFORMATION_CLASS FileInformationClass; - FS_INFORMATION_CLASS FsInformationClass; - - IoStackLocation = IoGetCurrentIrpStackLocation(Irp); - - FileObject = IoStackLocation->FileObject; - - FileName = L"Unknown"; - - if (DeviceObject == Ext2Global->DiskdevObject) { - - FileName = DEVICE_NAME; - - } else if (DeviceObject == Ext2Global->CdromdevObject) { - - FileName = CDROM_NAME; - - } else if (FileObject && FileObject->FsContext) { - - Fcb = (PEXT2_FCB) FileObject->FsContext; - - if (Fcb->Identifier.Type == EXT2VCB) { - FileName = L"\\Volume"; - } else if (Fcb->Identifier.Type == EXT2FCB && Fcb->Mcb->FullName.Buffer) { - FileName = Fcb->Mcb->FullName.Buffer; - } - } - - switch (IoStackLocation->MajorFunction) { - - case IRP_MJ_CREATE: - - FileName = NULL; - - if (DeviceObject == Ext2Global->DiskdevObject) { - FileName = DEVICE_NAME; - } else if (DeviceObject == Ext2Global->CdromdevObject) { - FileName = CDROM_NAME; - } else if (IoStackLocation->FileObject->FileName.Length == 0) { - FileName = L"\\Volume"; - } - - if (FileName) { - DEBUGNI(DL_FUN, ("%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } else if (IoStackLocation->FileObject->FileName.Buffer) { - DEBUGNI(DL_FUN, ("%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - IoStackLocation->FileObject->FileName.Buffer - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - "Unknown" - )); - } - - break; - - case IRP_MJ_CLOSE: - - DEBUGNI(DL_FUN, ("%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - - break; - - case IRP_MJ_READ: - - if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_COMPLETE\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %S Offset: %I64xh Length: %xh %s%s%s%s%s%s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.Read.ByteOffset.QuadPart, - IoStackLocation->Parameters.Read.Length, - (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "), - (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "), - (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "), - (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "), - (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "), - (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " ") - )); - } - - break; - - case IRP_MJ_WRITE: - - if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_COMPLETE\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %S Offset: %I64xh Length: %xh %s%s%s%s%s%s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.Read.ByteOffset.QuadPart, - IoStackLocation->Parameters.Read.Length, - (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "), - (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "), - (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "), - (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "), - (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "), - (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " ") - )); - } - - break; - - case IRP_MJ_QUERY_INFORMATION: - - FileInformationClass = - IoStackLocation->Parameters.QueryFile.FileInformationClass; - - if (FileInformationClass <= FileMaximumInformation) { - DEBUGNI(DL_FUN, ("%s %s %S %s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FileInformationClassStrings[FileInformationClass] - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown FileInformationClass %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FileInformationClass - )); - } - - break; - - case IRP_MJ_SET_INFORMATION: - - FileInformationClass = - IoStackLocation->Parameters.SetFile.FileInformationClass; - - if (FileInformationClass <= FileMaximumInformation) { - DEBUGNI(DL_FUN, ("%s %s %S %s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FileInformationClassStrings[FileInformationClass] - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown FileInformationClass %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FileInformationClass - )); - } - - break; - - case IRP_MJ_QUERY_VOLUME_INFORMATION: - - FsInformationClass = - IoStackLocation->Parameters.QueryVolume.FsInformationClass; - - if (FsInformationClass <= FileFsMaximumInformation) { - DEBUGNI(DL_FUN, ("%s %s %S %s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FsInformationClassStrings[FsInformationClass] - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown FsInformationClass %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FsInformationClass - )); - } - - break; - - case IRP_MJ_DIRECTORY_CONTROL: - - if (IoStackLocation->MinorFunction & IRP_MN_QUERY_DIRECTORY) { - -#ifndef _GNU_NTIFS_ - FileInformationClass = - IoStackLocation->Parameters.QueryDirectory.FileInformationClass; -#else - FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; -#endif - - if (FileInformationClass <= FileMaximumInformation) { - DEBUGNI(DL_FUN, ("%s %s %S %s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FileInformationClassStrings[FileInformationClass] - )); - - if ( -#ifndef _GNU_NTIFS_ - IoStackLocation->Parameters.QueryDirectory.FileName -#else - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileName -#endif - ) { -#ifndef _GNU_NTIFS_ - DEBUGNI(DL_FUN, ("%s FileName: %.*S FileIndex: %x %s%s%s\n", - Ext2GetCurrentProcessName(), - - IoStackLocation->Parameters.QueryDirectory.FileName->Length / 2, - IoStackLocation->Parameters.QueryDirectory.FileName->Buffer, - IoStackLocation->Parameters.QueryDirectory.FileIndex, - (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), - (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), - ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : "") - )); - -#else - DEBUGNI(DL_FUN, ("%s FileName: %.*S FileIndex: %x %s%s%s\n", - Ext2GetCurrentProcessName(), - - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileName->Length / 2, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileName->Buffer, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileIndex, - (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), - (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), - ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : "") - )); -#endif - } else { -#ifndef _GNU_NTIFS_ - DEBUGNI(DL_FUN, ("%s FileName: FileIndex: %#x %s%s%s\n", - Ext2GetCurrentProcessName(), - IoStackLocation->Parameters.QueryDirectory.FileIndex, - (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), - (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), - (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : "") - )); -#else - DEBUGNI(DL_FUN, ("%s FileName: FileIndex: %#x %s%s%s\n", - Ext2GetCurrentProcessName(), - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileIndex, - (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), - (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), - (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : "") - )); -#endif - } - } else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown FileInformationClass %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - FileInformationClass - )); - } - } else if (IoStackLocation->MinorFunction & IRP_MN_NOTIFY_CHANGE_DIRECTORY) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown minor function %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->MinorFunction - )); - } - - break; - - case IRP_MJ_FILE_SYSTEM_CONTROL: - - if (IoStackLocation->MinorFunction == IRP_MN_USER_FS_REQUEST) { -#ifndef _GNU_NTIFS_ - DEBUGNI(DL_FUN, ( "%s %s %S IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.FileSystemControl.FsControlCode - )); -#else - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.FileSystemControl.FsControlCode - )); -#endif - } else if (IoStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_MOUNT_VOLUME DeviceObject: %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.MountVolume.DeviceObject - )); - } else if (IoStackLocation->MinorFunction == IRP_MN_VERIFY_VOLUME) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_VERIFY_VOLUME DeviceObject: %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.VerifyVolume.DeviceObject - )); - } else if (IoStackLocation->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_LOAD_FILE_SYSTEM\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } -#if (_WIN32_WINNT >= 0x0500) - else if (IoStackLocation->MinorFunction == IRP_MN_KERNEL_CALL) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_KERNEL_CALL\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } -#endif // (_WIN32_WINNT >= 0x0500) - else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown minor function %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->MinorFunction - )); - } - - break; - - case IRP_MJ_DEVICE_CONTROL: - - DEBUGNI(DL_FUN, ("%s %s %S IoControlCode: %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.DeviceIoControl.IoControlCode - )); - - break; - - case IRP_MJ_LOCK_CONTROL: - - if (IoStackLocation->MinorFunction & IRP_MN_LOCK) { -#ifndef _GNU_NTIFS_ - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart, - IoStackLocation->Parameters.LockControl.Length->QuadPart, - IoStackLocation->Parameters.LockControl.Key, - (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""), - (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : "") - )); -#else - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.Length->QuadPart, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.Key, - (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""), - (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : "") - )); -#endif - } else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_SINGLE) { -#ifndef _GNU_NTIFS_ - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart, - IoStackLocation->Parameters.LockControl.Length->QuadPart, - IoStackLocation->Parameters.LockControl.Key - )); -#else - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.Length->QuadPart, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.Key - )); -#endif - } else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL) { - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_ALL\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL_BY_KEY) { -#ifndef _GNU_NTIFS_ - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->Parameters.LockControl.Key - )); -#else - DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.LockControl.Key - )); -#endif - } else { - DEBUGNI(DL_FUN, ("%s %s %S Unknown minor function %#x\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName, - IoStackLocation->MinorFunction - )); - } - - break; - - case IRP_MJ_CLEANUP: - - DEBUGNI(DL_FUN, ("%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - - break; - - case IRP_MJ_SHUTDOWN: - - DEBUGNI(DL_FUN, ("%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - - break; - -#if (_WIN32_WINNT >= 0x0500) - case IRP_MJ_PNP: - - DEBUGNI(DL_FUN, ( "%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - break; -#endif // (_WIN32_WINNT >= 0x0500) - - default: - - DEBUGNI(DL_FUN, ("%s %s %S\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - FileName - )); - } -} - -VOID -Ext2DbgPrintComplete (IN PIRP Irp, IN BOOLEAN bPrint) -{ - PIO_STACK_LOCATION IoStackLocation; - - if (!Irp) - return; - - if (Irp->IoStatus.Status != STATUS_SUCCESS) { - - IoStackLocation = IoGetCurrentIrpStackLocation(Irp); - - if (bPrint) { - DEBUGNI(DL_FUN, ("%s %s Status: %s (%#x).\n", - Ext2GetCurrentProcessName(), - IrpMjStrings[IoStackLocation->MajorFunction], - Ext2NtStatusToString(Irp->IoStatus.Status), - Irp->IoStatus.Status - )); - } - } -} - -PUCHAR -Ext2NtStatusToString ( IN NTSTATUS Status ) -{ - switch (Status) { - - case 0x00000000: - return "STATUS_SUCCESS"; - case 0x00000001: - return "STATUS_WAIT_1"; - case 0x00000002: - return "STATUS_WAIT_2"; - case 0x00000003: - return "STATUS_WAIT_3"; - case 0x0000003F: - return "STATUS_WAIT_63"; - case 0x00000080: - return "STATUS_ABANDONED_WAIT_0"; - case 0x000000BF: - return "STATUS_ABANDONED_WAIT_63"; - case 0x000000C0: - return "STATUS_USER_APC"; - case 0x00000100: - return "STATUS_KERNEL_APC"; - case 0x00000101: - return "STATUS_ALERTED"; - case 0x00000102: - return "STATUS_TIMEOUT"; - case 0x00000103: - return "STATUS_PENDING"; - case 0x00000104: - return "STATUS_REPARSE"; - case 0x00000105: - return "STATUS_MORE_ENTRIES"; - case 0x00000106: - return "STATUS_NOT_ALL_ASSIGNED"; - case 0x00000107: - return "STATUS_SOME_NOT_MAPPED"; - case 0x00000108: - return "STATUS_OPLOCK_BREAK_IN_PROGRESS"; - case 0x00000109: - return "STATUS_VOLUME_MOUNTED"; - case 0x0000010A: - return "STATUS_RXACT_COMMITTED"; - case 0x0000010B: - return "STATUS_NOTIFY_CLEANUP"; - case 0x0000010C: - return "STATUS_NOTIFY_ENUM_DIR"; - case 0x0000010D: - return "STATUS_NO_QUOTAS_FOR_ACCOUNT"; - case 0x0000010E: - return "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED"; - case 0x00000110: - return "STATUS_PAGE_FAULT_TRANSITION"; - case 0x00000111: - return "STATUS_PAGE_FAULT_DEMAND_ZERO"; - case 0x00000112: - return "STATUS_PAGE_FAULT_COPY_ON_WRITE"; - case 0x00000113: - return "STATUS_PAGE_FAULT_GUARD_PAGE"; - case 0x00000114: - return "STATUS_PAGE_FAULT_PAGING_FILE"; - case 0x00000115: - return "STATUS_CACHE_PAGE_LOCKED"; - case 0x00000116: - return "STATUS_CRASH_DUMP"; - case 0x00000117: - return "STATUS_BUFFER_ALL_ZEROS"; - case 0x00000118: - return "STATUS_REPARSE_OBJECT"; - case 0x00000119: - return "STATUS_RESOURCE_REQUIREMENTS_CHANGED"; - case 0x00000120: - return "STATUS_TRANSLATION_COMPLETE"; - case 0x00000121: - return "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY"; - case 0x00010001: - return "DBG_EXCEPTION_HANDLED"; - case 0x00010002: - return "DBG_CONTINUE"; - case 0x40000000: - return "STATUS_OBJECT_NAME_EXISTS"; - case 0x40000001: - return "STATUS_THREAD_WAS_SUSPENDED"; - case 0x40000002: - return "STATUS_WORKING_SET_LIMIT_RANGE"; - case 0x40000003: - return "STATUS_IMAGE_NOT_AT_BASE"; - case 0x40000004: - return "STATUS_RXACT_STATE_CREATED"; - case 0x40000005: - return "STATUS_SEGMENT_NOTIFICATION"; - case 0x40000006: - return "STATUS_LOCAL_USER_SESSION_KEY"; - case 0x40000007: - return "STATUS_BAD_CURRENT_DIRECTORY"; - case 0x40000008: - return "STATUS_SERIAL_MORE_WRITES"; - case 0x40000009: - return "STATUS_REGISTRY_RECOVERED"; - case 0x4000000A: - return "STATUS_FT_READ_RECOVERY_FROM_BACKUP"; - case 0x4000000B: - return "STATUS_FT_WRITE_RECOVERY"; - case 0x4000000C: - return "STATUS_SERIAL_COUNTER_TIMEOUT"; - case 0x4000000D: - return "STATUS_NULL_LM_PASSWORD"; - case 0x4000000E: - return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH"; - case 0x4000000F: - return "STATUS_RECEIVE_PARTIAL"; - case 0x40000010: - return "STATUS_RECEIVE_EXPEDITED"; - case 0x40000011: - return "STATUS_RECEIVE_PARTIAL_EXPEDITED"; - case 0x40000012: - return "STATUS_EVENT_DONE"; - case 0x40000013: - return "STATUS_EVENT_PENDING"; - case 0x40000014: - return "STATUS_CHECKING_FILE_SYSTEM"; - case 0x40000015: - return "STATUS_FATAL_APP_EXIT"; - case 0x40000016: - return "STATUS_PREDEFINED_HANDLE"; - case 0x40000017: - return "STATUS_WAS_UNLOCKED"; - case 0x40000018: - return "STATUS_SERVICE_NOTIFICATION"; - case 0x40000019: - return "STATUS_WAS_LOCKED"; - case 0x4000001A: - return "STATUS_LOG_HARD_ERROR"; - case 0x4000001B: - return "STATUS_ALREADY_WIN32"; - case 0x4000001C: - return "STATUS_WX86_UNSIMULATE"; - case 0x4000001D: - return "STATUS_WX86_CONTINUE"; - case 0x4000001E: - return "STATUS_WX86_SINGLE_STEP"; - case 0x4000001F: - return "STATUS_WX86_BREAKPOINT"; - case 0x40000020: - return "STATUS_WX86_EXCEPTION_CONTINUE"; - case 0x40000021: - return "STATUS_WX86_EXCEPTION_LASTCHANCE"; - case 0x40000022: - return "STATUS_WX86_EXCEPTION_CHAIN"; - case 0x40000023: - return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE"; - case 0x40000024: - return "STATUS_NO_YIELD_PERFORMED"; - case 0x40000025: - return "STATUS_TIMER_RESUME_IGNORED"; - case 0x40000026: - return "STATUS_ARBITRATION_UNHANDLED"; - case 0x40000027: - return "STATUS_CARDBUS_NOT_SUPPORTED"; - case 0x40000028: - return "STATUS_WX86_CREATEWX86TIB"; - case 0x40000029: - return "STATUS_MP_PROCESSOR_MISMATCH"; - case 0x40010001: - return "DBG_REPLY_LATER"; - case 0x40010002: - return "DBG_UNABLE_TO_PROVIDE_HANDLE"; - case 0x40010003: - return "DBG_TERMINATE_THREAD"; - case 0x40010004: - return "DBG_TERMINATE_PROCESS"; - case 0x40010005: - return "DBG_CONTROL_C"; - case 0x40010006: - return "DBG_PRINTEXCEPTION_C"; - case 0x40010007: - return "DBG_RIPEXCEPTION"; - case 0x40010008: - return "DBG_CONTROL_BREAK"; - case 0x80000001: - return "STATUS_GUARD_PAGE_VIOLATION"; - case 0x80000002: - return "STATUS_DATATYPE_MISALIGNMENT"; - case 0x80000003: - return "STATUS_BREAKPOINT"; - case 0x80000004: - return "STATUS_SINGLE_STEP"; - case 0x80000005: - return "STATUS_BUFFER_OVERFLOW"; - case 0x80000006: - return "STATUS_NO_MORE_FILES"; - case 0x80000007: - return "STATUS_WAKE_SYSTEM_DEBUGGER"; - case 0x8000000A: - return "STATUS_HANDLES_CLOSED"; - case 0x8000000B: - return "STATUS_NO_INHERITANCE"; - case 0x8000000C: - return "STATUS_GUID_SUBSTITUTION_MADE"; - case 0x8000000D: - return "STATUS_PARTIAL_COPY"; - case 0x8000000E: - return "STATUS_DEVICE_PAPER_EMPTY"; - case 0x8000000F: - return "STATUS_DEVICE_POWERED_OFF"; - case 0x80000010: - return "STATUS_DEVICE_OFF_LINE"; - case 0x80000011: - return "STATUS_DEVICE_BUSY"; - case 0x80000012: - return "STATUS_NO_MORE_EAS"; - case 0x80000013: - return "STATUS_INVALID_EA_NAME"; - case 0x80000014: - return "STATUS_EA_LIST_INCONSISTENT"; - case 0x80000015: - return "STATUS_INVALID_EA_FLAG"; - case 0x80000016: - return "STATUS_VERIFY_REQUIRED"; - case 0x80000017: - return "STATUS_EXTRANEOUS_INFORMATION"; - case 0x80000018: - return "STATUS_RXACT_COMMIT_NECESSARY"; - case 0x8000001A: - return "STATUS_NO_MORE_ENTRIES"; - case 0x8000001B: - return "STATUS_FILEMARK_DETECTED"; - case 0x8000001C: - return "STATUS_MEDIA_CHANGED"; - case 0x8000001D: - return "STATUS_BUS_RESET"; - case 0x8000001E: - return "STATUS_END_OF_MEDIA"; - case 0x8000001F: - return "STATUS_BEGINNING_OF_MEDIA"; - case 0x80000020: - return "STATUS_MEDIA_CHECK"; - case 0x80000021: - return "STATUS_SETMARK_DETECTED"; - case 0x80000022: - return "STATUS_NO_DATA_DETECTED"; - case 0x80000023: - return "STATUS_REDIRECTOR_HAS_OPEN_HANDLES"; - case 0x80000024: - return "STATUS_SERVER_HAS_OPEN_HANDLES"; - case 0x80000025: - return "STATUS_ALREADY_DISCONNECTED"; - case 0x80000026: - return "STATUS_LONGJUMP"; - case 0x80010001: - return "DBG_EXCEPTION_NOT_HANDLED"; - case 0xC0000001: - return "STATUS_UNSUCCESSFUL"; - case 0xC0000002: - return "STATUS_NOT_IMPLEMENTED"; - case 0xC0000003: - return "STATUS_INVALID_INFO_CLASS"; - case 0xC0000004: - return "STATUS_INFO_LENGTH_MISMATCH"; - case 0xC0000005: - return "STATUS_ACCESS_VIOLATION"; - case 0xC0000006: - return "STATUS_IN_PAGE_ERROR"; - case 0xC0000007: - return "STATUS_PAGEFILE_QUOTA"; - case 0xC0000008: - return "STATUS_INVALID_HANDLE"; - case 0xC0000009: - return "STATUS_BAD_INITIAL_STACK"; - case 0xC000000A: - return "STATUS_BAD_INITIAL_PC"; - case 0xC000000B: - return "STATUS_INVALID_CID"; - case 0xC000000C: - return "STATUS_TIMER_NOT_CANCELED"; - case 0xC000000D: - return "STATUS_INVALID_PARAMETER"; - case 0xC000000E: - return "STATUS_NO_SUCH_DEVICE"; - case 0xC000000F: - return "STATUS_NO_SUCH_FILE"; - case 0xC0000010: - return "STATUS_INVALID_DEVICE_REQUEST"; - case 0xC0000011: - return "STATUS_END_OF_FILE"; - case 0xC0000012: - return "STATUS_WRONG_VOLUME"; - case 0xC0000013: - return "STATUS_NO_MEDIA_IN_DEVICE"; - case 0xC0000014: - return "STATUS_UNRECOGNIZED_MEDIA"; - case 0xC0000015: - return "STATUS_NONEXISTENT_SECTOR"; - case 0xC0000016: - return "STATUS_MORE_PROCESSING_REQUIRED"; - case 0xC0000017: - return "STATUS_NO_MEMORY"; - case 0xC0000018: - return "STATUS_CONFLICTING_ADDRESSES"; - case 0xC0000019: - return "STATUS_NOT_MAPPED_VIEW"; - case 0xC000001A: - return "STATUS_UNABLE_TO_FREE_VM"; - case 0xC000001B: - return "STATUS_UNABLE_TO_DELETE_SECTION"; - case 0xC000001C: - return "STATUS_INVALID_SYSTEM_SERVICE"; - case 0xC000001D: - return "STATUS_ILLEGAL_INSTRUCTION"; - case 0xC000001E: - return "STATUS_INVALID_LOCK_SEQUENCE"; - case 0xC000001F: - return "STATUS_INVALID_VIEW_SIZE"; - case 0xC0000020: - return "STATUS_INVALID_FILE_FOR_SECTION"; - case 0xC0000021: - return "STATUS_ALREADY_COMMITTED"; - case 0xC0000022: - return "STATUS_ACCESS_DENIED"; - case 0xC0000023: - return "STATUS_BUFFER_TOO_SMALL"; - case 0xC0000024: - return "STATUS_OBJECT_TYPE_MISMATCH"; - case 0xC0000025: - return "STATUS_NONCONTINUABLE_EXCEPTION"; - case 0xC0000026: - return "STATUS_INVALID_DISPOSITION"; - case 0xC0000027: - return "STATUS_UNWIND"; - case 0xC0000028: - return "STATUS_BAD_STACK"; - case 0xC0000029: - return "STATUS_INVALID_UNWIND_TARGET"; - case 0xC000002A: - return "STATUS_NOT_LOCKED"; - case 0xC000002B: - return "STATUS_PARITY_ERROR"; - case 0xC000002C: - return "STATUS_UNABLE_TO_DECOMMIT_VM"; - case 0xC000002D: - return "STATUS_NOT_COMMITTED"; - case 0xC000002E: - return "STATUS_INVALID_PORT_ATTRIBUTES"; - case 0xC000002F: - return "STATUS_PORT_MESSAGE_TOO_LONG"; - case 0xC0000030: - return "STATUS_INVALID_PARAMETER_MIX"; - case 0xC0000031: - return "STATUS_INVALID_QUOTA_LOWER"; - case 0xC0000032: - return "STATUS_DISK_CORRUPT_ERROR"; - case 0xC0000033: - return "STATUS_OBJECT_NAME_INVALID"; - case 0xC0000034: - return "STATUS_OBJECT_NAME_NOT_FOUND"; - case 0xC0000035: - return "STATUS_OBJECT_NAME_COLLISION"; - case 0xC0000037: - return "STATUS_PORT_DISCONNECTED"; - case 0xC0000038: - return "STATUS_DEVICE_ALREADY_ATTACHED"; - case 0xC0000039: - return "STATUS_OBJECT_PATH_INVALID"; - case 0xC000003A: - return "STATUS_OBJECT_PATH_NOT_FOUND"; - case 0xC000003B: - return "STATUS_OBJECT_PATH_SYNTAX_BAD"; - case 0xC000003C: - return "STATUS_DATA_OVERRUN"; - case 0xC000003D: - return "STATUS_DATA_LATE_ERROR"; - case 0xC000003E: - return "STATUS_DATA_ERROR"; - case 0xC000003F: - return "STATUS_CRC_ERROR"; - case 0xC0000040: - return "STATUS_SECTION_TOO_BIG"; - case 0xC0000041: - return "STATUS_PORT_CONNECTION_REFUSED"; - case 0xC0000042: - return "STATUS_INVALID_PORT_HANDLE"; - case 0xC0000043: - return "STATUS_SHARING_VIOLATION"; - case 0xC0000044: - return "STATUS_QUOTA_EXCEEDED"; - case 0xC0000045: - return "STATUS_INVALID_PAGE_PROTECTION"; - case 0xC0000046: - return "STATUS_MUTANT_NOT_OWNED"; - case 0xC0000047: - return "STATUS_SEMAPHORE_LIMIT_EXCEEDED"; - case 0xC0000048: - return "STATUS_PORT_ALREADY_SET"; - case 0xC0000049: - return "STATUS_SECTION_NOT_IMAGE"; - case 0xC000004A: - return "STATUS_SUSPEND_COUNT_EXCEEDED"; - case 0xC000004B: - return "STATUS_THREAD_IS_TERMINATING"; - case 0xC000004C: - return "STATUS_BAD_WORKING_SET_LIMIT"; - case 0xC000004D: - return "STATUS_INCOMPATIBLE_FILE_MAP"; - case 0xC000004E: - return "STATUS_SECTION_PROTECTION"; - case 0xC000004F: - return "STATUS_EAS_NOT_SUPPORTED"; - case 0xC0000050: - return "STATUS_EA_TOO_LARGE"; - case 0xC0000051: - return "STATUS_NONEXISTENT_EA_ENTRY"; - case 0xC0000052: - return "STATUS_NO_EAS_ON_FILE"; - case 0xC0000053: - return "STATUS_EA_CORRUPT_ERROR"; - case 0xC0000054: - return "STATUS_FILE_LOCK_CONFLICT"; - case 0xC0000055: - return "STATUS_LOCK_NOT_GRANTED"; - case 0xC0000056: - return "STATUS_DELETE_PENDING"; - case 0xC0000057: - return "STATUS_CTL_FILE_NOT_SUPPORTED"; - case 0xC0000058: - return "STATUS_UNKNOWN_REVISION"; - case 0xC0000059: - return "STATUS_REVISION_MISMATCH"; - case 0xC000005A: - return "STATUS_INVALID_OWNER"; - case 0xC000005B: - return "STATUS_INVALID_PRIMARY_GROUP"; - case 0xC000005C: - return "STATUS_NO_IMPERSONATION_TOKEN"; - case 0xC000005D: - return "STATUS_CANT_DISABLE_MANDATORY"; - case 0xC000005E: - return "STATUS_NO_LOGON_SERVERS"; - case 0xC000005F: - return "STATUS_NO_SUCH_LOGON_SESSION"; - case 0xC0000060: - return "STATUS_NO_SUCH_PRIVILEGE"; - case 0xC0000061: - return "STATUS_PRIVILEGE_NOT_HELD"; - case 0xC0000062: - return "STATUS_INVALID_ACCOUNT_NAME"; - case 0xC0000063: - return "STATUS_USER_EXISTS"; - case 0xC0000064: - return "STATUS_NO_SUCH_USER"; - case 0xC0000065: - return "STATUS_GROUP_EXISTS"; - case 0xC0000066: - return "STATUS_NO_SUCH_GROUP"; - case 0xC0000067: - return "STATUS_MEMBER_IN_GROUP"; - case 0xC0000068: - return "STATUS_MEMBER_NOT_IN_GROUP"; - case 0xC0000069: - return "STATUS_LAST_ADMIN"; - case 0xC000006A: - return "STATUS_WRONG_PASSWORD"; - case 0xC000006B: - return "STATUS_ILL_FORMED_PASSWORD"; - case 0xC000006C: - return "STATUS_PASSWORD_RESTRICTION"; - case 0xC000006D: - return "STATUS_LOGON_FAILURE"; - case 0xC000006E: - return "STATUS_ACCOUNT_RESTRICTION"; - case 0xC000006F: - return "STATUS_INVALID_LOGON_HOURS"; - case 0xC0000070: - return "STATUS_INVALID_WORKSTATION"; - case 0xC0000071: - return "STATUS_PASSWORD_EXPIRED"; - case 0xC0000072: - return "STATUS_ACCOUNT_DISABLED"; - case 0xC0000073: - return "STATUS_NONE_MAPPED"; - case 0xC0000074: - return "STATUS_TOO_MANY_LUIDS_REQUESTED"; - case 0xC0000075: - return "STATUS_LUIDS_EXHAUSTED"; - case 0xC0000076: - return "STATUS_INVALID_SUB_AUTHORITY"; - case 0xC0000077: - return "STATUS_INVALID_ACL"; - case 0xC0000078: - return "STATUS_INVALID_SID"; - case 0xC0000079: - return "STATUS_INVALID_SECURITY_DESCR"; - case 0xC000007A: - return "STATUS_PROCEDURE_NOT_FOUND"; - case 0xC000007B: - return "STATUS_INVALID_IMAGE_FORMAT"; - case 0xC000007C: - return "STATUS_NO_TOKEN"; - case 0xC000007D: - return "STATUS_BAD_INHERITANCE_ACL"; - case 0xC000007E: - return "STATUS_RANGE_NOT_LOCKED"; - case 0xC000007F: - return "STATUS_DISK_FULL"; - case 0xC0000080: - return "STATUS_SERVER_DISABLED"; - case 0xC0000081: - return "STATUS_SERVER_NOT_DISABLED"; - case 0xC0000082: - return "STATUS_TOO_MANY_GUIDS_REQUESTED"; - case 0xC0000083: - return "STATUS_GUIDS_EXHAUSTED"; - case 0xC0000084: - return "STATUS_INVALID_ID_AUTHORITY"; - case 0xC0000085: - return "STATUS_AGENTS_EXHAUSTED"; - case 0xC0000086: - return "STATUS_INVALID_VOLUME_LABEL"; - case 0xC0000087: - return "STATUS_SECTION_NOT_EXTENDED"; - case 0xC0000088: - return "STATUS_NOT_MAPPED_DATA"; - case 0xC0000089: - return "STATUS_RESOURCE_DATA_NOT_FOUND"; - case 0xC000008A: - return "STATUS_RESOURCE_TYPE_NOT_FOUND"; - case 0xC000008B: - return "STATUS_RESOURCE_NAME_NOT_FOUND"; - case 0xC000008C: - return "STATUS_ARRAY_BOUNDS_EXCEEDED"; - case 0xC000008D: - return "STATUS_FLOAT_DENORMAL_OPERAND"; - case 0xC000008E: - return "STATUS_FLOAT_DIVIDE_BY_ZERO"; - case 0xC000008F: - return "STATUS_FLOAT_INEXACT_RESULT"; - case 0xC0000090: - return "STATUS_FLOAT_INVALID_OPERATION"; - case 0xC0000091: - return "STATUS_FLOAT_OVERFLOW"; - case 0xC0000092: - return "STATUS_FLOAT_STACK_CHECK"; - case 0xC0000093: - return "STATUS_FLOAT_UNDERFLOW"; - case 0xC0000094: - return "STATUS_INTEGER_DIVIDE_BY_ZERO"; - case 0xC0000095: - return "STATUS_INTEGER_OVERFLOW"; - case 0xC0000096: - return "STATUS_PRIVILEGED_INSTRUCTION"; - case 0xC0000097: - return "STATUS_TOO_MANY_PAGING_FILES"; - case 0xC0000098: - return "STATUS_FILE_INVALID"; - case 0xC0000099: - return "STATUS_ALLOTTED_SPACE_EXCEEDED"; - case 0xC000009A: - return "STATUS_INSUFFICIENT_RESOURCES"; - case 0xC000009B: - return "STATUS_DFS_EXIT_PATH_FOUND"; - case 0xC000009C: - return "STATUS_DEVICE_DATA_ERROR"; - case 0xC000009D: - return "STATUS_DEVICE_NOT_CONNECTED"; - case 0xC000009E: - return "STATUS_DEVICE_POWER_FAILURE"; - case 0xC000009F: - return "STATUS_FREE_VM_NOT_AT_BASE"; - case 0xC00000A0: - return "STATUS_MEMORY_NOT_ALLOCATED"; - case 0xC00000A1: - return "STATUS_WORKING_SET_QUOTA"; - case 0xC00000A2: - return "STATUS_MEDIA_WRITE_PROTECTED"; - case 0xC00000A3: - return "STATUS_DEVICE_NOT_READY"; - case 0xC00000A4: - return "STATUS_INVALID_GROUP_ATTRIBUTES"; - case 0xC00000A5: - return "STATUS_BAD_IMPERSONATION_LEVEL"; - case 0xC00000A6: - return "STATUS_CANT_OPEN_ANONYMOUS"; - case 0xC00000A7: - return "STATUS_BAD_VALIDATION_CLASS"; - case 0xC00000A8: - return "STATUS_BAD_TOKEN_TYPE"; - case 0xC00000A9: - return "STATUS_BAD_MASTER_BOOT_RECORD"; - case 0xC00000AA: - return "STATUS_INSTRUCTION_MISALIGNMENT"; - case 0xC00000AB: - return "STATUS_INSTANCE_NOT_AVAILABLE"; - case 0xC00000AC: - return "STATUS_PIPE_NOT_AVAILABLE"; - case 0xC00000AD: - return "STATUS_INVALID_PIPE_STATE"; - case 0xC00000AE: - return "STATUS_PIPE_BUSY"; - case 0xC00000AF: - return "STATUS_ILLEGAL_FUNCTION"; - case 0xC00000B0: - return "STATUS_PIPE_DISCONNECTED"; - case 0xC00000B1: - return "STATUS_PIPE_CLOSING"; - case 0xC00000B2: - return "STATUS_PIPE_CONNECTED"; - case 0xC00000B3: - return "STATUS_PIPE_LISTENING"; - case 0xC00000B4: - return "STATUS_INVALID_READ_MODE"; - case 0xC00000B5: - return "STATUS_IO_TIMEOUT"; - case 0xC00000B6: - return "STATUS_FILE_FORCED_CLOSED"; - case 0xC00000B7: - return "STATUS_PROFILING_NOT_STARTED"; - case 0xC00000B8: - return "STATUS_PROFILING_NOT_STOPPED"; - case 0xC00000B9: - return "STATUS_COULD_NOT_INTERPRET"; - case 0xC00000BA: - return "STATUS_FILE_IS_A_DIRECTORY"; - case 0xC00000BB: - return "STATUS_NOT_SUPPORTED"; - case 0xC00000BC: - return "STATUS_REMOTE_NOT_LISTENING"; - case 0xC00000BD: - return "STATUS_DUPLICATE_NAME"; - case 0xC00000BE: - return "STATUS_BAD_NETWORK_PATH"; - case 0xC00000BF: - return "STATUS_NETWORK_BUSY"; - case 0xC00000C0: - return "STATUS_DEVICE_DOES_NOT_EXIST"; - case 0xC00000C1: - return "STATUS_TOO_MANY_COMMANDS"; - case 0xC00000C2: - return "STATUS_ADAPTER_HARDWARE_ERROR"; - case 0xC00000C3: - return "STATUS_INVALID_NETWORK_RESPONSE"; - case 0xC00000C4: - return "STATUS_UNEXPECTED_NETWORK_ERROR"; - case 0xC00000C5: - return "STATUS_BAD_REMOTE_ADAPTER"; - case 0xC00000C6: - return "STATUS_PRINT_QUEUE_FULL"; - case 0xC00000C7: - return "STATUS_NO_SPOOL_SPACE"; - case 0xC00000C8: - return "STATUS_PRINT_CANCELLED"; - case 0xC00000C9: - return "STATUS_NETWORK_NAME_DELETED"; - case 0xC00000CA: - return "STATUS_NETWORK_ACCESS_DENIED"; - case 0xC00000CB: - return "STATUS_BAD_DEVICE_TYPE"; - case 0xC00000CC: - return "STATUS_BAD_NETWORK_NAME"; - case 0xC00000CD: - return "STATUS_TOO_MANY_NAMES"; - case 0xC00000CE: - return "STATUS_TOO_MANY_SESSIONS"; - case 0xC00000CF: - return "STATUS_SHARING_PAUSED"; - case 0xC00000D0: - return "STATUS_REQUEST_NOT_ACCEPTED"; - case 0xC00000D1: - return "STATUS_REDIRECTOR_PAUSED"; - case 0xC00000D2: - return "STATUS_NET_WRITE_FAULT"; - case 0xC00000D3: - return "STATUS_PROFILING_AT_LIMIT"; - case 0xC00000D4: - return "STATUS_NOT_SAME_DEVICE"; - case 0xC00000D5: - return "STATUS_FILE_RENAMED"; - case 0xC00000D6: - return "STATUS_VIRTUAL_CIRCUIT_CLOSED"; - case 0xC00000D7: - return "STATUS_NO_SECURITY_ON_OBJECT"; - case 0xC00000D8: - return "STATUS_CANT_WAIT"; - case 0xC00000D9: - return "STATUS_PIPE_EMPTY"; - case 0xC00000DA: - return "STATUS_CANT_ACCESS_DOMAIN_INFO"; - case 0xC00000DB: - return "STATUS_CANT_TERMINATE_SELF"; - case 0xC00000DC: - return "STATUS_INVALID_SERVER_STATE"; - case 0xC00000DD: - return "STATUS_INVALID_DOMAIN_STATE"; - case 0xC00000DE: - return "STATUS_INVALID_DOMAIN_ROLE"; - case 0xC00000DF: - return "STATUS_NO_SUCH_DOMAIN"; - case 0xC00000E0: - return "STATUS_DOMAIN_EXISTS"; - case 0xC00000E1: - return "STATUS_DOMAIN_LIMIT_EXCEEDED"; - case 0xC00000E2: - return "STATUS_OPLOCK_NOT_GRANTED"; - case 0xC00000E3: - return "STATUS_INVALID_OPLOCK_PROTOCOL"; - case 0xC00000E4: - return "STATUS_INTERNAL_DB_CORRUPTION"; - case 0xC00000E5: - return "STATUS_INTERNAL_ERROR"; - case 0xC00000E6: - return "STATUS_GENERIC_NOT_MAPPED"; - case 0xC00000E7: - return "STATUS_BAD_DESCRIPTOR_FORMAT"; - case 0xC00000E8: - return "STATUS_INVALID_USER_BUFFER"; - case 0xC00000E9: - return "STATUS_UNEXPECTED_IO_ERROR"; - case 0xC00000EA: - return "STATUS_UNEXPECTED_MM_CREATE_ERR"; - case 0xC00000EB: - return "STATUS_UNEXPECTED_MM_MAP_ERROR"; - case 0xC00000EC: - return "STATUS_UNEXPECTED_MM_EXTEND_ERR"; - case 0xC00000ED: - return "STATUS_NOT_LOGON_PROCESS"; - case 0xC00000EE: - return "STATUS_LOGON_SESSION_EXISTS"; - case 0xC00000EF: - return "STATUS_INVALID_PARAMETER_1"; - case 0xC00000F0: - return "STATUS_INVALID_PARAMETER_2"; - case 0xC00000F1: - return "STATUS_INVALID_PARAMETER_3"; - case 0xC00000F2: - return "STATUS_INVALID_PARAMETER_4"; - case 0xC00000F3: - return "STATUS_INVALID_PARAMETER_5"; - case 0xC00000F4: - return "STATUS_INVALID_PARAMETER_6"; - case 0xC00000F5: - return "STATUS_INVALID_PARAMETER_7"; - case 0xC00000F6: - return "STATUS_INVALID_PARAMETER_8"; - case 0xC00000F7: - return "STATUS_INVALID_PARAMETER_9"; - case 0xC00000F8: - return "STATUS_INVALID_PARAMETER_10"; - case 0xC00000F9: - return "STATUS_INVALID_PARAMETER_11"; - case 0xC00000FA: - return "STATUS_INVALID_PARAMETER_12"; - case 0xC00000FB: - return "STATUS_REDIRECTOR_NOT_STARTED"; - case 0xC00000FC: - return "STATUS_REDIRECTOR_STARTED"; - case 0xC00000FD: - return "STATUS_STACK_OVERFLOW"; - case 0xC00000FE: - return "STATUS_NO_SUCH_PACKAGE"; - case 0xC00000FF: - return "STATUS_BAD_FUNCTION_TABLE"; - case 0xC0000100: - return "STATUS_VARIABLE_NOT_FOUND"; - case 0xC0000101: - return "STATUS_DIRECTORY_NOT_EMPTY"; - case 0xC0000102: - return "STATUS_FILE_CORRUPT_ERROR"; - case 0xC0000103: - return "STATUS_NOT_A_DIRECTORY"; - case 0xC0000104: - return "STATUS_BAD_LOGON_SESSION_STATE"; - case 0xC0000105: - return "STATUS_LOGON_SESSION_COLLISION"; - case 0xC0000106: - return "STATUS_NAME_TOO_LONG"; - case 0xC0000107: - return "STATUS_FILES_OPEN"; - case 0xC0000108: - return "STATUS_CONNECTION_IN_USE"; - case 0xC0000109: - return "STATUS_MESSAGE_NOT_FOUND"; - case 0xC000010A: - return "STATUS_PROCESS_IS_TERMINATING"; - case 0xC000010B: - return "STATUS_INVALID_LOGON_TYPE"; - case 0xC000010C: - return "STATUS_NO_GUID_TRANSLATION"; - case 0xC000010D: - return "STATUS_CANNOT_IMPERSONATE"; - case 0xC000010E: - return "STATUS_IMAGE_ALREADY_LOADED"; - case 0xC000010F: - return "STATUS_ABIOS_NOT_PRESENT"; - case 0xC0000110: - return "STATUS_ABIOS_LID_NOT_EXIST"; - case 0xC0000111: - return "STATUS_ABIOS_LID_ALREADY_OWNED"; - case 0xC0000112: - return "STATUS_ABIOS_NOT_LID_OWNER"; - case 0xC0000113: - return "STATUS_ABIOS_INVALID_COMMAND"; - case 0xC0000114: - return "STATUS_ABIOS_INVALID_LID"; - case 0xC0000115: - return "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE"; - case 0xC0000116: - return "STATUS_ABIOS_INVALID_SELECTOR"; - case 0xC0000117: - return "STATUS_NO_LDT"; - case 0xC0000118: - return "STATUS_INVALID_LDT_SIZE"; - case 0xC0000119: - return "STATUS_INVALID_LDT_OFFSET"; - case 0xC000011A: - return "STATUS_INVALID_LDT_DESCRIPTOR"; - case 0xC000011B: - return "STATUS_INVALID_IMAGE_NE_FORMAT"; - case 0xC000011C: - return "STATUS_RXACT_INVALID_STATE"; - case 0xC000011D: - return "STATUS_RXACT_COMMIT_FAILURE"; - case 0xC000011E: - return "STATUS_MAPPED_FILE_SIZE_ZERO"; - case 0xC000011F: - return "STATUS_TOO_MANY_OPENED_FILES"; - case 0xC0000120: - return "STATUS_CANCELLED"; - case 0xC0000121: - return "STATUS_CANNOT_DELETE"; - case 0xC0000122: - return "STATUS_INVALID_COMPUTER_NAME"; - case 0xC0000123: - return "STATUS_FILE_DELETED"; - case 0xC0000124: - return "STATUS_SPECIAL_ACCOUNT"; - case 0xC0000125: - return "STATUS_SPECIAL_GROUP"; - case 0xC0000126: - return "STATUS_SPECIAL_USER"; - case 0xC0000127: - return "STATUS_MEMBERS_PRIMARY_GROUP"; - case 0xC0000128: - return "STATUS_FILE_CLOSED"; - case 0xC0000129: - return "STATUS_TOO_MANY_THREADS"; - case 0xC000012A: - return "STATUS_THREAD_NOT_IN_PROCESS"; - case 0xC000012B: - return "STATUS_TOKEN_ALREADY_IN_USE"; - case 0xC000012C: - return "STATUS_PAGEFILE_QUOTA_EXCEEDED"; - case 0xC000012D: - return "STATUS_COMMITMENT_LIMIT"; - case 0xC000012E: - return "STATUS_INVALID_IMAGE_LE_FORMAT"; - case 0xC000012F: - return "STATUS_INVALID_IMAGE_NOT_MZ"; - case 0xC0000130: - return "STATUS_INVALID_IMAGE_PROTECT"; - case 0xC0000131: - return "STATUS_INVALID_IMAGE_WIN_16"; - case 0xC0000132: - return "STATUS_LOGON_SERVER_CONFLICT"; - case 0xC0000133: - return "STATUS_TIME_DIFFERENCE_AT_DC"; - case 0xC0000134: - return "STATUS_SYNCHRONIZATION_REQUIRED"; - case 0xC0000135: - return "STATUS_DLL_NOT_FOUND"; - case 0xC0000136: - return "STATUS_OPEN_FAILED"; - case 0xC0000137: - return "STATUS_IO_PRIVILEGE_FAILED"; - case 0xC0000138: - return "STATUS_ORDINAL_NOT_FOUND"; - case 0xC0000139: - return "STATUS_ENTRYPOINT_NOT_FOUND"; - case 0xC000013A: - return "STATUS_CONTROL_C_EXIT"; - case 0xC000013B: - return "STATUS_LOCAL_DISCONNECT"; - case 0xC000013C: - return "STATUS_REMOTE_DISCONNECT"; - case 0xC000013D: - return "STATUS_REMOTE_RESOURCES"; - case 0xC000013E: - return "STATUS_LINK_FAILED"; - case 0xC000013F: - return "STATUS_LINK_TIMEOUT"; - case 0xC0000140: - return "STATUS_INVALID_CONNECTION"; - case 0xC0000141: - return "STATUS_INVALID_ADDRESS"; - case 0xC0000142: - return "STATUS_DLL_INIT_FAILED"; - case 0xC0000143: - return "STATUS_MISSING_SYSTEMFILE"; - case 0xC0000144: - return "STATUS_UNHANDLED_EXCEPTION"; - case 0xC0000145: - return "STATUS_APP_INIT_FAILURE"; - case 0xC0000146: - return "STATUS_PAGEFILE_CREATE_FAILED"; - case 0xC0000147: - return "STATUS_NO_PAGEFILE"; - case 0xC0000148: - return "STATUS_INVALID_LEVEL"; - case 0xC0000149: - return "STATUS_WRONG_PASSWORD_CORE"; - case 0xC000014A: - return "STATUS_ILLEGAL_FLOAT_CONTEXT"; - case 0xC000014B: - return "STATUS_PIPE_BROKEN"; - case 0xC000014C: - return "STATUS_REGISTRY_CORRUPT"; - case 0xC000014D: - return "STATUS_REGISTRY_IO_FAILED"; - case 0xC000014E: - return "STATUS_NO_EVENT_PAIR"; - case 0xC000014F: - return "STATUS_UNRECOGNIZED_VOLUME"; - case 0xC0000150: - return "STATUS_SERIAL_NO_DEVICE_INITED"; - case 0xC0000151: - return "STATUS_NO_SUCH_ALIAS"; - case 0xC0000152: - return "STATUS_MEMBER_NOT_IN_ALIAS"; - case 0xC0000153: - return "STATUS_MEMBER_IN_ALIAS"; - case 0xC0000154: - return "STATUS_ALIAS_EXISTS"; - case 0xC0000155: - return "STATUS_LOGON_NOT_GRANTED"; - case 0xC0000156: - return "STATUS_TOO_MANY_SECRETS"; - case 0xC0000157: - return "STATUS_SECRET_TOO_LONG"; - case 0xC0000158: - return "STATUS_INTERNAL_DB_ERROR"; - case 0xC0000159: - return "STATUS_FULLSCREEN_MODE"; - case 0xC000015A: - return "STATUS_TOO_MANY_CONTEXT_IDS"; - case 0xC000015B: - return "STATUS_LOGON_TYPE_NOT_GRANTED"; - case 0xC000015C: - return "STATUS_NOT_REGISTRY_FILE"; - case 0xC000015D: - return "STATUS_NT_CROSS_ENCRYPTION_REQUIRED"; - case 0xC000015E: - return "STATUS_DOMAIN_CTRLR_CONFIG_ERROR"; - case 0xC000015F: - return "STATUS_FT_MISSING_MEMBER"; - case 0xC0000160: - return "STATUS_ILL_FORMED_SERVICE_ENTRY"; - case 0xC0000161: - return "STATUS_ILLEGAL_CHARACTER"; - case 0xC0000162: - return "STATUS_UNMAPPABLE_CHARACTER"; - case 0xC0000163: - return "STATUS_UNDEFINED_CHARACTER"; - case 0xC0000164: - return "STATUS_FLOPPY_VOLUME"; - case 0xC0000165: - return "STATUS_FLOPPY_ID_MARK_NOT_FOUND"; - case 0xC0000166: - return "STATUS_FLOPPY_WRONG_CYLINDER"; - case 0xC0000167: - return "STATUS_FLOPPY_UNKNOWN_ERROR"; - case 0xC0000168: - return "STATUS_FLOPPY_BAD_REGISTERS"; - case 0xC0000169: - return "STATUS_DISK_RECALIBRATE_FAILED"; - case 0xC000016A: - return "STATUS_DISK_OPERATION_FAILED"; - case 0xC000016B: - return "STATUS_DISK_RESET_FAILED"; - case 0xC000016C: - return "STATUS_SHARED_IRQ_BUSY"; - case 0xC000016D: - return "STATUS_FT_ORPHANING"; - case 0xC000016E: - return "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT"; - case 0xC0000172: - return "STATUS_PARTITION_FAILURE"; - case 0xC0000173: - return "STATUS_INVALID_BLOCK_LENGTH"; - case 0xC0000174: - return "STATUS_DEVICE_NOT_PARTITIONED"; - case 0xC0000175: - return "STATUS_UNABLE_TO_LOCK_MEDIA"; - case 0xC0000176: - return "STATUS_UNABLE_TO_UNLOAD_MEDIA"; - case 0xC0000177: - return "STATUS_EOM_OVERFLOW"; - case 0xC0000178: - return "STATUS_NO_MEDIA"; - case 0xC000017A: - return "STATUS_NO_SUCH_MEMBER"; - case 0xC000017B: - return "STATUS_INVALID_MEMBER"; - case 0xC000017C: - return "STATUS_KEY_DELETED"; - case 0xC000017D: - return "STATUS_NO_LOG_SPACE"; - case 0xC000017E: - return "STATUS_TOO_MANY_SIDS"; - case 0xC000017F: - return "STATUS_LM_CROSS_ENCRYPTION_REQUIRED"; - case 0xC0000180: - return "STATUS_KEY_HAS_CHILDREN"; - case 0xC0000181: - return "STATUS_CHILD_MUST_BE_VOLATILE"; - case 0xC0000182: - return "STATUS_DEVICE_CONFIGURATION_ERROR"; - case 0xC0000183: - return "STATUS_DRIVER_INTERNAL_ERROR"; - case 0xC0000184: - return "STATUS_INVALID_DEVICE_STATE"; - case 0xC0000185: - return "STATUS_IO_DEVICE_ERROR"; - case 0xC0000186: - return "STATUS_DEVICE_PROTOCOL_ERROR"; - case 0xC0000187: - return "STATUS_BACKUP_CONTROLLER"; - case 0xC0000188: - return "STATUS_LOG_FILE_FULL"; - case 0xC0000189: - return "STATUS_TOO_LATE"; - case 0xC000018A: - return "STATUS_NO_TRUST_LSA_SECRET"; - case 0xC000018B: - return "STATUS_NO_TRUST_SAM_ACCOUNT"; - case 0xC000018C: - return "STATUS_TRUSTED_DOMAIN_FAILURE"; - case 0xC000018D: - return "STATUS_TRUSTED_RELATIONSHIP_FAILURE"; - case 0xC000018E: - return "STATUS_EVENTLOG_FILE_CORRUPT"; - case 0xC000018F: - return "STATUS_EVENTLOG_CANT_START"; - case 0xC0000190: - return "STATUS_TRUST_FAILURE"; - case 0xC0000191: - return "STATUS_MUTANT_LIMIT_EXCEEDED"; - case 0xC0000192: - return "STATUS_NETLOGON_NOT_STARTED"; - case 0xC0000193: - return "STATUS_ACCOUNT_EXPIRED"; - case 0xC0000194: - return "STATUS_POSSIBLE_DEADLOCK"; - case 0xC0000195: - return "STATUS_NETWORK_CREDENTIAL_CONFLICT"; - case 0xC0000196: - return "STATUS_REMOTE_SESSION_LIMIT"; - case 0xC0000197: - return "STATUS_EVENTLOG_FILE_CHANGED"; - case 0xC0000198: - return "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"; - case 0xC0000199: - return "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"; - case 0xC000019A: - return "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"; - case 0xC000019B: - return "STATUS_DOMAIN_TRUST_INCONSISTENT"; - case 0xC000019C: - return "STATUS_FS_DRIVER_REQUIRED"; - case 0xC0000202: - return "STATUS_NO_USER_SESSION_KEY"; - case 0xC0000203: - return "STATUS_USER_SESSION_DELETED"; - case 0xC0000204: - return "STATUS_RESOURCE_LANG_NOT_FOUND"; - case 0xC0000205: - return "STATUS_INSUFF_SERVER_RESOURCES"; - case 0xC0000206: - return "STATUS_INVALID_BUFFER_SIZE"; - case 0xC0000207: - return "STATUS_INVALID_ADDRESS_COMPONENT"; - case 0xC0000208: - return "STATUS_INVALID_ADDRESS_WILDCARD"; - case 0xC0000209: - return "STATUS_TOO_MANY_ADDRESSES"; - case 0xC000020A: - return "STATUS_ADDRESS_ALREADY_EXISTS"; - case 0xC000020B: - return "STATUS_ADDRESS_CLOSED"; - case 0xC000020C: - return "STATUS_CONNECTION_DISCONNECTED"; - case 0xC000020D: - return "STATUS_CONNECTION_RESET"; - case 0xC000020E: - return "STATUS_TOO_MANY_NODES"; - case 0xC000020F: - return "STATUS_TRANSACTION_ABORTED"; - case 0xC0000210: - return "STATUS_TRANSACTION_TIMED_OUT"; - case 0xC0000211: - return "STATUS_TRANSACTION_NO_RELEASE"; - case 0xC0000212: - return "STATUS_TRANSACTION_NO_MATCH"; - case 0xC0000213: - return "STATUS_TRANSACTION_RESPONDED"; - case 0xC0000214: - return "STATUS_TRANSACTION_INVALID_ID"; - case 0xC0000215: - return "STATUS_TRANSACTION_INVALID_TYPE"; - case 0xC0000216: - return "STATUS_NOT_SERVER_SESSION"; - case 0xC0000217: - return "STATUS_NOT_CLIENT_SESSION"; - case 0xC0000218: - return "STATUS_CANNOT_LOAD_REGISTRY_FILE"; - case 0xC0000219: - return "STATUS_DEBUG_ATTACH_FAILED"; - case 0xC000021A: - return "STATUS_SYSTEM_PROCESS_TERMINATED"; - case 0xC000021B: - return "STATUS_DATA_NOT_ACCEPTED"; - case 0xC000021C: - return "STATUS_NO_BROWSER_SERVERS_FOUND"; - case 0xC000021D: - return "STATUS_VDM_HARD_ERROR"; - case 0xC000021E: - return "STATUS_DRIVER_CANCEL_TIMEOUT"; - case 0xC000021F: - return "STATUS_REPLY_MESSAGE_MISMATCH"; - case 0xC0000220: - return "STATUS_MAPPED_ALIGNMENT"; - case 0xC0000221: - return "STATUS_IMAGE_CHECKSUM_MISMATCH"; - case 0xC0000222: - return "STATUS_LOST_WRITEBEHIND_DATA"; - case 0xC0000223: - return "STATUS_CLIENT_SERVER_PARAMETERS_INVALID"; - case 0xC0000224: - return "STATUS_PASSWORD_MUST_CHANGE"; - case 0xC0000225: - return "STATUS_NOT_FOUND"; - case 0xC0000226: - return "STATUS_NOT_TINY_STREAM"; - case 0xC0000227: - return "STATUS_RECOVERY_FAILURE"; - case 0xC0000228: - return "STATUS_STACK_OVERFLOW_READ"; - case 0xC0000229: - return "STATUS_FAIL_CHECK"; - case 0xC000022A: - return "STATUS_DUPLICATE_OBJECTID"; - case 0xC000022B: - return "STATUS_OBJECTID_EXISTS"; - case 0xC000022C: - return "STATUS_CONVERT_TO_LARGE"; - case 0xC000022D: - return "STATUS_RETRY"; - case 0xC000022E: - return "STATUS_FOUND_OUT_OF_SCOPE"; - case 0xC000022F: - return "STATUS_ALLOCATE_BUCKET"; - case 0xC0000230: - return "STATUS_PROPSET_NOT_FOUND"; - case 0xC0000231: - return "STATUS_MARSHALL_OVERFLOW"; - case 0xC0000232: - return "STATUS_INVALID_VARIANT"; - case 0xC0000233: - return "STATUS_DOMAIN_CONTROLLER_NOT_FOUND"; - case 0xC0000234: - return "STATUS_ACCOUNT_LOCKED_OUT"; - case 0xC0000235: - return "STATUS_HANDLE_NOT_CLOSABLE"; - case 0xC0000236: - return "STATUS_CONNECTION_REFUSED"; - case 0xC0000237: - return "STATUS_GRACEFUL_DISCONNECT"; - case 0xC0000238: - return "STATUS_ADDRESS_ALREADY_ASSOCIATED"; - case 0xC0000239: - return "STATUS_ADDRESS_NOT_ASSOCIATED"; - case 0xC000023A: - return "STATUS_CONNECTION_INVALID"; - case 0xC000023B: - return "STATUS_CONNECTION_ACTIVE"; - case 0xC000023C: - return "STATUS_NETWORK_UNREACHABLE"; - case 0xC000023D: - return "STATUS_HOST_UNREACHABLE"; - case 0xC000023E: - return "STATUS_PROTOCOL_UNREACHABLE"; - case 0xC000023F: - return "STATUS_PORT_UNREACHABLE"; - case 0xC0000240: - return "STATUS_REQUEST_ABORTED"; - case 0xC0000241: - return "STATUS_CONNECTION_ABORTED"; - case 0xC0000242: - return "STATUS_BAD_COMPRESSION_BUFFER"; - case 0xC0000243: - return "STATUS_USER_MAPPED_FILE"; - case 0xC0000244: - return "STATUS_AUDIT_FAILED"; - case 0xC0000245: - return "STATUS_TIMER_RESOLUTION_NOT_SET"; - case 0xC0000246: - return "STATUS_CONNECTION_COUNT_LIMIT"; - case 0xC0000247: - return "STATUS_LOGIN_TIME_RESTRICTION"; - case 0xC0000248: - return "STATUS_LOGIN_WKSTA_RESTRICTION"; - case 0xC0000249: - return "STATUS_IMAGE_MP_UP_MISMATCH"; - case 0xC0000250: - return "STATUS_INSUFFICIENT_LOGON_INFO"; - case 0xC0000251: - return "STATUS_BAD_DLL_ENTRYPOINT"; - case 0xC0000252: - return "STATUS_BAD_SERVICE_ENTRYPOINT"; - case 0xC0000253: - return "STATUS_LPC_REPLY_LOST"; - case 0xC0000254: - return "STATUS_IP_ADDRESS_CONFLICT1"; - case 0xC0000255: - return "STATUS_IP_ADDRESS_CONFLICT2"; - case 0xC0000256: - return "STATUS_REGISTRY_QUOTA_LIMIT"; - case 0xC0000257: - return "STATUS_PATH_NOT_COVERED"; - case 0xC0000258: - return "STATUS_NO_CALLBACK_ACTIVE"; - case 0xC0000259: - return "STATUS_LICENSE_QUOTA_EXCEEDED"; - case 0xC000025A: - return "STATUS_PWD_TOO_SHORT"; - case 0xC000025B: - return "STATUS_PWD_TOO_RECENT"; - case 0xC000025C: - return "STATUS_PWD_HISTORY_CONFLICT"; - case 0xC000025E: - return "STATUS_PLUGPLAY_NO_DEVICE"; - case 0xC000025F: - return "STATUS_UNSUPPORTED_COMPRESSION"; - case 0xC0000260: - return "STATUS_INVALID_HW_PROFILE"; - case 0xC0000261: - return "STATUS_INVALID_PLUGPLAY_DEVICE_PATH"; - case 0xC0000262: - return "STATUS_DRIVER_ORDINAL_NOT_FOUND"; - case 0xC0000263: - return "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND"; - case 0xC0000264: - return "STATUS_RESOURCE_NOT_OWNED"; - case 0xC0000265: - return "STATUS_TOO_MANY_LINKS"; - case 0xC0000266: - return "STATUS_QUOTA_LIST_INCONSISTENT"; - case 0xC0000267: - return "STATUS_FILE_IS_OFFLINE"; - case 0xC0000268: - return "STATUS_EVALUATION_EXPIRATION"; - case 0xC0000269: - return "STATUS_ILLEGAL_DLL_RELOCATION"; - case 0xC000026A: - return "STATUS_LICENSE_VIOLATION"; - case 0xC000026B: - return "STATUS_DLL_INIT_FAILED_LOGOFF"; - case 0xC000026C: - return "STATUS_DRIVER_UNABLE_TO_LOAD"; - case 0xC000026D: - return "STATUS_DFS_UNAVAILABLE"; - case 0xC000026E: - return "STATUS_VOLUME_DISMOUNTED"; - case 0xC000026F: - return "STATUS_WX86_INTERNAL_ERROR"; - case 0xC0000270: - return "STATUS_WX86_FLOAT_STACK_CHECK"; - case 0xC0000271: - return "STATUS_VALIDATE_CONTINUE"; - case 0xC0000272: - return "STATUS_NO_MATCH"; - case 0xC0000273: - return "STATUS_NO_MORE_MATCHES"; - case 0xC0000275: - return "STATUS_NOT_A_REPARSE_POINT"; - case 0xC0000276: - return "STATUS_IO_REPARSE_TAG_INVALID"; - case 0xC0000277: - return "STATUS_IO_REPARSE_TAG_MISMATCH"; - case 0xC0000278: - return "STATUS_IO_REPARSE_DATA_INVALID"; - case 0xC0000279: - return "STATUS_IO_REPARSE_TAG_NOT_HANDLED"; - case 0xC0000280: - return "STATUS_REPARSE_POINT_NOT_RESOLVED"; - case 0xC0000281: - return "STATUS_DIRECTORY_IS_A_REPARSE_POINT"; - case 0xC0000282: - return "STATUS_RANGE_LIST_CONFLICT"; - case 0xC0000283: - return "STATUS_SOURCE_ELEMENT_EMPTY"; - case 0xC0000284: - return "STATUS_DESTINATION_ELEMENT_FULL"; - case 0xC0000285: - return "STATUS_ILLEGAL_ELEMENT_ADDRESS"; - case 0xC0000286: - return "STATUS_MAGAZINE_NOT_PRESENT"; - case 0xC0000287: - return "STATUS_REINITIALIZATION_NEEDED"; - case 0x80000288: - return "STATUS_DEVICE_REQUIRES_CLEANING"; - case 0x80000289: - return "STATUS_DEVICE_DOOR_OPEN"; - case 0xC000028A: - return "STATUS_ENCRYPTION_FAILED"; - case 0xC000028B: - return "STATUS_DECRYPTION_FAILED"; - case 0xC000028C: - return "STATUS_RANGE_NOT_FOUND"; - case 0xC000028D: - return "STATUS_NO_RECOVERY_POLICY"; - case 0xC000028E: - return "STATUS_NO_EFS"; - case 0xC000028F: - return "STATUS_WRONG_EFS"; - case 0xC0000290: - return "STATUS_NO_USER_KEYS"; - case 0xC0000291: - return "STATUS_FILE_NOT_ENCRYPTED"; - case 0xC0000292: - return "STATUS_NOT_EXPORT_FORMAT"; - case 0xC0000293: - return "STATUS_FILE_ENCRYPTED"; - case 0x40000294: - return "STATUS_WAKE_SYSTEM"; - case 0xC0000295: - return "STATUS_WMI_GUID_NOT_FOUND"; - case 0xC0000296: - return "STATUS_WMI_INSTANCE_NOT_FOUND"; - case 0xC0000297: - return "STATUS_WMI_ITEMID_NOT_FOUND"; - case 0xC0000298: - return "STATUS_WMI_TRY_AGAIN"; - case 0xC0000299: - return "STATUS_SHARED_POLICY"; - case 0xC000029A: - return "STATUS_POLICY_OBJECT_NOT_FOUND"; - case 0xC000029B: - return "STATUS_POLICY_ONLY_IN_DS"; - case 0xC000029C: - return "STATUS_VOLUME_NOT_UPGRADED"; - case 0xC000029D: - return "STATUS_REMOTE_STORAGE_NOT_ACTIVE"; - case 0xC000029E: - return "STATUS_REMOTE_STORAGE_MEDIA_ERROR"; - case 0xC000029F: - return "STATUS_NO_TRACKING_SERVICE"; - case 0xC00002A0: - return "STATUS_SERVER_SID_MISMATCH"; - case 0xC00002A1: - return "STATUS_DS_NO_ATTRIBUTE_OR_VALUE"; - case 0xC00002A2: - return "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX"; - case 0xC00002A3: - return "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED"; - case 0xC00002A4: - return "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS"; - case 0xC00002A5: - return "STATUS_DS_BUSY"; - case 0xC00002A6: - return "STATUS_DS_UNAVAILABLE"; - case 0xC00002A7: - return "STATUS_DS_NO_RIDS_ALLOCATED"; - case 0xC00002A8: - return "STATUS_DS_NO_MORE_RIDS"; - case 0xC00002A9: - return "STATUS_DS_INCORRECT_ROLE_OWNER"; - case 0xC00002AA: - return "STATUS_DS_RIDMGR_INIT_ERROR"; - case 0xC00002AB: - return "STATUS_DS_OBJ_CLASS_VIOLATION"; - case 0xC00002AC: - return "STATUS_DS_CANT_ON_NON_LEAF"; - case 0xC00002AD: - return "STATUS_DS_CANT_ON_RDN"; - case 0xC00002AE: - return "STATUS_DS_CANT_MOD_OBJ_CLASS"; - case 0xC00002AF: - return "STATUS_DS_CROSS_DOM_MOVE_FAILED"; - case 0xC00002B0: - return "STATUS_DS_GC_NOT_AVAILABLE"; - case 0xC00002B1: - return "STATUS_DIRECTORY_SERVICE_REQUIRED"; - case 0xC00002B2: - return "STATUS_REPARSE_ATTRIBUTE_CONFLICT"; - case 0xC00002B3: - return "STATUS_CANT_ENABLE_DENY_ONLY"; - case 0xC00002B4: - return "STATUS_FLOAT_MULTIPLE_FAULTS"; - case 0xC00002B5: - return "STATUS_FLOAT_MULTIPLE_TRAPS"; - case 0xC00002B6: - return "STATUS_DEVICE_REMOVED"; - case 0xC00002B7: - return "STATUS_JOURNAL_DELETE_IN_PROGRESS"; - case 0xC00002B8: - return "STATUS_JOURNAL_NOT_ACTIVE"; - case 0xC00002B9: - return "STATUS_NOINTERFACE"; - case 0xC00002C1: - return "STATUS_DS_ADMIN_LIMIT_EXCEEDED"; - case 0xC00002C2: - return "STATUS_DRIVER_FAILED_SLEEP"; - case 0xC00002C3: - return "STATUS_MUTUAL_AUTHENTICATION_FAILED"; - case 0xC00002C4: - return "STATUS_CORRUPT_SYSTEM_FILE"; - case 0xC00002C5: - return "STATUS_DATATYPE_MISALIGNMENT_ERROR"; - case 0xC00002C6: - return "STATUS_WMI_READ_ONLY"; - case 0xC00002C7: - return "STATUS_WMI_SET_FAILURE"; - case 0xC00002C8: - return "STATUS_COMMITMENT_MINIMUM"; - case 0xC00002C9: - return "STATUS_REG_NAT_CONSUMPTION"; - case 0xC00002CA: - return "STATUS_TRANSPORT_FULL"; - case 0xC00002CB: - return "STATUS_DS_SAM_INIT_FAILURE"; - case 0xC00002CC: - return "STATUS_ONLY_IF_CONNECTED"; - case 0xC00002CD: - return "STATUS_DS_SENSITIVE_GROUP_VIOLATION"; - case 0xC00002CE: - return "STATUS_PNP_RESTART_ENUMERATION"; - case 0xC00002CF: - return "STATUS_JOURNAL_ENTRY_DELETED"; - case 0xC00002D0: - return "STATUS_DS_CANT_MOD_PRIMARYGROUPID"; - case 0xC00002D1: - return "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE"; - case 0xC00002D2: - return "STATUS_PNP_REBOOT_REQUIRED"; - case 0xC00002D3: - return "STATUS_POWER_STATE_INVALID"; - case 0xC00002D4: - return "STATUS_DS_INVALID_GROUP_TYPE"; - case 0xC00002D5: - return "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN"; - case 0xC00002D6: - return "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN"; - case 0xC00002D7: - return "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER"; - case 0xC00002D8: - return "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER"; - case 0xC00002D9: - return "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER"; - case 0xC00002DA: - return "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER"; - case 0xC00002DB: - return "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER"; - case 0xC00002DC: - return "STATUS_DS_HAVE_PRIMARY_MEMBERS"; - case 0xC00002DD: - return "STATUS_WMI_NOT_SUPPORTED"; - case 0xC00002DE: - return "STATUS_INSUFFICIENT_POWER"; - case 0xC00002DF: - return "STATUS_SAM_NEED_BOOTKEY_PASSWORD"; - case 0xC00002E0: - return "STATUS_SAM_NEED_BOOTKEY_FLOPPY"; - case 0xC00002E1: - return "STATUS_DS_CANT_START"; - case 0xC00002E2: - return "STATUS_DS_INIT_FAILURE"; - case 0xC00002E3: - return "STATUS_SAM_INIT_FAILURE"; - case 0xC00002E4: - return "STATUS_DS_GC_REQUIRED"; - case 0xC00002E5: - return "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY"; - case 0xC00002E6: - return "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS"; - case 0xC00002E7: - return "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED"; - case 0xC00002E8: - return "STATUS_MULTIPLE_FAULT_VIOLATION"; - case 0xC0000300: - return "STATUS_NOT_SUPPORTED_ON_SBS"; - case 0xC0009898: - return "STATUS_WOW_ASSERTION"; - case 0xC0010001: - return "DBG_NO_STATE_CHANGE"; - case 0xC0010002: - return "DBG_APP_NOT_IDLE"; - case 0xC0020001: - return "RPC_NT_INVALID_STRING_BINDING"; - case 0xC0020002: - return "RPC_NT_WRONG_KIND_OF_BINDING"; - case 0xC0020003: - return "RPC_NT_INVALID_BINDING"; - case 0xC0020004: - return "RPC_NT_PROTSEQ_NOT_SUPPORTED"; - case 0xC0020005: - return "RPC_NT_INVALID_RPC_PROTSEQ"; - case 0xC0020006: - return "RPC_NT_INVALID_STRING_UUID"; - case 0xC0020007: - return "RPC_NT_INVALID_ENDPOINT_FORMAT"; - case 0xC0020008: - return "RPC_NT_INVALID_NET_ADDR"; - case 0xC0020009: - return "RPC_NT_NO_ENDPOINT_FOUND"; - case 0xC002000A: - return "RPC_NT_INVALID_TIMEOUT"; - case 0xC002000B: - return "RPC_NT_OBJECT_NOT_FOUND"; - case 0xC002000C: - return "RPC_NT_ALREADY_REGISTERED"; - case 0xC002000D: - return "RPC_NT_TYPE_ALREADY_REGISTERED"; - case 0xC002000E: - return "RPC_NT_ALREADY_LISTENING"; - case 0xC002000F: - return "RPC_NT_NO_PROTSEQS_REGISTERED"; - case 0xC0020010: - return "RPC_NT_NOT_LISTENING"; - case 0xC0020011: - return "RPC_NT_UNKNOWN_MGR_TYPE"; - case 0xC0020012: - return "RPC_NT_UNKNOWN_IF"; - case 0xC0020013: - return "RPC_NT_NO_BINDINGS"; - case 0xC0020014: - return "RPC_NT_NO_PROTSEQS"; - case 0xC0020015: - return "RPC_NT_CANT_CREATE_ENDPOINT"; - case 0xC0020016: - return "RPC_NT_OUT_OF_RESOURCES"; - case 0xC0020017: - return "RPC_NT_SERVER_UNAVAILABLE"; - case 0xC0020018: - return "RPC_NT_SERVER_TOO_BUSY"; - case 0xC0020019: - return "RPC_NT_INVALID_NETWORK_OPTIONS"; - case 0xC002001A: - return "RPC_NT_NO_CALL_ACTIVE"; - case 0xC002001B: - return "RPC_NT_CALL_FAILED"; - case 0xC002001C: - return "RPC_NT_CALL_FAILED_DNE"; - case 0xC002001D: - return "RPC_NT_PROTOCOL_ERROR"; - case 0xC002001F: - return "RPC_NT_UNSUPPORTED_TRANS_SYN"; - case 0xC0020021: - return "RPC_NT_UNSUPPORTED_TYPE"; - case 0xC0020022: - return "RPC_NT_INVALID_TAG"; - case 0xC0020023: - return "RPC_NT_INVALID_BOUND"; - case 0xC0020024: - return "RPC_NT_NO_ENTRY_NAME"; - case 0xC0020025: - return "RPC_NT_INVALID_NAME_SYNTAX"; - case 0xC0020026: - return "RPC_NT_UNSUPPORTED_NAME_SYNTAX"; - case 0xC0020028: - return "RPC_NT_UUID_NO_ADDRESS"; - case 0xC0020029: - return "RPC_NT_DUPLICATE_ENDPOINT"; - case 0xC002002A: - return "RPC_NT_UNKNOWN_AUTHN_TYPE"; - case 0xC002002B: - return "RPC_NT_MAX_CALLS_TOO_SMALL"; - case 0xC002002C: - return "RPC_NT_STRING_TOO_LONG"; - case 0xC002002D: - return "RPC_NT_PROTSEQ_NOT_FOUND"; - case 0xC002002E: - return "RPC_NT_PROCNUM_OUT_OF_RANGE"; - case 0xC002002F: - return "RPC_NT_BINDING_HAS_NO_AUTH"; - case 0xC0020030: - return "RPC_NT_UNKNOWN_AUTHN_SERVICE"; - case 0xC0020031: - return "RPC_NT_UNKNOWN_AUTHN_LEVEL"; - case 0xC0020032: - return "RPC_NT_INVALID_AUTH_IDENTITY"; - case 0xC0020033: - return "RPC_NT_UNKNOWN_AUTHZ_SERVICE"; - case 0xC0020034: - return "EPT_NT_INVALID_ENTRY"; - case 0xC0020035: - return "EPT_NT_CANT_PERFORM_OP"; - case 0xC0020036: - return "EPT_NT_NOT_REGISTERED"; - case 0xC0020037: - return "RPC_NT_NOTHING_TO_EXPORT"; - case 0xC0020038: - return "RPC_NT_INCOMPLETE_NAME"; - case 0xC0020039: - return "RPC_NT_INVALID_VERS_OPTION"; - case 0xC002003A: - return "RPC_NT_NO_MORE_MEMBERS"; - case 0xC002003B: - return "RPC_NT_NOT_ALL_OBJS_UNEXPORTED"; - case 0xC002003C: - return "RPC_NT_INTERFACE_NOT_FOUND"; - case 0xC002003D: - return "RPC_NT_ENTRY_ALREADY_EXISTS"; - case 0xC002003E: - return "RPC_NT_ENTRY_NOT_FOUND"; - case 0xC002003F: - return "RPC_NT_NAME_SERVICE_UNAVAILABLE"; - case 0xC0020040: - return "RPC_NT_INVALID_NAF_ID"; - case 0xC0020041: - return "RPC_NT_CANNOT_SUPPORT"; - case 0xC0020042: - return "RPC_NT_NO_CONTEXT_AVAILABLE"; - case 0xC0020043: - return "RPC_NT_INTERNAL_ERROR"; - case 0xC0020044: - return "RPC_NT_ZERO_DIVIDE"; - case 0xC0020045: - return "RPC_NT_ADDRESS_ERROR"; - case 0xC0020046: - return "RPC_NT_FP_DIV_ZERO"; - case 0xC0020047: - return "RPC_NT_FP_UNDERFLOW"; - case 0xC0020048: - return "RPC_NT_FP_OVERFLOW"; - case 0xC0030001: - return "RPC_NT_NO_MORE_ENTRIES"; - case 0xC0030002: - return "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL"; - case 0xC0030003: - return "RPC_NT_SS_CHAR_TRANS_SHORT_FILE"; - case 0xC0030004: - return "RPC_NT_SS_IN_NULL_CONTEXT"; - case 0xC0030005: - return "RPC_NT_SS_CONTEXT_MISMATCH"; - case 0xC0030006: - return "RPC_NT_SS_CONTEXT_DAMAGED"; - case 0xC0030007: - return "RPC_NT_SS_HANDLES_MISMATCH"; - case 0xC0030008: - return "RPC_NT_SS_CANNOT_GET_CALL_HANDLE"; - case 0xC0030009: - return "RPC_NT_NULL_REF_POINTER"; - case 0xC003000A: - return "RPC_NT_ENUM_VALUE_OUT_OF_RANGE"; - case 0xC003000B: - return "RPC_NT_BYTE_COUNT_TOO_SMALL"; - case 0xC003000C: - return "RPC_NT_BAD_STUB_DATA"; - case 0xC0020049: - return "RPC_NT_CALL_IN_PROGRESS"; - case 0xC002004A: - return "RPC_NT_NO_MORE_BINDINGS"; - case 0xC002004B: - return "RPC_NT_GROUP_MEMBER_NOT_FOUND"; - case 0xC002004C: - return "EPT_NT_CANT_CREATE"; - case 0xC002004D: - return "RPC_NT_INVALID_OBJECT"; - case 0xC002004F: - return "RPC_NT_NO_INTERFACES"; - case 0xC0020050: - return "RPC_NT_CALL_CANCELLED"; - case 0xC0020051: - return "RPC_NT_BINDING_INCOMPLETE"; - case 0xC0020052: - return "RPC_NT_COMM_FAILURE"; - case 0xC0020053: - return "RPC_NT_UNSUPPORTED_AUTHN_LEVEL"; - case 0xC0020054: - return "RPC_NT_NO_PRINC_NAME"; - case 0xC0020055: - return "RPC_NT_NOT_RPC_ERROR"; - case 0x40020056: - return "RPC_NT_UUID_LOCAL_ONLY"; - case 0xC0020057: - return "RPC_NT_SEC_PKG_ERROR"; - case 0xC0020058: - return "RPC_NT_NOT_CANCELLED"; - case 0xC0030059: - return "RPC_NT_INVALID_ES_ACTION"; - case 0xC003005A: - return "RPC_NT_WRONG_ES_VERSION"; - case 0xC003005B: - return "RPC_NT_WRONG_STUB_VERSION"; - case 0xC003005C: - return "RPC_NT_INVALID_PIPE_OBJECT"; - case 0xC003005D: - return "RPC_NT_INVALID_PIPE_OPERATION"; - case 0xC003005E: - return "RPC_NT_WRONG_PIPE_VERSION"; - case 0xC003005F: - return "RPC_NT_PIPE_CLOSED"; - case 0xC0030060: - return "RPC_NT_PIPE_DISCIPLINE_ERROR"; - case 0xC0030061: - return "RPC_NT_PIPE_EMPTY"; - case 0xC0020062: - return "RPC_NT_INVALID_ASYNC_HANDLE"; - case 0xC0020063: - return "RPC_NT_INVALID_ASYNC_CALL"; - case 0x400200AF: - return "RPC_NT_SEND_INCOMPLETE"; - case 0xC0140001: - return "STATUS_ACPI_INVALID_OPCODE"; - case 0xC0140002: - return "STATUS_ACPI_STACK_OVERFLOW"; - case 0xC0140003: - return "STATUS_ACPI_ASSERT_FAILED"; - case 0xC0140004: - return "STATUS_ACPI_INVALID_INDEX"; - case 0xC0140005: - return "STATUS_ACPI_INVALID_ARGUMENT"; - case 0xC0140006: - return "STATUS_ACPI_FATAL"; - case 0xC0140007: - return "STATUS_ACPI_INVALID_SUPERNAME"; - case 0xC0140008: - return "STATUS_ACPI_INVALID_ARGTYPE"; - case 0xC0140009: - return "STATUS_ACPI_INVALID_OBJTYPE"; - case 0xC014000A: - return "STATUS_ACPI_INVALID_TARGETTYPE"; - case 0xC014000B: - return "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT"; - case 0xC014000C: - return "STATUS_ACPI_ADDRESS_NOT_MAPPED"; - case 0xC014000D: - return "STATUS_ACPI_INVALID_EVENTTYPE"; - case 0xC014000E: - return "STATUS_ACPI_HANDLER_COLLISION"; - case 0xC014000F: - return "STATUS_ACPI_INVALID_DATA"; - case 0xC0140010: - return "STATUS_ACPI_INVALID_REGION"; - case 0xC0140011: - return "STATUS_ACPI_INVALID_ACCESS_SIZE"; - case 0xC0140012: - return "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK"; - case 0xC0140013: - return "STATUS_ACPI_ALREADY_INITIALIZED"; - case 0xC0140014: - return "STATUS_ACPI_NOT_INITIALIZED"; - case 0xC0140015: - return "STATUS_ACPI_INVALID_MUTEX_LEVEL"; - case 0xC0140016: - return "STATUS_ACPI_MUTEX_NOT_OWNED"; - case 0xC0140017: - return "STATUS_ACPI_MUTEX_NOT_OWNER"; - case 0xC0140018: - return "STATUS_ACPI_RS_ACCESS"; - case 0xC0140019: - return "STATUS_ACPI_INVALID_TABLE"; - case 0xC0140020: - return "STATUS_ACPI_REG_HANDLER_FAILED"; - case 0xC0140021: - return "STATUS_ACPI_POWER_REQUEST_FAILED"; - case 0xC00A0001: - return "STATUS_CTX_WINSTATION_NAME_INVALID"; - case 0xC00A0002: - return "STATUS_CTX_INVALID_PD"; - case 0xC00A0003: - return "STATUS_CTX_PD_NOT_FOUND"; - case 0x400A0004: - return "STATUS_CTX_CDM_CONNECT"; - case 0x400A0005: - return "STATUS_CTX_CDM_DISCONNECT"; - case 0xC00A0006: - return "STATUS_CTX_CLOSE_PENDING"; - case 0xC00A0007: - return "STATUS_CTX_NO_OUTBUF"; - case 0xC00A0008: - return "STATUS_CTX_MODEM_INF_NOT_FOUND"; - case 0xC00A0009: - return "STATUS_CTX_INVALID_MODEMNAME"; - case 0xC00A000A: - return "STATUS_CTX_RESPONSE_ERROR"; - case 0xC00A000B: - return "STATUS_CTX_MODEM_RESPONSE_TIMEOUT"; - case 0xC00A000C: - return "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER"; - case 0xC00A000D: - return "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE"; - case 0xC00A000E: - return "STATUS_CTX_MODEM_RESPONSE_BUSY"; - case 0xC00A000F: - return "STATUS_CTX_MODEM_RESPONSE_VOICE"; - case 0xC00A0010: - return "STATUS_CTX_TD_ERROR"; - case 0xC00A0012: - return "STATUS_CTX_LICENSE_CLIENT_INVALID"; - case 0xC00A0013: - return "STATUS_CTX_LICENSE_NOT_AVAILABLE"; - case 0xC00A0014: - return "STATUS_CTX_LICENSE_EXPIRED"; - case 0xC00A0015: - return "STATUS_CTX_WINSTATION_NOT_FOUND"; - case 0xC00A0016: - return "STATUS_CTX_WINSTATION_NAME_COLLISION"; - case 0xC00A0017: - return "STATUS_CTX_WINSTATION_BUSY"; - case 0xC00A0018: - return "STATUS_CTX_BAD_VIDEO_MODE"; - case 0xC00A0022: - return "STATUS_CTX_GRAPHICS_INVALID"; - case 0xC00A0024: - return "STATUS_CTX_NOT_CONSOLE"; - case 0xC00A0026: - return "STATUS_CTX_CLIENT_QUERY_TIMEOUT"; - case 0xC00A0027: - return "STATUS_CTX_CONSOLE_DISCONNECT"; - case 0xC00A0028: - return "STATUS_CTX_CONSOLE_CONNECT"; - case 0xC00A002A: - return "STATUS_CTX_SHADOW_DENIED"; - case 0xC00A002B: - return "STATUS_CTX_WINSTATION_ACCESS_DENIED"; - case 0xC00A002E: - return "STATUS_CTX_INVALID_WD"; - case 0xC00A002F: - return "STATUS_CTX_WD_NOT_FOUND"; - case 0xC00A0030: - return "STATUS_CTX_SHADOW_INVALID"; - case 0xC00A0031: - return "STATUS_CTX_SHADOW_DISABLED"; - case 0xC00A0032: - return "STATUS_RDP_PROTOCOL_ERROR"; - case 0xC00A0033: - return "STATUS_CTX_CLIENT_LICENSE_NOT_SET"; - case 0xC00A0034: - return "STATUS_CTX_CLIENT_LICENSE_IN_USE"; - case 0xC0040035: - return "STATUS_PNP_BAD_MPS_TABLE"; - case 0xC0040036: - return "STATUS_PNP_TRANSLATION_FAILED"; - case 0xC0040037: - return "STATUS_PNP_IRQ_TRANSLATION_FAILED"; - default: - return "STATUS_UNKNOWN"; - } -} - - -/* avoid stack overflow for dead symlinks */ - -VOID -Ext2TraceMcb(PCHAR fn, USHORT lc, USHORT add, PEXT2_MCB Mcb) { - size_t i; - CHAR _space[33]; - - _snprintf(&_space[0], 32, "%s:%d:", fn, lc); - _space[32] = 0; - i = strlen(_space); - while (i < 32) { - _space[i++] = ' '; - _space[i]=0; - } - if (add) { - Ext2ReferXcb(&Mcb->Refercount); - DEBUG(DL_RES, ("%s +%2u %wZ (%p)\n", _space, (Mcb->Refercount - 1), &Mcb->FullName, Mcb)); - } else { - Ext2DerefXcb(&Mcb->Refercount); - DEBUG(DL_RES, ("%s -%2u %wZ (%p)\n", _space, Mcb->Refercount, &Mcb->FullName, Mcb)); - } -} - -KSPIN_LOCK Ext2MemoryLock; -ULONGLONG Ext2TotalMemorySize = 0; -ULONG Ext2TotalAllocates = 0; - -PVOID -Ext2AllocatePool( - IN POOL_TYPE PoolType, - IN SIZE_T NumberOfBytes, - IN ULONG Tag -) -{ - PUCHAR Buffer = ExAllocatePoolWithTag( - PoolType, - 0x20 + NumberOfBytes, - Tag); - if (Buffer) { - KIRQL Irql = 0; - PULONG Data = (PULONG)Buffer; - Data[0] = (ULONG)NumberOfBytes; - Data[1] = (ULONG)NumberOfBytes + 0x20; - memset(Buffer + 0x08, 'S', 8); - memset(Buffer + 0x10 + NumberOfBytes, 'E', 0x10); - Buffer += 0x10; - KeAcquireSpinLock(&Ext2MemoryLock, &Irql); - Ext2TotalMemorySize = Ext2TotalMemorySize + NumberOfBytes; - Ext2TotalAllocates += 1; - KeReleaseSpinLock(&Ext2MemoryLock, Irql); - } - - return Buffer; -} - -VOID -Ext2FreePool( - IN PVOID P, - IN ULONG Tag -) -{ - PUCHAR Buffer = (PUCHAR)P; - PULONG Data; - ULONG NumberOfBytes, i; - KIRQL Irql; - - Buffer -= 0x10; - Data = (PULONG)(Buffer); - NumberOfBytes = Data[0]; - if (Data[1] != NumberOfBytes + 0x20) { - DbgBreak(); - return; - } - for (i=0x08; i < 0x10; i++) { - if (Buffer[i] != 'S') { - DbgBreak(); - } - Buffer[i] = '-'; - } - for (i=0; i < 0x10; i++) { - if (Buffer[i + NumberOfBytes + 0x10] != 'E') { - DbgBreak(); - return; - } - Buffer[i + NumberOfBytes + 0x10] = '-'; - } - - KeAcquireSpinLock(&Ext2MemoryLock, &Irql); - Ext2TotalMemorySize = Ext2TotalMemorySize - NumberOfBytes; - Ext2TotalAllocates -= 1; - KeReleaseSpinLock(&Ext2MemoryLock, Irql); - - ExFreePoolWithTag(Buffer, Tag); -} - -#else // EXT2_DEBUG - -PVOID -Ext2AllocatePool( - IN POOL_TYPE PoolType, - IN SIZE_T NumberOfBytes, - IN ULONG Tag -) -{ - return ExAllocatePoolWithTag( - PoolType, - NumberOfBytes, - Tag); -} - -VOID -Ext2FreePool( - IN PVOID P, - IN ULONG Tag -) -{ - ExFreePoolWithTag(P, Tag); -} - -#endif // !EXT2_DEBUG +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: Debug.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES **************************************************************/ + +#include "stdarg.h" +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +#if EXT2_DEBUG + +#define SYSTEM_PROCESS_NAME "System" + +extern PEXT2_GLOBAL Ext2Global; + +ULONG DebugFilter = DL_DEFAULT; + +ULONG ProcessNameOffset = 0; + +/* DEFINITIONS ***********************************************************/ + + +/* Static Definitions ****************************************************/ + +static PUCHAR IrpMjStrings[] = { + "IRP_MJ_CREATE", + "IRP_MJ_CREATE_NAMED_PIPE", + "IRP_MJ_CLOSE", + "IRP_MJ_READ", + "IRP_MJ_WRITE", + "IRP_MJ_QUERY_INFORMATION", + "IRP_MJ_SET_INFORMATION", + "IRP_MJ_QUERY_EA", + "IRP_MJ_SET_EA", + "IRP_MJ_FLUSH_BUFFERS", + "IRP_MJ_QUERY_VOLUME_INFORMATION", + "IRP_MJ_SET_VOLUME_INFORMATION", + "IRP_MJ_DIRECTORY_CONTROL", + "IRP_MJ_FILE_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CONTROL", + "IRP_MJ_INTERNAL_DEVICE_CONTROL", + "IRP_MJ_SHUTDOWN", + "IRP_MJ_LOCK_CONTROL", + "IRP_MJ_CLEANUP", + "IRP_MJ_CREATE_MAILSLOT", + "IRP_MJ_QUERY_SECURITY", + "IRP_MJ_SET_SECURITY", + "IRP_MJ_POWER", + "IRP_MJ_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CHANGE", + "IRP_MJ_QUERY_QUOTA", + "IRP_MJ_SET_QUOTA", + "IRP_MJ_PNP" +}; + +static PUCHAR FileInformationClassStrings[] = { + "Unknown FileInformationClass 0", + "FileDirectoryInformation", + "FileFullDirectoryInformation", + "FileBothDirectoryInformation", + "FileBasicInformation", + "FileStandardInformation", + "FileInternalInformation", + "FileEaInformation", + "FileAccessInformation", + "FileNameInformation", + "FileRenameInformation", + "FileLinkInformation", + "FileNamesInformation", + "FileDispositionInformation", + "FilePositionInformation", + "FileFullEaInformation", + "FileModeInformation", + "FileAlignmentInformation", + "FileAllInformation", + "FileAllocationInformation", + "FileEndOfFileInformation", + "FileAlternateNameInformation", + "FileStreamInformation", + "FilePipeInformation", + "FilePipeLocalInformation", + "FilePipeRemoteInformation", + "FileMailslotQueryInformation", + "FileMailslotSetInformation", + "FileCompressionInformation", + "FileObjectIdInformation", + "FileCompletionInformation", + "FileMoveClusterInformation", + "FileQuotaInformation", + "FileReparsePointInformation", + "FileNetworkOpenInformation", + "FileAttributeTagInformation", + "FileTrackingInformation" +}; + +static PUCHAR FsInformationClassStrings[] = { + "Unknown FsInformationClass 0", + "FileFsVolumeInformation", + "FileFsLabelInformation", + "FileFsSizeInformation", + "FileFsDeviceInformation", + "FileFsAttributeInformation", + "FileFsControlInformation", + "FileFsFullSizeInformation", + "FileFsObjectIdInformation" +}; + +/* + * Ext2Printf + * This function is variable-argument, level-sensitive debug print routine. + * If the specified debug level for the print statement is lower or equal + * to the current debug level, the message will be printed. + * + * Arguments: + * DebugMessage - Variable argument ascii c string + * + * Return Value: + * N/A + * + * NOTES: + * N/A + */ + +#define DBG_BUF_LEN 0x100 +VOID +Ext2Printf( + PCHAR DebugMessage, + ... +) +{ + va_list ap; + LARGE_INTEGER CurrentTime; + TIME_FIELDS TimeFields; + CHAR Buffer[DBG_BUF_LEN]; + ULONG i; + + RtlZeroMemory(Buffer, DBG_BUF_LEN); + va_start(ap, DebugMessage); + + KeQuerySystemTime( &CurrentTime); + RtlTimeToTimeFields(&CurrentTime, &TimeFields); + _vsnprintf(&Buffer[0], DBG_BUF_LEN, DebugMessage, ap); + + DbgPrint(DRIVER_NAME":~%d: %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s", + KeGetCurrentProcessorNumber(), + TimeFields.Hour, TimeFields.Minute, + TimeFields.Second, TimeFields.Milliseconds, + PsGetCurrentThread(), Buffer); + + va_end(ap); +} + +VOID +Ext2NiPrintf( + PCHAR DebugMessage, + ... +) +{ + va_list ap; + LARGE_INTEGER CurrentTime; + TIME_FIELDS TimeFields; + CHAR Buffer[0x100]; + ULONG i; + + va_start(ap, DebugMessage); + + KeQuerySystemTime( &CurrentTime); + RtlTimeToTimeFields(&CurrentTime, &TimeFields); + _vsnprintf(&Buffer[0], 0x100, DebugMessage, ap); + + DbgPrint(DRIVER_NAME":~%d: %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s", + KeGetCurrentProcessorNumber(), + TimeFields.Hour, TimeFields.Minute, + TimeFields.Second, TimeFields.Milliseconds, + PsGetCurrentThread(), Buffer); + + va_end(ap); + +} // Ext2NiPrintf() + +ULONG +Ext2GetProcessNameOffset ( VOID ) +{ + PEPROCESS Process; + ULONG i; + + Process = PsGetCurrentProcess(); + + for (i = 0; i < PAGE_SIZE; i++) { + if (!strncmp( + SYSTEM_PROCESS_NAME, + (PCHAR) Process + i, + strlen(SYSTEM_PROCESS_NAME) + )) { + + return i; + } + } + + DEBUG(DL_ERR, ( ": *** FsdGetProcessNameOffset failed ***\n")); + + return 0; +} + + +VOID +Ext2DbgPrintCall (IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp ) +{ + PIO_STACK_LOCATION IoStackLocation; + PFILE_OBJECT FileObject; + PWCHAR FileName; + PEXT2_FCB Fcb; + FILE_INFORMATION_CLASS FileInformationClass; + FS_INFORMATION_CLASS FsInformationClass; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + FileObject = IoStackLocation->FileObject; + + FileName = L"Unknown"; + + if (DeviceObject == Ext2Global->DiskdevObject) { + + FileName = DEVICE_NAME; + + } else if (DeviceObject == Ext2Global->CdromdevObject) { + + FileName = CDROM_NAME; + + } else if (FileObject && FileObject->FsContext) { + + Fcb = (PEXT2_FCB) FileObject->FsContext; + + if (Fcb->Identifier.Type == EXT2VCB) { + FileName = L"\\Volume"; + } else if (Fcb->Identifier.Type == EXT2FCB && Fcb->Mcb->FullName.Buffer) { + FileName = Fcb->Mcb->FullName.Buffer; + } + } + + switch (IoStackLocation->MajorFunction) { + + case IRP_MJ_CREATE: + + FileName = NULL; + + if (DeviceObject == Ext2Global->DiskdevObject) { + FileName = DEVICE_NAME; + } else if (DeviceObject == Ext2Global->CdromdevObject) { + FileName = CDROM_NAME; + } else if (IoStackLocation->FileObject->FileName.Length == 0) { + FileName = L"\\Volume"; + } + + if (FileName) { + DEBUGNI(DL_FUN, ("%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } else if (IoStackLocation->FileObject->FileName.Buffer) { + DEBUGNI(DL_FUN, ("%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + IoStackLocation->FileObject->FileName.Buffer + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + "Unknown" + )); + } + + break; + + case IRP_MJ_CLOSE: + + DEBUGNI(DL_FUN, ("%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + + break; + + case IRP_MJ_READ: + + if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_COMPLETE\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %S Offset: %I64xh Length: %xh %s%s%s%s%s%s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.Read.ByteOffset.QuadPart, + IoStackLocation->Parameters.Read.Length, + (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "), + (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "), + (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "), + (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "), + (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "), + (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " ") + )); + } + + break; + + case IRP_MJ_WRITE: + + if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_COMPLETE\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %S Offset: %I64xh Length: %xh %s%s%s%s%s%s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.Read.ByteOffset.QuadPart, + IoStackLocation->Parameters.Read.Length, + (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "), + (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "), + (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "), + (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "), + (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "), + (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " ") + )); + } + + break; + + case IRP_MJ_QUERY_INFORMATION: + + FileInformationClass = + IoStackLocation->Parameters.QueryFile.FileInformationClass; + + if (FileInformationClass <= FileMaximumInformation) { + DEBUGNI(DL_FUN, ("%s %s %S %s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClassStrings[FileInformationClass] + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown FileInformationClass %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClass + )); + } + + break; + + case IRP_MJ_SET_INFORMATION: + + FileInformationClass = + IoStackLocation->Parameters.SetFile.FileInformationClass; + + if (FileInformationClass <= FileMaximumInformation) { + DEBUGNI(DL_FUN, ("%s %s %S %s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClassStrings[FileInformationClass] + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown FileInformationClass %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClass + )); + } + + break; + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + + FsInformationClass = + IoStackLocation->Parameters.QueryVolume.FsInformationClass; + + if (FsInformationClass <= FileFsMaximumInformation) { + DEBUGNI(DL_FUN, ("%s %s %S %s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FsInformationClassStrings[FsInformationClass] + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown FsInformationClass %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FsInformationClass + )); + } + + break; + + case IRP_MJ_DIRECTORY_CONTROL: + + if (IoStackLocation->MinorFunction & IRP_MN_QUERY_DIRECTORY) { + +#ifndef _GNU_NTIFS_ + FileInformationClass = + IoStackLocation->Parameters.QueryDirectory.FileInformationClass; +#else + FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; +#endif + + if (FileInformationClass <= FileMaximumInformation) { + DEBUGNI(DL_FUN, ("%s %s %S %s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClassStrings[FileInformationClass] + )); + + if ( +#ifndef _GNU_NTIFS_ + IoStackLocation->Parameters.QueryDirectory.FileName +#else + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName +#endif + ) { +#ifndef _GNU_NTIFS_ + DEBUGNI(DL_FUN, ("%s FileName: %.*S FileIndex: %x %s%s%s\n", + Ext2GetCurrentProcessName(), + + IoStackLocation->Parameters.QueryDirectory.FileName->Length / 2, + IoStackLocation->Parameters.QueryDirectory.FileName->Buffer, + IoStackLocation->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : "") + )); + +#else + DEBUGNI(DL_FUN, ("%s FileName: %.*S FileIndex: %x %s%s%s\n", + Ext2GetCurrentProcessName(), + + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName->Length / 2, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName->Buffer, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : "") + )); +#endif + } else { +#ifndef _GNU_NTIFS_ + DEBUGNI(DL_FUN, ("%s FileName: FileIndex: %#x %s%s%s\n", + Ext2GetCurrentProcessName(), + IoStackLocation->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : "") + )); +#else + DEBUGNI(DL_FUN, ("%s FileName: FileIndex: %#x %s%s%s\n", + Ext2GetCurrentProcessName(), + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : "") + )); +#endif + } + } else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown FileInformationClass %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClass + )); + } + } else if (IoStackLocation->MinorFunction & IRP_MN_NOTIFY_CHANGE_DIRECTORY) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown minor function %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->MinorFunction + )); + } + + break; + + case IRP_MJ_FILE_SYSTEM_CONTROL: + + if (IoStackLocation->MinorFunction == IRP_MN_USER_FS_REQUEST) { +#ifndef _GNU_NTIFS_ + DEBUGNI(DL_FUN, ( "%s %s %S IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.FileSystemControl.FsControlCode + )); +#else + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.FileSystemControl.FsControlCode + )); +#endif + } else if (IoStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_MOUNT_VOLUME DeviceObject: %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.MountVolume.DeviceObject + )); + } else if (IoStackLocation->MinorFunction == IRP_MN_VERIFY_VOLUME) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_VERIFY_VOLUME DeviceObject: %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.VerifyVolume.DeviceObject + )); + } else if (IoStackLocation->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_LOAD_FILE_SYSTEM\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } +#if (_WIN32_WINNT >= 0x0500) + else if (IoStackLocation->MinorFunction == IRP_MN_KERNEL_CALL) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_KERNEL_CALL\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } +#endif // (_WIN32_WINNT >= 0x0500) + else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown minor function %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->MinorFunction + )); + } + + break; + + case IRP_MJ_DEVICE_CONTROL: + + DEBUGNI(DL_FUN, ("%s %s %S IoControlCode: %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.DeviceIoControl.IoControlCode + )); + + break; + + case IRP_MJ_LOCK_CONTROL: + + if (IoStackLocation->MinorFunction & IRP_MN_LOCK) { +#ifndef _GNU_NTIFS_ + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart, + IoStackLocation->Parameters.LockControl.Length->QuadPart, + IoStackLocation->Parameters.LockControl.Key, + (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""), + (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : "") + )); +#else + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Length->QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Key, + (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""), + (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : "") + )); +#endif + } else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_SINGLE) { +#ifndef _GNU_NTIFS_ + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart, + IoStackLocation->Parameters.LockControl.Length->QuadPart, + IoStackLocation->Parameters.LockControl.Key + )); +#else + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Length->QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Key + )); +#endif + } else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL) { + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_ALL\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL_BY_KEY) { +#ifndef _GNU_NTIFS_ + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.LockControl.Key + )); +#else + DEBUGNI(DL_FUN, ("%s %s %S IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Key + )); +#endif + } else { + DEBUGNI(DL_FUN, ("%s %s %S Unknown minor function %#x\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->MinorFunction + )); + } + + break; + + case IRP_MJ_CLEANUP: + + DEBUGNI(DL_FUN, ("%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + + break; + + case IRP_MJ_SHUTDOWN: + + DEBUGNI(DL_FUN, ("%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + + break; + +#if (_WIN32_WINNT >= 0x0500) + case IRP_MJ_PNP: + + DEBUGNI(DL_FUN, ( "%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + break; +#endif // (_WIN32_WINNT >= 0x0500) + + default: + + DEBUGNI(DL_FUN, ("%s %s %S\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName + )); + } +} + +VOID +Ext2DbgPrintComplete (IN PIRP Irp, IN BOOLEAN bPrint) +{ + PIO_STACK_LOCATION IoStackLocation; + + if (!Irp) + return; + + if (Irp->IoStatus.Status != STATUS_SUCCESS) { + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + if (bPrint) { + DEBUGNI(DL_FUN, ("%s %s Status: %s (%#x).\n", + Ext2GetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + Ext2NtStatusToString(Irp->IoStatus.Status), + Irp->IoStatus.Status + )); + } + } +} + +PUCHAR +Ext2NtStatusToString ( IN NTSTATUS Status ) +{ + switch (Status) { + + case 0x00000000: + return "STATUS_SUCCESS"; + case 0x00000001: + return "STATUS_WAIT_1"; + case 0x00000002: + return "STATUS_WAIT_2"; + case 0x00000003: + return "STATUS_WAIT_3"; + case 0x0000003F: + return "STATUS_WAIT_63"; + case 0x00000080: + return "STATUS_ABANDONED_WAIT_0"; + case 0x000000BF: + return "STATUS_ABANDONED_WAIT_63"; + case 0x000000C0: + return "STATUS_USER_APC"; + case 0x00000100: + return "STATUS_KERNEL_APC"; + case 0x00000101: + return "STATUS_ALERTED"; + case 0x00000102: + return "STATUS_TIMEOUT"; + case 0x00000103: + return "STATUS_PENDING"; + case 0x00000104: + return "STATUS_REPARSE"; + case 0x00000105: + return "STATUS_MORE_ENTRIES"; + case 0x00000106: + return "STATUS_NOT_ALL_ASSIGNED"; + case 0x00000107: + return "STATUS_SOME_NOT_MAPPED"; + case 0x00000108: + return "STATUS_OPLOCK_BREAK_IN_PROGRESS"; + case 0x00000109: + return "STATUS_VOLUME_MOUNTED"; + case 0x0000010A: + return "STATUS_RXACT_COMMITTED"; + case 0x0000010B: + return "STATUS_NOTIFY_CLEANUP"; + case 0x0000010C: + return "STATUS_NOTIFY_ENUM_DIR"; + case 0x0000010D: + return "STATUS_NO_QUOTAS_FOR_ACCOUNT"; + case 0x0000010E: + return "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED"; + case 0x00000110: + return "STATUS_PAGE_FAULT_TRANSITION"; + case 0x00000111: + return "STATUS_PAGE_FAULT_DEMAND_ZERO"; + case 0x00000112: + return "STATUS_PAGE_FAULT_COPY_ON_WRITE"; + case 0x00000113: + return "STATUS_PAGE_FAULT_GUARD_PAGE"; + case 0x00000114: + return "STATUS_PAGE_FAULT_PAGING_FILE"; + case 0x00000115: + return "STATUS_CACHE_PAGE_LOCKED"; + case 0x00000116: + return "STATUS_CRASH_DUMP"; + case 0x00000117: + return "STATUS_BUFFER_ALL_ZEROS"; + case 0x00000118: + return "STATUS_REPARSE_OBJECT"; + case 0x00000119: + return "STATUS_RESOURCE_REQUIREMENTS_CHANGED"; + case 0x00000120: + return "STATUS_TRANSLATION_COMPLETE"; + case 0x00000121: + return "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY"; + case 0x00010001: + return "DBG_EXCEPTION_HANDLED"; + case 0x00010002: + return "DBG_CONTINUE"; + case 0x40000000: + return "STATUS_OBJECT_NAME_EXISTS"; + case 0x40000001: + return "STATUS_THREAD_WAS_SUSPENDED"; + case 0x40000002: + return "STATUS_WORKING_SET_LIMIT_RANGE"; + case 0x40000003: + return "STATUS_IMAGE_NOT_AT_BASE"; + case 0x40000004: + return "STATUS_RXACT_STATE_CREATED"; + case 0x40000005: + return "STATUS_SEGMENT_NOTIFICATION"; + case 0x40000006: + return "STATUS_LOCAL_USER_SESSION_KEY"; + case 0x40000007: + return "STATUS_BAD_CURRENT_DIRECTORY"; + case 0x40000008: + return "STATUS_SERIAL_MORE_WRITES"; + case 0x40000009: + return "STATUS_REGISTRY_RECOVERED"; + case 0x4000000A: + return "STATUS_FT_READ_RECOVERY_FROM_BACKUP"; + case 0x4000000B: + return "STATUS_FT_WRITE_RECOVERY"; + case 0x4000000C: + return "STATUS_SERIAL_COUNTER_TIMEOUT"; + case 0x4000000D: + return "STATUS_NULL_LM_PASSWORD"; + case 0x4000000E: + return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH"; + case 0x4000000F: + return "STATUS_RECEIVE_PARTIAL"; + case 0x40000010: + return "STATUS_RECEIVE_EXPEDITED"; + case 0x40000011: + return "STATUS_RECEIVE_PARTIAL_EXPEDITED"; + case 0x40000012: + return "STATUS_EVENT_DONE"; + case 0x40000013: + return "STATUS_EVENT_PENDING"; + case 0x40000014: + return "STATUS_CHECKING_FILE_SYSTEM"; + case 0x40000015: + return "STATUS_FATAL_APP_EXIT"; + case 0x40000016: + return "STATUS_PREDEFINED_HANDLE"; + case 0x40000017: + return "STATUS_WAS_UNLOCKED"; + case 0x40000018: + return "STATUS_SERVICE_NOTIFICATION"; + case 0x40000019: + return "STATUS_WAS_LOCKED"; + case 0x4000001A: + return "STATUS_LOG_HARD_ERROR"; + case 0x4000001B: + return "STATUS_ALREADY_WIN32"; + case 0x4000001C: + return "STATUS_WX86_UNSIMULATE"; + case 0x4000001D: + return "STATUS_WX86_CONTINUE"; + case 0x4000001E: + return "STATUS_WX86_SINGLE_STEP"; + case 0x4000001F: + return "STATUS_WX86_BREAKPOINT"; + case 0x40000020: + return "STATUS_WX86_EXCEPTION_CONTINUE"; + case 0x40000021: + return "STATUS_WX86_EXCEPTION_LASTCHANCE"; + case 0x40000022: + return "STATUS_WX86_EXCEPTION_CHAIN"; + case 0x40000023: + return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE"; + case 0x40000024: + return "STATUS_NO_YIELD_PERFORMED"; + case 0x40000025: + return "STATUS_TIMER_RESUME_IGNORED"; + case 0x40000026: + return "STATUS_ARBITRATION_UNHANDLED"; + case 0x40000027: + return "STATUS_CARDBUS_NOT_SUPPORTED"; + case 0x40000028: + return "STATUS_WX86_CREATEWX86TIB"; + case 0x40000029: + return "STATUS_MP_PROCESSOR_MISMATCH"; + case 0x40010001: + return "DBG_REPLY_LATER"; + case 0x40010002: + return "DBG_UNABLE_TO_PROVIDE_HANDLE"; + case 0x40010003: + return "DBG_TERMINATE_THREAD"; + case 0x40010004: + return "DBG_TERMINATE_PROCESS"; + case 0x40010005: + return "DBG_CONTROL_C"; + case 0x40010006: + return "DBG_PRINTEXCEPTION_C"; + case 0x40010007: + return "DBG_RIPEXCEPTION"; + case 0x40010008: + return "DBG_CONTROL_BREAK"; + case 0x80000001: + return "STATUS_GUARD_PAGE_VIOLATION"; + case 0x80000002: + return "STATUS_DATATYPE_MISALIGNMENT"; + case 0x80000003: + return "STATUS_BREAKPOINT"; + case 0x80000004: + return "STATUS_SINGLE_STEP"; + case 0x80000005: + return "STATUS_BUFFER_OVERFLOW"; + case 0x80000006: + return "STATUS_NO_MORE_FILES"; + case 0x80000007: + return "STATUS_WAKE_SYSTEM_DEBUGGER"; + case 0x8000000A: + return "STATUS_HANDLES_CLOSED"; + case 0x8000000B: + return "STATUS_NO_INHERITANCE"; + case 0x8000000C: + return "STATUS_GUID_SUBSTITUTION_MADE"; + case 0x8000000D: + return "STATUS_PARTIAL_COPY"; + case 0x8000000E: + return "STATUS_DEVICE_PAPER_EMPTY"; + case 0x8000000F: + return "STATUS_DEVICE_POWERED_OFF"; + case 0x80000010: + return "STATUS_DEVICE_OFF_LINE"; + case 0x80000011: + return "STATUS_DEVICE_BUSY"; + case 0x80000012: + return "STATUS_NO_MORE_EAS"; + case 0x80000013: + return "STATUS_INVALID_EA_NAME"; + case 0x80000014: + return "STATUS_EA_LIST_INCONSISTENT"; + case 0x80000015: + return "STATUS_INVALID_EA_FLAG"; + case 0x80000016: + return "STATUS_VERIFY_REQUIRED"; + case 0x80000017: + return "STATUS_EXTRANEOUS_INFORMATION"; + case 0x80000018: + return "STATUS_RXACT_COMMIT_NECESSARY"; + case 0x8000001A: + return "STATUS_NO_MORE_ENTRIES"; + case 0x8000001B: + return "STATUS_FILEMARK_DETECTED"; + case 0x8000001C: + return "STATUS_MEDIA_CHANGED"; + case 0x8000001D: + return "STATUS_BUS_RESET"; + case 0x8000001E: + return "STATUS_END_OF_MEDIA"; + case 0x8000001F: + return "STATUS_BEGINNING_OF_MEDIA"; + case 0x80000020: + return "STATUS_MEDIA_CHECK"; + case 0x80000021: + return "STATUS_SETMARK_DETECTED"; + case 0x80000022: + return "STATUS_NO_DATA_DETECTED"; + case 0x80000023: + return "STATUS_REDIRECTOR_HAS_OPEN_HANDLES"; + case 0x80000024: + return "STATUS_SERVER_HAS_OPEN_HANDLES"; + case 0x80000025: + return "STATUS_ALREADY_DISCONNECTED"; + case 0x80000026: + return "STATUS_LONGJUMP"; + case 0x80010001: + return "DBG_EXCEPTION_NOT_HANDLED"; + case 0xC0000001: + return "STATUS_UNSUCCESSFUL"; + case 0xC0000002: + return "STATUS_NOT_IMPLEMENTED"; + case 0xC0000003: + return "STATUS_INVALID_INFO_CLASS"; + case 0xC0000004: + return "STATUS_INFO_LENGTH_MISMATCH"; + case 0xC0000005: + return "STATUS_ACCESS_VIOLATION"; + case 0xC0000006: + return "STATUS_IN_PAGE_ERROR"; + case 0xC0000007: + return "STATUS_PAGEFILE_QUOTA"; + case 0xC0000008: + return "STATUS_INVALID_HANDLE"; + case 0xC0000009: + return "STATUS_BAD_INITIAL_STACK"; + case 0xC000000A: + return "STATUS_BAD_INITIAL_PC"; + case 0xC000000B: + return "STATUS_INVALID_CID"; + case 0xC000000C: + return "STATUS_TIMER_NOT_CANCELED"; + case 0xC000000D: + return "STATUS_INVALID_PARAMETER"; + case 0xC000000E: + return "STATUS_NO_SUCH_DEVICE"; + case 0xC000000F: + return "STATUS_NO_SUCH_FILE"; + case 0xC0000010: + return "STATUS_INVALID_DEVICE_REQUEST"; + case 0xC0000011: + return "STATUS_END_OF_FILE"; + case 0xC0000012: + return "STATUS_WRONG_VOLUME"; + case 0xC0000013: + return "STATUS_NO_MEDIA_IN_DEVICE"; + case 0xC0000014: + return "STATUS_UNRECOGNIZED_MEDIA"; + case 0xC0000015: + return "STATUS_NONEXISTENT_SECTOR"; + case 0xC0000016: + return "STATUS_MORE_PROCESSING_REQUIRED"; + case 0xC0000017: + return "STATUS_NO_MEMORY"; + case 0xC0000018: + return "STATUS_CONFLICTING_ADDRESSES"; + case 0xC0000019: + return "STATUS_NOT_MAPPED_VIEW"; + case 0xC000001A: + return "STATUS_UNABLE_TO_FREE_VM"; + case 0xC000001B: + return "STATUS_UNABLE_TO_DELETE_SECTION"; + case 0xC000001C: + return "STATUS_INVALID_SYSTEM_SERVICE"; + case 0xC000001D: + return "STATUS_ILLEGAL_INSTRUCTION"; + case 0xC000001E: + return "STATUS_INVALID_LOCK_SEQUENCE"; + case 0xC000001F: + return "STATUS_INVALID_VIEW_SIZE"; + case 0xC0000020: + return "STATUS_INVALID_FILE_FOR_SECTION"; + case 0xC0000021: + return "STATUS_ALREADY_COMMITTED"; + case 0xC0000022: + return "STATUS_ACCESS_DENIED"; + case 0xC0000023: + return "STATUS_BUFFER_TOO_SMALL"; + case 0xC0000024: + return "STATUS_OBJECT_TYPE_MISMATCH"; + case 0xC0000025: + return "STATUS_NONCONTINUABLE_EXCEPTION"; + case 0xC0000026: + return "STATUS_INVALID_DISPOSITION"; + case 0xC0000027: + return "STATUS_UNWIND"; + case 0xC0000028: + return "STATUS_BAD_STACK"; + case 0xC0000029: + return "STATUS_INVALID_UNWIND_TARGET"; + case 0xC000002A: + return "STATUS_NOT_LOCKED"; + case 0xC000002B: + return "STATUS_PARITY_ERROR"; + case 0xC000002C: + return "STATUS_UNABLE_TO_DECOMMIT_VM"; + case 0xC000002D: + return "STATUS_NOT_COMMITTED"; + case 0xC000002E: + return "STATUS_INVALID_PORT_ATTRIBUTES"; + case 0xC000002F: + return "STATUS_PORT_MESSAGE_TOO_LONG"; + case 0xC0000030: + return "STATUS_INVALID_PARAMETER_MIX"; + case 0xC0000031: + return "STATUS_INVALID_QUOTA_LOWER"; + case 0xC0000032: + return "STATUS_DISK_CORRUPT_ERROR"; + case 0xC0000033: + return "STATUS_OBJECT_NAME_INVALID"; + case 0xC0000034: + return "STATUS_OBJECT_NAME_NOT_FOUND"; + case 0xC0000035: + return "STATUS_OBJECT_NAME_COLLISION"; + case 0xC0000037: + return "STATUS_PORT_DISCONNECTED"; + case 0xC0000038: + return "STATUS_DEVICE_ALREADY_ATTACHED"; + case 0xC0000039: + return "STATUS_OBJECT_PATH_INVALID"; + case 0xC000003A: + return "STATUS_OBJECT_PATH_NOT_FOUND"; + case 0xC000003B: + return "STATUS_OBJECT_PATH_SYNTAX_BAD"; + case 0xC000003C: + return "STATUS_DATA_OVERRUN"; + case 0xC000003D: + return "STATUS_DATA_LATE_ERROR"; + case 0xC000003E: + return "STATUS_DATA_ERROR"; + case 0xC000003F: + return "STATUS_CRC_ERROR"; + case 0xC0000040: + return "STATUS_SECTION_TOO_BIG"; + case 0xC0000041: + return "STATUS_PORT_CONNECTION_REFUSED"; + case 0xC0000042: + return "STATUS_INVALID_PORT_HANDLE"; + case 0xC0000043: + return "STATUS_SHARING_VIOLATION"; + case 0xC0000044: + return "STATUS_QUOTA_EXCEEDED"; + case 0xC0000045: + return "STATUS_INVALID_PAGE_PROTECTION"; + case 0xC0000046: + return "STATUS_MUTANT_NOT_OWNED"; + case 0xC0000047: + return "STATUS_SEMAPHORE_LIMIT_EXCEEDED"; + case 0xC0000048: + return "STATUS_PORT_ALREADY_SET"; + case 0xC0000049: + return "STATUS_SECTION_NOT_IMAGE"; + case 0xC000004A: + return "STATUS_SUSPEND_COUNT_EXCEEDED"; + case 0xC000004B: + return "STATUS_THREAD_IS_TERMINATING"; + case 0xC000004C: + return "STATUS_BAD_WORKING_SET_LIMIT"; + case 0xC000004D: + return "STATUS_INCOMPATIBLE_FILE_MAP"; + case 0xC000004E: + return "STATUS_SECTION_PROTECTION"; + case 0xC000004F: + return "STATUS_EAS_NOT_SUPPORTED"; + case 0xC0000050: + return "STATUS_EA_TOO_LARGE"; + case 0xC0000051: + return "STATUS_NONEXISTENT_EA_ENTRY"; + case 0xC0000052: + return "STATUS_NO_EAS_ON_FILE"; + case 0xC0000053: + return "STATUS_EA_CORRUPT_ERROR"; + case 0xC0000054: + return "STATUS_FILE_LOCK_CONFLICT"; + case 0xC0000055: + return "STATUS_LOCK_NOT_GRANTED"; + case 0xC0000056: + return "STATUS_DELETE_PENDING"; + case 0xC0000057: + return "STATUS_CTL_FILE_NOT_SUPPORTED"; + case 0xC0000058: + return "STATUS_UNKNOWN_REVISION"; + case 0xC0000059: + return "STATUS_REVISION_MISMATCH"; + case 0xC000005A: + return "STATUS_INVALID_OWNER"; + case 0xC000005B: + return "STATUS_INVALID_PRIMARY_GROUP"; + case 0xC000005C: + return "STATUS_NO_IMPERSONATION_TOKEN"; + case 0xC000005D: + return "STATUS_CANT_DISABLE_MANDATORY"; + case 0xC000005E: + return "STATUS_NO_LOGON_SERVERS"; + case 0xC000005F: + return "STATUS_NO_SUCH_LOGON_SESSION"; + case 0xC0000060: + return "STATUS_NO_SUCH_PRIVILEGE"; + case 0xC0000061: + return "STATUS_PRIVILEGE_NOT_HELD"; + case 0xC0000062: + return "STATUS_INVALID_ACCOUNT_NAME"; + case 0xC0000063: + return "STATUS_USER_EXISTS"; + case 0xC0000064: + return "STATUS_NO_SUCH_USER"; + case 0xC0000065: + return "STATUS_GROUP_EXISTS"; + case 0xC0000066: + return "STATUS_NO_SUCH_GROUP"; + case 0xC0000067: + return "STATUS_MEMBER_IN_GROUP"; + case 0xC0000068: + return "STATUS_MEMBER_NOT_IN_GROUP"; + case 0xC0000069: + return "STATUS_LAST_ADMIN"; + case 0xC000006A: + return "STATUS_WRONG_PASSWORD"; + case 0xC000006B: + return "STATUS_ILL_FORMED_PASSWORD"; + case 0xC000006C: + return "STATUS_PASSWORD_RESTRICTION"; + case 0xC000006D: + return "STATUS_LOGON_FAILURE"; + case 0xC000006E: + return "STATUS_ACCOUNT_RESTRICTION"; + case 0xC000006F: + return "STATUS_INVALID_LOGON_HOURS"; + case 0xC0000070: + return "STATUS_INVALID_WORKSTATION"; + case 0xC0000071: + return "STATUS_PASSWORD_EXPIRED"; + case 0xC0000072: + return "STATUS_ACCOUNT_DISABLED"; + case 0xC0000073: + return "STATUS_NONE_MAPPED"; + case 0xC0000074: + return "STATUS_TOO_MANY_LUIDS_REQUESTED"; + case 0xC0000075: + return "STATUS_LUIDS_EXHAUSTED"; + case 0xC0000076: + return "STATUS_INVALID_SUB_AUTHORITY"; + case 0xC0000077: + return "STATUS_INVALID_ACL"; + case 0xC0000078: + return "STATUS_INVALID_SID"; + case 0xC0000079: + return "STATUS_INVALID_SECURITY_DESCR"; + case 0xC000007A: + return "STATUS_PROCEDURE_NOT_FOUND"; + case 0xC000007B: + return "STATUS_INVALID_IMAGE_FORMAT"; + case 0xC000007C: + return "STATUS_NO_TOKEN"; + case 0xC000007D: + return "STATUS_BAD_INHERITANCE_ACL"; + case 0xC000007E: + return "STATUS_RANGE_NOT_LOCKED"; + case 0xC000007F: + return "STATUS_DISK_FULL"; + case 0xC0000080: + return "STATUS_SERVER_DISABLED"; + case 0xC0000081: + return "STATUS_SERVER_NOT_DISABLED"; + case 0xC0000082: + return "STATUS_TOO_MANY_GUIDS_REQUESTED"; + case 0xC0000083: + return "STATUS_GUIDS_EXHAUSTED"; + case 0xC0000084: + return "STATUS_INVALID_ID_AUTHORITY"; + case 0xC0000085: + return "STATUS_AGENTS_EXHAUSTED"; + case 0xC0000086: + return "STATUS_INVALID_VOLUME_LABEL"; + case 0xC0000087: + return "STATUS_SECTION_NOT_EXTENDED"; + case 0xC0000088: + return "STATUS_NOT_MAPPED_DATA"; + case 0xC0000089: + return "STATUS_RESOURCE_DATA_NOT_FOUND"; + case 0xC000008A: + return "STATUS_RESOURCE_TYPE_NOT_FOUND"; + case 0xC000008B: + return "STATUS_RESOURCE_NAME_NOT_FOUND"; + case 0xC000008C: + return "STATUS_ARRAY_BOUNDS_EXCEEDED"; + case 0xC000008D: + return "STATUS_FLOAT_DENORMAL_OPERAND"; + case 0xC000008E: + return "STATUS_FLOAT_DIVIDE_BY_ZERO"; + case 0xC000008F: + return "STATUS_FLOAT_INEXACT_RESULT"; + case 0xC0000090: + return "STATUS_FLOAT_INVALID_OPERATION"; + case 0xC0000091: + return "STATUS_FLOAT_OVERFLOW"; + case 0xC0000092: + return "STATUS_FLOAT_STACK_CHECK"; + case 0xC0000093: + return "STATUS_FLOAT_UNDERFLOW"; + case 0xC0000094: + return "STATUS_INTEGER_DIVIDE_BY_ZERO"; + case 0xC0000095: + return "STATUS_INTEGER_OVERFLOW"; + case 0xC0000096: + return "STATUS_PRIVILEGED_INSTRUCTION"; + case 0xC0000097: + return "STATUS_TOO_MANY_PAGING_FILES"; + case 0xC0000098: + return "STATUS_FILE_INVALID"; + case 0xC0000099: + return "STATUS_ALLOTTED_SPACE_EXCEEDED"; + case 0xC000009A: + return "STATUS_INSUFFICIENT_RESOURCES"; + case 0xC000009B: + return "STATUS_DFS_EXIT_PATH_FOUND"; + case 0xC000009C: + return "STATUS_DEVICE_DATA_ERROR"; + case 0xC000009D: + return "STATUS_DEVICE_NOT_CONNECTED"; + case 0xC000009E: + return "STATUS_DEVICE_POWER_FAILURE"; + case 0xC000009F: + return "STATUS_FREE_VM_NOT_AT_BASE"; + case 0xC00000A0: + return "STATUS_MEMORY_NOT_ALLOCATED"; + case 0xC00000A1: + return "STATUS_WORKING_SET_QUOTA"; + case 0xC00000A2: + return "STATUS_MEDIA_WRITE_PROTECTED"; + case 0xC00000A3: + return "STATUS_DEVICE_NOT_READY"; + case 0xC00000A4: + return "STATUS_INVALID_GROUP_ATTRIBUTES"; + case 0xC00000A5: + return "STATUS_BAD_IMPERSONATION_LEVEL"; + case 0xC00000A6: + return "STATUS_CANT_OPEN_ANONYMOUS"; + case 0xC00000A7: + return "STATUS_BAD_VALIDATION_CLASS"; + case 0xC00000A8: + return "STATUS_BAD_TOKEN_TYPE"; + case 0xC00000A9: + return "STATUS_BAD_MASTER_BOOT_RECORD"; + case 0xC00000AA: + return "STATUS_INSTRUCTION_MISALIGNMENT"; + case 0xC00000AB: + return "STATUS_INSTANCE_NOT_AVAILABLE"; + case 0xC00000AC: + return "STATUS_PIPE_NOT_AVAILABLE"; + case 0xC00000AD: + return "STATUS_INVALID_PIPE_STATE"; + case 0xC00000AE: + return "STATUS_PIPE_BUSY"; + case 0xC00000AF: + return "STATUS_ILLEGAL_FUNCTION"; + case 0xC00000B0: + return "STATUS_PIPE_DISCONNECTED"; + case 0xC00000B1: + return "STATUS_PIPE_CLOSING"; + case 0xC00000B2: + return "STATUS_PIPE_CONNECTED"; + case 0xC00000B3: + return "STATUS_PIPE_LISTENING"; + case 0xC00000B4: + return "STATUS_INVALID_READ_MODE"; + case 0xC00000B5: + return "STATUS_IO_TIMEOUT"; + case 0xC00000B6: + return "STATUS_FILE_FORCED_CLOSED"; + case 0xC00000B7: + return "STATUS_PROFILING_NOT_STARTED"; + case 0xC00000B8: + return "STATUS_PROFILING_NOT_STOPPED"; + case 0xC00000B9: + return "STATUS_COULD_NOT_INTERPRET"; + case 0xC00000BA: + return "STATUS_FILE_IS_A_DIRECTORY"; + case 0xC00000BB: + return "STATUS_NOT_SUPPORTED"; + case 0xC00000BC: + return "STATUS_REMOTE_NOT_LISTENING"; + case 0xC00000BD: + return "STATUS_DUPLICATE_NAME"; + case 0xC00000BE: + return "STATUS_BAD_NETWORK_PATH"; + case 0xC00000BF: + return "STATUS_NETWORK_BUSY"; + case 0xC00000C0: + return "STATUS_DEVICE_DOES_NOT_EXIST"; + case 0xC00000C1: + return "STATUS_TOO_MANY_COMMANDS"; + case 0xC00000C2: + return "STATUS_ADAPTER_HARDWARE_ERROR"; + case 0xC00000C3: + return "STATUS_INVALID_NETWORK_RESPONSE"; + case 0xC00000C4: + return "STATUS_UNEXPECTED_NETWORK_ERROR"; + case 0xC00000C5: + return "STATUS_BAD_REMOTE_ADAPTER"; + case 0xC00000C6: + return "STATUS_PRINT_QUEUE_FULL"; + case 0xC00000C7: + return "STATUS_NO_SPOOL_SPACE"; + case 0xC00000C8: + return "STATUS_PRINT_CANCELLED"; + case 0xC00000C9: + return "STATUS_NETWORK_NAME_DELETED"; + case 0xC00000CA: + return "STATUS_NETWORK_ACCESS_DENIED"; + case 0xC00000CB: + return "STATUS_BAD_DEVICE_TYPE"; + case 0xC00000CC: + return "STATUS_BAD_NETWORK_NAME"; + case 0xC00000CD: + return "STATUS_TOO_MANY_NAMES"; + case 0xC00000CE: + return "STATUS_TOO_MANY_SESSIONS"; + case 0xC00000CF: + return "STATUS_SHARING_PAUSED"; + case 0xC00000D0: + return "STATUS_REQUEST_NOT_ACCEPTED"; + case 0xC00000D1: + return "STATUS_REDIRECTOR_PAUSED"; + case 0xC00000D2: + return "STATUS_NET_WRITE_FAULT"; + case 0xC00000D3: + return "STATUS_PROFILING_AT_LIMIT"; + case 0xC00000D4: + return "STATUS_NOT_SAME_DEVICE"; + case 0xC00000D5: + return "STATUS_FILE_RENAMED"; + case 0xC00000D6: + return "STATUS_VIRTUAL_CIRCUIT_CLOSED"; + case 0xC00000D7: + return "STATUS_NO_SECURITY_ON_OBJECT"; + case 0xC00000D8: + return "STATUS_CANT_WAIT"; + case 0xC00000D9: + return "STATUS_PIPE_EMPTY"; + case 0xC00000DA: + return "STATUS_CANT_ACCESS_DOMAIN_INFO"; + case 0xC00000DB: + return "STATUS_CANT_TERMINATE_SELF"; + case 0xC00000DC: + return "STATUS_INVALID_SERVER_STATE"; + case 0xC00000DD: + return "STATUS_INVALID_DOMAIN_STATE"; + case 0xC00000DE: + return "STATUS_INVALID_DOMAIN_ROLE"; + case 0xC00000DF: + return "STATUS_NO_SUCH_DOMAIN"; + case 0xC00000E0: + return "STATUS_DOMAIN_EXISTS"; + case 0xC00000E1: + return "STATUS_DOMAIN_LIMIT_EXCEEDED"; + case 0xC00000E2: + return "STATUS_OPLOCK_NOT_GRANTED"; + case 0xC00000E3: + return "STATUS_INVALID_OPLOCK_PROTOCOL"; + case 0xC00000E4: + return "STATUS_INTERNAL_DB_CORRUPTION"; + case 0xC00000E5: + return "STATUS_INTERNAL_ERROR"; + case 0xC00000E6: + return "STATUS_GENERIC_NOT_MAPPED"; + case 0xC00000E7: + return "STATUS_BAD_DESCRIPTOR_FORMAT"; + case 0xC00000E8: + return "STATUS_INVALID_USER_BUFFER"; + case 0xC00000E9: + return "STATUS_UNEXPECTED_IO_ERROR"; + case 0xC00000EA: + return "STATUS_UNEXPECTED_MM_CREATE_ERR"; + case 0xC00000EB: + return "STATUS_UNEXPECTED_MM_MAP_ERROR"; + case 0xC00000EC: + return "STATUS_UNEXPECTED_MM_EXTEND_ERR"; + case 0xC00000ED: + return "STATUS_NOT_LOGON_PROCESS"; + case 0xC00000EE: + return "STATUS_LOGON_SESSION_EXISTS"; + case 0xC00000EF: + return "STATUS_INVALID_PARAMETER_1"; + case 0xC00000F0: + return "STATUS_INVALID_PARAMETER_2"; + case 0xC00000F1: + return "STATUS_INVALID_PARAMETER_3"; + case 0xC00000F2: + return "STATUS_INVALID_PARAMETER_4"; + case 0xC00000F3: + return "STATUS_INVALID_PARAMETER_5"; + case 0xC00000F4: + return "STATUS_INVALID_PARAMETER_6"; + case 0xC00000F5: + return "STATUS_INVALID_PARAMETER_7"; + case 0xC00000F6: + return "STATUS_INVALID_PARAMETER_8"; + case 0xC00000F7: + return "STATUS_INVALID_PARAMETER_9"; + case 0xC00000F8: + return "STATUS_INVALID_PARAMETER_10"; + case 0xC00000F9: + return "STATUS_INVALID_PARAMETER_11"; + case 0xC00000FA: + return "STATUS_INVALID_PARAMETER_12"; + case 0xC00000FB: + return "STATUS_REDIRECTOR_NOT_STARTED"; + case 0xC00000FC: + return "STATUS_REDIRECTOR_STARTED"; + case 0xC00000FD: + return "STATUS_STACK_OVERFLOW"; + case 0xC00000FE: + return "STATUS_NO_SUCH_PACKAGE"; + case 0xC00000FF: + return "STATUS_BAD_FUNCTION_TABLE"; + case 0xC0000100: + return "STATUS_VARIABLE_NOT_FOUND"; + case 0xC0000101: + return "STATUS_DIRECTORY_NOT_EMPTY"; + case 0xC0000102: + return "STATUS_FILE_CORRUPT_ERROR"; + case 0xC0000103: + return "STATUS_NOT_A_DIRECTORY"; + case 0xC0000104: + return "STATUS_BAD_LOGON_SESSION_STATE"; + case 0xC0000105: + return "STATUS_LOGON_SESSION_COLLISION"; + case 0xC0000106: + return "STATUS_NAME_TOO_LONG"; + case 0xC0000107: + return "STATUS_FILES_OPEN"; + case 0xC0000108: + return "STATUS_CONNECTION_IN_USE"; + case 0xC0000109: + return "STATUS_MESSAGE_NOT_FOUND"; + case 0xC000010A: + return "STATUS_PROCESS_IS_TERMINATING"; + case 0xC000010B: + return "STATUS_INVALID_LOGON_TYPE"; + case 0xC000010C: + return "STATUS_NO_GUID_TRANSLATION"; + case 0xC000010D: + return "STATUS_CANNOT_IMPERSONATE"; + case 0xC000010E: + return "STATUS_IMAGE_ALREADY_LOADED"; + case 0xC000010F: + return "STATUS_ABIOS_NOT_PRESENT"; + case 0xC0000110: + return "STATUS_ABIOS_LID_NOT_EXIST"; + case 0xC0000111: + return "STATUS_ABIOS_LID_ALREADY_OWNED"; + case 0xC0000112: + return "STATUS_ABIOS_NOT_LID_OWNER"; + case 0xC0000113: + return "STATUS_ABIOS_INVALID_COMMAND"; + case 0xC0000114: + return "STATUS_ABIOS_INVALID_LID"; + case 0xC0000115: + return "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE"; + case 0xC0000116: + return "STATUS_ABIOS_INVALID_SELECTOR"; + case 0xC0000117: + return "STATUS_NO_LDT"; + case 0xC0000118: + return "STATUS_INVALID_LDT_SIZE"; + case 0xC0000119: + return "STATUS_INVALID_LDT_OFFSET"; + case 0xC000011A: + return "STATUS_INVALID_LDT_DESCRIPTOR"; + case 0xC000011B: + return "STATUS_INVALID_IMAGE_NE_FORMAT"; + case 0xC000011C: + return "STATUS_RXACT_INVALID_STATE"; + case 0xC000011D: + return "STATUS_RXACT_COMMIT_FAILURE"; + case 0xC000011E: + return "STATUS_MAPPED_FILE_SIZE_ZERO"; + case 0xC000011F: + return "STATUS_TOO_MANY_OPENED_FILES"; + case 0xC0000120: + return "STATUS_CANCELLED"; + case 0xC0000121: + return "STATUS_CANNOT_DELETE"; + case 0xC0000122: + return "STATUS_INVALID_COMPUTER_NAME"; + case 0xC0000123: + return "STATUS_FILE_DELETED"; + case 0xC0000124: + return "STATUS_SPECIAL_ACCOUNT"; + case 0xC0000125: + return "STATUS_SPECIAL_GROUP"; + case 0xC0000126: + return "STATUS_SPECIAL_USER"; + case 0xC0000127: + return "STATUS_MEMBERS_PRIMARY_GROUP"; + case 0xC0000128: + return "STATUS_FILE_CLOSED"; + case 0xC0000129: + return "STATUS_TOO_MANY_THREADS"; + case 0xC000012A: + return "STATUS_THREAD_NOT_IN_PROCESS"; + case 0xC000012B: + return "STATUS_TOKEN_ALREADY_IN_USE"; + case 0xC000012C: + return "STATUS_PAGEFILE_QUOTA_EXCEEDED"; + case 0xC000012D: + return "STATUS_COMMITMENT_LIMIT"; + case 0xC000012E: + return "STATUS_INVALID_IMAGE_LE_FORMAT"; + case 0xC000012F: + return "STATUS_INVALID_IMAGE_NOT_MZ"; + case 0xC0000130: + return "STATUS_INVALID_IMAGE_PROTECT"; + case 0xC0000131: + return "STATUS_INVALID_IMAGE_WIN_16"; + case 0xC0000132: + return "STATUS_LOGON_SERVER_CONFLICT"; + case 0xC0000133: + return "STATUS_TIME_DIFFERENCE_AT_DC"; + case 0xC0000134: + return "STATUS_SYNCHRONIZATION_REQUIRED"; + case 0xC0000135: + return "STATUS_DLL_NOT_FOUND"; + case 0xC0000136: + return "STATUS_OPEN_FAILED"; + case 0xC0000137: + return "STATUS_IO_PRIVILEGE_FAILED"; + case 0xC0000138: + return "STATUS_ORDINAL_NOT_FOUND"; + case 0xC0000139: + return "STATUS_ENTRYPOINT_NOT_FOUND"; + case 0xC000013A: + return "STATUS_CONTROL_C_EXIT"; + case 0xC000013B: + return "STATUS_LOCAL_DISCONNECT"; + case 0xC000013C: + return "STATUS_REMOTE_DISCONNECT"; + case 0xC000013D: + return "STATUS_REMOTE_RESOURCES"; + case 0xC000013E: + return "STATUS_LINK_FAILED"; + case 0xC000013F: + return "STATUS_LINK_TIMEOUT"; + case 0xC0000140: + return "STATUS_INVALID_CONNECTION"; + case 0xC0000141: + return "STATUS_INVALID_ADDRESS"; + case 0xC0000142: + return "STATUS_DLL_INIT_FAILED"; + case 0xC0000143: + return "STATUS_MISSING_SYSTEMFILE"; + case 0xC0000144: + return "STATUS_UNHANDLED_EXCEPTION"; + case 0xC0000145: + return "STATUS_APP_INIT_FAILURE"; + case 0xC0000146: + return "STATUS_PAGEFILE_CREATE_FAILED"; + case 0xC0000147: + return "STATUS_NO_PAGEFILE"; + case 0xC0000148: + return "STATUS_INVALID_LEVEL"; + case 0xC0000149: + return "STATUS_WRONG_PASSWORD_CORE"; + case 0xC000014A: + return "STATUS_ILLEGAL_FLOAT_CONTEXT"; + case 0xC000014B: + return "STATUS_PIPE_BROKEN"; + case 0xC000014C: + return "STATUS_REGISTRY_CORRUPT"; + case 0xC000014D: + return "STATUS_REGISTRY_IO_FAILED"; + case 0xC000014E: + return "STATUS_NO_EVENT_PAIR"; + case 0xC000014F: + return "STATUS_UNRECOGNIZED_VOLUME"; + case 0xC0000150: + return "STATUS_SERIAL_NO_DEVICE_INITED"; + case 0xC0000151: + return "STATUS_NO_SUCH_ALIAS"; + case 0xC0000152: + return "STATUS_MEMBER_NOT_IN_ALIAS"; + case 0xC0000153: + return "STATUS_MEMBER_IN_ALIAS"; + case 0xC0000154: + return "STATUS_ALIAS_EXISTS"; + case 0xC0000155: + return "STATUS_LOGON_NOT_GRANTED"; + case 0xC0000156: + return "STATUS_TOO_MANY_SECRETS"; + case 0xC0000157: + return "STATUS_SECRET_TOO_LONG"; + case 0xC0000158: + return "STATUS_INTERNAL_DB_ERROR"; + case 0xC0000159: + return "STATUS_FULLSCREEN_MODE"; + case 0xC000015A: + return "STATUS_TOO_MANY_CONTEXT_IDS"; + case 0xC000015B: + return "STATUS_LOGON_TYPE_NOT_GRANTED"; + case 0xC000015C: + return "STATUS_NOT_REGISTRY_FILE"; + case 0xC000015D: + return "STATUS_NT_CROSS_ENCRYPTION_REQUIRED"; + case 0xC000015E: + return "STATUS_DOMAIN_CTRLR_CONFIG_ERROR"; + case 0xC000015F: + return "STATUS_FT_MISSING_MEMBER"; + case 0xC0000160: + return "STATUS_ILL_FORMED_SERVICE_ENTRY"; + case 0xC0000161: + return "STATUS_ILLEGAL_CHARACTER"; + case 0xC0000162: + return "STATUS_UNMAPPABLE_CHARACTER"; + case 0xC0000163: + return "STATUS_UNDEFINED_CHARACTER"; + case 0xC0000164: + return "STATUS_FLOPPY_VOLUME"; + case 0xC0000165: + return "STATUS_FLOPPY_ID_MARK_NOT_FOUND"; + case 0xC0000166: + return "STATUS_FLOPPY_WRONG_CYLINDER"; + case 0xC0000167: + return "STATUS_FLOPPY_UNKNOWN_ERROR"; + case 0xC0000168: + return "STATUS_FLOPPY_BAD_REGISTERS"; + case 0xC0000169: + return "STATUS_DISK_RECALIBRATE_FAILED"; + case 0xC000016A: + return "STATUS_DISK_OPERATION_FAILED"; + case 0xC000016B: + return "STATUS_DISK_RESET_FAILED"; + case 0xC000016C: + return "STATUS_SHARED_IRQ_BUSY"; + case 0xC000016D: + return "STATUS_FT_ORPHANING"; + case 0xC000016E: + return "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT"; + case 0xC0000172: + return "STATUS_PARTITION_FAILURE"; + case 0xC0000173: + return "STATUS_INVALID_BLOCK_LENGTH"; + case 0xC0000174: + return "STATUS_DEVICE_NOT_PARTITIONED"; + case 0xC0000175: + return "STATUS_UNABLE_TO_LOCK_MEDIA"; + case 0xC0000176: + return "STATUS_UNABLE_TO_UNLOAD_MEDIA"; + case 0xC0000177: + return "STATUS_EOM_OVERFLOW"; + case 0xC0000178: + return "STATUS_NO_MEDIA"; + case 0xC000017A: + return "STATUS_NO_SUCH_MEMBER"; + case 0xC000017B: + return "STATUS_INVALID_MEMBER"; + case 0xC000017C: + return "STATUS_KEY_DELETED"; + case 0xC000017D: + return "STATUS_NO_LOG_SPACE"; + case 0xC000017E: + return "STATUS_TOO_MANY_SIDS"; + case 0xC000017F: + return "STATUS_LM_CROSS_ENCRYPTION_REQUIRED"; + case 0xC0000180: + return "STATUS_KEY_HAS_CHILDREN"; + case 0xC0000181: + return "STATUS_CHILD_MUST_BE_VOLATILE"; + case 0xC0000182: + return "STATUS_DEVICE_CONFIGURATION_ERROR"; + case 0xC0000183: + return "STATUS_DRIVER_INTERNAL_ERROR"; + case 0xC0000184: + return "STATUS_INVALID_DEVICE_STATE"; + case 0xC0000185: + return "STATUS_IO_DEVICE_ERROR"; + case 0xC0000186: + return "STATUS_DEVICE_PROTOCOL_ERROR"; + case 0xC0000187: + return "STATUS_BACKUP_CONTROLLER"; + case 0xC0000188: + return "STATUS_LOG_FILE_FULL"; + case 0xC0000189: + return "STATUS_TOO_LATE"; + case 0xC000018A: + return "STATUS_NO_TRUST_LSA_SECRET"; + case 0xC000018B: + return "STATUS_NO_TRUST_SAM_ACCOUNT"; + case 0xC000018C: + return "STATUS_TRUSTED_DOMAIN_FAILURE"; + case 0xC000018D: + return "STATUS_TRUSTED_RELATIONSHIP_FAILURE"; + case 0xC000018E: + return "STATUS_EVENTLOG_FILE_CORRUPT"; + case 0xC000018F: + return "STATUS_EVENTLOG_CANT_START"; + case 0xC0000190: + return "STATUS_TRUST_FAILURE"; + case 0xC0000191: + return "STATUS_MUTANT_LIMIT_EXCEEDED"; + case 0xC0000192: + return "STATUS_NETLOGON_NOT_STARTED"; + case 0xC0000193: + return "STATUS_ACCOUNT_EXPIRED"; + case 0xC0000194: + return "STATUS_POSSIBLE_DEADLOCK"; + case 0xC0000195: + return "STATUS_NETWORK_CREDENTIAL_CONFLICT"; + case 0xC0000196: + return "STATUS_REMOTE_SESSION_LIMIT"; + case 0xC0000197: + return "STATUS_EVENTLOG_FILE_CHANGED"; + case 0xC0000198: + return "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"; + case 0xC0000199: + return "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"; + case 0xC000019A: + return "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"; + case 0xC000019B: + return "STATUS_DOMAIN_TRUST_INCONSISTENT"; + case 0xC000019C: + return "STATUS_FS_DRIVER_REQUIRED"; + case 0xC0000202: + return "STATUS_NO_USER_SESSION_KEY"; + case 0xC0000203: + return "STATUS_USER_SESSION_DELETED"; + case 0xC0000204: + return "STATUS_RESOURCE_LANG_NOT_FOUND"; + case 0xC0000205: + return "STATUS_INSUFF_SERVER_RESOURCES"; + case 0xC0000206: + return "STATUS_INVALID_BUFFER_SIZE"; + case 0xC0000207: + return "STATUS_INVALID_ADDRESS_COMPONENT"; + case 0xC0000208: + return "STATUS_INVALID_ADDRESS_WILDCARD"; + case 0xC0000209: + return "STATUS_TOO_MANY_ADDRESSES"; + case 0xC000020A: + return "STATUS_ADDRESS_ALREADY_EXISTS"; + case 0xC000020B: + return "STATUS_ADDRESS_CLOSED"; + case 0xC000020C: + return "STATUS_CONNECTION_DISCONNECTED"; + case 0xC000020D: + return "STATUS_CONNECTION_RESET"; + case 0xC000020E: + return "STATUS_TOO_MANY_NODES"; + case 0xC000020F: + return "STATUS_TRANSACTION_ABORTED"; + case 0xC0000210: + return "STATUS_TRANSACTION_TIMED_OUT"; + case 0xC0000211: + return "STATUS_TRANSACTION_NO_RELEASE"; + case 0xC0000212: + return "STATUS_TRANSACTION_NO_MATCH"; + case 0xC0000213: + return "STATUS_TRANSACTION_RESPONDED"; + case 0xC0000214: + return "STATUS_TRANSACTION_INVALID_ID"; + case 0xC0000215: + return "STATUS_TRANSACTION_INVALID_TYPE"; + case 0xC0000216: + return "STATUS_NOT_SERVER_SESSION"; + case 0xC0000217: + return "STATUS_NOT_CLIENT_SESSION"; + case 0xC0000218: + return "STATUS_CANNOT_LOAD_REGISTRY_FILE"; + case 0xC0000219: + return "STATUS_DEBUG_ATTACH_FAILED"; + case 0xC000021A: + return "STATUS_SYSTEM_PROCESS_TERMINATED"; + case 0xC000021B: + return "STATUS_DATA_NOT_ACCEPTED"; + case 0xC000021C: + return "STATUS_NO_BROWSER_SERVERS_FOUND"; + case 0xC000021D: + return "STATUS_VDM_HARD_ERROR"; + case 0xC000021E: + return "STATUS_DRIVER_CANCEL_TIMEOUT"; + case 0xC000021F: + return "STATUS_REPLY_MESSAGE_MISMATCH"; + case 0xC0000220: + return "STATUS_MAPPED_ALIGNMENT"; + case 0xC0000221: + return "STATUS_IMAGE_CHECKSUM_MISMATCH"; + case 0xC0000222: + return "STATUS_LOST_WRITEBEHIND_DATA"; + case 0xC0000223: + return "STATUS_CLIENT_SERVER_PARAMETERS_INVALID"; + case 0xC0000224: + return "STATUS_PASSWORD_MUST_CHANGE"; + case 0xC0000225: + return "STATUS_NOT_FOUND"; + case 0xC0000226: + return "STATUS_NOT_TINY_STREAM"; + case 0xC0000227: + return "STATUS_RECOVERY_FAILURE"; + case 0xC0000228: + return "STATUS_STACK_OVERFLOW_READ"; + case 0xC0000229: + return "STATUS_FAIL_CHECK"; + case 0xC000022A: + return "STATUS_DUPLICATE_OBJECTID"; + case 0xC000022B: + return "STATUS_OBJECTID_EXISTS"; + case 0xC000022C: + return "STATUS_CONVERT_TO_LARGE"; + case 0xC000022D: + return "STATUS_RETRY"; + case 0xC000022E: + return "STATUS_FOUND_OUT_OF_SCOPE"; + case 0xC000022F: + return "STATUS_ALLOCATE_BUCKET"; + case 0xC0000230: + return "STATUS_PROPSET_NOT_FOUND"; + case 0xC0000231: + return "STATUS_MARSHALL_OVERFLOW"; + case 0xC0000232: + return "STATUS_INVALID_VARIANT"; + case 0xC0000233: + return "STATUS_DOMAIN_CONTROLLER_NOT_FOUND"; + case 0xC0000234: + return "STATUS_ACCOUNT_LOCKED_OUT"; + case 0xC0000235: + return "STATUS_HANDLE_NOT_CLOSABLE"; + case 0xC0000236: + return "STATUS_CONNECTION_REFUSED"; + case 0xC0000237: + return "STATUS_GRACEFUL_DISCONNECT"; + case 0xC0000238: + return "STATUS_ADDRESS_ALREADY_ASSOCIATED"; + case 0xC0000239: + return "STATUS_ADDRESS_NOT_ASSOCIATED"; + case 0xC000023A: + return "STATUS_CONNECTION_INVALID"; + case 0xC000023B: + return "STATUS_CONNECTION_ACTIVE"; + case 0xC000023C: + return "STATUS_NETWORK_UNREACHABLE"; + case 0xC000023D: + return "STATUS_HOST_UNREACHABLE"; + case 0xC000023E: + return "STATUS_PROTOCOL_UNREACHABLE"; + case 0xC000023F: + return "STATUS_PORT_UNREACHABLE"; + case 0xC0000240: + return "STATUS_REQUEST_ABORTED"; + case 0xC0000241: + return "STATUS_CONNECTION_ABORTED"; + case 0xC0000242: + return "STATUS_BAD_COMPRESSION_BUFFER"; + case 0xC0000243: + return "STATUS_USER_MAPPED_FILE"; + case 0xC0000244: + return "STATUS_AUDIT_FAILED"; + case 0xC0000245: + return "STATUS_TIMER_RESOLUTION_NOT_SET"; + case 0xC0000246: + return "STATUS_CONNECTION_COUNT_LIMIT"; + case 0xC0000247: + return "STATUS_LOGIN_TIME_RESTRICTION"; + case 0xC0000248: + return "STATUS_LOGIN_WKSTA_RESTRICTION"; + case 0xC0000249: + return "STATUS_IMAGE_MP_UP_MISMATCH"; + case 0xC0000250: + return "STATUS_INSUFFICIENT_LOGON_INFO"; + case 0xC0000251: + return "STATUS_BAD_DLL_ENTRYPOINT"; + case 0xC0000252: + return "STATUS_BAD_SERVICE_ENTRYPOINT"; + case 0xC0000253: + return "STATUS_LPC_REPLY_LOST"; + case 0xC0000254: + return "STATUS_IP_ADDRESS_CONFLICT1"; + case 0xC0000255: + return "STATUS_IP_ADDRESS_CONFLICT2"; + case 0xC0000256: + return "STATUS_REGISTRY_QUOTA_LIMIT"; + case 0xC0000257: + return "STATUS_PATH_NOT_COVERED"; + case 0xC0000258: + return "STATUS_NO_CALLBACK_ACTIVE"; + case 0xC0000259: + return "STATUS_LICENSE_QUOTA_EXCEEDED"; + case 0xC000025A: + return "STATUS_PWD_TOO_SHORT"; + case 0xC000025B: + return "STATUS_PWD_TOO_RECENT"; + case 0xC000025C: + return "STATUS_PWD_HISTORY_CONFLICT"; + case 0xC000025E: + return "STATUS_PLUGPLAY_NO_DEVICE"; + case 0xC000025F: + return "STATUS_UNSUPPORTED_COMPRESSION"; + case 0xC0000260: + return "STATUS_INVALID_HW_PROFILE"; + case 0xC0000261: + return "STATUS_INVALID_PLUGPLAY_DEVICE_PATH"; + case 0xC0000262: + return "STATUS_DRIVER_ORDINAL_NOT_FOUND"; + case 0xC0000263: + return "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND"; + case 0xC0000264: + return "STATUS_RESOURCE_NOT_OWNED"; + case 0xC0000265: + return "STATUS_TOO_MANY_LINKS"; + case 0xC0000266: + return "STATUS_QUOTA_LIST_INCONSISTENT"; + case 0xC0000267: + return "STATUS_FILE_IS_OFFLINE"; + case 0xC0000268: + return "STATUS_EVALUATION_EXPIRATION"; + case 0xC0000269: + return "STATUS_ILLEGAL_DLL_RELOCATION"; + case 0xC000026A: + return "STATUS_LICENSE_VIOLATION"; + case 0xC000026B: + return "STATUS_DLL_INIT_FAILED_LOGOFF"; + case 0xC000026C: + return "STATUS_DRIVER_UNABLE_TO_LOAD"; + case 0xC000026D: + return "STATUS_DFS_UNAVAILABLE"; + case 0xC000026E: + return "STATUS_VOLUME_DISMOUNTED"; + case 0xC000026F: + return "STATUS_WX86_INTERNAL_ERROR"; + case 0xC0000270: + return "STATUS_WX86_FLOAT_STACK_CHECK"; + case 0xC0000271: + return "STATUS_VALIDATE_CONTINUE"; + case 0xC0000272: + return "STATUS_NO_MATCH"; + case 0xC0000273: + return "STATUS_NO_MORE_MATCHES"; + case 0xC0000275: + return "STATUS_NOT_A_REPARSE_POINT"; + case 0xC0000276: + return "STATUS_IO_REPARSE_TAG_INVALID"; + case 0xC0000277: + return "STATUS_IO_REPARSE_TAG_MISMATCH"; + case 0xC0000278: + return "STATUS_IO_REPARSE_DATA_INVALID"; + case 0xC0000279: + return "STATUS_IO_REPARSE_TAG_NOT_HANDLED"; + case 0xC0000280: + return "STATUS_REPARSE_POINT_NOT_RESOLVED"; + case 0xC0000281: + return "STATUS_DIRECTORY_IS_A_REPARSE_POINT"; + case 0xC0000282: + return "STATUS_RANGE_LIST_CONFLICT"; + case 0xC0000283: + return "STATUS_SOURCE_ELEMENT_EMPTY"; + case 0xC0000284: + return "STATUS_DESTINATION_ELEMENT_FULL"; + case 0xC0000285: + return "STATUS_ILLEGAL_ELEMENT_ADDRESS"; + case 0xC0000286: + return "STATUS_MAGAZINE_NOT_PRESENT"; + case 0xC0000287: + return "STATUS_REINITIALIZATION_NEEDED"; + case 0x80000288: + return "STATUS_DEVICE_REQUIRES_CLEANING"; + case 0x80000289: + return "STATUS_DEVICE_DOOR_OPEN"; + case 0xC000028A: + return "STATUS_ENCRYPTION_FAILED"; + case 0xC000028B: + return "STATUS_DECRYPTION_FAILED"; + case 0xC000028C: + return "STATUS_RANGE_NOT_FOUND"; + case 0xC000028D: + return "STATUS_NO_RECOVERY_POLICY"; + case 0xC000028E: + return "STATUS_NO_EFS"; + case 0xC000028F: + return "STATUS_WRONG_EFS"; + case 0xC0000290: + return "STATUS_NO_USER_KEYS"; + case 0xC0000291: + return "STATUS_FILE_NOT_ENCRYPTED"; + case 0xC0000292: + return "STATUS_NOT_EXPORT_FORMAT"; + case 0xC0000293: + return "STATUS_FILE_ENCRYPTED"; + case 0x40000294: + return "STATUS_WAKE_SYSTEM"; + case 0xC0000295: + return "STATUS_WMI_GUID_NOT_FOUND"; + case 0xC0000296: + return "STATUS_WMI_INSTANCE_NOT_FOUND"; + case 0xC0000297: + return "STATUS_WMI_ITEMID_NOT_FOUND"; + case 0xC0000298: + return "STATUS_WMI_TRY_AGAIN"; + case 0xC0000299: + return "STATUS_SHARED_POLICY"; + case 0xC000029A: + return "STATUS_POLICY_OBJECT_NOT_FOUND"; + case 0xC000029B: + return "STATUS_POLICY_ONLY_IN_DS"; + case 0xC000029C: + return "STATUS_VOLUME_NOT_UPGRADED"; + case 0xC000029D: + return "STATUS_REMOTE_STORAGE_NOT_ACTIVE"; + case 0xC000029E: + return "STATUS_REMOTE_STORAGE_MEDIA_ERROR"; + case 0xC000029F: + return "STATUS_NO_TRACKING_SERVICE"; + case 0xC00002A0: + return "STATUS_SERVER_SID_MISMATCH"; + case 0xC00002A1: + return "STATUS_DS_NO_ATTRIBUTE_OR_VALUE"; + case 0xC00002A2: + return "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX"; + case 0xC00002A3: + return "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED"; + case 0xC00002A4: + return "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS"; + case 0xC00002A5: + return "STATUS_DS_BUSY"; + case 0xC00002A6: + return "STATUS_DS_UNAVAILABLE"; + case 0xC00002A7: + return "STATUS_DS_NO_RIDS_ALLOCATED"; + case 0xC00002A8: + return "STATUS_DS_NO_MORE_RIDS"; + case 0xC00002A9: + return "STATUS_DS_INCORRECT_ROLE_OWNER"; + case 0xC00002AA: + return "STATUS_DS_RIDMGR_INIT_ERROR"; + case 0xC00002AB: + return "STATUS_DS_OBJ_CLASS_VIOLATION"; + case 0xC00002AC: + return "STATUS_DS_CANT_ON_NON_LEAF"; + case 0xC00002AD: + return "STATUS_DS_CANT_ON_RDN"; + case 0xC00002AE: + return "STATUS_DS_CANT_MOD_OBJ_CLASS"; + case 0xC00002AF: + return "STATUS_DS_CROSS_DOM_MOVE_FAILED"; + case 0xC00002B0: + return "STATUS_DS_GC_NOT_AVAILABLE"; + case 0xC00002B1: + return "STATUS_DIRECTORY_SERVICE_REQUIRED"; + case 0xC00002B2: + return "STATUS_REPARSE_ATTRIBUTE_CONFLICT"; + case 0xC00002B3: + return "STATUS_CANT_ENABLE_DENY_ONLY"; + case 0xC00002B4: + return "STATUS_FLOAT_MULTIPLE_FAULTS"; + case 0xC00002B5: + return "STATUS_FLOAT_MULTIPLE_TRAPS"; + case 0xC00002B6: + return "STATUS_DEVICE_REMOVED"; + case 0xC00002B7: + return "STATUS_JOURNAL_DELETE_IN_PROGRESS"; + case 0xC00002B8: + return "STATUS_JOURNAL_NOT_ACTIVE"; + case 0xC00002B9: + return "STATUS_NOINTERFACE"; + case 0xC00002C1: + return "STATUS_DS_ADMIN_LIMIT_EXCEEDED"; + case 0xC00002C2: + return "STATUS_DRIVER_FAILED_SLEEP"; + case 0xC00002C3: + return "STATUS_MUTUAL_AUTHENTICATION_FAILED"; + case 0xC00002C4: + return "STATUS_CORRUPT_SYSTEM_FILE"; + case 0xC00002C5: + return "STATUS_DATATYPE_MISALIGNMENT_ERROR"; + case 0xC00002C6: + return "STATUS_WMI_READ_ONLY"; + case 0xC00002C7: + return "STATUS_WMI_SET_FAILURE"; + case 0xC00002C8: + return "STATUS_COMMITMENT_MINIMUM"; + case 0xC00002C9: + return "STATUS_REG_NAT_CONSUMPTION"; + case 0xC00002CA: + return "STATUS_TRANSPORT_FULL"; + case 0xC00002CB: + return "STATUS_DS_SAM_INIT_FAILURE"; + case 0xC00002CC: + return "STATUS_ONLY_IF_CONNECTED"; + case 0xC00002CD: + return "STATUS_DS_SENSITIVE_GROUP_VIOLATION"; + case 0xC00002CE: + return "STATUS_PNP_RESTART_ENUMERATION"; + case 0xC00002CF: + return "STATUS_JOURNAL_ENTRY_DELETED"; + case 0xC00002D0: + return "STATUS_DS_CANT_MOD_PRIMARYGROUPID"; + case 0xC00002D1: + return "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE"; + case 0xC00002D2: + return "STATUS_PNP_REBOOT_REQUIRED"; + case 0xC00002D3: + return "STATUS_POWER_STATE_INVALID"; + case 0xC00002D4: + return "STATUS_DS_INVALID_GROUP_TYPE"; + case 0xC00002D5: + return "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN"; + case 0xC00002D6: + return "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN"; + case 0xC00002D7: + return "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER"; + case 0xC00002D8: + return "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER"; + case 0xC00002D9: + return "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER"; + case 0xC00002DA: + return "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER"; + case 0xC00002DB: + return "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER"; + case 0xC00002DC: + return "STATUS_DS_HAVE_PRIMARY_MEMBERS"; + case 0xC00002DD: + return "STATUS_WMI_NOT_SUPPORTED"; + case 0xC00002DE: + return "STATUS_INSUFFICIENT_POWER"; + case 0xC00002DF: + return "STATUS_SAM_NEED_BOOTKEY_PASSWORD"; + case 0xC00002E0: + return "STATUS_SAM_NEED_BOOTKEY_FLOPPY"; + case 0xC00002E1: + return "STATUS_DS_CANT_START"; + case 0xC00002E2: + return "STATUS_DS_INIT_FAILURE"; + case 0xC00002E3: + return "STATUS_SAM_INIT_FAILURE"; + case 0xC00002E4: + return "STATUS_DS_GC_REQUIRED"; + case 0xC00002E5: + return "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY"; + case 0xC00002E6: + return "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS"; + case 0xC00002E7: + return "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED"; + case 0xC00002E8: + return "STATUS_MULTIPLE_FAULT_VIOLATION"; + case 0xC0000300: + return "STATUS_NOT_SUPPORTED_ON_SBS"; + case 0xC0009898: + return "STATUS_WOW_ASSERTION"; + case 0xC0010001: + return "DBG_NO_STATE_CHANGE"; + case 0xC0010002: + return "DBG_APP_NOT_IDLE"; + case 0xC0020001: + return "RPC_NT_INVALID_STRING_BINDING"; + case 0xC0020002: + return "RPC_NT_WRONG_KIND_OF_BINDING"; + case 0xC0020003: + return "RPC_NT_INVALID_BINDING"; + case 0xC0020004: + return "RPC_NT_PROTSEQ_NOT_SUPPORTED"; + case 0xC0020005: + return "RPC_NT_INVALID_RPC_PROTSEQ"; + case 0xC0020006: + return "RPC_NT_INVALID_STRING_UUID"; + case 0xC0020007: + return "RPC_NT_INVALID_ENDPOINT_FORMAT"; + case 0xC0020008: + return "RPC_NT_INVALID_NET_ADDR"; + case 0xC0020009: + return "RPC_NT_NO_ENDPOINT_FOUND"; + case 0xC002000A: + return "RPC_NT_INVALID_TIMEOUT"; + case 0xC002000B: + return "RPC_NT_OBJECT_NOT_FOUND"; + case 0xC002000C: + return "RPC_NT_ALREADY_REGISTERED"; + case 0xC002000D: + return "RPC_NT_TYPE_ALREADY_REGISTERED"; + case 0xC002000E: + return "RPC_NT_ALREADY_LISTENING"; + case 0xC002000F: + return "RPC_NT_NO_PROTSEQS_REGISTERED"; + case 0xC0020010: + return "RPC_NT_NOT_LISTENING"; + case 0xC0020011: + return "RPC_NT_UNKNOWN_MGR_TYPE"; + case 0xC0020012: + return "RPC_NT_UNKNOWN_IF"; + case 0xC0020013: + return "RPC_NT_NO_BINDINGS"; + case 0xC0020014: + return "RPC_NT_NO_PROTSEQS"; + case 0xC0020015: + return "RPC_NT_CANT_CREATE_ENDPOINT"; + case 0xC0020016: + return "RPC_NT_OUT_OF_RESOURCES"; + case 0xC0020017: + return "RPC_NT_SERVER_UNAVAILABLE"; + case 0xC0020018: + return "RPC_NT_SERVER_TOO_BUSY"; + case 0xC0020019: + return "RPC_NT_INVALID_NETWORK_OPTIONS"; + case 0xC002001A: + return "RPC_NT_NO_CALL_ACTIVE"; + case 0xC002001B: + return "RPC_NT_CALL_FAILED"; + case 0xC002001C: + return "RPC_NT_CALL_FAILED_DNE"; + case 0xC002001D: + return "RPC_NT_PROTOCOL_ERROR"; + case 0xC002001F: + return "RPC_NT_UNSUPPORTED_TRANS_SYN"; + case 0xC0020021: + return "RPC_NT_UNSUPPORTED_TYPE"; + case 0xC0020022: + return "RPC_NT_INVALID_TAG"; + case 0xC0020023: + return "RPC_NT_INVALID_BOUND"; + case 0xC0020024: + return "RPC_NT_NO_ENTRY_NAME"; + case 0xC0020025: + return "RPC_NT_INVALID_NAME_SYNTAX"; + case 0xC0020026: + return "RPC_NT_UNSUPPORTED_NAME_SYNTAX"; + case 0xC0020028: + return "RPC_NT_UUID_NO_ADDRESS"; + case 0xC0020029: + return "RPC_NT_DUPLICATE_ENDPOINT"; + case 0xC002002A: + return "RPC_NT_UNKNOWN_AUTHN_TYPE"; + case 0xC002002B: + return "RPC_NT_MAX_CALLS_TOO_SMALL"; + case 0xC002002C: + return "RPC_NT_STRING_TOO_LONG"; + case 0xC002002D: + return "RPC_NT_PROTSEQ_NOT_FOUND"; + case 0xC002002E: + return "RPC_NT_PROCNUM_OUT_OF_RANGE"; + case 0xC002002F: + return "RPC_NT_BINDING_HAS_NO_AUTH"; + case 0xC0020030: + return "RPC_NT_UNKNOWN_AUTHN_SERVICE"; + case 0xC0020031: + return "RPC_NT_UNKNOWN_AUTHN_LEVEL"; + case 0xC0020032: + return "RPC_NT_INVALID_AUTH_IDENTITY"; + case 0xC0020033: + return "RPC_NT_UNKNOWN_AUTHZ_SERVICE"; + case 0xC0020034: + return "EPT_NT_INVALID_ENTRY"; + case 0xC0020035: + return "EPT_NT_CANT_PERFORM_OP"; + case 0xC0020036: + return "EPT_NT_NOT_REGISTERED"; + case 0xC0020037: + return "RPC_NT_NOTHING_TO_EXPORT"; + case 0xC0020038: + return "RPC_NT_INCOMPLETE_NAME"; + case 0xC0020039: + return "RPC_NT_INVALID_VERS_OPTION"; + case 0xC002003A: + return "RPC_NT_NO_MORE_MEMBERS"; + case 0xC002003B: + return "RPC_NT_NOT_ALL_OBJS_UNEXPORTED"; + case 0xC002003C: + return "RPC_NT_INTERFACE_NOT_FOUND"; + case 0xC002003D: + return "RPC_NT_ENTRY_ALREADY_EXISTS"; + case 0xC002003E: + return "RPC_NT_ENTRY_NOT_FOUND"; + case 0xC002003F: + return "RPC_NT_NAME_SERVICE_UNAVAILABLE"; + case 0xC0020040: + return "RPC_NT_INVALID_NAF_ID"; + case 0xC0020041: + return "RPC_NT_CANNOT_SUPPORT"; + case 0xC0020042: + return "RPC_NT_NO_CONTEXT_AVAILABLE"; + case 0xC0020043: + return "RPC_NT_INTERNAL_ERROR"; + case 0xC0020044: + return "RPC_NT_ZERO_DIVIDE"; + case 0xC0020045: + return "RPC_NT_ADDRESS_ERROR"; + case 0xC0020046: + return "RPC_NT_FP_DIV_ZERO"; + case 0xC0020047: + return "RPC_NT_FP_UNDERFLOW"; + case 0xC0020048: + return "RPC_NT_FP_OVERFLOW"; + case 0xC0030001: + return "RPC_NT_NO_MORE_ENTRIES"; + case 0xC0030002: + return "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL"; + case 0xC0030003: + return "RPC_NT_SS_CHAR_TRANS_SHORT_FILE"; + case 0xC0030004: + return "RPC_NT_SS_IN_NULL_CONTEXT"; + case 0xC0030005: + return "RPC_NT_SS_CONTEXT_MISMATCH"; + case 0xC0030006: + return "RPC_NT_SS_CONTEXT_DAMAGED"; + case 0xC0030007: + return "RPC_NT_SS_HANDLES_MISMATCH"; + case 0xC0030008: + return "RPC_NT_SS_CANNOT_GET_CALL_HANDLE"; + case 0xC0030009: + return "RPC_NT_NULL_REF_POINTER"; + case 0xC003000A: + return "RPC_NT_ENUM_VALUE_OUT_OF_RANGE"; + case 0xC003000B: + return "RPC_NT_BYTE_COUNT_TOO_SMALL"; + case 0xC003000C: + return "RPC_NT_BAD_STUB_DATA"; + case 0xC0020049: + return "RPC_NT_CALL_IN_PROGRESS"; + case 0xC002004A: + return "RPC_NT_NO_MORE_BINDINGS"; + case 0xC002004B: + return "RPC_NT_GROUP_MEMBER_NOT_FOUND"; + case 0xC002004C: + return "EPT_NT_CANT_CREATE"; + case 0xC002004D: + return "RPC_NT_INVALID_OBJECT"; + case 0xC002004F: + return "RPC_NT_NO_INTERFACES"; + case 0xC0020050: + return "RPC_NT_CALL_CANCELLED"; + case 0xC0020051: + return "RPC_NT_BINDING_INCOMPLETE"; + case 0xC0020052: + return "RPC_NT_COMM_FAILURE"; + case 0xC0020053: + return "RPC_NT_UNSUPPORTED_AUTHN_LEVEL"; + case 0xC0020054: + return "RPC_NT_NO_PRINC_NAME"; + case 0xC0020055: + return "RPC_NT_NOT_RPC_ERROR"; + case 0x40020056: + return "RPC_NT_UUID_LOCAL_ONLY"; + case 0xC0020057: + return "RPC_NT_SEC_PKG_ERROR"; + case 0xC0020058: + return "RPC_NT_NOT_CANCELLED"; + case 0xC0030059: + return "RPC_NT_INVALID_ES_ACTION"; + case 0xC003005A: + return "RPC_NT_WRONG_ES_VERSION"; + case 0xC003005B: + return "RPC_NT_WRONG_STUB_VERSION"; + case 0xC003005C: + return "RPC_NT_INVALID_PIPE_OBJECT"; + case 0xC003005D: + return "RPC_NT_INVALID_PIPE_OPERATION"; + case 0xC003005E: + return "RPC_NT_WRONG_PIPE_VERSION"; + case 0xC003005F: + return "RPC_NT_PIPE_CLOSED"; + case 0xC0030060: + return "RPC_NT_PIPE_DISCIPLINE_ERROR"; + case 0xC0030061: + return "RPC_NT_PIPE_EMPTY"; + case 0xC0020062: + return "RPC_NT_INVALID_ASYNC_HANDLE"; + case 0xC0020063: + return "RPC_NT_INVALID_ASYNC_CALL"; + case 0x400200AF: + return "RPC_NT_SEND_INCOMPLETE"; + case 0xC0140001: + return "STATUS_ACPI_INVALID_OPCODE"; + case 0xC0140002: + return "STATUS_ACPI_STACK_OVERFLOW"; + case 0xC0140003: + return "STATUS_ACPI_ASSERT_FAILED"; + case 0xC0140004: + return "STATUS_ACPI_INVALID_INDEX"; + case 0xC0140005: + return "STATUS_ACPI_INVALID_ARGUMENT"; + case 0xC0140006: + return "STATUS_ACPI_FATAL"; + case 0xC0140007: + return "STATUS_ACPI_INVALID_SUPERNAME"; + case 0xC0140008: + return "STATUS_ACPI_INVALID_ARGTYPE"; + case 0xC0140009: + return "STATUS_ACPI_INVALID_OBJTYPE"; + case 0xC014000A: + return "STATUS_ACPI_INVALID_TARGETTYPE"; + case 0xC014000B: + return "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT"; + case 0xC014000C: + return "STATUS_ACPI_ADDRESS_NOT_MAPPED"; + case 0xC014000D: + return "STATUS_ACPI_INVALID_EVENTTYPE"; + case 0xC014000E: + return "STATUS_ACPI_HANDLER_COLLISION"; + case 0xC014000F: + return "STATUS_ACPI_INVALID_DATA"; + case 0xC0140010: + return "STATUS_ACPI_INVALID_REGION"; + case 0xC0140011: + return "STATUS_ACPI_INVALID_ACCESS_SIZE"; + case 0xC0140012: + return "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK"; + case 0xC0140013: + return "STATUS_ACPI_ALREADY_INITIALIZED"; + case 0xC0140014: + return "STATUS_ACPI_NOT_INITIALIZED"; + case 0xC0140015: + return "STATUS_ACPI_INVALID_MUTEX_LEVEL"; + case 0xC0140016: + return "STATUS_ACPI_MUTEX_NOT_OWNED"; + case 0xC0140017: + return "STATUS_ACPI_MUTEX_NOT_OWNER"; + case 0xC0140018: + return "STATUS_ACPI_RS_ACCESS"; + case 0xC0140019: + return "STATUS_ACPI_INVALID_TABLE"; + case 0xC0140020: + return "STATUS_ACPI_REG_HANDLER_FAILED"; + case 0xC0140021: + return "STATUS_ACPI_POWER_REQUEST_FAILED"; + case 0xC00A0001: + return "STATUS_CTX_WINSTATION_NAME_INVALID"; + case 0xC00A0002: + return "STATUS_CTX_INVALID_PD"; + case 0xC00A0003: + return "STATUS_CTX_PD_NOT_FOUND"; + case 0x400A0004: + return "STATUS_CTX_CDM_CONNECT"; + case 0x400A0005: + return "STATUS_CTX_CDM_DISCONNECT"; + case 0xC00A0006: + return "STATUS_CTX_CLOSE_PENDING"; + case 0xC00A0007: + return "STATUS_CTX_NO_OUTBUF"; + case 0xC00A0008: + return "STATUS_CTX_MODEM_INF_NOT_FOUND"; + case 0xC00A0009: + return "STATUS_CTX_INVALID_MODEMNAME"; + case 0xC00A000A: + return "STATUS_CTX_RESPONSE_ERROR"; + case 0xC00A000B: + return "STATUS_CTX_MODEM_RESPONSE_TIMEOUT"; + case 0xC00A000C: + return "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER"; + case 0xC00A000D: + return "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE"; + case 0xC00A000E: + return "STATUS_CTX_MODEM_RESPONSE_BUSY"; + case 0xC00A000F: + return "STATUS_CTX_MODEM_RESPONSE_VOICE"; + case 0xC00A0010: + return "STATUS_CTX_TD_ERROR"; + case 0xC00A0012: + return "STATUS_CTX_LICENSE_CLIENT_INVALID"; + case 0xC00A0013: + return "STATUS_CTX_LICENSE_NOT_AVAILABLE"; + case 0xC00A0014: + return "STATUS_CTX_LICENSE_EXPIRED"; + case 0xC00A0015: + return "STATUS_CTX_WINSTATION_NOT_FOUND"; + case 0xC00A0016: + return "STATUS_CTX_WINSTATION_NAME_COLLISION"; + case 0xC00A0017: + return "STATUS_CTX_WINSTATION_BUSY"; + case 0xC00A0018: + return "STATUS_CTX_BAD_VIDEO_MODE"; + case 0xC00A0022: + return "STATUS_CTX_GRAPHICS_INVALID"; + case 0xC00A0024: + return "STATUS_CTX_NOT_CONSOLE"; + case 0xC00A0026: + return "STATUS_CTX_CLIENT_QUERY_TIMEOUT"; + case 0xC00A0027: + return "STATUS_CTX_CONSOLE_DISCONNECT"; + case 0xC00A0028: + return "STATUS_CTX_CONSOLE_CONNECT"; + case 0xC00A002A: + return "STATUS_CTX_SHADOW_DENIED"; + case 0xC00A002B: + return "STATUS_CTX_WINSTATION_ACCESS_DENIED"; + case 0xC00A002E: + return "STATUS_CTX_INVALID_WD"; + case 0xC00A002F: + return "STATUS_CTX_WD_NOT_FOUND"; + case 0xC00A0030: + return "STATUS_CTX_SHADOW_INVALID"; + case 0xC00A0031: + return "STATUS_CTX_SHADOW_DISABLED"; + case 0xC00A0032: + return "STATUS_RDP_PROTOCOL_ERROR"; + case 0xC00A0033: + return "STATUS_CTX_CLIENT_LICENSE_NOT_SET"; + case 0xC00A0034: + return "STATUS_CTX_CLIENT_LICENSE_IN_USE"; + case 0xC0040035: + return "STATUS_PNP_BAD_MPS_TABLE"; + case 0xC0040036: + return "STATUS_PNP_TRANSLATION_FAILED"; + case 0xC0040037: + return "STATUS_PNP_IRQ_TRANSLATION_FAILED"; + default: + return "STATUS_UNKNOWN"; + } +} + + +/* avoid stack overflow for dead symlinks */ + +VOID +Ext2TraceMcb(PCHAR fn, USHORT lc, USHORT add, PEXT2_MCB Mcb) { + size_t i; + CHAR _space[33]; + + _snprintf(&_space[0], 32, "%s:%d:", fn, lc); + _space[32] = 0; + i = strlen(_space); + while (i < 32) { + _space[i++] = ' '; + _space[i]=0; + } + if (add) { + Ext2ReferXcb(&Mcb->Refercount); + DEBUG(DL_RES, ("%s +%2u %wZ (%p)\n", _space, (Mcb->Refercount - 1), &Mcb->FullName, Mcb)); + } else { + Ext2DerefXcb(&Mcb->Refercount); + DEBUG(DL_RES, ("%s -%2u %wZ (%p)\n", _space, Mcb->Refercount, &Mcb->FullName, Mcb)); + } +} + +KSPIN_LOCK Ext2MemoryLock; +ULONGLONG Ext2TotalMemorySize = 0; +ULONG Ext2TotalAllocates = 0; + +PVOID +Ext2AllocatePool( + IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag +) +{ + PUCHAR Buffer = ExAllocatePoolWithTag( + PoolType, + 0x20 + NumberOfBytes, + Tag); + if (Buffer) { + KIRQL Irql = 0; + PULONG Data = (PULONG)Buffer; + Data[0] = (ULONG)NumberOfBytes; + Data[1] = (ULONG)NumberOfBytes + 0x20; + memset(Buffer + 0x08, 'S', 8); + memset(Buffer + 0x10 + NumberOfBytes, 'E', 0x10); + Buffer += 0x10; + KeAcquireSpinLock(&Ext2MemoryLock, &Irql); + Ext2TotalMemorySize = Ext2TotalMemorySize + NumberOfBytes; + Ext2TotalAllocates += 1; + KeReleaseSpinLock(&Ext2MemoryLock, Irql); + } + + return Buffer; +} + +VOID +Ext2FreePool( + IN PVOID P, + IN ULONG Tag +) +{ + PUCHAR Buffer = (PUCHAR)P; + PULONG Data; + ULONG NumberOfBytes, i; + KIRQL Irql; + + Buffer -= 0x10; + Data = (PULONG)(Buffer); + NumberOfBytes = Data[0]; + if (Data[1] != NumberOfBytes + 0x20) { + DbgBreak(); + return; + } + for (i=0x08; i < 0x10; i++) { + if (Buffer[i] != 'S') { + DbgBreak(); + } + Buffer[i] = '-'; + } + for (i=0; i < 0x10; i++) { + if (Buffer[i + NumberOfBytes + 0x10] != 'E') { + DbgBreak(); + return; + } + Buffer[i + NumberOfBytes + 0x10] = '-'; + } + + KeAcquireSpinLock(&Ext2MemoryLock, &Irql); + Ext2TotalMemorySize = Ext2TotalMemorySize - NumberOfBytes; + Ext2TotalAllocates -= 1; + KeReleaseSpinLock(&Ext2MemoryLock, Irql); + + ExFreePoolWithTag(Buffer, Tag); +} + +#else // EXT2_DEBUG + +PVOID +Ext2AllocatePool( + IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag +) +{ + return ExAllocatePoolWithTag( + PoolType, + NumberOfBytes, + Tag); +} + +VOID +Ext2FreePool( + IN PVOID P, + IN ULONG Tag +) +{ + ExFreePoolWithTag(P, Tag); +} + +#endif // !EXT2_DEBUG diff --git a/Ext4Fsd/devctl.c b/Ext4Fsd/devctl.c index 43d5405..0ca56ee 100644 --- a/Ext4Fsd/devctl.c +++ b/Ext4Fsd/devctl.c @@ -1,812 +1,812 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: devctl.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -NTSTATUS -Ext2DeviceControlCompletion ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context); - - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Ext2DeviceControl) -#pragma alloc_text(PAGE, Ext2DeviceControlNormal) -#pragma alloc_text(PAGE, Ext2ProcessVolumeProperty) -#pragma alloc_text(PAGE, Ext2ProcessUserProperty) -#pragma alloc_text(PAGE, Ext2ProcessGlobalProperty) -#pragma alloc_text(PAGE, Ex2ProcessUserPerfStat) -#pragma alloc_text(PAGE, Ex2ProcessMountPoint) -#if EXT2_UNLOAD -#pragma alloc_text(PAGE, Ext2PrepareToUnload) -#endif -#endif - - -NTSTATUS -Ext2DeviceControlCompletion ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context -) -{ - if (Irp->PendingReturned) { - IoMarkIrpPending(Irp); - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - BOOLEAN CompleteRequest = TRUE; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - PEXT2_VCB Vcb; - - PIRP Irp; - PIO_STACK_LOCATION IrpSp; - PIO_STACK_LOCATION NextIrpSp; - - PDEVICE_OBJECT TargetDeviceObject; - - __try { - - ASSERT(IrpContext != NULL); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - CompleteRequest = TRUE; - - DeviceObject = IrpContext->DeviceObject; - - if (IsExt2FsDevice(DeviceObject)) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Irp = IrpContext->Irp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext; - - if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && - (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - TargetDeviceObject = Vcb->TargetDeviceObject; - - // - // Pass on the IOCTL to the driver below - // - - CompleteRequest = FALSE; - - NextIrpSp = IoGetNextIrpStackLocation( Irp ); - *NextIrpSp = *IrpSp; - - IoSetCompletionRoutine( - Irp, - Ext2DeviceControlCompletion, - NULL, - FALSE, - TRUE, - TRUE ); - - Status = IoCallDriver(TargetDeviceObject, Irp); - - } __finally { - - if (!IrpContext->ExceptionInProgress) { - if (IrpContext) { - if (!CompleteRequest) { - IrpContext->Irp = NULL; - } - - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} - - -#if EXT2_UNLOAD - -NTSTATUS -Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - BOOLEAN GlobalDataResourceAcquired = FALSE; - - __try { - - ASSERT(IrpContext != NULL); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - DeviceObject = IrpContext->DeviceObject; - - if (IsExt2FsDevice(DeviceObject)) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - ExAcquireResourceExclusiveLite( - &Ext2Global->Resource, - TRUE ); - - GlobalDataResourceAcquired = TRUE; - - if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) { - DEBUG(DL_ERR, ( "Ext2PrepareUnload: Already ready to unload.\n")); - - Status = STATUS_ACCESS_DENIED; - - __leave; - } - - { - PEXT2_VCB Vcb; - PLIST_ENTRY ListEntry; - - ListEntry = Ext2Global->VcbList.Flink; - - while (ListEntry != &(Ext2Global->VcbList)) { - - Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); - ListEntry = ListEntry->Flink; - - if (Vcb && (!Vcb->ReferenceCount) && - IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { - Ext2RemoveVcb(Vcb); - Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); - - Ext2DestroyVcb(Vcb); - } - } - } - - if (!IsListEmpty(&(Ext2Global->VcbList))) { - - DEBUG(DL_ERR, ( "Ext2PrepareUnload: Mounted volumes exists.\n")); - - Status = STATUS_ACCESS_DENIED; - - __leave; - } - - IoUnregisterFileSystem(Ext2Global->DiskdevObject); - IoUnregisterFileSystem(Ext2Global->CdromdevObject); - Ext2Global->DriverObject->DriverUnload = DriverUnload; - SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING); - Status = STATUS_SUCCESS; - - DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n")); - - } __finally { - - if (GlobalDataResourceAcquired) { - ExReleaseResourceLite(&Ext2Global->Resource); - } - - if (!IrpContext->ExceptionInProgress) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - return Status; -} - -#endif - -extern CHAR gVersion[]; -extern CHAR gTime[]; -extern CHAR gDate[]; - -NTSTATUS -Ext2ProcessGlobalProperty( - IN PDEVICE_OBJECT DeviceObject, - IN PEXT2_VOLUME_PROPERTY3 Property3, - IN ULONG Length -) -{ - PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3; - PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; - struct nls_table * PageTable = NULL; - - NTSTATUS Status = STATUS_SUCCESS; - BOOLEAN GlobalDataResourceAcquired = FALSE; - - __try { - - if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - /* query Ext2Fsd's version and built date/time*/ - if (Property->Command == APP_CMD_QUERY_VERSION) { - PEXT2_VOLUME_PROPERTY_VERSION PVPV = - (PEXT2_VOLUME_PROPERTY_VERSION) Property; - - if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - RtlZeroMemory(&PVPV->Date[0], 0x20); - RtlZeroMemory(&PVPV->Time[0], 0x20); - RtlZeroMemory(&PVPV->Version[0],0x1C); - strncpy(&PVPV->Version[0], gVersion, 0x1B); - strncpy(&PVPV->Date[0], gDate, 0x1F); - strncpy(&PVPV->Time[0], gTime, 0x1F); - __leave; - } - - /* must be property query/set commands */ - if (Property->Command == APP_CMD_SET_PROPERTY) { - if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - } else if (Property->Command == APP_CMD_SET_PROPERTY2) { - if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - } else if (Property->Command == APP_CMD_SET_PROPERTY3) { - if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - } else { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE); - GlobalDataResourceAcquired = TRUE; - - - switch (Property->Command) { - - case APP_CMD_SET_PROPERTY3: - - if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { - if (Property3->AutoMount) - SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - else - ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - } - - case APP_CMD_SET_PROPERTY2: - - RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN); - if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) { - RtlCopyMemory( Ext2Global->sHidingPrefix, - Property2->sHidingPrefix, - HIDINGPAT_LEN - 1); - } - RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN); - if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) { - RtlCopyMemory( Ext2Global->sHidingSuffix, - Property2->sHidingSuffix, - HIDINGPAT_LEN - 1); - } - - case APP_CMD_SET_PROPERTY: - - if (Property->bReadonly) { - ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); - ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); - } else { - SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); - if (Property->bExt3Writable) { - SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); - } else { - ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); - } - } - - PageTable = load_nls(Property->Codepage); - if (PageTable) { - memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); - Ext2Global->Codepage.PageTable = PageTable; - } - - break; - - default: - break; - } - - } __finally { - - if (GlobalDataResourceAcquired) { - ExReleaseResourceLite(&Ext2Global->Resource); - } - } - - return Status; -} - - -NTSTATUS -Ext2ProcessVolumeProperty( - IN PEXT2_VCB Vcb, - IN PEXT2_VOLUME_PROPERTY3 Property3, - IN ULONG Length -) -{ - struct nls_table * PageTable = NULL; - PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3; - PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; - NTSTATUS Status = STATUS_SUCCESS; - BOOLEAN VcbResourceAcquired = FALSE; - - __try { - - ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); - VcbResourceAcquired = TRUE; - - if (Property->Command == APP_CMD_SET_PROPERTY || - Property->Command == APP_CMD_QUERY_PROPERTY) { - if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - } else if (Property->Command == APP_CMD_SET_PROPERTY2 || - Property->Command == APP_CMD_QUERY_PROPERTY2) { - if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - } else if (Property->Command == APP_CMD_SET_PROPERTY3 || - Property->Command == APP_CMD_QUERY_PROPERTY3) { - if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - } - - switch (Property->Command) { - - case APP_CMD_SET_PROPERTY3: - - if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { - if (Property3->AutoMount) - SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - else - ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - } - if (Property3->Flags2 & EXT2_VPROP3_USERIDS) { - SetFlag(Vcb->Flags, VCB_USER_IDS); - Vcb->uid = Property3->uid; - Vcb->gid = Property3->gid; - if (Property3->EIDS) { - Vcb->euid = Property3->euid; - Vcb->egid = Property3->egid; - SetFlag(Vcb->Flags, VCB_USER_EIDS); - } else { - Vcb->euid = Vcb->egid = 0; - ClearFlag(Vcb->Flags, VCB_USER_EIDS); - } - } else { - ClearFlag(Vcb->Flags, VCB_USER_IDS); - ClearFlag(Vcb->Flags, VCB_USER_EIDS); - Vcb->uid = Vcb->gid = 0; - Vcb->euid = Vcb->egid = 0; - } - - case APP_CMD_SET_PROPERTY2: - - RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN); - if (Vcb->bHidingPrefix = Property2->bHidingPrefix) { - RtlCopyMemory( Vcb->sHidingPrefix, - Property2->sHidingPrefix, - HIDINGPAT_LEN - 1); - } - - RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN); - if (Vcb->bHidingSuffix = Property2->bHidingSuffix) { - RtlCopyMemory( Vcb->sHidingSuffix, - Property2->sHidingSuffix, - HIDINGPAT_LEN - 1); - } - Vcb->DrvLetter = Property2->DrvLetter; - - case APP_CMD_SET_PROPERTY: - - if (Property->bReadonly) { - if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { - Ext2FlushFiles(NULL, Vcb, FALSE); - Ext2FlushVolume(NULL, Vcb, FALSE); - } - SetLongFlag(Vcb->Flags, VCB_READ_ONLY); - - } else { - - if (Property->bExt3Writable) { - SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING); - } - - if (!Vcb->IsExt3fs) { - ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); - } else if (!Property->bExt3Writable) { - SetLongFlag(Vcb->Flags, VCB_READ_ONLY); - } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { - ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); - Ext2RecoverJournal(NULL, Vcb); - if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { - SetLongFlag(Vcb->Flags, VCB_READ_ONLY); - } else { - ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); - } - } else { - ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); - } - } - - PageTable = load_nls(Property->Codepage); - memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); - Vcb->Codepage.PageTable = PageTable; - if (Vcb->Codepage.PageTable) { - Ext2InitializeLabel(Vcb, Vcb->SuperBlock); - } - - break; - - case APP_CMD_QUERY_PROPERTY3: - - if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) { - SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); - Property3->AutoMount = TRUE; - } else { - ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); - Property3->AutoMount = FALSE; - } - - if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) { - SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); - Property3->uid = Vcb->uid; - Property3->gid = Vcb->gid; - if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { - Property3->EIDS = TRUE; - Property3->euid = Vcb->euid; - Property3->egid = Vcb->egid; - } else { - Property3->EIDS = FALSE; - } - } else { - ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); - } - - case APP_CMD_QUERY_PROPERTY2: - - RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16); - Property2->DrvLetter = Vcb->DrvLetter; - - if (Property2->bHidingPrefix = Vcb->bHidingPrefix) { - RtlCopyMemory( Property2->sHidingPrefix, - Vcb->sHidingPrefix, - HIDINGPAT_LEN); - } else { - RtlZeroMemory( Property2->sHidingPrefix, - HIDINGPAT_LEN); - } - - if (Property2->bHidingSuffix = Vcb->bHidingSuffix) { - RtlCopyMemory( Property2->sHidingSuffix, - Vcb->sHidingSuffix, - HIDINGPAT_LEN); - } else { - RtlZeroMemory( Property2->sHidingSuffix, - HIDINGPAT_LEN); - } - - case APP_CMD_QUERY_PROPERTY: - - Property->bExt2 = TRUE; - Property->bExt3 = Vcb->IsExt3fs; - Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY); - if (!Property->bReadonly && Vcb->IsExt3fs) { - Property->bExt3Writable = TRUE; - } else { - Property->bExt3Writable = FALSE; - } - - RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN); - if (Vcb->Codepage.PageTable) { - strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN); - } else { - strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN); - } - break; - - default: - Status = STATUS_INVALID_PARAMETER; - break; - } - - } __finally { - - if (VcbResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - } - - return Status; -} - -NTSTATUS -Ext2ProcessUserProperty( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VOLUME_PROPERTY3 Property, - IN ULONG Length -) -{ - NTSTATUS Status = STATUS_SUCCESS; - PEXT2_VCB Vcb = NULL; - PDEVICE_OBJECT DeviceObject = NULL; - - __try { - - ASSERT(IrpContext != NULL); - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - if (Property->Magic != EXT2_VOLUME_PROPERTY_MAGIC) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - DeviceObject = IrpContext->DeviceObject; - if (IsExt2FsDevice(DeviceObject)) { - Status = Ext2ProcessGlobalProperty(DeviceObject, Property, Length); - } else { - Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; - if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && - (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - Status = Ext2ProcessVolumeProperty(Vcb, Property, Length); - } - - if (NT_SUCCESS(Status)) { - IrpContext->Irp->IoStatus.Information = Length; - } - - } __finally { - - if (!IrpContext->ExceptionInProgress) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - return Status; -} - -NTSTATUS -Ex2ProcessUserPerfStat( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_QUERY_PERFSTAT QueryPerf, - IN ULONG Length -) -{ - PEXT2_VCB Vcb = NULL; - PDEVICE_OBJECT DeviceObject = NULL; - - BOOLEAN GlobalDataResourceAcquired = FALSE; - NTSTATUS Status = STATUS_SUCCESS; - - __try { - - ASSERT(IrpContext != NULL); - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - DeviceObject = IrpContext->DeviceObject; - if (IsExt2FsDevice(DeviceObject)) { - - if (QueryPerf->Magic != EXT2_QUERY_PERFSTAT_MAGIC) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (QueryPerf->Command != IOCTL_APP_QUERY_PERFSTAT) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (Length != EXT2_QUERY_PERFSTAT_SZV1 && - Length != EXT2_QUERY_PERFSTAT_SZV2) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE); - GlobalDataResourceAcquired = TRUE; - - if (Length == EXT2_QUERY_PERFSTAT_SZV2) { - QueryPerf->Flags = EXT2_QUERY_PERFSTAT_VER2; - QueryPerf->PerfStatV2 = Ext2Global->PerfStat; - } else { - memcpy(&QueryPerf->PerfStatV1.Irps[0], &Ext2Global->PerfStat.Irps[0], - FIELD_OFFSET(EXT2_PERF_STATISTICS_V1, Unit)); - memcpy(&QueryPerf->PerfStatV1.Unit, &Ext2Global->PerfStat.Unit, - sizeof(EXT2_STAT_ARRAY_V1)); - memcpy(&QueryPerf->PerfStatV1.Current, &Ext2Global->PerfStat.Current, - sizeof(EXT2_STAT_ARRAY_V1)); - memcpy(&QueryPerf->PerfStatV1.Size, &Ext2Global->PerfStat.Size, - sizeof(EXT2_STAT_ARRAY_V1)); - memcpy(&QueryPerf->PerfStatV1.Total, &Ext2Global->PerfStat.Total, - sizeof(EXT2_STAT_ARRAY_V1)); - } - - } else { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (NT_SUCCESS(Status)) { - IrpContext->Irp->IoStatus.Information = Length; - } - - } __finally { - - if (GlobalDataResourceAcquired) { - ExReleaseResourceLite(&Ext2Global->Resource); - } - - if (!IrpContext->ExceptionInProgress) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - return Status; -} - -NTSTATUS -Ex2ProcessMountPoint( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_MOUNT_POINT MountPoint, - IN ULONG Length -) -{ - UNICODE_STRING Link; - UNICODE_STRING Target; - WCHAR Buffer[] = L"\\DosDevices\\Global\\Z:"; - NTSTATUS status = STATUS_SUCCESS; - - PDEVICE_OBJECT DeviceObject = NULL; - - __try { - - ASSERT(IrpContext != NULL); - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - DeviceObject = IrpContext->DeviceObject; - if (!IsExt2FsDevice(DeviceObject)) { - status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (Length != sizeof(EXT2_MOUNT_POINT) || - MountPoint->Magic != EXT2_APP_MOUNTPOINT_MAGIC) { - status = STATUS_INVALID_PARAMETER; - __leave; - } - - RtlInitUnicodeString(&Link, Buffer); - Buffer[12] = MountPoint->Link[0]; - - switch (MountPoint->Command) { - - case APP_CMD_ADD_DOS_SYMLINK: - RtlInitUnicodeString(&Target, &MountPoint->Name[0]); - status = IoCreateSymbolicLink(&Link, &Target); - break; - - case APP_CMD_DEL_DOS_SYMLINK: - status = IoDeleteSymbolicLink(&Link); - break; - - default: - status = STATUS_INVALID_PARAMETER; - } - - } __finally { - - if (!IrpContext->ExceptionInProgress) { - Ext2CompleteIrpContext(IrpContext, status); - } - } - - return status; -} - -NTSTATUS -Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PIRP Irp; - PIO_STACK_LOCATION irpSp; - ULONG code; - ULONG length; - NTSTATUS Status; - - ASSERT(IrpContext); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - Irp = IrpContext->Irp; - - irpSp = IoGetCurrentIrpStackLocation(Irp); - - code = irpSp->Parameters.DeviceIoControl.IoControlCode; - length = irpSp->Parameters.DeviceIoControl.OutputBufferLength; - - switch (code) { - - case IOCTL_APP_VOLUME_PROPERTY: - Status = Ext2ProcessUserProperty( - IrpContext, - Irp->AssociatedIrp.SystemBuffer, - length - ); - break; - - case IOCTL_APP_QUERY_PERFSTAT: - Status = Ex2ProcessUserPerfStat( - IrpContext, - Irp->AssociatedIrp.SystemBuffer, - length - ); - break; - - case IOCTL_APP_MOUNT_POINT: - Status = Ex2ProcessMountPoint( - IrpContext, - Irp->AssociatedIrp.SystemBuffer, - length - ); - break; - -#if EXT2_UNLOAD - case IOCTL_PREPARE_TO_UNLOAD: - Status = Ext2PrepareToUnload(IrpContext); - break; -#endif - default: - Status = Ext2DeviceControlNormal(IrpContext); - } - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: devctl.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +NTSTATUS +Ext2DeviceControlCompletion ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, Ext2DeviceControl) +#pragma alloc_text(PAGE, Ext2DeviceControlNormal) +#pragma alloc_text(PAGE, Ext2ProcessVolumeProperty) +#pragma alloc_text(PAGE, Ext2ProcessUserProperty) +#pragma alloc_text(PAGE, Ext2ProcessGlobalProperty) +#pragma alloc_text(PAGE, Ex2ProcessUserPerfStat) +#pragma alloc_text(PAGE, Ex2ProcessMountPoint) +#if EXT2_UNLOAD +#pragma alloc_text(PAGE, Ext2PrepareToUnload) +#endif +#endif + + +NTSTATUS +Ext2DeviceControlCompletion ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context +) +{ + if (Irp->PendingReturned) { + IoMarkIrpPending(Irp); + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + BOOLEAN CompleteRequest = TRUE; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PEXT2_VCB Vcb; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PIO_STACK_LOCATION NextIrpSp; + + PDEVICE_OBJECT TargetDeviceObject; + + __try { + + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + CompleteRequest = TRUE; + + DeviceObject = IrpContext->DeviceObject; + + if (IsExt2FsDevice(DeviceObject)) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext; + + if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && + (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + TargetDeviceObject = Vcb->TargetDeviceObject; + + // + // Pass on the IOCTL to the driver below + // + + CompleteRequest = FALSE; + + NextIrpSp = IoGetNextIrpStackLocation( Irp ); + *NextIrpSp = *IrpSp; + + IoSetCompletionRoutine( + Irp, + Ext2DeviceControlCompletion, + NULL, + FALSE, + TRUE, + TRUE ); + + Status = IoCallDriver(TargetDeviceObject, Irp); + + } __finally { + + if (!IrpContext->ExceptionInProgress) { + if (IrpContext) { + if (!CompleteRequest) { + IrpContext->Irp = NULL; + } + + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} + + +#if EXT2_UNLOAD + +NTSTATUS +Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN GlobalDataResourceAcquired = FALSE; + + __try { + + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + if (IsExt2FsDevice(DeviceObject)) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + ExAcquireResourceExclusiveLite( + &Ext2Global->Resource, + TRUE ); + + GlobalDataResourceAcquired = TRUE; + + if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) { + DEBUG(DL_ERR, ( "Ext2PrepareUnload: Already ready to unload.\n")); + + Status = STATUS_ACCESS_DENIED; + + __leave; + } + + { + PEXT2_VCB Vcb; + PLIST_ENTRY ListEntry; + + ListEntry = Ext2Global->VcbList.Flink; + + while (ListEntry != &(Ext2Global->VcbList)) { + + Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); + ListEntry = ListEntry->Flink; + + if (Vcb && (!Vcb->ReferenceCount) && + IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { + Ext2RemoveVcb(Vcb); + Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); + + Ext2DestroyVcb(Vcb); + } + } + } + + if (!IsListEmpty(&(Ext2Global->VcbList))) { + + DEBUG(DL_ERR, ( "Ext2PrepareUnload: Mounted volumes exists.\n")); + + Status = STATUS_ACCESS_DENIED; + + __leave; + } + + IoUnregisterFileSystem(Ext2Global->DiskdevObject); + IoUnregisterFileSystem(Ext2Global->CdromdevObject); + Ext2Global->DriverObject->DriverUnload = DriverUnload; + SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING); + Status = STATUS_SUCCESS; + + DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n")); + + } __finally { + + if (GlobalDataResourceAcquired) { + ExReleaseResourceLite(&Ext2Global->Resource); + } + + if (!IrpContext->ExceptionInProgress) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + return Status; +} + +#endif + +extern CHAR gVersion[]; +extern CHAR gTime[]; +extern CHAR gDate[]; + +NTSTATUS +Ext2ProcessGlobalProperty( + IN PDEVICE_OBJECT DeviceObject, + IN PEXT2_VOLUME_PROPERTY3 Property3, + IN ULONG Length +) +{ + PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3; + PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; + struct nls_table * PageTable = NULL; + + NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN GlobalDataResourceAcquired = FALSE; + + __try { + + if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + /* query Ext2Fsd's version and built date/time*/ + if (Property->Command == APP_CMD_QUERY_VERSION) { + PEXT2_VOLUME_PROPERTY_VERSION PVPV = + (PEXT2_VOLUME_PROPERTY_VERSION) Property; + + if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + RtlZeroMemory(&PVPV->Date[0], 0x20); + RtlZeroMemory(&PVPV->Time[0], 0x20); + RtlZeroMemory(&PVPV->Version[0],0x1C); + strncpy(&PVPV->Version[0], gVersion, 0x1B); + strncpy(&PVPV->Date[0], gDate, 0x1F); + strncpy(&PVPV->Time[0], gTime, 0x1F); + __leave; + } + + /* must be property query/set commands */ + if (Property->Command == APP_CMD_SET_PROPERTY) { + if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + } else if (Property->Command == APP_CMD_SET_PROPERTY2) { + if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + } else if (Property->Command == APP_CMD_SET_PROPERTY3) { + if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + } else { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE); + GlobalDataResourceAcquired = TRUE; + + + switch (Property->Command) { + + case APP_CMD_SET_PROPERTY3: + + if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { + if (Property3->AutoMount) + SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + else + ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + } + + case APP_CMD_SET_PROPERTY2: + + RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN); + if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) { + RtlCopyMemory( Ext2Global->sHidingPrefix, + Property2->sHidingPrefix, + HIDINGPAT_LEN - 1); + } + RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN); + if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) { + RtlCopyMemory( Ext2Global->sHidingSuffix, + Property2->sHidingSuffix, + HIDINGPAT_LEN - 1); + } + + case APP_CMD_SET_PROPERTY: + + if (Property->bReadonly) { + ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); + ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); + } else { + SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); + if (Property->bExt3Writable) { + SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); + } else { + ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); + } + } + + PageTable = load_nls(Property->Codepage); + if (PageTable) { + memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); + Ext2Global->Codepage.PageTable = PageTable; + } + + break; + + default: + break; + } + + } __finally { + + if (GlobalDataResourceAcquired) { + ExReleaseResourceLite(&Ext2Global->Resource); + } + } + + return Status; +} + + +NTSTATUS +Ext2ProcessVolumeProperty( + IN PEXT2_VCB Vcb, + IN PEXT2_VOLUME_PROPERTY3 Property3, + IN ULONG Length +) +{ + struct nls_table * PageTable = NULL; + PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3; + PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; + NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN VcbResourceAcquired = FALSE; + + __try { + + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + VcbResourceAcquired = TRUE; + + if (Property->Command == APP_CMD_SET_PROPERTY || + Property->Command == APP_CMD_QUERY_PROPERTY) { + if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + } else if (Property->Command == APP_CMD_SET_PROPERTY2 || + Property->Command == APP_CMD_QUERY_PROPERTY2) { + if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + } else if (Property->Command == APP_CMD_SET_PROPERTY3 || + Property->Command == APP_CMD_QUERY_PROPERTY3) { + if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + } + + switch (Property->Command) { + + case APP_CMD_SET_PROPERTY3: + + if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { + if (Property3->AutoMount) + SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + else + ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + } + if (Property3->Flags2 & EXT2_VPROP3_USERIDS) { + SetFlag(Vcb->Flags, VCB_USER_IDS); + Vcb->uid = Property3->uid; + Vcb->gid = Property3->gid; + if (Property3->EIDS) { + Vcb->euid = Property3->euid; + Vcb->egid = Property3->egid; + SetFlag(Vcb->Flags, VCB_USER_EIDS); + } else { + Vcb->euid = Vcb->egid = 0; + ClearFlag(Vcb->Flags, VCB_USER_EIDS); + } + } else { + ClearFlag(Vcb->Flags, VCB_USER_IDS); + ClearFlag(Vcb->Flags, VCB_USER_EIDS); + Vcb->uid = Vcb->gid = 0; + Vcb->euid = Vcb->egid = 0; + } + + case APP_CMD_SET_PROPERTY2: + + RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN); + if (Vcb->bHidingPrefix = Property2->bHidingPrefix) { + RtlCopyMemory( Vcb->sHidingPrefix, + Property2->sHidingPrefix, + HIDINGPAT_LEN - 1); + } + + RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN); + if (Vcb->bHidingSuffix = Property2->bHidingSuffix) { + RtlCopyMemory( Vcb->sHidingSuffix, + Property2->sHidingSuffix, + HIDINGPAT_LEN - 1); + } + Vcb->DrvLetter = Property2->DrvLetter; + + case APP_CMD_SET_PROPERTY: + + if (Property->bReadonly) { + if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { + Ext2FlushFiles(NULL, Vcb, FALSE); + Ext2FlushVolume(NULL, Vcb, FALSE); + } + SetLongFlag(Vcb->Flags, VCB_READ_ONLY); + + } else { + + if (Property->bExt3Writable) { + SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING); + } + + if (!Vcb->IsExt3fs) { + ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); + } else if (!Property->bExt3Writable) { + SetLongFlag(Vcb->Flags, VCB_READ_ONLY); + } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { + ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); + Ext2RecoverJournal(NULL, Vcb); + if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { + SetLongFlag(Vcb->Flags, VCB_READ_ONLY); + } else { + ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); + } + } else { + ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); + } + } + + PageTable = load_nls(Property->Codepage); + memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); + Vcb->Codepage.PageTable = PageTable; + if (Vcb->Codepage.PageTable) { + Ext2InitializeLabel(Vcb, Vcb->SuperBlock); + } + + break; + + case APP_CMD_QUERY_PROPERTY3: + + if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) { + SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); + Property3->AutoMount = TRUE; + } else { + ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); + Property3->AutoMount = FALSE; + } + + if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) { + SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); + Property3->uid = Vcb->uid; + Property3->gid = Vcb->gid; + if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { + Property3->EIDS = TRUE; + Property3->euid = Vcb->euid; + Property3->egid = Vcb->egid; + } else { + Property3->EIDS = FALSE; + } + } else { + ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); + } + + case APP_CMD_QUERY_PROPERTY2: + + RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16); + Property2->DrvLetter = Vcb->DrvLetter; + + if (Property2->bHidingPrefix = Vcb->bHidingPrefix) { + RtlCopyMemory( Property2->sHidingPrefix, + Vcb->sHidingPrefix, + HIDINGPAT_LEN); + } else { + RtlZeroMemory( Property2->sHidingPrefix, + HIDINGPAT_LEN); + } + + if (Property2->bHidingSuffix = Vcb->bHidingSuffix) { + RtlCopyMemory( Property2->sHidingSuffix, + Vcb->sHidingSuffix, + HIDINGPAT_LEN); + } else { + RtlZeroMemory( Property2->sHidingSuffix, + HIDINGPAT_LEN); + } + + case APP_CMD_QUERY_PROPERTY: + + Property->bExt2 = TRUE; + Property->bExt3 = Vcb->IsExt3fs; + Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY); + if (!Property->bReadonly && Vcb->IsExt3fs) { + Property->bExt3Writable = TRUE; + } else { + Property->bExt3Writable = FALSE; + } + + RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN); + if (Vcb->Codepage.PageTable) { + strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN); + } else { + strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN); + } + break; + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + + } __finally { + + if (VcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + } + } + + return Status; +} + +NTSTATUS +Ext2ProcessUserProperty( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VOLUME_PROPERTY3 Property, + IN ULONG Length +) +{ + NTSTATUS Status = STATUS_SUCCESS; + PEXT2_VCB Vcb = NULL; + PDEVICE_OBJECT DeviceObject = NULL; + + __try { + + ASSERT(IrpContext != NULL); + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + if (Property->Magic != EXT2_VOLUME_PROPERTY_MAGIC) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + DeviceObject = IrpContext->DeviceObject; + if (IsExt2FsDevice(DeviceObject)) { + Status = Ext2ProcessGlobalProperty(DeviceObject, Property, Length); + } else { + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && + (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + Status = Ext2ProcessVolumeProperty(Vcb, Property, Length); + } + + if (NT_SUCCESS(Status)) { + IrpContext->Irp->IoStatus.Information = Length; + } + + } __finally { + + if (!IrpContext->ExceptionInProgress) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + return Status; +} + +NTSTATUS +Ex2ProcessUserPerfStat( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_QUERY_PERFSTAT QueryPerf, + IN ULONG Length +) +{ + PEXT2_VCB Vcb = NULL; + PDEVICE_OBJECT DeviceObject = NULL; + + BOOLEAN GlobalDataResourceAcquired = FALSE; + NTSTATUS Status = STATUS_SUCCESS; + + __try { + + ASSERT(IrpContext != NULL); + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + if (IsExt2FsDevice(DeviceObject)) { + + if (QueryPerf->Magic != EXT2_QUERY_PERFSTAT_MAGIC) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (QueryPerf->Command != IOCTL_APP_QUERY_PERFSTAT) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (Length != EXT2_QUERY_PERFSTAT_SZV1 && + Length != EXT2_QUERY_PERFSTAT_SZV2) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE); + GlobalDataResourceAcquired = TRUE; + + if (Length == EXT2_QUERY_PERFSTAT_SZV2) { + QueryPerf->Flags = EXT2_QUERY_PERFSTAT_VER2; + QueryPerf->PerfStatV2 = Ext2Global->PerfStat; + } else { + memcpy(&QueryPerf->PerfStatV1.Irps[0], &Ext2Global->PerfStat.Irps[0], + FIELD_OFFSET(EXT2_PERF_STATISTICS_V1, Unit)); + memcpy(&QueryPerf->PerfStatV1.Unit, &Ext2Global->PerfStat.Unit, + sizeof(EXT2_STAT_ARRAY_V1)); + memcpy(&QueryPerf->PerfStatV1.Current, &Ext2Global->PerfStat.Current, + sizeof(EXT2_STAT_ARRAY_V1)); + memcpy(&QueryPerf->PerfStatV1.Size, &Ext2Global->PerfStat.Size, + sizeof(EXT2_STAT_ARRAY_V1)); + memcpy(&QueryPerf->PerfStatV1.Total, &Ext2Global->PerfStat.Total, + sizeof(EXT2_STAT_ARRAY_V1)); + } + + } else { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (NT_SUCCESS(Status)) { + IrpContext->Irp->IoStatus.Information = Length; + } + + } __finally { + + if (GlobalDataResourceAcquired) { + ExReleaseResourceLite(&Ext2Global->Resource); + } + + if (!IrpContext->ExceptionInProgress) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + return Status; +} + +NTSTATUS +Ex2ProcessMountPoint( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_MOUNT_POINT MountPoint, + IN ULONG Length +) +{ + UNICODE_STRING Link; + UNICODE_STRING Target; + WCHAR Buffer[] = L"\\DosDevices\\Global\\Z:"; + NTSTATUS status = STATUS_SUCCESS; + + PDEVICE_OBJECT DeviceObject = NULL; + + __try { + + ASSERT(IrpContext != NULL); + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + if (!IsExt2FsDevice(DeviceObject)) { + status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (Length != sizeof(EXT2_MOUNT_POINT) || + MountPoint->Magic != EXT2_APP_MOUNTPOINT_MAGIC) { + status = STATUS_INVALID_PARAMETER; + __leave; + } + + RtlInitUnicodeString(&Link, Buffer); + Buffer[12] = MountPoint->Link[0]; + + switch (MountPoint->Command) { + + case APP_CMD_ADD_DOS_SYMLINK: + RtlInitUnicodeString(&Target, &MountPoint->Name[0]); + status = IoCreateSymbolicLink(&Link, &Target); + break; + + case APP_CMD_DEL_DOS_SYMLINK: + status = IoDeleteSymbolicLink(&Link); + break; + + default: + status = STATUS_INVALID_PARAMETER; + } + + } __finally { + + if (!IrpContext->ExceptionInProgress) { + Ext2CompleteIrpContext(IrpContext, status); + } + } + + return status; +} + +NTSTATUS +Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PIRP Irp; + PIO_STACK_LOCATION irpSp; + ULONG code; + ULONG length; + NTSTATUS Status; + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + Irp = IrpContext->Irp; + + irpSp = IoGetCurrentIrpStackLocation(Irp); + + code = irpSp->Parameters.DeviceIoControl.IoControlCode; + length = irpSp->Parameters.DeviceIoControl.OutputBufferLength; + + switch (code) { + + case IOCTL_APP_VOLUME_PROPERTY: + Status = Ext2ProcessUserProperty( + IrpContext, + Irp->AssociatedIrp.SystemBuffer, + length + ); + break; + + case IOCTL_APP_QUERY_PERFSTAT: + Status = Ex2ProcessUserPerfStat( + IrpContext, + Irp->AssociatedIrp.SystemBuffer, + length + ); + break; + + case IOCTL_APP_MOUNT_POINT: + Status = Ex2ProcessMountPoint( + IrpContext, + Irp->AssociatedIrp.SystemBuffer, + length + ); + break; + +#if EXT2_UNLOAD + case IOCTL_PREPARE_TO_UNLOAD: + Status = Ext2PrepareToUnload(IrpContext); + break; +#endif + default: + Status = Ext2DeviceControlNormal(IrpContext); + } + + return Status; +} diff --git a/Ext4Fsd/dirctl.c b/Ext4Fsd/dirctl.c index 1e0ddec..044c8db 100644 --- a/Ext4Fsd/dirctl.c +++ b/Ext4Fsd/dirctl.c @@ -1,1274 +1,1274 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: dirctl.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, Ext2GetInfoLength) -#pragma alloc_text(PAGE, Ext2ProcessEntry) -#pragma alloc_text(PAGE, Ext2QueryDirectory) -#pragma alloc_text(PAGE, Ext2NotifyChangeDirectory) -#pragma alloc_text(PAGE, Ext2DirectoryControl) -#pragma alloc_text(PAGE, Ext2IsDirectoryEmpty) -#endif - -ULONG -Ext2GetInfoLength(IN FILE_INFORMATION_CLASS FileInformationClass) -{ - switch (FileInformationClass) { - - case FileDirectoryInformation: - return FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName[0]); - - case FileFullDirectoryInformation: - return FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName[0]); - - case FileBothDirectoryInformation: - return FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[0]); - - case FileNamesInformation: - return FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName[0]); - - case FileIdFullDirectoryInformation: - return FIELD_OFFSET(FILE_ID_FULL_DIR_INFORMATION, FileName[0]); - - case FileIdBothDirectoryInformation: - return FIELD_OFFSET(FILE_ID_BOTH_DIR_INFORMATION, FileName[0]); - - default: - break; - } - - return 0; -} - -NTSTATUS -Ext2ProcessEntry( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Dcb, - IN FILE_INFORMATION_CLASS FileInformationClass, - IN ULONG in, - IN PVOID Buffer, - IN ULONG UsedLength, - IN ULONG Length, - IN ULONG FileIndex, - IN PUNICODE_STRING pName, - OUT PULONG EntrySize, - IN BOOLEAN Single -) -{ - PFILE_DIRECTORY_INFORMATION FDI = NULL; - PFILE_FULL_DIR_INFORMATION FFI = NULL; - PFILE_ID_FULL_DIR_INFORMATION FIF = NULL; - - PFILE_BOTH_DIR_INFORMATION FBI = NULL; - PFILE_ID_BOTH_DIR_INFORMATION FIB = NULL; - - PFILE_NAMES_INFORMATION FNI = NULL; - - PEXT2_MCB Mcb = NULL; - PEXT2_MCB Target = NULL; - - NTSTATUS Status = STATUS_SUCCESS; - struct inode Inode = { 0 }; - - ULONG InfoLength = 0; - ULONG NameLength = 0; - ULONG dwBytes = 0; - LONGLONG FileSize = 0; - LONGLONG AllocationSize; - ULONG FileAttributes = 0; - - BOOLEAN IsEntrySymlink = FALSE; - - *EntrySize = 0; - NameLength = pName->Length; - ASSERT((UsedLength & 7) == 0); - - InfoLength = Ext2GetInfoLength(FileInformationClass); - if (InfoLength == 0) { - DEBUG(DL_ERR, ("Ext2ProcessDirEntry: Invalid Info Class %xh for %wZ in %wZ\n", - FileInformationClass, pName, &Dcb->Mcb->FullName )); - return STATUS_INVALID_INFO_CLASS; - } - - if (InfoLength + NameLength > Length) { - DEBUG(DL_INF, ( "Ext2PricessDirEntry: Buffer is not enough.\n")); - Status = STATUS_BUFFER_OVERFLOW; - if (UsedLength || InfoLength > Length) { - DEBUG(DL_CP, ("Ext2ProcessDirEntry: Buffer overflows for %wZ in %wZ\n", - pName, &Dcb->Mcb->FullName )); - return Status; - } - } - - DEBUG(DL_CP, ("Ext2ProcessDirEntry: %wZ in %wZ\n", pName, &Dcb->Mcb->FullName )); - - Mcb = Ext2SearchMcb(Vcb, Dcb->Mcb, pName); - if (NULL != Mcb) { - if (S_ISLNK(Mcb->Inode.i_mode) && NULL == Mcb->Target) { - Ext2FollowLink( IrpContext, Vcb, Dcb->Mcb, Mcb, 0); - } - - } else { - - Inode.i_ino = in; - Inode.i_sb = &Vcb->sb; - if (!Ext2LoadInode(Vcb, &Inode)) { - DEBUG(DL_ERR, ("Ext2PricessDirEntry: Loading inode %xh (%wZ) error.\n", - in, pName )); - DbgBreak(); - Status = STATUS_SUCCESS; - goto errorout; - } - - if (S_ISDIR(Inode.i_mode) || S_ISREG(Inode.i_mode)) { - } else if (S_ISLNK(Inode.i_mode)) { - DEBUG(DL_RES, ("Ext2ProcessDirEntry: SymLink: %wZ\\%wZ\n", - &Dcb->Mcb->FullName, pName)); - Ext2LookupFile(IrpContext, Vcb, pName, Dcb->Mcb, &Mcb,0); - - if (Mcb && IsMcbSpecialFile(Mcb)) { - Ext2DerefMcb(Mcb); - Mcb = NULL; - } - } else { - Inode.i_size = 0; - } - } - - if (Mcb != NULL) { - - FileAttributes = Mcb->FileAttr; - if (IsMcbSymLink(Mcb)) { - Target = Mcb->Target; - ASSERT(Target); - ASSERT(!IsMcbSymLink(Target)); - if (IsMcbDirectory(Target)) { - FileSize = 0; - FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; - } else { - FileSize = Target->Inode.i_size; - } - if (IsFileDeleted(Target)) { - ClearFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY); - FileSize = 0; - } - } else { - if (IsMcbDirectory(Mcb)) { - FileSize = 0; - } else { - FileSize = Mcb->Inode.i_size; - } - } - - if (IsInodeSymLink(&Mcb->Inode)) { - IsEntrySymlink = TRUE; - } - - } else { - - if (S_ISDIR(Inode.i_mode)) { - FileSize = 0; - } else { - FileSize = Inode.i_size; - } - - if (S_ISDIR(Inode.i_mode)) { - FileAttributes = FILE_ATTRIBUTE_DIRECTORY; - } else if (S_ISLNK(Inode.i_mode)) { - FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT; - IsEntrySymlink = TRUE; - } else { - FileAttributes = FILE_ATTRIBUTE_NORMAL; - } - - if (!Ext2CheckInodeAccess(Vcb, &Inode, Ext2FileCanWrite)) { - SetFlag(FileAttributes, FILE_ATTRIBUTE_READONLY); - } - } - - if (FileAttributes == 0) - FileAttributes = FILE_ATTRIBUTE_NORMAL; - - AllocationSize = CEILING_ALIGNED(ULONGLONG, FileSize, BLOCK_SIZE); - - /* process special files under root directory */ - if (IsRoot(Dcb)) { - /* set hidden and system attributes for Recycled / - RECYCLER / pagefile.sys */ - BOOLEAN IsDirectory = IsFlagOn(FileAttributes, FILE_ATTRIBUTE_DIRECTORY); - if (Ext2IsSpecialSystemFile(pName, IsDirectory)) { - SetFlag(FileAttributes, FILE_ATTRIBUTE_HIDDEN); - SetFlag(FileAttributes, FILE_ATTRIBUTE_SYSTEM); - } - } - - /* set hidden attribute for all entries starting with '.' */ - if (( pName->Length >= 4 && pName->Buffer[0] == L'.') && - ((pName->Length == 4 && pName->Buffer[1] != L'.') || - pName->Length >= 6 )) { - SetFlag(FileAttributes, FILE_ATTRIBUTE_HIDDEN); - } - - switch (FileInformationClass) { - - case FileIdFullDirectoryInformation: - FIF = (PFILE_ID_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); - case FileFullDirectoryInformation: - FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); - case FileDirectoryInformation: - FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength); - - if (!Single) { - FDI->NextEntryOffset = CEILING_ALIGNED(ULONG, InfoLength + NameLength, 8); - } - - FDI->FileIndex = FileIndex; - - if (Mcb) { - - FDI->CreationTime = Mcb->CreationTime; - FDI->LastAccessTime = Mcb->LastAccessTime; - FDI->LastWriteTime = Mcb->LastWriteTime; - FDI->ChangeTime = Mcb->ChangeTime; - - } else { - - FDI->CreationTime = Ext2NtTime(Inode.i_ctime); - FDI->LastAccessTime = Ext2NtTime(Inode.i_atime); - FDI->LastWriteTime = Ext2NtTime(Inode.i_mtime); - FDI->ChangeTime = Ext2NtTime(Inode.i_mtime); - } - - FDI->FileAttributes = FileAttributes; - FDI->EndOfFile.QuadPart = FileSize; - FDI->AllocationSize.QuadPart = AllocationSize; - - FDI->FileNameLength = NameLength; - if (InfoLength + NameLength > Length) { - NameLength = Length - InfoLength; - } - - if (FIF) { - FIF->FileId.QuadPart = (LONGLONG) in; - if (IsEntrySymlink) { - FIF->EaSize = IO_REPARSE_TAG_SYMLINK; - } - RtlCopyMemory(&FIF->FileName[0], &pName->Buffer[0], NameLength); - } else if (FFI) { - if (IsEntrySymlink) { - FFI->EaSize = IO_REPARSE_TAG_SYMLINK; - } - RtlCopyMemory(&FFI->FileName[0], &pName->Buffer[0], NameLength); - } else { - RtlCopyMemory(&FDI->FileName[0], &pName->Buffer[0], NameLength); - } - - *EntrySize = InfoLength + NameLength; - break; - - - case FileIdBothDirectoryInformation: - FIB = (PFILE_ID_BOTH_DIR_INFORMATION)((PUCHAR)Buffer + UsedLength); - case FileBothDirectoryInformation: - FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); - - if (!Single) { - FBI->NextEntryOffset = CEILING_ALIGNED(ULONG, InfoLength + NameLength, 8); - } - - FBI->FileIndex = FileIndex; - FBI->EndOfFile.QuadPart = FileSize; - FBI->AllocationSize.QuadPart = AllocationSize; - - if (Mcb) { - - FBI->CreationTime = Mcb->CreationTime; - FBI->LastAccessTime = Mcb->LastAccessTime; - FBI->LastWriteTime = Mcb->LastWriteTime; - FBI->ChangeTime = Mcb->ChangeTime; - - } else { - - FBI->CreationTime = Ext2NtTime(Inode.i_ctime); - FBI->LastAccessTime = Ext2NtTime(Inode.i_atime); - FBI->LastWriteTime = Ext2NtTime(Inode.i_mtime); - FBI->ChangeTime = Ext2NtTime(Inode.i_mtime); - } - - FBI->FileAttributes = FileAttributes; - - FBI->FileNameLength = NameLength; - if (InfoLength + NameLength > Length) { - NameLength = Length - InfoLength; - } - - if (FIB) { - FIB->FileId.QuadPart = (LONGLONG)in; - if (IsEntrySymlink) { - FIB->EaSize = IO_REPARSE_TAG_SYMLINK; - } - RtlCopyMemory(&FIB->FileName[0], &pName->Buffer[0], NameLength); - } else { - RtlCopyMemory(&FBI->FileName[0], &pName->Buffer[0], NameLength); - } - - *EntrySize = InfoLength + NameLength; - break; - - case FileNamesInformation: - - FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength); - if (!Single) { - FNI->NextEntryOffset = CEILING_ALIGNED(ULONG, InfoLength + NameLength, 8); - } - - FNI->FileNameLength = NameLength; - if (InfoLength + NameLength > Length) { - NameLength = Length - InfoLength; - } - RtlCopyMemory(&FNI->FileName[0], &pName->Buffer[0], NameLength); - - *EntrySize = InfoLength + NameLength; - break; - - default: - Status = STATUS_INVALID_INFO_CLASS; - break; - } - - if (Mcb) { - Ext2DerefMcb(Mcb); - } - -errorout: - - DEBUG(DL_CP, ("Ext2ProcessDirEntry: Status = %xh for %wZ in %wZ\n", - Status, pName, &Dcb->Mcb->FullName )); - - return Status; -} - - -BOOLEAN -Ext2IsWearingCloak( - IN PEXT2_VCB Vcb, - IN POEM_STRING OemName -) -{ - size_t PatLen = 0; - - /* we could not filter the files: "." and ".." */ - if (OemName->Length >= 1 && OemName->Buffer[0] == '.') { - - if ( OemName->Length == 2 && OemName->Buffer[1] == '.') { - return FALSE; - } else if (OemName->Length == 1) { - return FALSE; - } - } - - /* checking name prefix */ - if (Vcb->bHidingPrefix) { - PatLen = strlen(&Vcb->sHidingPrefix[0]); - if (PatLen > 0 && PatLen <= OemName->Length) { - if ( _strnicmp( OemName->Buffer, - Vcb->sHidingPrefix, - PatLen ) == 0) { - return TRUE; - } - } - } - - /* checking name suffix */ - if (Vcb->bHidingSuffix) { - PatLen = strlen(&Vcb->sHidingSuffix[0]); - if (PatLen > 0 && PatLen <= OemName->Length) { - if ( _strnicmp(&OemName->Buffer[OemName->Length - PatLen], - Vcb->sHidingSuffix, PatLen ) == 0) { - return TRUE; - } - } - } - - return FALSE; -} - -static int Ext2FillEntry(void *context, const char *name, int namlen, - ULONG offset, __u32 ino, unsigned int d_type) -{ - PEXT2_FILLDIR_CONTEXT fc = context; - PEXT2_IRP_CONTEXT IrpContext = fc->efc_irp; - - PEXT2_FCB Fcb = IrpContext->Fcb; - PEXT2_CCB Ccb = IrpContext->Ccb; - PEXT2_VCB Vcb = Fcb->Vcb; - - OEM_STRING Oem; - UNICODE_STRING Unicode = { 0 }; - NTSTATUS Status = STATUS_SUCCESS; - ULONG EntrySize; - USHORT NameLen; - int rc = 0; - - if (fc->efc_start > 0 && (fc->efc_single || (fc->efc_size < - fc->efc_start + namlen * 2 + Ext2GetInfoLength(fc->efc_fi)) )) { - rc = 1; - goto errorout; - } - - - Oem.Buffer = (void *)name; - Oem.Length = namlen & 0xFF; - Oem.MaximumLength = Oem.Length; - - /* skip . and .. */ - if ((Oem.Length == 1 && name[0] == '.') || (Oem.Length == 2 && - name[0] == '.' && name[1] == '.' )) { - goto errorout; - } - - if (Ext2IsWearingCloak(Vcb, &Oem)) { - goto errorout; - } - - NameLen = (USHORT)Ext2OEMToUnicodeSize(Vcb, &Oem); - if (NameLen <= 0) { - fc->efc_status = STATUS_INSUFFICIENT_RESOURCES; - rc = -ENOMEM; - goto errorout; - } - - Unicode.MaximumLength = NameLen + 2; - Unicode.Buffer = Ext2AllocatePool( - PagedPool, - Unicode.MaximumLength, - EXT2_INAME_MAGIC - ); - if (!Unicode.Buffer) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to " - "allocate InodeFileName.\n")); - fc->efc_status = STATUS_INSUFFICIENT_RESOURCES; - rc = -ENOMEM; - goto errorout; - } - RtlZeroMemory(Unicode.Buffer, Unicode.MaximumLength); - INC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength); - - Status = Ext2OEMToUnicode(Vcb, &Unicode, &Oem); - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: Ext2OEMtoUnicode failed with %xh.\n", Status)); - fc->efc_status = STATUS_INSUFFICIENT_RESOURCES; - rc = -ENOMEM; - goto errorout; - } - - if (FsRtlDoesNameContainWildCards( &Ccb->DirectorySearchPattern) ? - FsRtlIsNameInExpression(&Ccb->DirectorySearchPattern, - &Unicode, TRUE, NULL) : - !RtlCompareUnicodeString(&Ccb->DirectorySearchPattern, - &Unicode, TRUE)) { - Status = Ext2ProcessEntry(fc->efc_irp, Vcb, Fcb, fc->efc_fi, ino, fc->efc_buf, - CEILING_ALIGNED(ULONG, fc->efc_start, 8), - fc->efc_size - CEILING_ALIGNED(ULONG, fc->efc_start, 8), - offset, &Unicode, &EntrySize, fc->efc_single); - if (NT_SUCCESS(Status)) { - if (EntrySize > 0) { - fc->efc_prev = CEILING_ALIGNED(ULONG, fc->efc_start, 8); - fc->efc_start = fc->efc_prev + EntrySize; - } else { - DbgBreak(); - } - } else { - if (Status == STATUS_BUFFER_OVERFLOW) { - if (fc->efc_start == 0) { - fc->efc_start = EntrySize; - } else { - Status = STATUS_SUCCESS; - } - } - rc = 1; - } - } - -errorout: - - fc->efc_status = Status; - if (Unicode.Buffer) { - DEC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength ); - Ext2FreePool(Unicode.Buffer, EXT2_INAME_MAGIC); - } - - return rc; -} - - -NTSTATUS -Ext2QueryDirectory (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb = NULL; - PFILE_OBJECT FileObject = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_MCB Mcb = NULL; - PEXT2_CCB Ccb = NULL; - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - - ULONG Length; - ULONG FileIndex; - PUNICODE_STRING FileName; - PUCHAR Buffer; - - BOOLEAN RestartScan; - BOOLEAN ReturnSingleEntry; - BOOLEAN IndexSpecified; - BOOLEAN FirstQuery; - BOOLEAN FcbResourceAcquired = FALSE; - - USHORT NameLen; - FILE_INFORMATION_CLASS fi; - - OEM_STRING Oem = { 0 }; - UNICODE_STRING Unicode = { 0 }; - PEXT2_DIR_ENTRY2 pDir = NULL; - - ULONG ByteOffset; - ULONG RecLen = 0; - ULONG EntrySize = 0; - - EXT2_FILLDIR_CONTEXT fc = { 0 }; - - __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; - __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; - __leave; - } - - if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { - Status = STATUS_ACCESS_DENIED; - __leave; - } - - FileObject = IrpContext->FileObject; - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - Mcb = Fcb->Mcb; - if (NULL == Mcb) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - ASSERT (!IsMcbSymLink(Mcb)); - - // - // This request is not allowed on volumes - // - if (Fcb->Identifier.Type == EXT2VCB) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (!IsMcbDirectory(Mcb)) { - Status = STATUS_NOT_A_DIRECTORY; - __leave; - } - - if (IsFileDeleted(Mcb)) { - Status = STATUS_NOT_A_DIRECTORY; - __leave; - } - - Ccb = (PEXT2_CCB) FileObject->FsContext2; - - ASSERT(Ccb); - ASSERT((Ccb->Identifier.Type == EXT2CCB) && - (Ccb->Identifier.Size == sizeof(EXT2_CCB))); - - Irp = IrpContext->Irp; - IoStackLocation = IoGetCurrentIrpStackLocation(Irp); - -#ifndef _GNU_NTIFS_ - - fi = IoStackLocation->Parameters.QueryDirectory.FileInformationClass; - - Length = IoStackLocation->Parameters.QueryDirectory.Length; - - FileName = (PUNICODE_STRING)IoStackLocation->Parameters.QueryDirectory.FileName; - - FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex; - -#else // _GNU_NTIFS_ - - fi = ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; - - Length = ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.Length; - - FileName = ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileName; - - FileIndex = ((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Parameters.QueryDirectory.FileIndex; - -#endif // _GNU_NTIFS_ - - RestartScan = FlagOn(((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Flags, SL_RESTART_SCAN); - ReturnSingleEntry = FlagOn(((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Flags, SL_RETURN_SINGLE_ENTRY); - IndexSpecified = FlagOn(((PEXTENDED_IO_STACK_LOCATION) - IoStackLocation)->Flags, SL_INDEX_SPECIFIED); - - Buffer = Ext2GetUserBuffer(Irp); - if (Buffer == NULL) { - DbgBreak(); - Status = STATUS_INVALID_USER_BUFFER; - __leave; - } - - if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { - Status = STATUS_PENDING; - __leave; - } - - if (!ExAcquireResourceSharedLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { - Status = STATUS_PENDING; - __leave; - } - FcbResourceAcquired = TRUE; - - if (FileName != NULL) { - - if (Ccb->DirectorySearchPattern.Buffer != NULL) { - - FirstQuery = FALSE; - - } else { - - FirstQuery = TRUE; - - Ccb->DirectorySearchPattern.Length = - Ccb->DirectorySearchPattern.MaximumLength = - FileName->Length; - - Ccb->DirectorySearchPattern.Buffer = - Ext2AllocatePool(PagedPool, FileName->Length, - EXT2_DIRSP_MAGIC); - - if (Ccb->DirectorySearchPattern.Buffer == NULL) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to allocate SerarchPattern.\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - INC_MEM_COUNT( PS_DIR_PATTERN, - Ccb->DirectorySearchPattern.Buffer, - Ccb->DirectorySearchPattern.MaximumLength); - - Status = RtlUpcaseUnicodeString( - &(Ccb->DirectorySearchPattern), - FileName, - FALSE); - - if (!NT_SUCCESS(Status)) { - __leave; - } - } - - } else if (Ccb->DirectorySearchPattern.Buffer != NULL) { - - FirstQuery = FALSE; - FileName = &Ccb->DirectorySearchPattern; - - } else { - - FirstQuery = TRUE; - - Ccb->DirectorySearchPattern.Length = - Ccb->DirectorySearchPattern.MaximumLength = 2; - - Ccb->DirectorySearchPattern.Buffer = - Ext2AllocatePool(PagedPool, 4, EXT2_DIRSP_MAGIC); - - if (Ccb->DirectorySearchPattern.Buffer == NULL) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to allocate SerarchPattern (1st).\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - INC_MEM_COUNT( PS_DIR_PATTERN, - Ccb->DirectorySearchPattern.Buffer, - Ccb->DirectorySearchPattern.MaximumLength); - - RtlZeroMemory(Ccb->DirectorySearchPattern.Buffer, 4); - RtlCopyMemory( - Ccb->DirectorySearchPattern.Buffer, - L"*\0", 2); - } - - if (IndexSpecified) { - Ccb->filp.f_pos = FileIndex; - } else { - if (RestartScan || FirstQuery) { - Ccb->filp.f_pos = FileIndex = 0; - } else { - FileIndex = (ULONG)Ccb->filp.f_pos; - } - } - - RtlZeroMemory(Buffer, Length); - - fc.efc_irp = IrpContext; - fc.efc_buf = Buffer; - fc.efc_size = Length; - fc.efc_start = 0; - fc.efc_single = ReturnSingleEntry; - fc.efc_fi = fi; - fc.efc_status = STATUS_SUCCESS; - -#ifdef EXT2_HTREE_INDEX - - if (EXT3_HAS_COMPAT_FEATURE(Mcb->Inode.i_sb, - EXT3_FEATURE_COMPAT_DIR_INDEX) && - ((EXT3_I(&Mcb->Inode)->i_flags & EXT3_INDEX_FL) || - ((Mcb->Inode.i_size >> BLOCK_BITS) == 1)) ) { - int rc = ext3_dx_readdir(&Ccb->filp, Ext2FillEntry, &fc); - Status = fc.efc_status; - if (rc != ERR_BAD_DX_DIR) { - goto errorout; - } - /* - * We don't set the inode dirty flag since it's not - * critical that it get flushed back to the disk. - */ - EXT3_I(&Mcb->Inode)->i_flags &= ~EXT3_INDEX_FL; - } -#endif - - if (Mcb->Inode.i_size <= Ccb->filp.f_pos) { - Status = STATUS_NO_MORE_FILES; - __leave; - } - - pDir = Ext2AllocatePool( - PagedPool, - sizeof(EXT2_DIR_ENTRY2), - EXT2_DENTRY_MAGIC - ); - - if (!pDir) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to allocate pDir.\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - INC_MEM_COUNT(PS_DIR_ENTRY, pDir, sizeof(EXT2_DIR_ENTRY2)); - ByteOffset = FileIndex; - - DEBUG(DL_CP, ("Ex2QueryDirectory: Dir: %wZ Index=%xh Pattern : %wZ.\n", - &Fcb->Mcb->FullName, FileIndex, &Ccb->DirectorySearchPattern)); - - while ((ByteOffset < Mcb->Inode.i_size) && - (CEILING_ALIGNED(ULONG, fc.efc_start, 8) < Length)) { - - RtlZeroMemory(pDir, sizeof(EXT2_DIR_ENTRY2)); - - Status = Ext2ReadInode( - IrpContext, - Vcb, - Mcb, - (ULONGLONG)ByteOffset, - (PVOID)pDir, - sizeof(EXT2_DIR_ENTRY2), - FALSE, - &EntrySize); - - if (!NT_SUCCESS(Status)) { - DbgBreak(); - __leave; - } - - if (pDir->rec_len == 0) { - RecLen = BLOCK_SIZE - (ByteOffset & (BLOCK_SIZE - 1)); - } else { - RecLen = ext3_rec_len_from_disk(pDir->rec_len); - } - - if (!pDir->inode || pDir->inode >= INODES_COUNT) { - goto ProcessNextEntry; - } - - /* skip . and .. */ - if ((pDir->name_len == 1 && pDir->name[0] == '.') || - (pDir->name_len == 2 && pDir->name[0] == '.' && pDir->name[1] == '.' )) { - goto ProcessNextEntry; - } - - Oem.Buffer = pDir->name; - Oem.Length = (pDir->name_len & 0xff); - Oem.MaximumLength = Oem.Length; - - if (Ext2IsWearingCloak(Vcb, &Oem)) { - goto ProcessNextEntry; - } - - NameLen = (USHORT) Ext2OEMToUnicodeSize(Vcb, &Oem); - - if (NameLen <= 0) { - DEBUG(DL_CP, ("Ext2QueryDirectory: failed to count unicode length for inode: %xh\n", - pDir->inode)); - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - if ( Unicode.Buffer != NULL && Unicode.MaximumLength > NameLen) { - /* reuse buffer */ - } else { - /* free and re-allocate it */ - if (Unicode.Buffer) { - DEC_MEM_COUNT(PS_INODE_NAME, - Unicode.Buffer, - Unicode.MaximumLength); - Ext2FreePool(Unicode.Buffer, EXT2_INAME_MAGIC); - } - Unicode.MaximumLength = NameLen + 2; - Unicode.Buffer = Ext2AllocatePool( - PagedPool, Unicode.MaximumLength, - EXT2_INAME_MAGIC - ); - if (!Unicode.Buffer) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to " - "allocate InodeFileName.\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - INC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength); - } - - Unicode.Length = 0; - RtlZeroMemory(Unicode.Buffer, Unicode.MaximumLength); - - Status = Ext2OEMToUnicode(Vcb, &Unicode, &Oem); - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ( "Ex2QueryDirectory: Ext2OEMtoUnicode failed with %xh.\n", Status)); - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - DEBUG(DL_CP, ( "Ex2QueryDirectory: process inode: %xh / %wZ (%d).\n", - pDir->inode, &Unicode, Unicode.Length)); - - if (FsRtlDoesNameContainWildCards( - &(Ccb->DirectorySearchPattern)) ? - FsRtlIsNameInExpression( - &(Ccb->DirectorySearchPattern), - &Unicode, - TRUE, - NULL) : - !RtlCompareUnicodeString( - &(Ccb->DirectorySearchPattern), - &Unicode, - TRUE) ) { - - Status = Ext2ProcessEntry( - IrpContext, - Vcb, - Fcb, - fi, - pDir->inode, - Buffer, - CEILING_ALIGNED(ULONG, fc.efc_start, 8), - Length - CEILING_ALIGNED(ULONG, fc.efc_start, 8), - ByteOffset, - &Unicode, - &EntrySize, - ReturnSingleEntry - ); - - if (NT_SUCCESS(Status)) { - if (EntrySize > 0) { - fc.efc_prev = CEILING_ALIGNED(ULONG, fc.efc_start, 8); - fc.efc_start = fc.efc_prev + EntrySize; - } else { - DbgBreak(); - } - } else { - if (Status == STATUS_BUFFER_OVERFLOW) { - if (fc.efc_start == 0) { - fc.efc_start = EntrySize; - } else { - Status = STATUS_SUCCESS; - } - } else { - __leave; - } - break; - } - } - -ProcessNextEntry: - - ByteOffset += RecLen; - Ccb->filp.f_pos = ByteOffset; - - if (fc.efc_start && ReturnSingleEntry) { - Status = STATUS_SUCCESS; - goto errorout; - } - } - -errorout: - - ((PULONG)((PUCHAR)Buffer + fc.efc_prev))[0] = 0; - FileIndex = ByteOffset; - - if (Status == STATUS_BUFFER_OVERFLOW) { - /* just return fc.efc_start/EntrySize bytes that we filled */ - } else if (!fc.efc_start) { - if (NT_SUCCESS(Status)) { - if (FirstQuery) { - Status = STATUS_NO_SUCH_FILE; - } else { - Status = STATUS_NO_MORE_FILES; - } - } - } else { - Status = STATUS_SUCCESS; - } - - } __finally { - - if (FcbResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (pDir != NULL) { - Ext2FreePool(pDir, EXT2_DENTRY_MAGIC); - DEC_MEM_COUNT(PS_DIR_ENTRY, pDir, sizeof(EXT2_DIR_ENTRY2)); - } - - if (Unicode.Buffer != NULL) { - DEC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength); - Ext2FreePool(Unicode.Buffer, EXT2_INAME_MAGIC); - } - - if (!IrpContext->ExceptionInProgress) { - - 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 { - IrpContext->Irp->IoStatus.Information = fc.efc_start; - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} - -NTSTATUS -Ext2NotifyChangeDirectory ( - IN PEXT2_IRP_CONTEXT IrpContext -) -{ - PDEVICE_OBJECT DeviceObject; - BOOLEAN CompleteRequest = TRUE; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PIRP Irp = NULL; - PIO_STACK_LOCATION IrpSp; - PFILE_OBJECT FileObject; - ULONG CompletionFilter; - BOOLEAN WatchTree; - - BOOLEAN bFcbAcquired = FALSE; - - __try { - - ASSERT(IrpContext); - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - // - // Always set the wait flag in the Irp context for the original request. - // - - SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ); - - DeviceObject = IrpContext->DeviceObject; - - if (IsExt2FsDevice(DeviceObject)) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - 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); - if (Fcb->Identifier.Type == EXT2VCB) { - DbgBreak(); - Status = STATUS_INVALID_PARAMETER; - __leave; - } - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - Ccb = (PEXT2_CCB) FileObject->FsContext2; - ASSERT(Ccb); - ASSERT((Ccb->Identifier.Type == EXT2CCB) && - (Ccb->Identifier.Size == sizeof(EXT2_CCB))); - - /* do nothing if target fie was deleted */ - if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { - Status = STATUS_FILE_DELETED; - __leave; - } - - if (!IsDirectory(Fcb)) { - DbgBreak(); - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - TRUE )) { - bFcbAcquired = TRUE; - } else { - Status = STATUS_PENDING; - __leave; - } - - Irp = IrpContext->Irp; - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - -#ifndef _GNU_NTIFS_ - - CompletionFilter = - IrpSp->Parameters.NotifyDirectory.CompletionFilter; - -#else // _GNU_NTIFS_ - - CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION) - IrpSp)->Parameters.NotifyDirectory.CompletionFilter; - -#endif // _GNU_NTIFS_ - - WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE); - - if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { - Status = STATUS_DELETE_PENDING; - __leave; - } - - FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, - &Vcb->NotifyList, - FileObject->FsContext2, - (PSTRING)(&Fcb->Mcb->FullName), - WatchTree, - FALSE, - CompletionFilter, - Irp, - NULL, - NULL ); - - CompleteRequest = FALSE; - - Status = STATUS_PENDING; - - /* - Currently the driver is read-only but here is an example on how to use the - FsRtl-functions to report a change: - - ANSI_STRING TestString; - USHORT FileNamePartLength; - - RtlInitAnsiString(&TestString, "\\ntifs.h"); - - FileNamePartLength = 7; - - FsRtlNotifyReportChange( - Vcb->NotifySync, // PNOTIFY_SYNC NotifySync - &Vcb->NotifyList, // PLIST_ENTRY NotifyList - &TestString, // PSTRING FullTargetName - &FileNamePartLength, // PUSHORT FileNamePartLength - FILE_NOTIFY_CHANGE_NAME // ULONG FilterMatch - ); - - or - - ANSI_STRING TestString; - - RtlInitAnsiString(&TestString, "\\ntifs.h"); - - FsRtlNotifyFullReportChange( - Vcb->NotifySync, // PNOTIFY_SYNC NotifySync - &Vcb->NotifyList, // PLIST_ENTRY NotifyList - &TestString, // PSTRING FullTargetName - 1, // USHORT TargetNameOffset - NULL, // PSTRING StreamName OPTIONAL - NULL, // PSTRING NormalizedParentName OPTIONAL - FILE_NOTIFY_CHANGE_NAME, // ULONG FilterMatch - 0, // ULONG Action - NULL // PVOID TargetContext - ); - */ - - } __finally { - - if (bFcbAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (!IrpContext->ExceptionInProgress) { - if (CompleteRequest) { - if (Status == STATUS_PENDING) { - Ext2QueueRequest(IrpContext); - } else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } else { - IrpContext->Irp = NULL; - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} - -VOID -Ext2NotifyReportChange ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Filter, - IN ULONG Action ) -{ - USHORT Offset; - - Offset = (USHORT) ( Mcb->FullName.Length - - Mcb->ShortName.Length); - - FsRtlNotifyFullReportChange( Vcb->NotifySync, - &(Vcb->NotifyList), - (PSTRING) (&Mcb->FullName), - (USHORT) Offset, - (PSTRING)NULL, - (PSTRING) NULL, - (ULONG) Filter, - (ULONG) Action, - (PVOID) NULL ); - - // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -} - - -NTSTATUS -Ext2DirectoryControl (IN PEXT2_IRP_CONTEXT IrpContext) -{ - NTSTATUS Status; - - ASSERT(IrpContext); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - switch (IrpContext->MinorFunction) { - - case IRP_MN_QUERY_DIRECTORY: - Status = Ext2QueryDirectory(IrpContext); - break; - - case IRP_MN_NOTIFY_CHANGE_DIRECTORY: - Status = Ext2NotifyChangeDirectory(IrpContext); - break; - - default: - Status = STATUS_INVALID_DEVICE_REQUEST; - Ext2CompleteIrpContext(IrpContext, Status); - } - - return Status; -} - - -BOOLEAN -Ext2IsDirectoryEmpty ( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb -) -{ - if (!IsMcbDirectory(Mcb) || IsMcbSymLink(Mcb)) { - return TRUE; - } - - return !!ext3_is_dir_empty(IrpContext, &Mcb->Inode); -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: dirctl.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, Ext2GetInfoLength) +#pragma alloc_text(PAGE, Ext2ProcessEntry) +#pragma alloc_text(PAGE, Ext2QueryDirectory) +#pragma alloc_text(PAGE, Ext2NotifyChangeDirectory) +#pragma alloc_text(PAGE, Ext2DirectoryControl) +#pragma alloc_text(PAGE, Ext2IsDirectoryEmpty) +#endif + +ULONG +Ext2GetInfoLength(IN FILE_INFORMATION_CLASS FileInformationClass) +{ + switch (FileInformationClass) { + + case FileDirectoryInformation: + return FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName[0]); + + case FileFullDirectoryInformation: + return FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName[0]); + + case FileBothDirectoryInformation: + return FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[0]); + + case FileNamesInformation: + return FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName[0]); + + case FileIdFullDirectoryInformation: + return FIELD_OFFSET(FILE_ID_FULL_DIR_INFORMATION, FileName[0]); + + case FileIdBothDirectoryInformation: + return FIELD_OFFSET(FILE_ID_BOTH_DIR_INFORMATION, FileName[0]); + + default: + break; + } + + return 0; +} + +NTSTATUS +Ext2ProcessEntry( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG in, + IN PVOID Buffer, + IN ULONG UsedLength, + IN ULONG Length, + IN ULONG FileIndex, + IN PUNICODE_STRING pName, + OUT PULONG EntrySize, + IN BOOLEAN Single +) +{ + PFILE_DIRECTORY_INFORMATION FDI = NULL; + PFILE_FULL_DIR_INFORMATION FFI = NULL; + PFILE_ID_FULL_DIR_INFORMATION FIF = NULL; + + PFILE_BOTH_DIR_INFORMATION FBI = NULL; + PFILE_ID_BOTH_DIR_INFORMATION FIB = NULL; + + PFILE_NAMES_INFORMATION FNI = NULL; + + PEXT2_MCB Mcb = NULL; + PEXT2_MCB Target = NULL; + + NTSTATUS Status = STATUS_SUCCESS; + struct inode Inode = { 0 }; + + ULONG InfoLength = 0; + ULONG NameLength = 0; + ULONG dwBytes = 0; + LONGLONG FileSize = 0; + LONGLONG AllocationSize; + ULONG FileAttributes = 0; + + BOOLEAN IsEntrySymlink = FALSE; + + *EntrySize = 0; + NameLength = pName->Length; + ASSERT((UsedLength & 7) == 0); + + InfoLength = Ext2GetInfoLength(FileInformationClass); + if (InfoLength == 0) { + DEBUG(DL_ERR, ("Ext2ProcessDirEntry: Invalid Info Class %xh for %wZ in %wZ\n", + FileInformationClass, pName, &Dcb->Mcb->FullName )); + return STATUS_INVALID_INFO_CLASS; + } + + if (InfoLength + NameLength > Length) { + DEBUG(DL_INF, ( "Ext2PricessDirEntry: Buffer is not enough.\n")); + Status = STATUS_BUFFER_OVERFLOW; + if (UsedLength || InfoLength > Length) { + DEBUG(DL_CP, ("Ext2ProcessDirEntry: Buffer overflows for %wZ in %wZ\n", + pName, &Dcb->Mcb->FullName )); + return Status; + } + } + + DEBUG(DL_CP, ("Ext2ProcessDirEntry: %wZ in %wZ\n", pName, &Dcb->Mcb->FullName )); + + Mcb = Ext2SearchMcb(Vcb, Dcb->Mcb, pName); + if (NULL != Mcb) { + if (S_ISLNK(Mcb->Inode.i_mode) && NULL == Mcb->Target) { + Ext2FollowLink( IrpContext, Vcb, Dcb->Mcb, Mcb, 0); + } + + } else { + + Inode.i_ino = in; + Inode.i_sb = &Vcb->sb; + if (!Ext2LoadInode(Vcb, &Inode)) { + DEBUG(DL_ERR, ("Ext2PricessDirEntry: Loading inode %xh (%wZ) error.\n", + in, pName )); + DbgBreak(); + Status = STATUS_SUCCESS; + goto errorout; + } + + if (S_ISDIR(Inode.i_mode) || S_ISREG(Inode.i_mode)) { + } else if (S_ISLNK(Inode.i_mode)) { + DEBUG(DL_RES, ("Ext2ProcessDirEntry: SymLink: %wZ\\%wZ\n", + &Dcb->Mcb->FullName, pName)); + Ext2LookupFile(IrpContext, Vcb, pName, Dcb->Mcb, &Mcb,0); + + if (Mcb && IsMcbSpecialFile(Mcb)) { + Ext2DerefMcb(Mcb); + Mcb = NULL; + } + } else { + Inode.i_size = 0; + } + } + + if (Mcb != NULL) { + + FileAttributes = Mcb->FileAttr; + if (IsMcbSymLink(Mcb)) { + Target = Mcb->Target; + ASSERT(Target); + ASSERT(!IsMcbSymLink(Target)); + if (IsMcbDirectory(Target)) { + FileSize = 0; + FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + } else { + FileSize = Target->Inode.i_size; + } + if (IsFileDeleted(Target)) { + ClearFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY); + FileSize = 0; + } + } else { + if (IsMcbDirectory(Mcb)) { + FileSize = 0; + } else { + FileSize = Mcb->Inode.i_size; + } + } + + if (IsInodeSymLink(&Mcb->Inode)) { + IsEntrySymlink = TRUE; + } + + } else { + + if (S_ISDIR(Inode.i_mode)) { + FileSize = 0; + } else { + FileSize = Inode.i_size; + } + + if (S_ISDIR(Inode.i_mode)) { + FileAttributes = FILE_ATTRIBUTE_DIRECTORY; + } else if (S_ISLNK(Inode.i_mode)) { + FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT; + IsEntrySymlink = TRUE; + } else { + FileAttributes = FILE_ATTRIBUTE_NORMAL; + } + + if (!Ext2CheckInodeAccess(Vcb, &Inode, Ext2FileCanWrite)) { + SetFlag(FileAttributes, FILE_ATTRIBUTE_READONLY); + } + } + + if (FileAttributes == 0) + FileAttributes = FILE_ATTRIBUTE_NORMAL; + + AllocationSize = CEILING_ALIGNED(ULONGLONG, FileSize, BLOCK_SIZE); + + /* process special files under root directory */ + if (IsRoot(Dcb)) { + /* set hidden and system attributes for Recycled / + RECYCLER / pagefile.sys */ + BOOLEAN IsDirectory = IsFlagOn(FileAttributes, FILE_ATTRIBUTE_DIRECTORY); + if (Ext2IsSpecialSystemFile(pName, IsDirectory)) { + SetFlag(FileAttributes, FILE_ATTRIBUTE_HIDDEN); + SetFlag(FileAttributes, FILE_ATTRIBUTE_SYSTEM); + } + } + + /* set hidden attribute for all entries starting with '.' */ + if (( pName->Length >= 4 && pName->Buffer[0] == L'.') && + ((pName->Length == 4 && pName->Buffer[1] != L'.') || + pName->Length >= 6 )) { + SetFlag(FileAttributes, FILE_ATTRIBUTE_HIDDEN); + } + + switch (FileInformationClass) { + + case FileIdFullDirectoryInformation: + FIF = (PFILE_ID_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); + case FileFullDirectoryInformation: + FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); + case FileDirectoryInformation: + FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength); + + if (!Single) { + FDI->NextEntryOffset = CEILING_ALIGNED(ULONG, InfoLength + NameLength, 8); + } + + FDI->FileIndex = FileIndex; + + if (Mcb) { + + FDI->CreationTime = Mcb->CreationTime; + FDI->LastAccessTime = Mcb->LastAccessTime; + FDI->LastWriteTime = Mcb->LastWriteTime; + FDI->ChangeTime = Mcb->ChangeTime; + + } else { + + FDI->CreationTime = Ext2NtTime(Inode.i_ctime); + FDI->LastAccessTime = Ext2NtTime(Inode.i_atime); + FDI->LastWriteTime = Ext2NtTime(Inode.i_mtime); + FDI->ChangeTime = Ext2NtTime(Inode.i_mtime); + } + + FDI->FileAttributes = FileAttributes; + FDI->EndOfFile.QuadPart = FileSize; + FDI->AllocationSize.QuadPart = AllocationSize; + + FDI->FileNameLength = NameLength; + if (InfoLength + NameLength > Length) { + NameLength = Length - InfoLength; + } + + if (FIF) { + FIF->FileId.QuadPart = (LONGLONG) in; + if (IsEntrySymlink) { + FIF->EaSize = IO_REPARSE_TAG_SYMLINK; + } + RtlCopyMemory(&FIF->FileName[0], &pName->Buffer[0], NameLength); + } else if (FFI) { + if (IsEntrySymlink) { + FFI->EaSize = IO_REPARSE_TAG_SYMLINK; + } + RtlCopyMemory(&FFI->FileName[0], &pName->Buffer[0], NameLength); + } else { + RtlCopyMemory(&FDI->FileName[0], &pName->Buffer[0], NameLength); + } + + *EntrySize = InfoLength + NameLength; + break; + + + case FileIdBothDirectoryInformation: + FIB = (PFILE_ID_BOTH_DIR_INFORMATION)((PUCHAR)Buffer + UsedLength); + case FileBothDirectoryInformation: + FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); + + if (!Single) { + FBI->NextEntryOffset = CEILING_ALIGNED(ULONG, InfoLength + NameLength, 8); + } + + FBI->FileIndex = FileIndex; + FBI->EndOfFile.QuadPart = FileSize; + FBI->AllocationSize.QuadPart = AllocationSize; + + if (Mcb) { + + FBI->CreationTime = Mcb->CreationTime; + FBI->LastAccessTime = Mcb->LastAccessTime; + FBI->LastWriteTime = Mcb->LastWriteTime; + FBI->ChangeTime = Mcb->ChangeTime; + + } else { + + FBI->CreationTime = Ext2NtTime(Inode.i_ctime); + FBI->LastAccessTime = Ext2NtTime(Inode.i_atime); + FBI->LastWriteTime = Ext2NtTime(Inode.i_mtime); + FBI->ChangeTime = Ext2NtTime(Inode.i_mtime); + } + + FBI->FileAttributes = FileAttributes; + + FBI->FileNameLength = NameLength; + if (InfoLength + NameLength > Length) { + NameLength = Length - InfoLength; + } + + if (FIB) { + FIB->FileId.QuadPart = (LONGLONG)in; + if (IsEntrySymlink) { + FIB->EaSize = IO_REPARSE_TAG_SYMLINK; + } + RtlCopyMemory(&FIB->FileName[0], &pName->Buffer[0], NameLength); + } else { + RtlCopyMemory(&FBI->FileName[0], &pName->Buffer[0], NameLength); + } + + *EntrySize = InfoLength + NameLength; + break; + + case FileNamesInformation: + + FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength); + if (!Single) { + FNI->NextEntryOffset = CEILING_ALIGNED(ULONG, InfoLength + NameLength, 8); + } + + FNI->FileNameLength = NameLength; + if (InfoLength + NameLength > Length) { + NameLength = Length - InfoLength; + } + RtlCopyMemory(&FNI->FileName[0], &pName->Buffer[0], NameLength); + + *EntrySize = InfoLength + NameLength; + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + break; + } + + if (Mcb) { + Ext2DerefMcb(Mcb); + } + +errorout: + + DEBUG(DL_CP, ("Ext2ProcessDirEntry: Status = %xh for %wZ in %wZ\n", + Status, pName, &Dcb->Mcb->FullName )); + + return Status; +} + + +BOOLEAN +Ext2IsWearingCloak( + IN PEXT2_VCB Vcb, + IN POEM_STRING OemName +) +{ + size_t PatLen = 0; + + /* we could not filter the files: "." and ".." */ + if (OemName->Length >= 1 && OemName->Buffer[0] == '.') { + + if ( OemName->Length == 2 && OemName->Buffer[1] == '.') { + return FALSE; + } else if (OemName->Length == 1) { + return FALSE; + } + } + + /* checking name prefix */ + if (Vcb->bHidingPrefix) { + PatLen = strlen(&Vcb->sHidingPrefix[0]); + if (PatLen > 0 && PatLen <= OemName->Length) { + if ( _strnicmp( OemName->Buffer, + Vcb->sHidingPrefix, + PatLen ) == 0) { + return TRUE; + } + } + } + + /* checking name suffix */ + if (Vcb->bHidingSuffix) { + PatLen = strlen(&Vcb->sHidingSuffix[0]); + if (PatLen > 0 && PatLen <= OemName->Length) { + if ( _strnicmp(&OemName->Buffer[OemName->Length - PatLen], + Vcb->sHidingSuffix, PatLen ) == 0) { + return TRUE; + } + } + } + + return FALSE; +} + +static int Ext2FillEntry(void *context, const char *name, int namlen, + ULONG offset, __u32 ino, unsigned int d_type) +{ + PEXT2_FILLDIR_CONTEXT fc = context; + PEXT2_IRP_CONTEXT IrpContext = fc->efc_irp; + + PEXT2_FCB Fcb = IrpContext->Fcb; + PEXT2_CCB Ccb = IrpContext->Ccb; + PEXT2_VCB Vcb = Fcb->Vcb; + + OEM_STRING Oem; + UNICODE_STRING Unicode = { 0 }; + NTSTATUS Status = STATUS_SUCCESS; + ULONG EntrySize; + USHORT NameLen; + int rc = 0; + + if (fc->efc_start > 0 && (fc->efc_single || (fc->efc_size < + fc->efc_start + namlen * 2 + Ext2GetInfoLength(fc->efc_fi)) )) { + rc = 1; + goto errorout; + } + + + Oem.Buffer = (void *)name; + Oem.Length = namlen & 0xFF; + Oem.MaximumLength = Oem.Length; + + /* skip . and .. */ + if ((Oem.Length == 1 && name[0] == '.') || (Oem.Length == 2 && + name[0] == '.' && name[1] == '.' )) { + goto errorout; + } + + if (Ext2IsWearingCloak(Vcb, &Oem)) { + goto errorout; + } + + NameLen = (USHORT)Ext2OEMToUnicodeSize(Vcb, &Oem); + if (NameLen <= 0) { + fc->efc_status = STATUS_INSUFFICIENT_RESOURCES; + rc = -ENOMEM; + goto errorout; + } + + Unicode.MaximumLength = NameLen + 2; + Unicode.Buffer = Ext2AllocatePool( + PagedPool, + Unicode.MaximumLength, + EXT2_INAME_MAGIC + ); + if (!Unicode.Buffer) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to " + "allocate InodeFileName.\n")); + fc->efc_status = STATUS_INSUFFICIENT_RESOURCES; + rc = -ENOMEM; + goto errorout; + } + RtlZeroMemory(Unicode.Buffer, Unicode.MaximumLength); + INC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength); + + Status = Ext2OEMToUnicode(Vcb, &Unicode, &Oem); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: Ext2OEMtoUnicode failed with %xh.\n", Status)); + fc->efc_status = STATUS_INSUFFICIENT_RESOURCES; + rc = -ENOMEM; + goto errorout; + } + + if (FsRtlDoesNameContainWildCards( &Ccb->DirectorySearchPattern) ? + FsRtlIsNameInExpression(&Ccb->DirectorySearchPattern, + &Unicode, TRUE, NULL) : + !RtlCompareUnicodeString(&Ccb->DirectorySearchPattern, + &Unicode, TRUE)) { + Status = Ext2ProcessEntry(fc->efc_irp, Vcb, Fcb, fc->efc_fi, ino, fc->efc_buf, + CEILING_ALIGNED(ULONG, fc->efc_start, 8), + fc->efc_size - CEILING_ALIGNED(ULONG, fc->efc_start, 8), + offset, &Unicode, &EntrySize, fc->efc_single); + if (NT_SUCCESS(Status)) { + if (EntrySize > 0) { + fc->efc_prev = CEILING_ALIGNED(ULONG, fc->efc_start, 8); + fc->efc_start = fc->efc_prev + EntrySize; + } else { + DbgBreak(); + } + } else { + if (Status == STATUS_BUFFER_OVERFLOW) { + if (fc->efc_start == 0) { + fc->efc_start = EntrySize; + } else { + Status = STATUS_SUCCESS; + } + } + rc = 1; + } + } + +errorout: + + fc->efc_status = Status; + if (Unicode.Buffer) { + DEC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength ); + Ext2FreePool(Unicode.Buffer, EXT2_INAME_MAGIC); + } + + return rc; +} + + +NTSTATUS +Ext2QueryDirectory (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PEXT2_VCB Vcb = NULL; + PFILE_OBJECT FileObject = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_MCB Mcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + + ULONG Length; + ULONG FileIndex; + PUNICODE_STRING FileName; + PUCHAR Buffer; + + BOOLEAN RestartScan; + BOOLEAN ReturnSingleEntry; + BOOLEAN IndexSpecified; + BOOLEAN FirstQuery; + BOOLEAN FcbResourceAcquired = FALSE; + + USHORT NameLen; + FILE_INFORMATION_CLASS fi; + + OEM_STRING Oem = { 0 }; + UNICODE_STRING Unicode = { 0 }; + PEXT2_DIR_ENTRY2 pDir = NULL; + + ULONG ByteOffset; + ULONG RecLen = 0; + ULONG EntrySize = 0; + + EXT2_FILLDIR_CONTEXT fc = { 0 }; + + __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; + __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; + __leave; + } + + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { + Status = STATUS_ACCESS_DENIED; + __leave; + } + + FileObject = IrpContext->FileObject; + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + Mcb = Fcb->Mcb; + if (NULL == Mcb) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + ASSERT (!IsMcbSymLink(Mcb)); + + // + // This request is not allowed on volumes + // + if (Fcb->Identifier.Type == EXT2VCB) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (!IsMcbDirectory(Mcb)) { + Status = STATUS_NOT_A_DIRECTORY; + __leave; + } + + if (IsFileDeleted(Mcb)) { + Status = STATUS_NOT_A_DIRECTORY; + __leave; + } + + Ccb = (PEXT2_CCB) FileObject->FsContext2; + + ASSERT(Ccb); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + + Irp = IrpContext->Irp; + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + +#ifndef _GNU_NTIFS_ + + fi = IoStackLocation->Parameters.QueryDirectory.FileInformationClass; + + Length = IoStackLocation->Parameters.QueryDirectory.Length; + + FileName = (PUNICODE_STRING)IoStackLocation->Parameters.QueryDirectory.FileName; + + FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex; + +#else // _GNU_NTIFS_ + + fi = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; + + Length = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.Length; + + FileName = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName; + + FileIndex = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileIndex; + +#endif // _GNU_NTIFS_ + + RestartScan = FlagOn(((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Flags, SL_RESTART_SCAN); + ReturnSingleEntry = FlagOn(((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Flags, SL_RETURN_SINGLE_ENTRY); + IndexSpecified = FlagOn(((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Flags, SL_INDEX_SPECIFIED); + + Buffer = Ext2GetUserBuffer(Irp); + if (Buffer == NULL) { + DbgBreak(); + Status = STATUS_INVALID_USER_BUFFER; + __leave; + } + + if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { + Status = STATUS_PENDING; + __leave; + } + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + __leave; + } + FcbResourceAcquired = TRUE; + + if (FileName != NULL) { + + if (Ccb->DirectorySearchPattern.Buffer != NULL) { + + FirstQuery = FALSE; + + } else { + + FirstQuery = TRUE; + + Ccb->DirectorySearchPattern.Length = + Ccb->DirectorySearchPattern.MaximumLength = + FileName->Length; + + Ccb->DirectorySearchPattern.Buffer = + Ext2AllocatePool(PagedPool, FileName->Length, + EXT2_DIRSP_MAGIC); + + if (Ccb->DirectorySearchPattern.Buffer == NULL) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to allocate SerarchPattern.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + INC_MEM_COUNT( PS_DIR_PATTERN, + Ccb->DirectorySearchPattern.Buffer, + Ccb->DirectorySearchPattern.MaximumLength); + + Status = RtlUpcaseUnicodeString( + &(Ccb->DirectorySearchPattern), + FileName, + FALSE); + + if (!NT_SUCCESS(Status)) { + __leave; + } + } + + } else if (Ccb->DirectorySearchPattern.Buffer != NULL) { + + FirstQuery = FALSE; + FileName = &Ccb->DirectorySearchPattern; + + } else { + + FirstQuery = TRUE; + + Ccb->DirectorySearchPattern.Length = + Ccb->DirectorySearchPattern.MaximumLength = 2; + + Ccb->DirectorySearchPattern.Buffer = + Ext2AllocatePool(PagedPool, 4, EXT2_DIRSP_MAGIC); + + if (Ccb->DirectorySearchPattern.Buffer == NULL) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to allocate SerarchPattern (1st).\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + INC_MEM_COUNT( PS_DIR_PATTERN, + Ccb->DirectorySearchPattern.Buffer, + Ccb->DirectorySearchPattern.MaximumLength); + + RtlZeroMemory(Ccb->DirectorySearchPattern.Buffer, 4); + RtlCopyMemory( + Ccb->DirectorySearchPattern.Buffer, + L"*\0", 2); + } + + if (IndexSpecified) { + Ccb->filp.f_pos = FileIndex; + } else { + if (RestartScan || FirstQuery) { + Ccb->filp.f_pos = FileIndex = 0; + } else { + FileIndex = (ULONG)Ccb->filp.f_pos; + } + } + + RtlZeroMemory(Buffer, Length); + + fc.efc_irp = IrpContext; + fc.efc_buf = Buffer; + fc.efc_size = Length; + fc.efc_start = 0; + fc.efc_single = ReturnSingleEntry; + fc.efc_fi = fi; + fc.efc_status = STATUS_SUCCESS; + +#ifdef EXT2_HTREE_INDEX + + if (EXT3_HAS_COMPAT_FEATURE(Mcb->Inode.i_sb, + EXT3_FEATURE_COMPAT_DIR_INDEX) && + ((EXT3_I(&Mcb->Inode)->i_flags & EXT3_INDEX_FL) || + ((Mcb->Inode.i_size >> BLOCK_BITS) == 1)) ) { + int rc = ext3_dx_readdir(&Ccb->filp, Ext2FillEntry, &fc); + Status = fc.efc_status; + if (rc != ERR_BAD_DX_DIR) { + goto errorout; + } + /* + * We don't set the inode dirty flag since it's not + * critical that it get flushed back to the disk. + */ + EXT3_I(&Mcb->Inode)->i_flags &= ~EXT3_INDEX_FL; + } +#endif + + if (Mcb->Inode.i_size <= Ccb->filp.f_pos) { + Status = STATUS_NO_MORE_FILES; + __leave; + } + + pDir = Ext2AllocatePool( + PagedPool, + sizeof(EXT2_DIR_ENTRY2), + EXT2_DENTRY_MAGIC + ); + + if (!pDir) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to allocate pDir.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + INC_MEM_COUNT(PS_DIR_ENTRY, pDir, sizeof(EXT2_DIR_ENTRY2)); + ByteOffset = FileIndex; + + DEBUG(DL_CP, ("Ex2QueryDirectory: Dir: %wZ Index=%xh Pattern : %wZ.\n", + &Fcb->Mcb->FullName, FileIndex, &Ccb->DirectorySearchPattern)); + + while ((ByteOffset < Mcb->Inode.i_size) && + (CEILING_ALIGNED(ULONG, fc.efc_start, 8) < Length)) { + + RtlZeroMemory(pDir, sizeof(EXT2_DIR_ENTRY2)); + + Status = Ext2ReadInode( + IrpContext, + Vcb, + Mcb, + (ULONGLONG)ByteOffset, + (PVOID)pDir, + sizeof(EXT2_DIR_ENTRY2), + FALSE, + &EntrySize); + + if (!NT_SUCCESS(Status)) { + DbgBreak(); + __leave; + } + + if (pDir->rec_len == 0) { + RecLen = BLOCK_SIZE - (ByteOffset & (BLOCK_SIZE - 1)); + } else { + RecLen = ext3_rec_len_from_disk(pDir->rec_len); + } + + if (!pDir->inode || pDir->inode >= INODES_COUNT) { + goto ProcessNextEntry; + } + + /* skip . and .. */ + if ((pDir->name_len == 1 && pDir->name[0] == '.') || + (pDir->name_len == 2 && pDir->name[0] == '.' && pDir->name[1] == '.' )) { + goto ProcessNextEntry; + } + + Oem.Buffer = pDir->name; + Oem.Length = (pDir->name_len & 0xff); + Oem.MaximumLength = Oem.Length; + + if (Ext2IsWearingCloak(Vcb, &Oem)) { + goto ProcessNextEntry; + } + + NameLen = (USHORT) Ext2OEMToUnicodeSize(Vcb, &Oem); + + if (NameLen <= 0) { + DEBUG(DL_CP, ("Ext2QueryDirectory: failed to count unicode length for inode: %xh\n", + pDir->inode)); + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + if ( Unicode.Buffer != NULL && Unicode.MaximumLength > NameLen) { + /* reuse buffer */ + } else { + /* free and re-allocate it */ + if (Unicode.Buffer) { + DEC_MEM_COUNT(PS_INODE_NAME, + Unicode.Buffer, + Unicode.MaximumLength); + Ext2FreePool(Unicode.Buffer, EXT2_INAME_MAGIC); + } + Unicode.MaximumLength = NameLen + 2; + Unicode.Buffer = Ext2AllocatePool( + PagedPool, Unicode.MaximumLength, + EXT2_INAME_MAGIC + ); + if (!Unicode.Buffer) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: failed to " + "allocate InodeFileName.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + INC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength); + } + + Unicode.Length = 0; + RtlZeroMemory(Unicode.Buffer, Unicode.MaximumLength); + + Status = Ext2OEMToUnicode(Vcb, &Unicode, &Oem); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ( "Ex2QueryDirectory: Ext2OEMtoUnicode failed with %xh.\n", Status)); + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + + DEBUG(DL_CP, ( "Ex2QueryDirectory: process inode: %xh / %wZ (%d).\n", + pDir->inode, &Unicode, Unicode.Length)); + + if (FsRtlDoesNameContainWildCards( + &(Ccb->DirectorySearchPattern)) ? + FsRtlIsNameInExpression( + &(Ccb->DirectorySearchPattern), + &Unicode, + TRUE, + NULL) : + !RtlCompareUnicodeString( + &(Ccb->DirectorySearchPattern), + &Unicode, + TRUE) ) { + + Status = Ext2ProcessEntry( + IrpContext, + Vcb, + Fcb, + fi, + pDir->inode, + Buffer, + CEILING_ALIGNED(ULONG, fc.efc_start, 8), + Length - CEILING_ALIGNED(ULONG, fc.efc_start, 8), + ByteOffset, + &Unicode, + &EntrySize, + ReturnSingleEntry + ); + + if (NT_SUCCESS(Status)) { + if (EntrySize > 0) { + fc.efc_prev = CEILING_ALIGNED(ULONG, fc.efc_start, 8); + fc.efc_start = fc.efc_prev + EntrySize; + } else { + DbgBreak(); + } + } else { + if (Status == STATUS_BUFFER_OVERFLOW) { + if (fc.efc_start == 0) { + fc.efc_start = EntrySize; + } else { + Status = STATUS_SUCCESS; + } + } else { + __leave; + } + break; + } + } + +ProcessNextEntry: + + ByteOffset += RecLen; + Ccb->filp.f_pos = ByteOffset; + + if (fc.efc_start && ReturnSingleEntry) { + Status = STATUS_SUCCESS; + goto errorout; + } + } + +errorout: + + ((PULONG)((PUCHAR)Buffer + fc.efc_prev))[0] = 0; + FileIndex = ByteOffset; + + if (Status == STATUS_BUFFER_OVERFLOW) { + /* just return fc.efc_start/EntrySize bytes that we filled */ + } else if (!fc.efc_start) { + if (NT_SUCCESS(Status)) { + if (FirstQuery) { + Status = STATUS_NO_SUCH_FILE; + } else { + Status = STATUS_NO_MORE_FILES; + } + } + } else { + Status = STATUS_SUCCESS; + } + + } __finally { + + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (pDir != NULL) { + Ext2FreePool(pDir, EXT2_DENTRY_MAGIC); + DEC_MEM_COUNT(PS_DIR_ENTRY, pDir, sizeof(EXT2_DIR_ENTRY2)); + } + + if (Unicode.Buffer != NULL) { + DEC_MEM_COUNT(PS_INODE_NAME, Unicode.Buffer, Unicode.MaximumLength); + Ext2FreePool(Unicode.Buffer, EXT2_INAME_MAGIC); + } + + if (!IrpContext->ExceptionInProgress) { + + 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 { + IrpContext->Irp->IoStatus.Information = fc.efc_start; + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} + +NTSTATUS +Ext2NotifyChangeDirectory ( + IN PEXT2_IRP_CONTEXT IrpContext +) +{ + PDEVICE_OBJECT DeviceObject; + BOOLEAN CompleteRequest = TRUE; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IrpSp; + PFILE_OBJECT FileObject; + ULONG CompletionFilter; + BOOLEAN WatchTree; + + BOOLEAN bFcbAcquired = FALSE; + + __try { + + ASSERT(IrpContext); + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + // + // Always set the wait flag in the Irp context for the original request. + // + + SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ); + + DeviceObject = IrpContext->DeviceObject; + + if (IsExt2FsDevice(DeviceObject)) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + 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); + if (Fcb->Identifier.Type == EXT2VCB) { + DbgBreak(); + Status = STATUS_INVALID_PARAMETER; + __leave; + } + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + Ccb = (PEXT2_CCB) FileObject->FsContext2; + ASSERT(Ccb); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + + /* do nothing if target fie was deleted */ + if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { + Status = STATUS_FILE_DELETED; + __leave; + } + + if (!IsDirectory(Fcb)) { + DbgBreak(); + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + TRUE )) { + bFcbAcquired = TRUE; + } else { + Status = STATUS_PENDING; + __leave; + } + + Irp = IrpContext->Irp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + +#ifndef _GNU_NTIFS_ + + CompletionFilter = + IrpSp->Parameters.NotifyDirectory.CompletionFilter; + +#else // _GNU_NTIFS_ + + CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION) + IrpSp)->Parameters.NotifyDirectory.CompletionFilter; + +#endif // _GNU_NTIFS_ + + WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE); + + if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { + Status = STATUS_DELETE_PENDING; + __leave; + } + + FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, + &Vcb->NotifyList, + FileObject->FsContext2, + (PSTRING)(&Fcb->Mcb->FullName), + WatchTree, + FALSE, + CompletionFilter, + Irp, + NULL, + NULL ); + + CompleteRequest = FALSE; + + Status = STATUS_PENDING; + + /* + Currently the driver is read-only but here is an example on how to use the + FsRtl-functions to report a change: + + ANSI_STRING TestString; + USHORT FileNamePartLength; + + RtlInitAnsiString(&TestString, "\\ntifs.h"); + + FileNamePartLength = 7; + + FsRtlNotifyReportChange( + Vcb->NotifySync, // PNOTIFY_SYNC NotifySync + &Vcb->NotifyList, // PLIST_ENTRY NotifyList + &TestString, // PSTRING FullTargetName + &FileNamePartLength, // PUSHORT FileNamePartLength + FILE_NOTIFY_CHANGE_NAME // ULONG FilterMatch + ); + + or + + ANSI_STRING TestString; + + RtlInitAnsiString(&TestString, "\\ntifs.h"); + + FsRtlNotifyFullReportChange( + Vcb->NotifySync, // PNOTIFY_SYNC NotifySync + &Vcb->NotifyList, // PLIST_ENTRY NotifyList + &TestString, // PSTRING FullTargetName + 1, // USHORT TargetNameOffset + NULL, // PSTRING StreamName OPTIONAL + NULL, // PSTRING NormalizedParentName OPTIONAL + FILE_NOTIFY_CHANGE_NAME, // ULONG FilterMatch + 0, // ULONG Action + NULL // PVOID TargetContext + ); + */ + + } __finally { + + if (bFcbAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (!IrpContext->ExceptionInProgress) { + if (CompleteRequest) { + if (Status == STATUS_PENDING) { + Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } else { + IrpContext->Irp = NULL; + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} + +VOID +Ext2NotifyReportChange ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Filter, + IN ULONG Action ) +{ + USHORT Offset; + + Offset = (USHORT) ( Mcb->FullName.Length - + Mcb->ShortName.Length); + + FsRtlNotifyFullReportChange( Vcb->NotifySync, + &(Vcb->NotifyList), + (PSTRING) (&Mcb->FullName), + (USHORT) Offset, + (PSTRING)NULL, + (PSTRING) NULL, + (ULONG) Filter, + (ULONG) Action, + (PVOID) NULL ); + + // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); +} + + +NTSTATUS +Ext2DirectoryControl (IN PEXT2_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + switch (IrpContext->MinorFunction) { + + case IRP_MN_QUERY_DIRECTORY: + Status = Ext2QueryDirectory(IrpContext); + break; + + case IRP_MN_NOTIFY_CHANGE_DIRECTORY: + Status = Ext2NotifyChangeDirectory(IrpContext); + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + Ext2CompleteIrpContext(IrpContext, Status); + } + + return Status; +} + + +BOOLEAN +Ext2IsDirectoryEmpty ( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb +) +{ + if (!IsMcbDirectory(Mcb) || IsMcbSymLink(Mcb)) { + return TRUE; + } + + return !!ext3_is_dir_empty(IrpContext, &Mcb->Inode); +} diff --git a/Ext4Fsd/dispatch.c b/Ext4Fsd/dispatch.c index 59054de..75b655c 100644 --- a/Ext4Fsd/dispatch.c +++ b/Ext4Fsd/dispatch.c @@ -1,354 +1,354 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: dispatch.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, Ext2QueueRequest) -#pragma alloc_text(PAGE, Ext2DeQueueRequest) -#endif - -/* - * Ext2OplockComplete - * - * callback routine of FsRtlCheckOplock when an oplock break has - * completed, allowing an Irp to resume execution. - * - * Arguments: - * - * Context: the IrpContext to be queued - * Irp: the I/O request packet - * - * Return Value: - * N/A - */ - -VOID -Ext2OplockComplete ( - IN PVOID Context, - IN PIRP Irp -) -{ - // - // Check on the return value in the Irp. - // - - if (Irp->IoStatus.Status == STATUS_SUCCESS) { - - // - // queue the Irp context in the workqueue. - // - - Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context); - - } else { - - // - // complete the request in case of failure - // - - Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context, - Irp->IoStatus.Status ); - } - - return; -} - - -/* - * Ext2LockIrp - * - * performs buffer locking if we need pend the process of the Irp - * - * Arguments: - * Context: the irp context - * Irp: the I/O request packet. - * - * Return Value: - * N/A - */ - -VOID -Ext2LockIrp ( - IN PVOID Context, - IN PIRP Irp -) -{ - PIO_STACK_LOCATION IrpSp; - PEXT2_IRP_CONTEXT IrpContext; - - if (Irp == NULL) { - return; - } - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - IrpContext = (PEXT2_IRP_CONTEXT) Context; - - if ( IrpContext->MajorFunction == IRP_MJ_READ || - IrpContext->MajorFunction == IRP_MJ_WRITE ) { - - // - // lock the user's buffer to MDL, if the I/O is bufferred - // - - if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { - - Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length, - (IrpContext->MajorFunction == IRP_MJ_READ) ? - IoWriteAccess : IoReadAccess ); - } - - } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL - && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) { - - ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length; - Ext2LockUserBuffer(Irp, Length, IoWriteAccess); - - } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) { - - ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length; - Ext2LockUserBuffer(Irp, Length, IoWriteAccess); - - } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) { - ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length; - Ext2LockUserBuffer(Irp, Length, IoReadAccess); - - } else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && - (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) { - PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; - if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) || - (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) || - (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) { - ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength; - Ext2LockUserBuffer(Irp, Length, IoWriteAccess); - } - } - - // Mark the request as pending status - - IoMarkIrpPending( Irp ); - - return; -} - -NTSTATUS -Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext) -{ - ASSERT(IrpContext); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - /* set the flags of "can wait" and "queued" */ - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); - - /* make sure the buffer is kept valid in system context */ - Ext2LockIrp(IrpContext, IrpContext->Irp); - - /* initialize workite*/ - ExInitializeWorkItem( - &IrpContext->WorkQueueItem, - Ext2DeQueueRequest, - IrpContext ); - - /* dispatch it */ - ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); - - return STATUS_PENDING; -} - - -VOID -Ext2DeQueueRequest (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))); - - __try { - - __try { - - FsRtlEnterFileSystem(); - - if (!IrpContext->IsTopLevel) { - IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); - } - - Ext2DispatchRequest(IrpContext); - - } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { - - Ext2ExceptionHandler(IrpContext); - } - - } __finally { - - IoSetTopLevelIrp(NULL); - - FsRtlExitFileSystem(); - } -} - - -NTSTATUS -Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext) -{ - ASSERT(IrpContext); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - switch (IrpContext->MajorFunction) { - - case IRP_MJ_CREATE: - return Ext2Create(IrpContext); - - case IRP_MJ_CLOSE: - return Ext2Close(IrpContext); - - case IRP_MJ_READ: - return Ext2Read(IrpContext); - - case IRP_MJ_WRITE: - return Ext2Write(IrpContext); - - case IRP_MJ_FLUSH_BUFFERS: - return Ext2Flush(IrpContext); - - case IRP_MJ_QUERY_INFORMATION: - return Ext2QueryFileInformation(IrpContext); - - case IRP_MJ_SET_INFORMATION: - return Ext2SetFileInformation(IrpContext); - - case IRP_MJ_QUERY_VOLUME_INFORMATION: - return Ext2QueryVolumeInformation(IrpContext); - - case IRP_MJ_SET_VOLUME_INFORMATION: - return Ext2SetVolumeInformation(IrpContext); - - case IRP_MJ_DIRECTORY_CONTROL: - return Ext2DirectoryControl(IrpContext); - - case IRP_MJ_FILE_SYSTEM_CONTROL: - return Ext2FileSystemControl(IrpContext); - - case IRP_MJ_DEVICE_CONTROL: - return Ext2DeviceControl(IrpContext); - - case IRP_MJ_LOCK_CONTROL: - return Ext2LockControl(IrpContext); - - case IRP_MJ_CLEANUP: - return Ext2Cleanup(IrpContext); - - case IRP_MJ_SHUTDOWN: - return Ext2ShutDown(IrpContext); - - case IRP_MJ_QUERY_EA: - return Ext2QueryEa(IrpContext); - - case IRP_MJ_SET_EA: - return Ext2SetEa(IrpContext); - -#if (_WIN32_WINNT >= 0x0500) - case IRP_MJ_PNP: - return Ext2Pnp(IrpContext); -#endif //(_WIN32_WINNT >= 0x0500) - default: - DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n", - IrpContext->MajorFunction)); - - Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR); - - return STATUS_DRIVER_INTERNAL_ERROR; - } -} - - -NTSTATUS -Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - BOOLEAN AtIrqlPassiveLevel = FALSE; - BOOLEAN IsTopLevelIrp = FALSE; - PEXT2_IRP_CONTEXT IrpContext = NULL; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - __try { - - __try { - -#if EXT2_DEBUG - Ext2DbgPrintCall(DeviceObject, Irp); -#endif - - AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL); - - if (AtIrqlPassiveLevel) { - FsRtlEnterFileSystem(); - } - - if (!IoGetTopLevelIrp()) { - IsTopLevelIrp = TRUE; - IoSetTopLevelIrp(Irp); - } - - IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp); - - if (!IrpContext) { - - Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Status = Status; - - Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT); - - } else { - - if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && - !AtIrqlPassiveLevel) { - - DbgBreak(); - } - - Status = Ext2DispatchRequest(IrpContext); - } - } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { - - Status = Ext2ExceptionHandler(IrpContext); - } - - } __finally { - - if (IsTopLevelIrp) { - IoSetTopLevelIrp(NULL); - } - - if (AtIrqlPassiveLevel) { - FsRtlExitFileSystem(); - } - } - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: dispatch.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, Ext2QueueRequest) +#pragma alloc_text(PAGE, Ext2DeQueueRequest) +#endif + +/* + * Ext2OplockComplete + * + * callback routine of FsRtlCheckOplock when an oplock break has + * completed, allowing an Irp to resume execution. + * + * Arguments: + * + * Context: the IrpContext to be queued + * Irp: the I/O request packet + * + * Return Value: + * N/A + */ + +VOID +Ext2OplockComplete ( + IN PVOID Context, + IN PIRP Irp +) +{ + // + // Check on the return value in the Irp. + // + + if (Irp->IoStatus.Status == STATUS_SUCCESS) { + + // + // queue the Irp context in the workqueue. + // + + Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context); + + } else { + + // + // complete the request in case of failure + // + + Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context, + Irp->IoStatus.Status ); + } + + return; +} + + +/* + * Ext2LockIrp + * + * performs buffer locking if we need pend the process of the Irp + * + * Arguments: + * Context: the irp context + * Irp: the I/O request packet. + * + * Return Value: + * N/A + */ + +VOID +Ext2LockIrp ( + IN PVOID Context, + IN PIRP Irp +) +{ + PIO_STACK_LOCATION IrpSp; + PEXT2_IRP_CONTEXT IrpContext; + + if (Irp == NULL) { + return; + } + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + IrpContext = (PEXT2_IRP_CONTEXT) Context; + + if ( IrpContext->MajorFunction == IRP_MJ_READ || + IrpContext->MajorFunction == IRP_MJ_WRITE ) { + + // + // lock the user's buffer to MDL, if the I/O is bufferred + // + + if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { + + Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length, + (IrpContext->MajorFunction == IRP_MJ_READ) ? + IoWriteAccess : IoReadAccess ); + } + + } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL + && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) { + + ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length; + Ext2LockUserBuffer(Irp, Length, IoWriteAccess); + + } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) { + + ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length; + Ext2LockUserBuffer(Irp, Length, IoWriteAccess); + + } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) { + ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length; + Ext2LockUserBuffer(Irp, Length, IoReadAccess); + + } else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && + (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) { + PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; + if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) || + (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) || + (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) { + ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength; + Ext2LockUserBuffer(Irp, Length, IoWriteAccess); + } + } + + // Mark the request as pending status + + IoMarkIrpPending( Irp ); + + return; +} + +NTSTATUS +Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext) +{ + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + /* set the flags of "can wait" and "queued" */ + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); + + /* make sure the buffer is kept valid in system context */ + Ext2LockIrp(IrpContext, IrpContext->Irp); + + /* initialize workite*/ + ExInitializeWorkItem( + &IrpContext->WorkQueueItem, + Ext2DeQueueRequest, + IrpContext ); + + /* dispatch it */ + ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); + + return STATUS_PENDING; +} + + +VOID +Ext2DeQueueRequest (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))); + + __try { + + __try { + + FsRtlEnterFileSystem(); + + if (!IrpContext->IsTopLevel) { + IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); + } + + Ext2DispatchRequest(IrpContext); + + } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { + + Ext2ExceptionHandler(IrpContext); + } + + } __finally { + + IoSetTopLevelIrp(NULL); + + FsRtlExitFileSystem(); + } +} + + +NTSTATUS +Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext) +{ + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + switch (IrpContext->MajorFunction) { + + case IRP_MJ_CREATE: + return Ext2Create(IrpContext); + + case IRP_MJ_CLOSE: + return Ext2Close(IrpContext); + + case IRP_MJ_READ: + return Ext2Read(IrpContext); + + case IRP_MJ_WRITE: + return Ext2Write(IrpContext); + + case IRP_MJ_FLUSH_BUFFERS: + return Ext2Flush(IrpContext); + + case IRP_MJ_QUERY_INFORMATION: + return Ext2QueryFileInformation(IrpContext); + + case IRP_MJ_SET_INFORMATION: + return Ext2SetFileInformation(IrpContext); + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + return Ext2QueryVolumeInformation(IrpContext); + + case IRP_MJ_SET_VOLUME_INFORMATION: + return Ext2SetVolumeInformation(IrpContext); + + case IRP_MJ_DIRECTORY_CONTROL: + return Ext2DirectoryControl(IrpContext); + + case IRP_MJ_FILE_SYSTEM_CONTROL: + return Ext2FileSystemControl(IrpContext); + + case IRP_MJ_DEVICE_CONTROL: + return Ext2DeviceControl(IrpContext); + + case IRP_MJ_LOCK_CONTROL: + return Ext2LockControl(IrpContext); + + case IRP_MJ_CLEANUP: + return Ext2Cleanup(IrpContext); + + case IRP_MJ_SHUTDOWN: + return Ext2ShutDown(IrpContext); + + case IRP_MJ_QUERY_EA: + return Ext2QueryEa(IrpContext); + + case IRP_MJ_SET_EA: + return Ext2SetEa(IrpContext); + +#if (_WIN32_WINNT >= 0x0500) + case IRP_MJ_PNP: + return Ext2Pnp(IrpContext); +#endif //(_WIN32_WINNT >= 0x0500) + default: + DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n", + IrpContext->MajorFunction)); + + Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR); + + return STATUS_DRIVER_INTERNAL_ERROR; + } +} + + +NTSTATUS +Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + BOOLEAN AtIrqlPassiveLevel = FALSE; + BOOLEAN IsTopLevelIrp = FALSE; + PEXT2_IRP_CONTEXT IrpContext = NULL; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + __try { + + __try { + +#if EXT2_DEBUG + Ext2DbgPrintCall(DeviceObject, Irp); +#endif + + AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL); + + if (AtIrqlPassiveLevel) { + FsRtlEnterFileSystem(); + } + + if (!IoGetTopLevelIrp()) { + IsTopLevelIrp = TRUE; + IoSetTopLevelIrp(Irp); + } + + IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp); + + if (!IrpContext) { + + Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Status = Status; + + Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT); + + } else { + + if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && + !AtIrqlPassiveLevel) { + + DbgBreak(); + } + + Status = Ext2DispatchRequest(IrpContext); + } + } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { + + Status = Ext2ExceptionHandler(IrpContext); + } + + } __finally { + + if (IsTopLevelIrp) { + IoSetTopLevelIrp(NULL); + } + + if (AtIrqlPassiveLevel) { + FsRtlExitFileSystem(); + } + } + + return Status; +} diff --git a/Ext4Fsd/ea.c b/Ext4Fsd/ea.c index ccc671d..776611b 100644 --- a/Ext4Fsd/ea.c +++ b/Ext4Fsd/ea.c @@ -1,604 +1,604 @@ -/* -* COPYRIGHT: See COPYRIGHT.TXT -* PROJECT: Ext2 File System Driver for Windows >= NT -* FILE: ea.c -* PROGRAMMER: Matt Wu Kaho Ng -* HOMEPAGE: http://www.ext2fsd.com -* UPDATE HISTORY: -*/ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" -#include - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Ext2QueryEa) -#pragma alloc_text(PAGE, Ext2SetEa) -#pragma alloc_text(PAGE, Ext2IsEaNameValid) -#endif - -// Ea iterator -struct EaIterator { - // Return only an entry - BOOLEAN ReturnSingleEntry; - - // Is the buffer overflowing? - BOOL OverFlow; - - // FILE_FULL_EA_INFORMATION output buffer - PFILE_FULL_EA_INFORMATION FullEa; - PFILE_FULL_EA_INFORMATION LastFullEa; - - // UserBuffer's size - ULONG UserBufferLength; - - // Remaining UserBuffer's size - ULONG RemainingUserBufferLength; - - // Start scanning from this EA - ULONG EaIndex; - - // Next EA index returned by Ext2IterateAllEa - ULONG EaIndexCounter; -}; - -static int Ext2IterateAllEa(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item, BOOL is_last) -{ - struct EaIterator *pEaIterator = xattr_ref->iter_arg; - ULONG EaEntrySize = 4 + 1 + 1 + 2 + item->name_len + 1 + item->data_size; - ASSERT(pEaIterator); - if (!is_last && !pEaIterator->ReturnSingleEntry) - EaEntrySize = ALIGN_UP(EaEntrySize, ULONG); - - // Start iteration from index specified - if (pEaIterator->EaIndexCounter < pEaIterator->EaIndex) { - pEaIterator->EaIndexCounter++; - return EXT4_XATTR_ITERATE_CONT; - } - pEaIterator->EaIndexCounter++; - - if (EaEntrySize > pEaIterator->RemainingUserBufferLength) { - pEaIterator->OverFlow = TRUE; - return EXT4_XATTR_ITERATE_STOP; - } - pEaIterator->FullEa->NextEntryOffset = 0; - pEaIterator->FullEa->Flags = 0; - pEaIterator->FullEa->EaNameLength = (UCHAR)item->name_len; - pEaIterator->FullEa->EaValueLength = (USHORT)item->data_size; - RtlCopyMemory(&pEaIterator->FullEa->EaName[0], - item->name, - item->name_len); - RtlCopyMemory(&pEaIterator->FullEa->EaName[0] + item->name_len + 1, - item->data, - item->data_size); - - // Link FullEa and LastFullEa together - if (pEaIterator->LastFullEa) { - pEaIterator->LastFullEa->NextEntryOffset = (ULONG) - ((PCHAR)pEaIterator->FullEa - (PCHAR)pEaIterator->LastFullEa); - } - - pEaIterator->LastFullEa = pEaIterator->FullEa; - pEaIterator->FullEa = (PFILE_FULL_EA_INFORMATION) - ((PCHAR)pEaIterator->FullEa + EaEntrySize); - pEaIterator->RemainingUserBufferLength -= EaEntrySize; - - if (pEaIterator->ReturnSingleEntry) - return EXT4_XATTR_ITERATE_STOP; - - return EXT4_XATTR_ITERATE_CONT; -} - -NTSTATUS -Ext2QueryEa ( - IN PEXT2_IRP_CONTEXT IrpContext -) -{ - PIRP Irp = NULL; - PIO_STACK_LOCATION IrpSp; - - PDEVICE_OBJECT DeviceObject; - - PEXT2_VCB Vcb = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PEXT2_MCB Mcb = NULL; - - PUCHAR UserEaList; - ULONG UserEaListLength; - ULONG UserEaIndex; - - BOOLEAN RestartScan; - BOOLEAN ReturnSingleEntry; - BOOLEAN IndexSpecified; - - BOOLEAN MainResourceAcquired = FALSE; - BOOLEAN XattrRefAcquired = FALSE; - - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - struct ext4_xattr_ref xattr_ref; - PCHAR UserBuffer; - - ULONG UserBufferLength = 0; - ULONG RemainingUserBufferLength = 0; - - PFILE_FULL_EA_INFORMATION FullEa, LastFullEa = NULL; - - __try { - - Ccb = IrpContext->Ccb; - ASSERT(Ccb != NULL); - ASSERT((Ccb->Identifier.Type == EXT2CCB) && - (Ccb->Identifier.Size == sizeof(EXT2_CCB))); - DeviceObject = IrpContext->DeviceObject; - Vcb = (PEXT2_VCB)DeviceObject->DeviceExtension; - Fcb = IrpContext->Fcb; - Mcb = Fcb->Mcb; - Irp = IrpContext->Irp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - Irp->IoStatus.Information = 0; - - // - // Receive input parameter from caller - // - UserBuffer = Ext2GetUserBuffer(Irp); - if (!UserBuffer) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - UserBufferLength = IrpSp->Parameters.QueryEa.Length; - RemainingUserBufferLength = UserBufferLength; - UserEaList = IrpSp->Parameters.QueryEa.EaList; - UserEaListLength = IrpSp->Parameters.QueryEa.EaListLength; - UserEaIndex = IrpSp->Parameters.QueryEa.EaIndex; - RestartScan = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN); - ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY); - IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED); - - if (!Mcb) - __leave; - - // - // We do not allow multiple instance gaining EA access to the same file - // - if (!ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { - Status = STATUS_PENDING; - __leave; - } - MainResourceAcquired = TRUE; - - Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); - if (!NT_SUCCESS(Status)) { - DbgPrint("ext4_fs_get_xattr_ref() failed!\n"); - __leave; - } - - FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; - - XattrRefAcquired = TRUE; - - if (RemainingUserBufferLength) - RtlZeroMemory(FullEa, RemainingUserBufferLength); - - if (UserEaList != NULL) { - int i = 0; - PFILE_GET_EA_INFORMATION GetEa; - for (GetEa = (PFILE_GET_EA_INFORMATION)&UserEaList[0]; - GetEa < (PFILE_GET_EA_INFORMATION)((PUCHAR)UserEaList - + UserEaListLength); - GetEa = (GetEa->NextEntryOffset == 0 - ? (PFILE_GET_EA_INFORMATION)MAXUINT_PTR - : (PFILE_GET_EA_INFORMATION)((PUCHAR)GetEa - + GetEa->NextEntryOffset))) { - - size_t ItemSize; - OEM_STRING Str; - ULONG EaEntrySize; - BOOL is_last = !GetEa->NextEntryOffset; - - Str.MaximumLength = Str.Length = GetEa->EaNameLength; - Str.Buffer = &GetEa->EaName[0]; - - // - // At the moment we only need to know whether the item exists - // and its size. - // - Status = Ext2WinntError(ext4_fs_get_xattr(&xattr_ref, - EXT4_XATTR_INDEX_USER, - Str.Buffer, - Str.Length, - NULL, - 0, - &ItemSize)); - if (!NT_SUCCESS(Status)) - continue; - - // - // We were not able to locate the name therefore we must - // dummy up a entry for the query. The needed Ea size is - // the size of the name + 4 (next entry offset) + 1 (flags) - // + 1 (name length) + 2 (value length) + the name length + - // 1 (null byte) + Data Size. - // - EaEntrySize = 4 + 1 + 1 + 2 + GetEa->EaNameLength + 1 + ItemSize; - if (!is_last) - EaEntrySize = ALIGN_UP(EaEntrySize, ULONG); - - if (EaEntrySize > RemainingUserBufferLength) { - - Status = i ? STATUS_BUFFER_OVERFLOW : STATUS_BUFFER_TOO_SMALL; - __leave; - } - FullEa->NextEntryOffset = 0; - FullEa->Flags = 0; - FullEa->EaNameLength = GetEa->EaNameLength; - FullEa->EaValueLength = (USHORT)ItemSize; - RtlCopyMemory(&FullEa->EaName[0], - &GetEa->EaName[0], - GetEa->EaNameLength); - - // - // This query must succeed, or is guarenteed to succeed - // since we are only looking up - // an EA entry in a in-memory tree structure. - // Otherwise that means someone might be operating on - // the xattr_ref without acquiring Inode lock. - // - ASSERT(NT_SUCCESS(Ext2WinntError( - ext4_fs_get_xattr(&xattr_ref, - EXT4_XATTR_INDEX_USER, - Str.Buffer, - Str.Length, - &FullEa->EaName[0] + FullEa->EaNameLength + 1, - ItemSize, - &ItemSize - )))); - FullEa->EaValueLength = (USHORT)ItemSize; - - // Link FullEa and LastFullEa together - if (LastFullEa) - LastFullEa->NextEntryOffset = (ULONG)((PCHAR)FullEa - - (PCHAR)LastFullEa); - - LastFullEa = FullEa; - FullEa = (PFILE_FULL_EA_INFORMATION) - ((PCHAR)FullEa + EaEntrySize); - RemainingUserBufferLength -= EaEntrySize; - i++; - } - } else if (IndexSpecified) { - struct EaIterator EaIterator; - // - // The user supplied an index into the Ea list. - // - if (RemainingUserBufferLength) - RtlZeroMemory(FullEa, RemainingUserBufferLength); - - EaIterator.OverFlow = FALSE; - EaIterator.RemainingUserBufferLength = UserBufferLength; - // In this case, return only an entry. - EaIterator.ReturnSingleEntry = TRUE; - EaIterator.FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; - EaIterator.LastFullEa = NULL; - EaIterator.UserBufferLength = UserBufferLength; - EaIterator.EaIndex = UserEaIndex; - EaIterator.EaIndexCounter = 1; - - xattr_ref.iter_arg = &EaIterator; - ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); - - RemainingUserBufferLength = EaIterator.RemainingUserBufferLength; - - Status = STATUS_SUCCESS; - - // It seems that the item isn't found - if (RemainingUserBufferLength == UserBufferLength) - Status = STATUS_OBJECTID_NOT_FOUND; - - if (EaIterator.OverFlow) { - if (RemainingUserBufferLength == UserBufferLength) - Status = STATUS_BUFFER_TOO_SMALL; - else - Status = STATUS_BUFFER_OVERFLOW; - } - - } else { - struct EaIterator EaIterator; - // - // Else perform a simple scan, taking into account the restart - // flag and the position of the next Ea stored in the Ccb. - // - if (RestartScan) - Ccb->EaIndex = 1; - - if (RemainingUserBufferLength) - RtlZeroMemory(FullEa, RemainingUserBufferLength); - - EaIterator.OverFlow = FALSE; - EaIterator.RemainingUserBufferLength = UserBufferLength; - EaIterator.ReturnSingleEntry = ReturnSingleEntry; - EaIterator.FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; - EaIterator.LastFullEa = NULL; - EaIterator.UserBufferLength = UserBufferLength; - EaIterator.EaIndex = Ccb->EaIndex; - EaIterator.EaIndexCounter = 1; - - xattr_ref.iter_arg = &EaIterator; - ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); - - RemainingUserBufferLength = EaIterator.RemainingUserBufferLength; - - if (Ccb->EaIndex < EaIterator.EaIndexCounter) - Ccb->EaIndex = EaIterator.EaIndexCounter; - - Status = STATUS_SUCCESS; - - if (EaIterator.OverFlow) { - if (RemainingUserBufferLength == UserBufferLength) - Status = STATUS_BUFFER_TOO_SMALL; - else - Status = STATUS_BUFFER_OVERFLOW; - } - - } - } - __finally { - - if (XattrRefAcquired) { - if (!NT_SUCCESS(Status)) { - xattr_ref.dirty = FALSE; - ext4_fs_put_xattr_ref(&xattr_ref); - } - else - Status = Ext2WinntError(ext4_fs_put_xattr_ref(&xattr_ref)); - } - - if (MainResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (NT_SUCCESS(Status)) { - Ext2NotifyReportChange( - IrpContext, - Vcb, - Mcb, - FILE_NOTIFY_CHANGE_EA, - FILE_ACTION_MODIFIED); - Irp->IoStatus.Information = UserBufferLength - RemainingUserBufferLength; - } - - if (!AbnormalTermination()) { - if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { - Status = Ext2QueueRequest(IrpContext); - } - else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} - -BOOLEAN -Ext2IsEaNameValid( - IN OEM_STRING Name -) -{ - ULONG Index; - UCHAR Char; - - // - // Empty names are not valid - // - - if (Name.Length == 0) - return FALSE; - - // - // Do not allow EA name longer than 255 bytes - // - if (Name.Length > 255) - return FALSE; - - for (Index = 0; Index < (ULONG)Name.Length; Index += 1) { - - Char = Name.Buffer[Index]; - - // - // Skip over and Dbcs chacters - // - if (FsRtlIsLeadDbcsCharacter(Char)) { - - ASSERT(Index != (ULONG)(Name.Length - 1)); - Index += 1; - continue; - } - - // - // Make sure this character is legal, and if a wild card, that - // wild cards are permissible. - // - if (!FsRtlIsAnsiCharacterLegalFat(Char, FALSE)) - return FALSE; - - } - - return TRUE; -} - -NTSTATUS -Ext2SetEa ( - IN PEXT2_IRP_CONTEXT IrpContext -) -{ - PIRP Irp = NULL; - PIO_STACK_LOCATION IrpSp; - - PDEVICE_OBJECT DeviceObject; - - PEXT2_VCB Vcb = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PEXT2_MCB Mcb = NULL; - - BOOLEAN MainResourceAcquired = FALSE; - BOOLEAN FcbLockAcquired = FALSE; - BOOLEAN XattrRefAcquired = FALSE; - - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - struct ext4_xattr_ref xattr_ref; - PCHAR UserBuffer; - ULONG UserBufferLength; - - PFILE_FULL_EA_INFORMATION FullEa; - - __try { - - Ccb = IrpContext->Ccb; - ASSERT(Ccb != NULL); - ASSERT((Ccb->Identifier.Type == EXT2CCB) && - (Ccb->Identifier.Size == sizeof(EXT2_CCB))); - DeviceObject = IrpContext->DeviceObject; - Vcb = (PEXT2_VCB)DeviceObject->DeviceExtension; - Fcb = IrpContext->Fcb; - Mcb = Fcb->Mcb; - Irp = IrpContext->Irp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - Irp->IoStatus.Information = 0; - - // - // Receive input parameter from caller - // - UserBufferLength = IrpSp->Parameters.SetEa.Length; - UserBuffer = Irp->UserBuffer; - - // Check if the EA buffer provided is valid - Status = IoCheckEaBufferValidity((PFILE_FULL_EA_INFORMATION)UserBuffer, - UserBufferLength, - (PULONG)&Irp->IoStatus.Information); - if (!NT_SUCCESS(Status)) - __leave; - - ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); - FcbLockAcquired = TRUE; - - if (!Mcb) - __leave; - - // - // We do not allow multiple instance gaining EA access to the same file - // - if (!ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { - Status = STATUS_PENDING; - __leave; - } - MainResourceAcquired = TRUE; - - Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); - if (!NT_SUCCESS(Status)) { - DbgPrint("ext4_fs_get_xattr_ref() failed!\n"); - __leave; - } - - XattrRefAcquired = TRUE; - - // - // Remove all existing EA entries. - // - ext4_xattr_purge_items(&xattr_ref); - xattr_ref.dirty = TRUE; - Status = STATUS_SUCCESS; - - // Iterate the whole EA buffer to do inspection - for (FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; - FullEa < (PFILE_FULL_EA_INFORMATION)&UserBuffer[UserBufferLength]; - FullEa = (PFILE_FULL_EA_INFORMATION)(FullEa->NextEntryOffset == 0 ? - &UserBuffer[UserBufferLength] : - (PCHAR)FullEa + FullEa->NextEntryOffset)) { - - OEM_STRING EaName; - - EaName.MaximumLength = EaName.Length = FullEa->EaNameLength; - EaName.Buffer = &FullEa->EaName[0]; - - // Check if EA's name is valid - if (!Ext2IsEaNameValid(EaName)) { - Irp->IoStatus.Information = (PCHAR)FullEa - UserBuffer; - Status = STATUS_INVALID_EA_NAME; - __leave; - } - } - - // Now add EA entries to the inode - for (FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; - FullEa < (PFILE_FULL_EA_INFORMATION)&UserBuffer[UserBufferLength]; - FullEa = (PFILE_FULL_EA_INFORMATION)(FullEa->NextEntryOffset == 0 ? - &UserBuffer[UserBufferLength] : - (PCHAR)FullEa + FullEa->NextEntryOffset)) { - - int ret; - OEM_STRING EaName; - - EaName.MaximumLength = EaName.Length = FullEa->EaNameLength; - EaName.Buffer = &FullEa->EaName[0]; - - Status = Ext2WinntError(ret = - ext4_fs_set_xattr_ordered(&xattr_ref, - EXT4_XATTR_INDEX_USER, - EaName.Buffer, - EaName.Length, - &FullEa->EaName[0] + FullEa->EaNameLength + 1, - FullEa->EaValueLength)); - if (!NT_SUCCESS(Status)) - __leave; - - } - } __finally { - - if (XattrRefAcquired) { - if (!NT_SUCCESS(Status)) { - xattr_ref.dirty = FALSE; - ext4_fs_put_xattr_ref(&xattr_ref); - } else - Status = Ext2WinntError(ext4_fs_put_xattr_ref(&xattr_ref)); - } - - if (FcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - FcbLockAcquired = FALSE; - } - - if (MainResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (NT_SUCCESS(Status)) { - Ext2NotifyReportChange( - IrpContext, - Vcb, - Mcb, - FILE_NOTIFY_CHANGE_EA, - FILE_ACTION_MODIFIED); - } - - if (!AbnormalTermination()) { - if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { - Status = Ext2QueueRequest(IrpContext); - } - else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - return Status; -} +/* +* COPYRIGHT: See COPYRIGHT.TXT +* PROJECT: Ext2 File System Driver for Windows >= NT +* FILE: ea.c +* PROGRAMMER: Matt Wu Kaho Ng +* HOMEPAGE: http://www.ext2fsd.com +* UPDATE HISTORY: +*/ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" +#include + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, Ext2QueryEa) +#pragma alloc_text(PAGE, Ext2SetEa) +#pragma alloc_text(PAGE, Ext2IsEaNameValid) +#endif + +// Ea iterator +struct EaIterator { + // Return only an entry + BOOLEAN ReturnSingleEntry; + + // Is the buffer overflowing? + BOOL OverFlow; + + // FILE_FULL_EA_INFORMATION output buffer + PFILE_FULL_EA_INFORMATION FullEa; + PFILE_FULL_EA_INFORMATION LastFullEa; + + // UserBuffer's size + ULONG UserBufferLength; + + // Remaining UserBuffer's size + ULONG RemainingUserBufferLength; + + // Start scanning from this EA + ULONG EaIndex; + + // Next EA index returned by Ext2IterateAllEa + ULONG EaIndexCounter; +}; + +static int Ext2IterateAllEa(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item, BOOL is_last) +{ + struct EaIterator *pEaIterator = xattr_ref->iter_arg; + ULONG EaEntrySize = 4 + 1 + 1 + 2 + item->name_len + 1 + item->data_size; + ASSERT(pEaIterator); + if (!is_last && !pEaIterator->ReturnSingleEntry) + EaEntrySize = ALIGN_UP(EaEntrySize, ULONG); + + // Start iteration from index specified + if (pEaIterator->EaIndexCounter < pEaIterator->EaIndex) { + pEaIterator->EaIndexCounter++; + return EXT4_XATTR_ITERATE_CONT; + } + pEaIterator->EaIndexCounter++; + + if (EaEntrySize > pEaIterator->RemainingUserBufferLength) { + pEaIterator->OverFlow = TRUE; + return EXT4_XATTR_ITERATE_STOP; + } + pEaIterator->FullEa->NextEntryOffset = 0; + pEaIterator->FullEa->Flags = 0; + pEaIterator->FullEa->EaNameLength = (UCHAR)item->name_len; + pEaIterator->FullEa->EaValueLength = (USHORT)item->data_size; + RtlCopyMemory(&pEaIterator->FullEa->EaName[0], + item->name, + item->name_len); + RtlCopyMemory(&pEaIterator->FullEa->EaName[0] + item->name_len + 1, + item->data, + item->data_size); + + // Link FullEa and LastFullEa together + if (pEaIterator->LastFullEa) { + pEaIterator->LastFullEa->NextEntryOffset = (ULONG) + ((PCHAR)pEaIterator->FullEa - (PCHAR)pEaIterator->LastFullEa); + } + + pEaIterator->LastFullEa = pEaIterator->FullEa; + pEaIterator->FullEa = (PFILE_FULL_EA_INFORMATION) + ((PCHAR)pEaIterator->FullEa + EaEntrySize); + pEaIterator->RemainingUserBufferLength -= EaEntrySize; + + if (pEaIterator->ReturnSingleEntry) + return EXT4_XATTR_ITERATE_STOP; + + return EXT4_XATTR_ITERATE_CONT; +} + +NTSTATUS +Ext2QueryEa ( + IN PEXT2_IRP_CONTEXT IrpContext +) +{ + PIRP Irp = NULL; + PIO_STACK_LOCATION IrpSp; + + PDEVICE_OBJECT DeviceObject; + + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + + PUCHAR UserEaList; + ULONG UserEaListLength; + ULONG UserEaIndex; + + BOOLEAN RestartScan; + BOOLEAN ReturnSingleEntry; + BOOLEAN IndexSpecified; + + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN XattrRefAcquired = FALSE; + + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + struct ext4_xattr_ref xattr_ref; + PCHAR UserBuffer; + + ULONG UserBufferLength = 0; + ULONG RemainingUserBufferLength = 0; + + PFILE_FULL_EA_INFORMATION FullEa, LastFullEa = NULL; + + __try { + + Ccb = IrpContext->Ccb; + ASSERT(Ccb != NULL); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + DeviceObject = IrpContext->DeviceObject; + Vcb = (PEXT2_VCB)DeviceObject->DeviceExtension; + Fcb = IrpContext->Fcb; + Mcb = Fcb->Mcb; + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Irp->IoStatus.Information = 0; + + // + // Receive input parameter from caller + // + UserBuffer = Ext2GetUserBuffer(Irp); + if (!UserBuffer) { + Status = STATUS_INSUFFICIENT_RESOURCES; + __leave; + } + UserBufferLength = IrpSp->Parameters.QueryEa.Length; + RemainingUserBufferLength = UserBufferLength; + UserEaList = IrpSp->Parameters.QueryEa.EaList; + UserEaListLength = IrpSp->Parameters.QueryEa.EaListLength; + UserEaIndex = IrpSp->Parameters.QueryEa.EaIndex; + RestartScan = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN); + ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY); + IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED); + + if (!Mcb) + __leave; + + // + // We do not allow multiple instance gaining EA access to the same file + // + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { + Status = STATUS_PENDING; + __leave; + } + MainResourceAcquired = TRUE; + + Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); + if (!NT_SUCCESS(Status)) { + DbgPrint("ext4_fs_get_xattr_ref() failed!\n"); + __leave; + } + + FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; + + XattrRefAcquired = TRUE; + + if (RemainingUserBufferLength) + RtlZeroMemory(FullEa, RemainingUserBufferLength); + + if (UserEaList != NULL) { + int i = 0; + PFILE_GET_EA_INFORMATION GetEa; + for (GetEa = (PFILE_GET_EA_INFORMATION)&UserEaList[0]; + GetEa < (PFILE_GET_EA_INFORMATION)((PUCHAR)UserEaList + + UserEaListLength); + GetEa = (GetEa->NextEntryOffset == 0 + ? (PFILE_GET_EA_INFORMATION)MAXUINT_PTR + : (PFILE_GET_EA_INFORMATION)((PUCHAR)GetEa + + GetEa->NextEntryOffset))) { + + size_t ItemSize; + OEM_STRING Str; + ULONG EaEntrySize; + BOOL is_last = !GetEa->NextEntryOffset; + + Str.MaximumLength = Str.Length = GetEa->EaNameLength; + Str.Buffer = &GetEa->EaName[0]; + + // + // At the moment we only need to know whether the item exists + // and its size. + // + Status = Ext2WinntError(ext4_fs_get_xattr(&xattr_ref, + EXT4_XATTR_INDEX_USER, + Str.Buffer, + Str.Length, + NULL, + 0, + &ItemSize)); + if (!NT_SUCCESS(Status)) + continue; + + // + // We were not able to locate the name therefore we must + // dummy up a entry for the query. The needed Ea size is + // the size of the name + 4 (next entry offset) + 1 (flags) + // + 1 (name length) + 2 (value length) + the name length + + // 1 (null byte) + Data Size. + // + EaEntrySize = 4 + 1 + 1 + 2 + GetEa->EaNameLength + 1 + ItemSize; + if (!is_last) + EaEntrySize = ALIGN_UP(EaEntrySize, ULONG); + + if (EaEntrySize > RemainingUserBufferLength) { + + Status = i ? STATUS_BUFFER_OVERFLOW : STATUS_BUFFER_TOO_SMALL; + __leave; + } + FullEa->NextEntryOffset = 0; + FullEa->Flags = 0; + FullEa->EaNameLength = GetEa->EaNameLength; + FullEa->EaValueLength = (USHORT)ItemSize; + RtlCopyMemory(&FullEa->EaName[0], + &GetEa->EaName[0], + GetEa->EaNameLength); + + // + // This query must succeed, or is guarenteed to succeed + // since we are only looking up + // an EA entry in a in-memory tree structure. + // Otherwise that means someone might be operating on + // the xattr_ref without acquiring Inode lock. + // + ASSERT(NT_SUCCESS(Ext2WinntError( + ext4_fs_get_xattr(&xattr_ref, + EXT4_XATTR_INDEX_USER, + Str.Buffer, + Str.Length, + &FullEa->EaName[0] + FullEa->EaNameLength + 1, + ItemSize, + &ItemSize + )))); + FullEa->EaValueLength = (USHORT)ItemSize; + + // Link FullEa and LastFullEa together + if (LastFullEa) + LastFullEa->NextEntryOffset = (ULONG)((PCHAR)FullEa - + (PCHAR)LastFullEa); + + LastFullEa = FullEa; + FullEa = (PFILE_FULL_EA_INFORMATION) + ((PCHAR)FullEa + EaEntrySize); + RemainingUserBufferLength -= EaEntrySize; + i++; + } + } else if (IndexSpecified) { + struct EaIterator EaIterator; + // + // The user supplied an index into the Ea list. + // + if (RemainingUserBufferLength) + RtlZeroMemory(FullEa, RemainingUserBufferLength); + + EaIterator.OverFlow = FALSE; + EaIterator.RemainingUserBufferLength = UserBufferLength; + // In this case, return only an entry. + EaIterator.ReturnSingleEntry = TRUE; + EaIterator.FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; + EaIterator.LastFullEa = NULL; + EaIterator.UserBufferLength = UserBufferLength; + EaIterator.EaIndex = UserEaIndex; + EaIterator.EaIndexCounter = 1; + + xattr_ref.iter_arg = &EaIterator; + ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); + + RemainingUserBufferLength = EaIterator.RemainingUserBufferLength; + + Status = STATUS_SUCCESS; + + // It seems that the item isn't found + if (RemainingUserBufferLength == UserBufferLength) + Status = STATUS_OBJECTID_NOT_FOUND; + + if (EaIterator.OverFlow) { + if (RemainingUserBufferLength == UserBufferLength) + Status = STATUS_BUFFER_TOO_SMALL; + else + Status = STATUS_BUFFER_OVERFLOW; + } + + } else { + struct EaIterator EaIterator; + // + // Else perform a simple scan, taking into account the restart + // flag and the position of the next Ea stored in the Ccb. + // + if (RestartScan) + Ccb->EaIndex = 1; + + if (RemainingUserBufferLength) + RtlZeroMemory(FullEa, RemainingUserBufferLength); + + EaIterator.OverFlow = FALSE; + EaIterator.RemainingUserBufferLength = UserBufferLength; + EaIterator.ReturnSingleEntry = ReturnSingleEntry; + EaIterator.FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; + EaIterator.LastFullEa = NULL; + EaIterator.UserBufferLength = UserBufferLength; + EaIterator.EaIndex = Ccb->EaIndex; + EaIterator.EaIndexCounter = 1; + + xattr_ref.iter_arg = &EaIterator; + ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); + + RemainingUserBufferLength = EaIterator.RemainingUserBufferLength; + + if (Ccb->EaIndex < EaIterator.EaIndexCounter) + Ccb->EaIndex = EaIterator.EaIndexCounter; + + Status = STATUS_SUCCESS; + + if (EaIterator.OverFlow) { + if (RemainingUserBufferLength == UserBufferLength) + Status = STATUS_BUFFER_TOO_SMALL; + else + Status = STATUS_BUFFER_OVERFLOW; + } + + } + } + __finally { + + if (XattrRefAcquired) { + if (!NT_SUCCESS(Status)) { + xattr_ref.dirty = FALSE; + ext4_fs_put_xattr_ref(&xattr_ref); + } + else + Status = Ext2WinntError(ext4_fs_put_xattr_ref(&xattr_ref)); + } + + if (MainResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (NT_SUCCESS(Status)) { + Ext2NotifyReportChange( + IrpContext, + Vcb, + Mcb, + FILE_NOTIFY_CHANGE_EA, + FILE_ACTION_MODIFIED); + Irp->IoStatus.Information = UserBufferLength - RemainingUserBufferLength; + } + + if (!AbnormalTermination()) { + if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { + Status = Ext2QueueRequest(IrpContext); + } + else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} + +BOOLEAN +Ext2IsEaNameValid( + IN OEM_STRING Name +) +{ + ULONG Index; + UCHAR Char; + + // + // Empty names are not valid + // + + if (Name.Length == 0) + return FALSE; + + // + // Do not allow EA name longer than 255 bytes + // + if (Name.Length > 255) + return FALSE; + + for (Index = 0; Index < (ULONG)Name.Length; Index += 1) { + + Char = Name.Buffer[Index]; + + // + // Skip over and Dbcs chacters + // + if (FsRtlIsLeadDbcsCharacter(Char)) { + + ASSERT(Index != (ULONG)(Name.Length - 1)); + Index += 1; + continue; + } + + // + // Make sure this character is legal, and if a wild card, that + // wild cards are permissible. + // + if (!FsRtlIsAnsiCharacterLegalFat(Char, FALSE)) + return FALSE; + + } + + return TRUE; +} + +NTSTATUS +Ext2SetEa ( + IN PEXT2_IRP_CONTEXT IrpContext +) +{ + PIRP Irp = NULL; + PIO_STACK_LOCATION IrpSp; + + PDEVICE_OBJECT DeviceObject; + + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN FcbLockAcquired = FALSE; + BOOLEAN XattrRefAcquired = FALSE; + + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + struct ext4_xattr_ref xattr_ref; + PCHAR UserBuffer; + ULONG UserBufferLength; + + PFILE_FULL_EA_INFORMATION FullEa; + + __try { + + Ccb = IrpContext->Ccb; + ASSERT(Ccb != NULL); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + DeviceObject = IrpContext->DeviceObject; + Vcb = (PEXT2_VCB)DeviceObject->DeviceExtension; + Fcb = IrpContext->Fcb; + Mcb = Fcb->Mcb; + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Irp->IoStatus.Information = 0; + + // + // Receive input parameter from caller + // + UserBufferLength = IrpSp->Parameters.SetEa.Length; + UserBuffer = Irp->UserBuffer; + + // Check if the EA buffer provided is valid + Status = IoCheckEaBufferValidity((PFILE_FULL_EA_INFORMATION)UserBuffer, + UserBufferLength, + (PULONG)&Irp->IoStatus.Information); + if (!NT_SUCCESS(Status)) + __leave; + + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + FcbLockAcquired = TRUE; + + if (!Mcb) + __leave; + + // + // We do not allow multiple instance gaining EA access to the same file + // + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { + Status = STATUS_PENDING; + __leave; + } + MainResourceAcquired = TRUE; + + Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); + if (!NT_SUCCESS(Status)) { + DbgPrint("ext4_fs_get_xattr_ref() failed!\n"); + __leave; + } + + XattrRefAcquired = TRUE; + + // + // Remove all existing EA entries. + // + ext4_xattr_purge_items(&xattr_ref); + xattr_ref.dirty = TRUE; + Status = STATUS_SUCCESS; + + // Iterate the whole EA buffer to do inspection + for (FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; + FullEa < (PFILE_FULL_EA_INFORMATION)&UserBuffer[UserBufferLength]; + FullEa = (PFILE_FULL_EA_INFORMATION)(FullEa->NextEntryOffset == 0 ? + &UserBuffer[UserBufferLength] : + (PCHAR)FullEa + FullEa->NextEntryOffset)) { + + OEM_STRING EaName; + + EaName.MaximumLength = EaName.Length = FullEa->EaNameLength; + EaName.Buffer = &FullEa->EaName[0]; + + // Check if EA's name is valid + if (!Ext2IsEaNameValid(EaName)) { + Irp->IoStatus.Information = (PCHAR)FullEa - UserBuffer; + Status = STATUS_INVALID_EA_NAME; + __leave; + } + } + + // Now add EA entries to the inode + for (FullEa = (PFILE_FULL_EA_INFORMATION)UserBuffer; + FullEa < (PFILE_FULL_EA_INFORMATION)&UserBuffer[UserBufferLength]; + FullEa = (PFILE_FULL_EA_INFORMATION)(FullEa->NextEntryOffset == 0 ? + &UserBuffer[UserBufferLength] : + (PCHAR)FullEa + FullEa->NextEntryOffset)) { + + int ret; + OEM_STRING EaName; + + EaName.MaximumLength = EaName.Length = FullEa->EaNameLength; + EaName.Buffer = &FullEa->EaName[0]; + + Status = Ext2WinntError(ret = + ext4_fs_set_xattr_ordered(&xattr_ref, + EXT4_XATTR_INDEX_USER, + EaName.Buffer, + EaName.Length, + &FullEa->EaName[0] + FullEa->EaNameLength + 1, + FullEa->EaValueLength)); + if (!NT_SUCCESS(Status)) + __leave; + + } + } __finally { + + if (XattrRefAcquired) { + if (!NT_SUCCESS(Status)) { + xattr_ref.dirty = FALSE; + ext4_fs_put_xattr_ref(&xattr_ref); + } else + Status = Ext2WinntError(ext4_fs_put_xattr_ref(&xattr_ref)); + } + + if (FcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + FcbLockAcquired = FALSE; + } + + if (MainResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (NT_SUCCESS(Status)) { + Ext2NotifyReportChange( + IrpContext, + Vcb, + Mcb, + FILE_NOTIFY_CHANGE_EA, + FILE_ACTION_MODIFIED); + } + + if (!AbnormalTermination()) { + if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { + Status = Ext2QueueRequest(IrpContext); + } + else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + return Status; +} diff --git a/Ext4Fsd/except.c b/Ext4Fsd/except.c index 405d606..aba6232 100644 --- a/Ext4Fsd/except.c +++ b/Ext4Fsd/except.c @@ -1,273 +1,273 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: except.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -NTSTATUS -Ext2ExceptionFilter ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXCEPTION_POINTERS ExceptionPointer -) -{ - NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER; - NTSTATUS ExceptionCode; - PEXCEPTION_RECORD ExceptRecord; - - ExceptRecord = ExceptionPointer->ExceptionRecord; - ExceptionCode = ExceptRecord->ExceptionCode; - - DbgPrint("-------------------------------------------------------------\n"); - DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode); - DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord, - ExceptionPointer->ContextRecord); - DbgPrint("-------------------------------------------------------------\n"); - - DbgBreak(); - - // - // Check IrpContext is valid or not - // - - if (IrpContext) { - if ((IrpContext->Identifier.Type != EXT2ICX) || - (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { - DbgBreak(); - IrpContext = NULL; - } else if (IrpContext->DeviceObject) { - PEXT2_VCB Vcb = NULL; - Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; - if (NULL == Vcb) { - Status = EXCEPTION_EXECUTE_HANDLER; - } else { - if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) { - Status = EXCEPTION_EXECUTE_HANDLER; - } - } - } - } else { - if (FsRtlIsNtstatusExpected(ExceptionCode)) { - return EXCEPTION_EXECUTE_HANDLER; - } else { - Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord, - (ULONG_PTR)ExceptionPointer->ContextRecord, - (ULONG_PTR)ExceptRecord->ExceptionAddress ); - } - } - - if (IrpContext) { - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); - } - - if ( Status == EXCEPTION_EXECUTE_HANDLER || - FsRtlIsNtstatusExpected(ExceptionCode)) { - // - // If the exception is expected execute our handler - // - - DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n", - ExceptionCode)); - - Status = EXCEPTION_EXECUTE_HANDLER; - - if (IrpContext) { - IrpContext->ExceptionInProgress = TRUE; - IrpContext->ExceptionCode = ExceptionCode; - } - - } else { - - // - // Continue search for an higher level exception handler - // - - DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n", - ExceptionCode)); - - Status = EXCEPTION_CONTINUE_SEARCH; - - if (IrpContext) { - Ext2FreeIrpContext(IrpContext); - } - } - - return Status; -} - - -NTSTATUS -Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext) -{ - NTSTATUS Status; - - if (IrpContext) { - - if ( (IrpContext->Identifier.Type != EXT2ICX) || - (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { - DbgBreak(); - return STATUS_UNSUCCESSFUL; - } - - Status = IrpContext->ExceptionCode; - - if (IrpContext->Irp) { - - // - // Check if this error is a result of user actions - // - - PEXT2_VCB Vcb = NULL; - PIRP Irp = IrpContext->Irp; - PIO_STACK_LOCATION IrpSp; - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; - - if (NULL == Vcb) { - Status = STATUS_INVALID_PARAMETER; - } else if (Vcb->Identifier.Type != EXT2VCB) { - Status = STATUS_INVALID_PARAMETER; - } else if (!IsMounted(Vcb)) { - if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) { - Status = STATUS_NO_SUCH_DEVICE; - } else { - Status = STATUS_VOLUME_DISMOUNTED; - } - } else { - - /* queue it again if our request is at top level */ - if (IrpContext->IsTopLevel && - ((Status == STATUS_CANT_WAIT) || - ((Status == STATUS_VERIFY_REQUIRED) && - (KeGetCurrentIrql() >= APC_LEVEL)))) { - - Status = Ext2QueueRequest(IrpContext); - } - } - - if (Status == STATUS_PENDING) { - goto errorout; - } - - Irp->IoStatus.Status = Status; - - if (IoIsErrorUserInduced(Status)) { - - // - // Now we will generate a pop-up to user - // - - PDEVICE_OBJECT RealDevice; - PVPB Vpb = NULL; - PETHREAD Thread; - - if (IrpSp->FileObject != NULL) { - Vpb = IrpSp->FileObject->Vpb; - } - - // - // Get the initial thread - // - - Thread = Irp->Tail.Overlay.Thread; - RealDevice = IoGetDeviceToVerify( Thread ); - - if (RealDevice == NULL) { - // - // Get current thread - // - - Thread = PsGetCurrentThread(); - RealDevice = IoGetDeviceToVerify( Thread ); - - ASSERT( RealDevice != NULL ); - } - - Status = IrpContext->ExceptionCode; - - if (RealDevice != NULL) { - - if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) { - - Status = IoVerifyVolume (RealDevice, FALSE); - - ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE); - if (NT_SUCCESS(Status) && (!IsMounted(Vcb) || - IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) { - Status = STATUS_WRONG_VOLUME; - } - ExReleaseResourceLite(&Vcb->MainResource); - - if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) { - Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED); - Status = STATUS_VOLUME_DISMOUNTED; - Irp = NULL; - goto errorout; - } - - if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) && - (IrpContext->FileObject->RelatedFileObject == NULL) && - ((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) { - - Irp->IoStatus.Information = IO_REMOUNT; - - Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE); - Status = STATUS_REPARSE; - Irp = NULL; - } - - if (Irp) { - - if (!NT_SUCCESS(Status)) { - IoSetHardErrorOrVerifyDevice(Irp, RealDevice); - ASSERT (STATUS_VERIFY_REQUIRED != Status); - Ext2NormalizeAndRaiseStatus(IrpContext, Status); - } - - Status = Ext2QueueRequest(IrpContext); - } - - goto errorout; - - } else { - - Status = STATUS_PENDING; - - IoMarkIrpPending( Irp ); - IoRaiseHardError( Irp, Vpb, RealDevice ); - IoSetDeviceToVerify( Thread, NULL ); - goto release_context; - } - } - } - - Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT); - } - -release_context: - - Ext2FreeIrpContext(IrpContext); - - } else { - - Status = STATUS_INVALID_PARAMETER; - } - -errorout: - - return Status; -} - +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: except.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +NTSTATUS +Ext2ExceptionFilter ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXCEPTION_POINTERS ExceptionPointer +) +{ + NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER; + NTSTATUS ExceptionCode; + PEXCEPTION_RECORD ExceptRecord; + + ExceptRecord = ExceptionPointer->ExceptionRecord; + ExceptionCode = ExceptRecord->ExceptionCode; + + DbgPrint("-------------------------------------------------------------\n"); + DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode); + DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord, + ExceptionPointer->ContextRecord); + DbgPrint("-------------------------------------------------------------\n"); + + DbgBreak(); + + // + // Check IrpContext is valid or not + // + + if (IrpContext) { + if ((IrpContext->Identifier.Type != EXT2ICX) || + (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { + DbgBreak(); + IrpContext = NULL; + } else if (IrpContext->DeviceObject) { + PEXT2_VCB Vcb = NULL; + Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; + if (NULL == Vcb) { + Status = EXCEPTION_EXECUTE_HANDLER; + } else { + if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) { + Status = EXCEPTION_EXECUTE_HANDLER; + } + } + } + } else { + if (FsRtlIsNtstatusExpected(ExceptionCode)) { + return EXCEPTION_EXECUTE_HANDLER; + } else { + Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord, + (ULONG_PTR)ExceptionPointer->ContextRecord, + (ULONG_PTR)ExceptRecord->ExceptionAddress ); + } + } + + if (IrpContext) { + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + } + + if ( Status == EXCEPTION_EXECUTE_HANDLER || + FsRtlIsNtstatusExpected(ExceptionCode)) { + // + // If the exception is expected execute our handler + // + + DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n", + ExceptionCode)); + + Status = EXCEPTION_EXECUTE_HANDLER; + + if (IrpContext) { + IrpContext->ExceptionInProgress = TRUE; + IrpContext->ExceptionCode = ExceptionCode; + } + + } else { + + // + // Continue search for an higher level exception handler + // + + DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n", + ExceptionCode)); + + Status = EXCEPTION_CONTINUE_SEARCH; + + if (IrpContext) { + Ext2FreeIrpContext(IrpContext); + } + } + + return Status; +} + + +NTSTATUS +Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + if (IrpContext) { + + if ( (IrpContext->Identifier.Type != EXT2ICX) || + (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { + DbgBreak(); + return STATUS_UNSUCCESSFUL; + } + + Status = IrpContext->ExceptionCode; + + if (IrpContext->Irp) { + + // + // Check if this error is a result of user actions + // + + PEXT2_VCB Vcb = NULL; + PIRP Irp = IrpContext->Irp; + PIO_STACK_LOCATION IrpSp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; + + if (NULL == Vcb) { + Status = STATUS_INVALID_PARAMETER; + } else if (Vcb->Identifier.Type != EXT2VCB) { + Status = STATUS_INVALID_PARAMETER; + } else if (!IsMounted(Vcb)) { + if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) { + Status = STATUS_NO_SUCH_DEVICE; + } else { + Status = STATUS_VOLUME_DISMOUNTED; + } + } else { + + /* queue it again if our request is at top level */ + if (IrpContext->IsTopLevel && + ((Status == STATUS_CANT_WAIT) || + ((Status == STATUS_VERIFY_REQUIRED) && + (KeGetCurrentIrql() >= APC_LEVEL)))) { + + Status = Ext2QueueRequest(IrpContext); + } + } + + if (Status == STATUS_PENDING) { + goto errorout; + } + + Irp->IoStatus.Status = Status; + + if (IoIsErrorUserInduced(Status)) { + + // + // Now we will generate a pop-up to user + // + + PDEVICE_OBJECT RealDevice; + PVPB Vpb = NULL; + PETHREAD Thread; + + if (IrpSp->FileObject != NULL) { + Vpb = IrpSp->FileObject->Vpb; + } + + // + // Get the initial thread + // + + Thread = Irp->Tail.Overlay.Thread; + RealDevice = IoGetDeviceToVerify( Thread ); + + if (RealDevice == NULL) { + // + // Get current thread + // + + Thread = PsGetCurrentThread(); + RealDevice = IoGetDeviceToVerify( Thread ); + + ASSERT( RealDevice != NULL ); + } + + Status = IrpContext->ExceptionCode; + + if (RealDevice != NULL) { + + if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) { + + Status = IoVerifyVolume (RealDevice, FALSE); + + ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE); + if (NT_SUCCESS(Status) && (!IsMounted(Vcb) || + IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) { + Status = STATUS_WRONG_VOLUME; + } + ExReleaseResourceLite(&Vcb->MainResource); + + if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) { + Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED); + Status = STATUS_VOLUME_DISMOUNTED; + Irp = NULL; + goto errorout; + } + + if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) && + (IrpContext->FileObject->RelatedFileObject == NULL) && + ((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) { + + Irp->IoStatus.Information = IO_REMOUNT; + + Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE); + Status = STATUS_REPARSE; + Irp = NULL; + } + + if (Irp) { + + if (!NT_SUCCESS(Status)) { + IoSetHardErrorOrVerifyDevice(Irp, RealDevice); + ASSERT (STATUS_VERIFY_REQUIRED != Status); + Ext2NormalizeAndRaiseStatus(IrpContext, Status); + } + + Status = Ext2QueueRequest(IrpContext); + } + + goto errorout; + + } else { + + Status = STATUS_PENDING; + + IoMarkIrpPending( Irp ); + IoRaiseHardError( Irp, Vpb, RealDevice ); + IoSetDeviceToVerify( Thread, NULL ); + goto release_context; + } + } + } + + Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT); + } + +release_context: + + Ext2FreeIrpContext(IrpContext); + + } else { + + Status = STATUS_INVALID_PARAMETER; + } + +errorout: + + return Status; +} + diff --git a/Ext4Fsd/ext3/indirect.c b/Ext4Fsd/ext3/indirect.c index e4d7f02..6918537 100644 --- a/Ext4Fsd/ext3/indirect.c +++ b/Ext4Fsd/ext3/indirect.c @@ -1,1159 +1,1159 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: indirect.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS *****************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -#ifdef ALLOC_PRAGMA -#endif - - -NTSTATUS -Ext2ExpandLast( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Base, - IN ULONG Layer, - IN PULONG * Data, - IN PULONG Hint, - IN PULONG Block, - IN OUT PULONG Number -) -{ - PULONG pData = NULL; - ULONG i; - NTSTATUS Status = STATUS_SUCCESS; - - if (Layer > 0 || IsMcbDirectory(Mcb)) { - - /* allocate buffer for new block */ - pData = (ULONG *) Ext2AllocatePool( - PagedPool, - BLOCK_SIZE, - EXT2_DATA_MAGIC - ); - if (!pData) { - DEBUG(DL_ERR, ( "Ex2ExpandBlock: failed to allocate memory for Data.\n")); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; - } - RtlZeroMemory(pData, BLOCK_SIZE); - INC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); - } - - /* allocate block from disk */ - Status = Ext2NewBlock( - IrpContext, - Vcb, - (Mcb->Inode.i_ino - 1) / BLOCKS_PER_GROUP, - *Hint, - Block, - Number - ); - - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - /* increase inode i_blocks */ - Mcb->Inode.i_blocks += (*Number << (BLOCK_BITS - 9)); - - if (Layer == 0) { - - if (IsMcbDirectory(Mcb)) { - /* for directory we need initialize it's entry structure */ - PEXT2_DIR_ENTRY2 pEntry; - pEntry = (PEXT2_DIR_ENTRY2) pData; - pEntry->rec_len = (USHORT)(BLOCK_SIZE); - ASSERT(*Number == 1); - Ext2SaveBlock(IrpContext, Vcb, *Block, (PVOID)pData); - } - - /* add new Extent into Mcb */ - if (!Ext2AddBlockExtent(Vcb, Mcb, Base, (*Block), *Number)) { - DbgBreak(); - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - Ext2ClearAllExtents(&Mcb->Extents); - } - - } else { - - /* zero the content of all meta blocks */ - for (i = 0; i < *Number; i++) { - Ext2SaveBlock(IrpContext, Vcb, *Block + i, (PVOID)pData); - /* add block to meta extents */ - if (!Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1)) { - DbgBreak(); - Ext2Sleep(500); - Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1); - } - } - } - -errorout: - - if (NT_SUCCESS(Status)) { - *Hint = *Block + *Number; - if (Data) { - *Data = pData; - ASSERT(*Number == 1); - } else { - if (pData) { - Ext2FreePool(pData, EXT2_DATA_MAGIC); - DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); - } - } - } else { - if (pData) { - Ext2FreePool(pData, EXT2_DATA_MAGIC); - DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); - } - if (*Block) { - Ext2FreeBlock(IrpContext, Vcb, *Block, *Number); - Mcb->Inode.i_blocks -= (*Number << (BLOCK_BITS - 9)); - *Block = 0; - } - } - - return Status; -} - -NTSTATUS -Ext2GetBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Base, - IN ULONG Layer, - IN ULONG Start, - IN ULONG SizeArray, - IN PULONG BlockArray, - IN BOOLEAN bAlloc, - IN OUT PULONG Hint, - OUT PULONG Block, - OUT PULONG Number -) -{ - NTSTATUS Status = STATUS_SUCCESS; - PBCB Bcb = NULL; - PULONG pData = NULL; - ULONG Slot = 0, i = 0; - ULONG Unit = 1; - - LARGE_INTEGER Offset; - - if (Layer == 0) { - - *Number = 1; - if (BlockArray[0] == 0 && bAlloc) { - - /* now allocate new block */ - Status = Ext2ExpandLast( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - NULL, - Hint, - &BlockArray[0], - Number - ); - - if (!NT_SUCCESS(Status)) { - goto errorout; - } - } else { - /* check the block is valid or not */ - if (BlockArray[0] >= TOTAL_BLOCKS) { - DbgBreak(); - Status = STATUS_DISK_CORRUPT_ERROR; - goto errorout; - } - } - - *Block = BlockArray[0]; - for (i=1; i < SizeArray; i++) { - if (BlockArray[i] == BlockArray[i-1] + 1) { - *Number = *Number + 1; - } else { - break; - } - } - *Hint = BlockArray[*Number - 1]; - - } else if (Layer <= 3) { - - /* check the block is valid or not */ - if (BlockArray[0] == 0 || BlockArray[0] >= TOTAL_BLOCKS) { - DbgBreak(); - Status = STATUS_DISK_CORRUPT_ERROR; - goto errorout; - } - - /* add block to meta extents */ - if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[0], 1)) { - DbgBreak(); - Ext2Sleep(500); - Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[0], 1); - } - - /* map memory in cache for the index block */ - Offset.QuadPart = ((LONGLONG)BlockArray[0]) << BLOCK_BITS; - if ( !CcPinRead( Vcb->Volume, - (PLARGE_INTEGER) (&Offset), - BLOCK_SIZE, - PIN_WAIT, - &Bcb, - &pData )) { - - DEBUG(DL_ERR, ( "Ext2GetBlock: Failed to PinLock block: %xh ...\n", - BlockArray[0] )); - Status = STATUS_CANT_WAIT; - goto errorout; - } - - if (Layer > 1) { - Unit = Vcb->max_blocks_per_layer[Layer - 1]; - } else { - Unit = 1; - } - - Slot = Start / Unit; - Start = Start % Unit; - - if (pData[Slot] == 0) { - - if (bAlloc) { - - /* we need allocate new block and zero all data in case - it's an in-direct block. Index stores the new block no. */ - ULONG Count = 1; - Status = Ext2ExpandLast( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - NULL, - Hint, - &pData[Slot], - &Count - ); - - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - /* refresh hint block */ - *Hint = pData[Slot]; - - /* set dirty bit to notify system to flush */ - CcSetDirtyPinnedData(Bcb, NULL ); - SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED); - if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart, - (LONGLONG)BLOCK_SIZE)) { - DbgBreak(); - Ext2Sleep(100); - if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart, - (LONGLONG)BLOCK_SIZE)) { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; - } - } - - /* save inode information here */ - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - - } else { - - *Number = 1; - - if (Layer == 1) { - for (i = Slot + 1; i < BLOCK_SIZE/4; i++) { - if (pData[i] == 0) { - *Number = *Number + 1; - } else { - break; - } - } - } else if (Layer == 2) { - *Number = BLOCK_SIZE/4 - Start; - } else { - *Number = BLOCK_SIZE/4; - } - - goto errorout; - } - } - - /* transfer to next recursion call */ - Status = Ext2GetBlock( - IrpContext, - Vcb, - Mcb, - Base, - Layer - 1, - Start, - BLOCK_SIZE/4 - Slot, - &pData[Slot], - bAlloc, - Hint, - Block, - Number - ); - - if (!NT_SUCCESS(Status)) { - goto errorout; - } - } - -errorout: - - /* free the memory of pData */ - if (Bcb) { - CcUnpinData(Bcb); - } - - if (!NT_SUCCESS(Status)) { - *Block = 0; - } - - return Status; -} - - -NTSTATUS -Ext2ExpandBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Base, - IN ULONG Layer, - IN ULONG Start, - IN ULONG SizeArray, - IN PULONG BlockArray, - IN PULONG Hint, - IN PULONG Extra -) -{ - ULONG i = 0; - ULONG j; - ULONG Slot; - ULONG Block = 0; - LARGE_INTEGER Offset; - - PBCB Bcb = NULL; - PULONG pData = NULL; - ULONG Skip = 0; - - ULONG Number; - ULONG Wanted; - - NTSTATUS Status = STATUS_SUCCESS; - - if (Layer == 1) { - - /* - * try to make all leaf block continuous to avoid fragments - */ - - Number = min(SizeArray, ((*Extra + (Start & (BLOCK_SIZE/4 - 1))) * 4 / BLOCK_SIZE)); - Wanted = 0; - DEBUG(DL_BLK, ("Ext2ExpandBlock: SizeArray=%xh Extra=%xh Start=%xh %xh\n", - SizeArray, *Extra, Start, Number )); - - for (i=0; i < Number; i++) { - if (BlockArray[i] == 0) { - Wanted += 1; - } - } - - i = 0; - while (Wanted > 0) { - - Number = Wanted; - Status = Ext2ExpandLast( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - NULL, - Hint, - &Block, - &Number - ); - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - ASSERT(Number > 0); - Wanted -= Number; - while (Number) { - if (BlockArray[i] == 0) { - BlockArray[i] = Block++; - Number--; - } - i++; - } - } - - } else if (Layer == 0) { - - /* - * bulk allocation for inode data blocks - */ - - i = 0; - - while (*Extra && i < SizeArray) { - - Wanted = 0; - Number = 1; - - for (j = i; j < SizeArray && j < i + *Extra; j++) { - - if (BlockArray[j] >= TOTAL_BLOCKS) { - DbgBreak(); - BlockArray[j] = 0; - } - - if (BlockArray[j] == 0) { - Wanted += 1; - } else { - break; - } - } - - if (Wanted == 0) { - - /* add block extent into Mcb */ - ASSERT(BlockArray[i] != 0); - if (!Ext2AddBlockExtent(Vcb, Mcb, Base + i, BlockArray[i], 1)) { - DbgBreak(); - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - Ext2ClearAllExtents(&Mcb->Extents); - } - - } else { - - Number = Wanted; - Status = Ext2ExpandLast( - IrpContext, - Vcb, - Mcb, - Base + i, - 0, - NULL, - Hint, - &Block, - &Number - ); - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - ASSERT(Number > 0); - for (j = 0; j < Number; j++) { - BlockArray[i + j] = Block++; - } - } - - *Extra -= Number; - i += Number; - } - - goto errorout; - } - - - /* - * only for meta blocks allocation - */ - - for (i = 0; *Extra && i < SizeArray; i++) { - - if (Layer <= 3) { - - if (BlockArray[i] >= TOTAL_BLOCKS) { - DbgBreak(); - BlockArray[i] = 0; - } - - if (BlockArray[i] == 0) { - Number = 1; - Status = Ext2ExpandLast( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - &pData, - Hint, - &BlockArray[i], - &Number - ); - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - } else { - - Offset.QuadPart = (((LONGLONG)BlockArray[i]) << BLOCK_BITS); - if (!CcPinRead( - Vcb->Volume, - &Offset, - BLOCK_SIZE, - PIN_WAIT, - &Bcb, - &pData )) { - - DEBUG(DL_ERR, ( "Ext2ExpandInode: failed to PinLock offset :%I64xh...\n", - Offset.QuadPart)); - Status = STATUS_CANT_WAIT; - DbgBreak(); - goto errorout; - } - - /* add block to meta extents */ - if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1)) { - DbgBreak(); - Ext2Sleep(500); - Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1); - } - } - - Skip = Vcb->max_blocks_per_layer[Layer] * i; - - if (i == 0) { - if (Layer > 1) { - Slot = Start / Vcb->max_blocks_per_layer[Layer - 1]; - Start = Start % Vcb->max_blocks_per_layer[Layer - 1]; - Skip += Slot * Vcb->max_blocks_per_layer[Layer - 1]; - } else { - Slot = Start; - Start = 0; - Skip += Slot; - } - } else { - Start = 0; - Slot = 0; - } - - Status = Ext2ExpandBlock( - IrpContext, - Vcb, - Mcb, - Base + Skip, - Layer - 1, - Start, - BLOCK_SIZE/4 - Slot, - &pData[Slot], - Hint, - Extra - ); - - if (Bcb) { - CcSetDirtyPinnedData(Bcb, NULL); - if (!Ext2AddBlockExtent(Vcb, NULL, - BlockArray[i], - BlockArray[i], 1)) { - DbgBreak(); - Ext2Sleep(500); - if (!Ext2AddBlockExtent(Vcb, NULL, - BlockArray[i], - BlockArray[i], 1)) { - } - } - } else { - Ext2SaveBlock(IrpContext, Vcb, BlockArray[i], (PVOID)pData); - } - - if (pData) { - if (Bcb) { - CcUnpinData(Bcb); - Bcb = NULL; - } else { - Ext2FreePool(pData, EXT2_DATA_MAGIC); - DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); - } - pData = NULL; - } - - if (!NT_SUCCESS(Status)) { - DbgBreak(); - break; - } - } - } - -errorout: - - return Status; -} - -BOOLEAN -Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray) -{ - ULONG i = 0; - for (i=0; i < SizeArray; i++) { - if (BlockArray[i]) { - break; - } - } - return (i == SizeArray); -} - - -NTSTATUS -Ext2TruncateBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Base, - IN ULONG Start, - IN ULONG Layer, - IN ULONG SizeArray, - IN PULONG BlockArray, - IN PULONG Extra -) -{ - NTSTATUS Status = STATUS_SUCCESS; - ULONG i = 0; - ULONG Slot = 0; - ULONG Skip = 0; - - LONGLONG Offset; - PBCB Bcb = NULL; - PULONG pData = NULL; - - ASSERT(Mcb != NULL); - - for (i = 0; i < SizeArray; i++) { - - if (Layer == 0) { - - ULONG Number = 1; - - while (Extra && SizeArray > i + 1 && Number < *Extra) { - - if (BlockArray[SizeArray - i - 1] == - BlockArray[SizeArray - i - 2] + 1) { - - BlockArray[SizeArray - i - 1] = 0; - Number++; - SizeArray--; - - } else { - break; - } - } - - if (BlockArray[SizeArray - i - 1]) { - - Status = Ext2FreeBlock(IrpContext, Vcb, BlockArray[SizeArray - i - 1], Number); - if (NT_SUCCESS(Status)) { - ASSERT(Mcb->Inode.i_blocks >= (Number << (BLOCK_BITS - 9))); - if (Mcb->Inode.i_blocks < (Number << (BLOCK_BITS - 9))) { - Mcb->Inode.i_blocks = 0; - DbgBreak(); - } else { - Mcb->Inode.i_blocks -= (Number << (BLOCK_BITS - 9)); - } - BlockArray[SizeArray - i - 1] = 0; - } - } - - if (Extra) { - - /* dec blocks count */ - ASSERT(*Extra >= Number); - *Extra = *Extra - Number; - - /* remove block mapping frm Mcb Extents */ - if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + SizeArray - 1 - i, Number)) { - DbgBreak(); - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - Ext2ClearAllExtents(&Mcb->Extents); - } - } - - } else { - - ASSERT(Layer <= 3); - - if (BlockArray[SizeArray - i - 1] >= TOTAL_BLOCKS) { - DbgBreak(); - BlockArray[SizeArray - i - 1] = 0; - } - - if (i == 0) { - if (Layer > 1) { - Slot = Start / Vcb->max_blocks_per_layer[Layer - 1]; - Start = Start % Vcb->max_blocks_per_layer[Layer - 1]; - } else { - Slot = Start; - Start = (BLOCK_SIZE / 4) - 1; - } - } else { - Slot = Start = (BLOCK_SIZE / 4) - 1; - } - - Skip = (SizeArray - i - 1) * Vcb->max_blocks_per_layer[Layer]; - - if (BlockArray[SizeArray - i - 1]) { - - Offset = (LONGLONG) (BlockArray[SizeArray - i - 1]); - Offset = Offset << BLOCK_BITS; - - if (!CcPinRead( Vcb->Volume, - (PLARGE_INTEGER) (&Offset), - BLOCK_SIZE, - PIN_WAIT, - &Bcb, - &pData )) { - - DEBUG(DL_ERR, ( "Ext2TruncateBlock: PinLock failed on block %xh ...\n", - BlockArray[SizeArray - i - 1])); - Status = STATUS_CANT_WAIT; - DbgBreak(); - goto errorout; - } - - Status = Ext2TruncateBlock( - IrpContext, - Vcb, - Mcb, - Base + Skip, - Start, - Layer - 1, - Slot + 1, - &pData[0], - Extra - ); - - if (!NT_SUCCESS(Status)) { - break; - } - - CcSetDirtyPinnedData(Bcb, NULL); - Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)BLOCK_SIZE); - - if (*Extra || Ext2IsBlockEmpty(pData, BLOCK_SIZE/4)) { - - Ext2TruncateBlock( - IrpContext, - Vcb, - Mcb, - Base + Skip, /* base */ - 0, /* start */ - 0, /* layer */ - 1, - &BlockArray[SizeArray - i - 1], - NULL - ); - - if (!Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1)) { - DbgBreak(); - Ext2Sleep(500); - Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1); - } - } - - if (pData) { - CcUnpinData(Bcb); - Bcb = NULL; - pData = NULL; - } - - } else { - - if (Layer > 1) { - if (*Extra > Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1) { - *Extra -= (Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1); - } else { - *Extra = 0; - } - } else { - if (*Extra > Slot + 1) { - *Extra -= (Slot + 1); - } else { - *Extra = 0; - } - } - - if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + Skip, (Start + 1))) { - DbgBreak(); - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - Ext2ClearAllExtents(&Mcb->Extents); - } - } - } - - if (Extra && *Extra == 0) { - break; - } - } - -errorout: - - if (pData) { - CcUnpinData(Bcb); - } - - return Status; -} - -NTSTATUS -Ext2MapIndirect( - 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 -) -{ - ULONG Layer; - ULONG Slot; - - ULONG Base = Index; - - NTSTATUS Status = STATUS_SUCCESS; - - *pBlock = 0; - *Number = 0; - - for (Layer = 0; Layer < EXT2_BLOCK_TYPES; Layer++) { - - if (Index < Vcb->max_blocks_per_layer[Layer]) { - - ULONG dwRet = 0, dwBlk = 0, dwHint = 0, dwArray = 0; - - Slot = (Layer==0) ? (Index):(Layer + EXT2_NDIR_BLOCKS - 1); - dwBlk = Mcb->Inode.i_block[Slot]; - - if (dwBlk == 0) { - - if (!bAlloc) { - - *Number = 1; - goto errorout; - - } else { - - if (Slot) { - dwHint = Mcb->Inode.i_block[Slot - 1]; - } - - /* allocate and zero block if necessary */ - *Number = 1; - Status = Ext2ExpandLast( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - NULL, - &dwHint, - &dwBlk, - Number - ); - - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - /* save the it into inode*/ - Mcb->Inode.i_block[Slot] = dwBlk; - - /* save the inode */ - if (!Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode)) { - DbgBreak(); - Status = STATUS_UNSUCCESSFUL; - goto errorout; - } - } - } - - if (Layer == 0) - dwArray = Vcb->max_blocks_per_layer[Layer] - Index; - else - dwArray = 1; - - /* querying block number of the index-th file block */ - Status = Ext2GetBlock( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - Index, - dwArray, - &Mcb->Inode.i_block[Slot], - bAlloc, - &dwHint, - &dwRet, - Number - ); - - if (NT_SUCCESS(Status)) { - *pBlock = dwRet; - } - - break; - } - - Index -= Vcb->max_blocks_per_layer[Layer]; - } - -errorout: - - return Status; -} - -NTSTATUS -Ext2ExpandIndirect( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - ULONG Start, - ULONG End, - PLARGE_INTEGER Size -) -{ - NTSTATUS Status = STATUS_SUCCESS; - - ULONG Layer = 0; - ULONG Extra = 0; - ULONG Hint = 0; - ULONG Slot = 0; - ULONG Base = 0; - - Extra = End - Start; - - /* exceeds the biggest file size (indirect) */ - if (End > Vcb->max_data_blocks) { - return STATUS_INVALID_PARAMETER; - } - - for (Layer = 0; Layer < EXT2_BLOCK_TYPES && Extra; Layer++) { - - if (Start >= Vcb->max_blocks_per_layer[Layer]) { - - Base += Vcb->max_blocks_per_layer[Layer]; - Start -= Vcb->max_blocks_per_layer[Layer]; - - } else { - - /* get the slot in i_block array */ - if (Layer == 0) { - Base = Slot = Start; - } else { - Slot = Layer + EXT2_NDIR_BLOCKS - 1; - } - - /* set block hint to avoid fragments */ - if (Hint == 0) { - if (Mcb->Inode.i_block[Slot] != 0) { - Hint = Mcb->Inode.i_block[Slot]; - } else if (Slot > 1) { - Hint = Mcb->Inode.i_block[Slot-1]; - } - } - - /* now expand this slot */ - Status = Ext2ExpandBlock( - IrpContext, - Vcb, - Mcb, - Base, - Layer, - Start, - (Layer == 0) ? (Vcb->max_blocks_per_layer[Layer] - Start) : 1, - &Mcb->Inode.i_block[Slot], - &Hint, - &Extra - ); - if (!NT_SUCCESS(Status)) { - break; - } - - Start = 0; - if (Layer == 0) { - Base = 0; - } - Base += Vcb->max_blocks_per_layer[Layer]; - } - } - - Size->QuadPart = ((LONGLONG)(End - Extra)) << BLOCK_BITS; - - /* save inode whatever it succeeds to expand or not */ - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - - return Status; -} - -NTSTATUS -Ext2TruncateIndirectFast( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb - ) -{ - LONGLONG Vba; - LONGLONG Lba; - LONGLONG Length; - NTSTATUS Status = STATUS_SUCCESS; - int i; - - /* try to load all indirect blocks if mcb zone is not initialized */ - if (!IsZoneInited(Mcb)) { - Status = Ext2InitializeZone(IrpContext, Vcb, Mcb); - if (!NT_SUCCESS(Status)) { - DbgBreak(); - ClearLongFlag(Mcb->Flags, MCB_ZONE_INITED); - goto errorout; - } - } - - ASSERT (IsZoneInited(Mcb)); - - /* delete all data blocks here */ - if (FsRtlNumberOfRunsInLargeMcb(&Mcb->Extents) != 0) { - for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->Extents, i, &Vba, &Lba, &Length); i++) { - /* ignore the non-existing runs */ - if (-1 == Lba || Vba == 0 || Length <= 0) - continue; - /* now do data block free */ - Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length); - } - } - - /* delete all meta blocks here */ - if (FsRtlNumberOfRunsInLargeMcb(&Mcb->MetaExts) != 0) { - for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->MetaExts, i, &Vba, &Lba, &Length); i++) { - /* ignore the non-existing runs */ - if (-1 == Lba || Vba == 0 || Length <= 0) - continue; - /* now do meta block free */ - Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length); - } - } - - /* clear data and meta extents */ - Ext2ClearAllExtents(&Mcb->Extents); - Ext2ClearAllExtents(&Mcb->MetaExts); - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - - /* clear inode blocks & sizes */ - Mcb->Inode.i_blocks = 0; - Mcb->Inode.i_size = 0; - memset(&Mcb->Inode.i_block[0], 0, sizeof(__u32) * 15); - - /* the caller will do inode save */ - -errorout: - - return Status; -} - -NTSTATUS -Ext2TruncateIndirect( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - PLARGE_INTEGER Size -) -{ - NTSTATUS Status = STATUS_SUCCESS; - - ULONG Layer = 0; - - ULONG Extra = 0; - ULONG Wanted = 0; - ULONG End; - ULONG Base; - - ULONG SizeArray = 0; - PULONG BlockArray = NULL; - - /* translate file size to block */ - End = Base = Vcb->max_data_blocks; - Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); - - /* do fast deletion here */ - if (Wanted == 0) { - Status = Ext2TruncateIndirectFast(IrpContext, Vcb, Mcb); - if (NT_SUCCESS(Status)) - goto errorout; - } - - /* calculate blocks to be freed */ - Extra = End - Wanted; - - for (Layer = EXT2_BLOCK_TYPES; Layer > 0 && Extra; Layer--) { - - if (Vcb->max_blocks_per_layer[Layer - 1] == 0) { - continue; - } - - Base -= Vcb->max_blocks_per_layer[Layer - 1]; - - if (Layer - 1 == 0) { - BlockArray = &Mcb->Inode.i_block[0]; - SizeArray = End; - ASSERT(End == EXT2_NDIR_BLOCKS && Base == 0); - } else { - BlockArray = &Mcb->Inode.i_block[EXT2_NDIR_BLOCKS - 1 + Layer - 1]; - SizeArray = 1; - } - - Status = Ext2TruncateBlock( - IrpContext, - Vcb, - Mcb, - Base, - End - Base - 1, - Layer - 1, - SizeArray, - BlockArray, - &Extra - ); - if (!NT_SUCCESS(Status)) { - break; - } - - End = Base; - } - -errorout: - - if (!NT_SUCCESS(Status)) { - Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS); - } - - /* save inode */ - if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart)) - Mcb->Inode.i_size = (loff_t)(Size->QuadPart); - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: indirect.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS *****************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +#ifdef ALLOC_PRAGMA +#endif + + +NTSTATUS +Ext2ExpandLast( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Base, + IN ULONG Layer, + IN PULONG * Data, + IN PULONG Hint, + IN PULONG Block, + IN OUT PULONG Number +) +{ + PULONG pData = NULL; + ULONG i; + NTSTATUS Status = STATUS_SUCCESS; + + if (Layer > 0 || IsMcbDirectory(Mcb)) { + + /* allocate buffer for new block */ + pData = (ULONG *) Ext2AllocatePool( + PagedPool, + BLOCK_SIZE, + EXT2_DATA_MAGIC + ); + if (!pData) { + DEBUG(DL_ERR, ( "Ex2ExpandBlock: failed to allocate memory for Data.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + RtlZeroMemory(pData, BLOCK_SIZE); + INC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); + } + + /* allocate block from disk */ + Status = Ext2NewBlock( + IrpContext, + Vcb, + (Mcb->Inode.i_ino - 1) / BLOCKS_PER_GROUP, + *Hint, + Block, + Number + ); + + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + /* increase inode i_blocks */ + Mcb->Inode.i_blocks += (*Number << (BLOCK_BITS - 9)); + + if (Layer == 0) { + + if (IsMcbDirectory(Mcb)) { + /* for directory we need initialize it's entry structure */ + PEXT2_DIR_ENTRY2 pEntry; + pEntry = (PEXT2_DIR_ENTRY2) pData; + pEntry->rec_len = (USHORT)(BLOCK_SIZE); + ASSERT(*Number == 1); + Ext2SaveBlock(IrpContext, Vcb, *Block, (PVOID)pData); + } + + /* add new Extent into Mcb */ + if (!Ext2AddBlockExtent(Vcb, Mcb, Base, (*Block), *Number)) { + DbgBreak(); + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + Ext2ClearAllExtents(&Mcb->Extents); + } + + } else { + + /* zero the content of all meta blocks */ + for (i = 0; i < *Number; i++) { + Ext2SaveBlock(IrpContext, Vcb, *Block + i, (PVOID)pData); + /* add block to meta extents */ + if (!Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1)) { + DbgBreak(); + Ext2Sleep(500); + Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1); + } + } + } + +errorout: + + if (NT_SUCCESS(Status)) { + *Hint = *Block + *Number; + if (Data) { + *Data = pData; + ASSERT(*Number == 1); + } else { + if (pData) { + Ext2FreePool(pData, EXT2_DATA_MAGIC); + DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); + } + } + } else { + if (pData) { + Ext2FreePool(pData, EXT2_DATA_MAGIC); + DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); + } + if (*Block) { + Ext2FreeBlock(IrpContext, Vcb, *Block, *Number); + Mcb->Inode.i_blocks -= (*Number << (BLOCK_BITS - 9)); + *Block = 0; + } + } + + return Status; +} + +NTSTATUS +Ext2GetBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Base, + IN ULONG Layer, + IN ULONG Start, + IN ULONG SizeArray, + IN PULONG BlockArray, + IN BOOLEAN bAlloc, + IN OUT PULONG Hint, + OUT PULONG Block, + OUT PULONG Number +) +{ + NTSTATUS Status = STATUS_SUCCESS; + PBCB Bcb = NULL; + PULONG pData = NULL; + ULONG Slot = 0, i = 0; + ULONG Unit = 1; + + LARGE_INTEGER Offset; + + if (Layer == 0) { + + *Number = 1; + if (BlockArray[0] == 0 && bAlloc) { + + /* now allocate new block */ + Status = Ext2ExpandLast( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + NULL, + Hint, + &BlockArray[0], + Number + ); + + if (!NT_SUCCESS(Status)) { + goto errorout; + } + } else { + /* check the block is valid or not */ + if (BlockArray[0] >= TOTAL_BLOCKS) { + DbgBreak(); + Status = STATUS_DISK_CORRUPT_ERROR; + goto errorout; + } + } + + *Block = BlockArray[0]; + for (i=1; i < SizeArray; i++) { + if (BlockArray[i] == BlockArray[i-1] + 1) { + *Number = *Number + 1; + } else { + break; + } + } + *Hint = BlockArray[*Number - 1]; + + } else if (Layer <= 3) { + + /* check the block is valid or not */ + if (BlockArray[0] == 0 || BlockArray[0] >= TOTAL_BLOCKS) { + DbgBreak(); + Status = STATUS_DISK_CORRUPT_ERROR; + goto errorout; + } + + /* add block to meta extents */ + if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[0], 1)) { + DbgBreak(); + Ext2Sleep(500); + Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[0], 1); + } + + /* map memory in cache for the index block */ + Offset.QuadPart = ((LONGLONG)BlockArray[0]) << BLOCK_BITS; + if ( !CcPinRead( Vcb->Volume, + (PLARGE_INTEGER) (&Offset), + BLOCK_SIZE, + PIN_WAIT, + &Bcb, + &pData )) { + + DEBUG(DL_ERR, ( "Ext2GetBlock: Failed to PinLock block: %xh ...\n", + BlockArray[0] )); + Status = STATUS_CANT_WAIT; + goto errorout; + } + + if (Layer > 1) { + Unit = Vcb->max_blocks_per_layer[Layer - 1]; + } else { + Unit = 1; + } + + Slot = Start / Unit; + Start = Start % Unit; + + if (pData[Slot] == 0) { + + if (bAlloc) { + + /* we need allocate new block and zero all data in case + it's an in-direct block. Index stores the new block no. */ + ULONG Count = 1; + Status = Ext2ExpandLast( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + NULL, + Hint, + &pData[Slot], + &Count + ); + + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + /* refresh hint block */ + *Hint = pData[Slot]; + + /* set dirty bit to notify system to flush */ + CcSetDirtyPinnedData(Bcb, NULL ); + SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED); + if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart, + (LONGLONG)BLOCK_SIZE)) { + DbgBreak(); + Ext2Sleep(100); + if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart, + (LONGLONG)BLOCK_SIZE)) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + } + + /* save inode information here */ + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + } else { + + *Number = 1; + + if (Layer == 1) { + for (i = Slot + 1; i < BLOCK_SIZE/4; i++) { + if (pData[i] == 0) { + *Number = *Number + 1; + } else { + break; + } + } + } else if (Layer == 2) { + *Number = BLOCK_SIZE/4 - Start; + } else { + *Number = BLOCK_SIZE/4; + } + + goto errorout; + } + } + + /* transfer to next recursion call */ + Status = Ext2GetBlock( + IrpContext, + Vcb, + Mcb, + Base, + Layer - 1, + Start, + BLOCK_SIZE/4 - Slot, + &pData[Slot], + bAlloc, + Hint, + Block, + Number + ); + + if (!NT_SUCCESS(Status)) { + goto errorout; + } + } + +errorout: + + /* free the memory of pData */ + if (Bcb) { + CcUnpinData(Bcb); + } + + if (!NT_SUCCESS(Status)) { + *Block = 0; + } + + return Status; +} + + +NTSTATUS +Ext2ExpandBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Base, + IN ULONG Layer, + IN ULONG Start, + IN ULONG SizeArray, + IN PULONG BlockArray, + IN PULONG Hint, + IN PULONG Extra +) +{ + ULONG i = 0; + ULONG j; + ULONG Slot; + ULONG Block = 0; + LARGE_INTEGER Offset; + + PBCB Bcb = NULL; + PULONG pData = NULL; + ULONG Skip = 0; + + ULONG Number; + ULONG Wanted; + + NTSTATUS Status = STATUS_SUCCESS; + + if (Layer == 1) { + + /* + * try to make all leaf block continuous to avoid fragments + */ + + Number = min(SizeArray, ((*Extra + (Start & (BLOCK_SIZE/4 - 1))) * 4 / BLOCK_SIZE)); + Wanted = 0; + DEBUG(DL_BLK, ("Ext2ExpandBlock: SizeArray=%xh Extra=%xh Start=%xh %xh\n", + SizeArray, *Extra, Start, Number )); + + for (i=0; i < Number; i++) { + if (BlockArray[i] == 0) { + Wanted += 1; + } + } + + i = 0; + while (Wanted > 0) { + + Number = Wanted; + Status = Ext2ExpandLast( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + NULL, + Hint, + &Block, + &Number + ); + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + ASSERT(Number > 0); + Wanted -= Number; + while (Number) { + if (BlockArray[i] == 0) { + BlockArray[i] = Block++; + Number--; + } + i++; + } + } + + } else if (Layer == 0) { + + /* + * bulk allocation for inode data blocks + */ + + i = 0; + + while (*Extra && i < SizeArray) { + + Wanted = 0; + Number = 1; + + for (j = i; j < SizeArray && j < i + *Extra; j++) { + + if (BlockArray[j] >= TOTAL_BLOCKS) { + DbgBreak(); + BlockArray[j] = 0; + } + + if (BlockArray[j] == 0) { + Wanted += 1; + } else { + break; + } + } + + if (Wanted == 0) { + + /* add block extent into Mcb */ + ASSERT(BlockArray[i] != 0); + if (!Ext2AddBlockExtent(Vcb, Mcb, Base + i, BlockArray[i], 1)) { + DbgBreak(); + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + Ext2ClearAllExtents(&Mcb->Extents); + } + + } else { + + Number = Wanted; + Status = Ext2ExpandLast( + IrpContext, + Vcb, + Mcb, + Base + i, + 0, + NULL, + Hint, + &Block, + &Number + ); + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + ASSERT(Number > 0); + for (j = 0; j < Number; j++) { + BlockArray[i + j] = Block++; + } + } + + *Extra -= Number; + i += Number; + } + + goto errorout; + } + + + /* + * only for meta blocks allocation + */ + + for (i = 0; *Extra && i < SizeArray; i++) { + + if (Layer <= 3) { + + if (BlockArray[i] >= TOTAL_BLOCKS) { + DbgBreak(); + BlockArray[i] = 0; + } + + if (BlockArray[i] == 0) { + Number = 1; + Status = Ext2ExpandLast( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + &pData, + Hint, + &BlockArray[i], + &Number + ); + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + } else { + + Offset.QuadPart = (((LONGLONG)BlockArray[i]) << BLOCK_BITS); + if (!CcPinRead( + Vcb->Volume, + &Offset, + BLOCK_SIZE, + PIN_WAIT, + &Bcb, + &pData )) { + + DEBUG(DL_ERR, ( "Ext2ExpandInode: failed to PinLock offset :%I64xh...\n", + Offset.QuadPart)); + Status = STATUS_CANT_WAIT; + DbgBreak(); + goto errorout; + } + + /* add block to meta extents */ + if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1)) { + DbgBreak(); + Ext2Sleep(500); + Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1); + } + } + + Skip = Vcb->max_blocks_per_layer[Layer] * i; + + if (i == 0) { + if (Layer > 1) { + Slot = Start / Vcb->max_blocks_per_layer[Layer - 1]; + Start = Start % Vcb->max_blocks_per_layer[Layer - 1]; + Skip += Slot * Vcb->max_blocks_per_layer[Layer - 1]; + } else { + Slot = Start; + Start = 0; + Skip += Slot; + } + } else { + Start = 0; + Slot = 0; + } + + Status = Ext2ExpandBlock( + IrpContext, + Vcb, + Mcb, + Base + Skip, + Layer - 1, + Start, + BLOCK_SIZE/4 - Slot, + &pData[Slot], + Hint, + Extra + ); + + if (Bcb) { + CcSetDirtyPinnedData(Bcb, NULL); + if (!Ext2AddBlockExtent(Vcb, NULL, + BlockArray[i], + BlockArray[i], 1)) { + DbgBreak(); + Ext2Sleep(500); + if (!Ext2AddBlockExtent(Vcb, NULL, + BlockArray[i], + BlockArray[i], 1)) { + } + } + } else { + Ext2SaveBlock(IrpContext, Vcb, BlockArray[i], (PVOID)pData); + } + + if (pData) { + if (Bcb) { + CcUnpinData(Bcb); + Bcb = NULL; + } else { + Ext2FreePool(pData, EXT2_DATA_MAGIC); + DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE); + } + pData = NULL; + } + + if (!NT_SUCCESS(Status)) { + DbgBreak(); + break; + } + } + } + +errorout: + + return Status; +} + +BOOLEAN +Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray) +{ + ULONG i = 0; + for (i=0; i < SizeArray; i++) { + if (BlockArray[i]) { + break; + } + } + return (i == SizeArray); +} + + +NTSTATUS +Ext2TruncateBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Base, + IN ULONG Start, + IN ULONG Layer, + IN ULONG SizeArray, + IN PULONG BlockArray, + IN PULONG Extra +) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG i = 0; + ULONG Slot = 0; + ULONG Skip = 0; + + LONGLONG Offset; + PBCB Bcb = NULL; + PULONG pData = NULL; + + ASSERT(Mcb != NULL); + + for (i = 0; i < SizeArray; i++) { + + if (Layer == 0) { + + ULONG Number = 1; + + while (Extra && SizeArray > i + 1 && Number < *Extra) { + + if (BlockArray[SizeArray - i - 1] == + BlockArray[SizeArray - i - 2] + 1) { + + BlockArray[SizeArray - i - 1] = 0; + Number++; + SizeArray--; + + } else { + break; + } + } + + if (BlockArray[SizeArray - i - 1]) { + + Status = Ext2FreeBlock(IrpContext, Vcb, BlockArray[SizeArray - i - 1], Number); + if (NT_SUCCESS(Status)) { + ASSERT(Mcb->Inode.i_blocks >= (Number << (BLOCK_BITS - 9))); + if (Mcb->Inode.i_blocks < (Number << (BLOCK_BITS - 9))) { + Mcb->Inode.i_blocks = 0; + DbgBreak(); + } else { + Mcb->Inode.i_blocks -= (Number << (BLOCK_BITS - 9)); + } + BlockArray[SizeArray - i - 1] = 0; + } + } + + if (Extra) { + + /* dec blocks count */ + ASSERT(*Extra >= Number); + *Extra = *Extra - Number; + + /* remove block mapping frm Mcb Extents */ + if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + SizeArray - 1 - i, Number)) { + DbgBreak(); + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + Ext2ClearAllExtents(&Mcb->Extents); + } + } + + } else { + + ASSERT(Layer <= 3); + + if (BlockArray[SizeArray - i - 1] >= TOTAL_BLOCKS) { + DbgBreak(); + BlockArray[SizeArray - i - 1] = 0; + } + + if (i == 0) { + if (Layer > 1) { + Slot = Start / Vcb->max_blocks_per_layer[Layer - 1]; + Start = Start % Vcb->max_blocks_per_layer[Layer - 1]; + } else { + Slot = Start; + Start = (BLOCK_SIZE / 4) - 1; + } + } else { + Slot = Start = (BLOCK_SIZE / 4) - 1; + } + + Skip = (SizeArray - i - 1) * Vcb->max_blocks_per_layer[Layer]; + + if (BlockArray[SizeArray - i - 1]) { + + Offset = (LONGLONG) (BlockArray[SizeArray - i - 1]); + Offset = Offset << BLOCK_BITS; + + if (!CcPinRead( Vcb->Volume, + (PLARGE_INTEGER) (&Offset), + BLOCK_SIZE, + PIN_WAIT, + &Bcb, + &pData )) { + + DEBUG(DL_ERR, ( "Ext2TruncateBlock: PinLock failed on block %xh ...\n", + BlockArray[SizeArray - i - 1])); + Status = STATUS_CANT_WAIT; + DbgBreak(); + goto errorout; + } + + Status = Ext2TruncateBlock( + IrpContext, + Vcb, + Mcb, + Base + Skip, + Start, + Layer - 1, + Slot + 1, + &pData[0], + Extra + ); + + if (!NT_SUCCESS(Status)) { + break; + } + + CcSetDirtyPinnedData(Bcb, NULL); + Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)BLOCK_SIZE); + + if (*Extra || Ext2IsBlockEmpty(pData, BLOCK_SIZE/4)) { + + Ext2TruncateBlock( + IrpContext, + Vcb, + Mcb, + Base + Skip, /* base */ + 0, /* start */ + 0, /* layer */ + 1, + &BlockArray[SizeArray - i - 1], + NULL + ); + + if (!Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1)) { + DbgBreak(); + Ext2Sleep(500); + Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1); + } + } + + if (pData) { + CcUnpinData(Bcb); + Bcb = NULL; + pData = NULL; + } + + } else { + + if (Layer > 1) { + if (*Extra > Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1) { + *Extra -= (Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1); + } else { + *Extra = 0; + } + } else { + if (*Extra > Slot + 1) { + *Extra -= (Slot + 1); + } else { + *Extra = 0; + } + } + + if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + Skip, (Start + 1))) { + DbgBreak(); + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + Ext2ClearAllExtents(&Mcb->Extents); + } + } + } + + if (Extra && *Extra == 0) { + break; + } + } + +errorout: + + if (pData) { + CcUnpinData(Bcb); + } + + return Status; +} + +NTSTATUS +Ext2MapIndirect( + 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 +) +{ + ULONG Layer; + ULONG Slot; + + ULONG Base = Index; + + NTSTATUS Status = STATUS_SUCCESS; + + *pBlock = 0; + *Number = 0; + + for (Layer = 0; Layer < EXT2_BLOCK_TYPES; Layer++) { + + if (Index < Vcb->max_blocks_per_layer[Layer]) { + + ULONG dwRet = 0, dwBlk = 0, dwHint = 0, dwArray = 0; + + Slot = (Layer==0) ? (Index):(Layer + EXT2_NDIR_BLOCKS - 1); + dwBlk = Mcb->Inode.i_block[Slot]; + + if (dwBlk == 0) { + + if (!bAlloc) { + + *Number = 1; + goto errorout; + + } else { + + if (Slot) { + dwHint = Mcb->Inode.i_block[Slot - 1]; + } + + /* allocate and zero block if necessary */ + *Number = 1; + Status = Ext2ExpandLast( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + NULL, + &dwHint, + &dwBlk, + Number + ); + + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + /* save the it into inode*/ + Mcb->Inode.i_block[Slot] = dwBlk; + + /* save the inode */ + if (!Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode)) { + DbgBreak(); + Status = STATUS_UNSUCCESSFUL; + goto errorout; + } + } + } + + if (Layer == 0) + dwArray = Vcb->max_blocks_per_layer[Layer] - Index; + else + dwArray = 1; + + /* querying block number of the index-th file block */ + Status = Ext2GetBlock( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + Index, + dwArray, + &Mcb->Inode.i_block[Slot], + bAlloc, + &dwHint, + &dwRet, + Number + ); + + if (NT_SUCCESS(Status)) { + *pBlock = dwRet; + } + + break; + } + + Index -= Vcb->max_blocks_per_layer[Layer]; + } + +errorout: + + return Status; +} + +NTSTATUS +Ext2ExpandIndirect( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Start, + ULONG End, + PLARGE_INTEGER Size +) +{ + NTSTATUS Status = STATUS_SUCCESS; + + ULONG Layer = 0; + ULONG Extra = 0; + ULONG Hint = 0; + ULONG Slot = 0; + ULONG Base = 0; + + Extra = End - Start; + + /* exceeds the biggest file size (indirect) */ + if (End > Vcb->max_data_blocks) { + return STATUS_INVALID_PARAMETER; + } + + for (Layer = 0; Layer < EXT2_BLOCK_TYPES && Extra; Layer++) { + + if (Start >= Vcb->max_blocks_per_layer[Layer]) { + + Base += Vcb->max_blocks_per_layer[Layer]; + Start -= Vcb->max_blocks_per_layer[Layer]; + + } else { + + /* get the slot in i_block array */ + if (Layer == 0) { + Base = Slot = Start; + } else { + Slot = Layer + EXT2_NDIR_BLOCKS - 1; + } + + /* set block hint to avoid fragments */ + if (Hint == 0) { + if (Mcb->Inode.i_block[Slot] != 0) { + Hint = Mcb->Inode.i_block[Slot]; + } else if (Slot > 1) { + Hint = Mcb->Inode.i_block[Slot-1]; + } + } + + /* now expand this slot */ + Status = Ext2ExpandBlock( + IrpContext, + Vcb, + Mcb, + Base, + Layer, + Start, + (Layer == 0) ? (Vcb->max_blocks_per_layer[Layer] - Start) : 1, + &Mcb->Inode.i_block[Slot], + &Hint, + &Extra + ); + if (!NT_SUCCESS(Status)) { + break; + } + + Start = 0; + if (Layer == 0) { + Base = 0; + } + Base += Vcb->max_blocks_per_layer[Layer]; + } + } + + Size->QuadPart = ((LONGLONG)(End - Extra)) << BLOCK_BITS; + + /* save inode whatever it succeeds to expand or not */ + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + return Status; +} + +NTSTATUS +Ext2TruncateIndirectFast( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb + ) +{ + LONGLONG Vba; + LONGLONG Lba; + LONGLONG Length; + NTSTATUS Status = STATUS_SUCCESS; + int i; + + /* try to load all indirect blocks if mcb zone is not initialized */ + if (!IsZoneInited(Mcb)) { + Status = Ext2InitializeZone(IrpContext, Vcb, Mcb); + if (!NT_SUCCESS(Status)) { + DbgBreak(); + ClearLongFlag(Mcb->Flags, MCB_ZONE_INITED); + goto errorout; + } + } + + ASSERT (IsZoneInited(Mcb)); + + /* delete all data blocks here */ + if (FsRtlNumberOfRunsInLargeMcb(&Mcb->Extents) != 0) { + for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->Extents, i, &Vba, &Lba, &Length); i++) { + /* ignore the non-existing runs */ + if (-1 == Lba || Vba == 0 || Length <= 0) + continue; + /* now do data block free */ + Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length); + } + } + + /* delete all meta blocks here */ + if (FsRtlNumberOfRunsInLargeMcb(&Mcb->MetaExts) != 0) { + for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->MetaExts, i, &Vba, &Lba, &Length); i++) { + /* ignore the non-existing runs */ + if (-1 == Lba || Vba == 0 || Length <= 0) + continue; + /* now do meta block free */ + Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length); + } + } + + /* clear data and meta extents */ + Ext2ClearAllExtents(&Mcb->Extents); + Ext2ClearAllExtents(&Mcb->MetaExts); + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + + /* clear inode blocks & sizes */ + Mcb->Inode.i_blocks = 0; + Mcb->Inode.i_size = 0; + memset(&Mcb->Inode.i_block[0], 0, sizeof(__u32) * 15); + + /* the caller will do inode save */ + +errorout: + + return Status; +} + +NTSTATUS +Ext2TruncateIndirect( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + PLARGE_INTEGER Size +) +{ + NTSTATUS Status = STATUS_SUCCESS; + + ULONG Layer = 0; + + ULONG Extra = 0; + ULONG Wanted = 0; + ULONG End; + ULONG Base; + + ULONG SizeArray = 0; + PULONG BlockArray = NULL; + + /* translate file size to block */ + End = Base = Vcb->max_data_blocks; + Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); + + /* do fast deletion here */ + if (Wanted == 0) { + Status = Ext2TruncateIndirectFast(IrpContext, Vcb, Mcb); + if (NT_SUCCESS(Status)) + goto errorout; + } + + /* calculate blocks to be freed */ + Extra = End - Wanted; + + for (Layer = EXT2_BLOCK_TYPES; Layer > 0 && Extra; Layer--) { + + if (Vcb->max_blocks_per_layer[Layer - 1] == 0) { + continue; + } + + Base -= Vcb->max_blocks_per_layer[Layer - 1]; + + if (Layer - 1 == 0) { + BlockArray = &Mcb->Inode.i_block[0]; + SizeArray = End; + ASSERT(End == EXT2_NDIR_BLOCKS && Base == 0); + } else { + BlockArray = &Mcb->Inode.i_block[EXT2_NDIR_BLOCKS - 1 + Layer - 1]; + SizeArray = 1; + } + + Status = Ext2TruncateBlock( + IrpContext, + Vcb, + Mcb, + Base, + End - Base - 1, + Layer - 1, + SizeArray, + BlockArray, + &Extra + ); + if (!NT_SUCCESS(Status)) { + break; + } + + End = Base; + } + +errorout: + + if (!NT_SUCCESS(Status)) { + Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS); + } + + /* save inode */ + if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart)) + Mcb->Inode.i_size = (loff_t)(Size->QuadPart); + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + return Status; +} diff --git a/Ext4Fsd/ext4/ext4_bh.c b/Ext4Fsd/ext4/ext4_bh.c index a874bbd..463a811 100644 --- a/Ext4Fsd/ext4/ext4_bh.c +++ b/Ext4Fsd/ext4/ext4_bh.c @@ -1,68 +1,68 @@ -#include -#include -#include - -/* - * extents_bread: This function is a wrapper of CcPinRead routine. - * - * @sb: the device we need to undergo buffered IO on. - * @block: the block we want to read from. - * - * If the call to this routine succeeds, the pages underlying the buffer header - * will be locked into memory, so that the buffer header returned for use is safe. - */ -struct buffer_head * -extents_bread(struct super_block *sb, sector_t block) -{ - return sb_getblk(sb, block); -} - -/* - * extents_bwrite: This function is a wrapper of CcPreparePinWrite routine. - * - * @sb: the device we need to undergo buffered IO on. - * @block: the block we want to write to. - */ -struct buffer_head * -extents_bwrite(struct super_block *sb, sector_t block) -{ - return sb_getblk_zero(sb, block); - -} - -/* - * extents_mark_buffer_dirty: Mark the buffer dirtied and so - * that changes will be written back. - * - * @bh: The corresponding buffer header that is modified. - */ -void extents_mark_buffer_dirty(struct buffer_head *bh) -{ - set_buffer_dirty(bh); -} - -/* - * extents_brelse: Release the corresponding buffer header. - * - * @bh: The corresponding buffer header that is going to be freed. - * - * The pages underlying the buffer header will be unlocked. - */ -void extents_brelse(struct buffer_head *bh) -{ - brelse(bh); -} - -/* - * extents_bforget: Release the corresponding buffer header. - * NOTE: The page owned by @bh will be marked invalidated. - * - * @bh: The corresponding buffer header that is going to be freed. - * - * The pages underlying the buffer header will be unlocked. - */ -void extents_bforget(struct buffer_head *bh) -{ - clear_buffer_uptodate(bh); - bforget(bh); -} +#include +#include +#include + +/* + * extents_bread: This function is a wrapper of CcPinRead routine. + * + * @sb: the device we need to undergo buffered IO on. + * @block: the block we want to read from. + * + * If the call to this routine succeeds, the pages underlying the buffer header + * will be locked into memory, so that the buffer header returned for use is safe. + */ +struct buffer_head * +extents_bread(struct super_block *sb, sector_t block) +{ + return sb_getblk(sb, block); +} + +/* + * extents_bwrite: This function is a wrapper of CcPreparePinWrite routine. + * + * @sb: the device we need to undergo buffered IO on. + * @block: the block we want to write to. + */ +struct buffer_head * +extents_bwrite(struct super_block *sb, sector_t block) +{ + return sb_getblk_zero(sb, block); + +} + +/* + * extents_mark_buffer_dirty: Mark the buffer dirtied and so + * that changes will be written back. + * + * @bh: The corresponding buffer header that is modified. + */ +void extents_mark_buffer_dirty(struct buffer_head *bh) +{ + set_buffer_dirty(bh); +} + +/* + * extents_brelse: Release the corresponding buffer header. + * + * @bh: The corresponding buffer header that is going to be freed. + * + * The pages underlying the buffer header will be unlocked. + */ +void extents_brelse(struct buffer_head *bh) +{ + brelse(bh); +} + +/* + * extents_bforget: Release the corresponding buffer header. + * NOTE: The page owned by @bh will be marked invalidated. + * + * @bh: The corresponding buffer header that is going to be freed. + * + * The pages underlying the buffer header will be unlocked. + */ +void extents_bforget(struct buffer_head *bh) +{ + clear_buffer_uptodate(bh); + bforget(bh); +} diff --git a/Ext4Fsd/ext4/extents.c b/Ext4Fsd/ext4/extents.c index c132911..be19e6d 100644 --- a/Ext4Fsd/ext4/extents.c +++ b/Ext4Fsd/ext4/extents.c @@ -1,244 +1,244 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: extents.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS *****************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -#ifdef ALLOC_PRAGMA -#endif - - -NTSTATUS -Ext2MapExtent( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Index, - IN BOOLEAN Alloc, - OUT PULONG Block, - OUT PULONG Number -) -{ - EXT4_EXTENT_HEADER *eh; - struct buffer_head bh_got = {0}; - int flags, rc; - ULONG max_blocks = 0; - - memset(&bh_got, 0, sizeof(struct buffer_head)); - eh = get_ext4_header(&Mcb->Inode); - - if (eh->eh_magic != EXT4_EXT_MAGIC) { - if (Alloc) { - /* now initialize inode extent root node */ - ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); - } else { - /* return empty-mapping when inode extent isn't initialized */ - if (Block) - *Block = 0; - if (Number) { - LONGLONG _len = _len = Mcb->Inode.i_size; - if (Mcb->Fcb) - _len = Mcb->Fcb->Header.AllocationSize.QuadPart; - *Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS); - } - return STATUS_SUCCESS; - } - } - - /* IrpContext is NULL when called during journal initialization */ - if (IsMcbDirectory(Mcb) || IrpContext == NULL || - IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){ - flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; - max_blocks = EXT_INIT_MAX_LEN; - } else { - flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; - max_blocks = EXT_UNWRITTEN_MAX_LEN; - } - - if (Alloc) { - if (Number && !*Number) { - if (max_blocks > *Number) { - max_blocks = *Number; - } - } else { - max_blocks = 1; - } - } - - if ((rc = ext4_ext_get_blocks( - IrpContext, - NULL, - &Mcb->Inode, - Index, - max_blocks, - &bh_got, - Alloc, - flags)) < 0) { - DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc)); - return Ext2WinntError(rc); - } - if (Alloc) - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - if (Number) - *Number = rc ? rc : 1; - if (Block) - *Block = (ULONG)bh_got.b_blocknr; - - return STATUS_SUCCESS; -} - - -NTSTATUS -Ext2DoExtentExpand( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Index, - IN OUT PULONG Block, - IN OUT PULONG Number -) -{ - EXT4_EXTENT_HEADER *eh; - struct buffer_head bh_got; - int rc, flags; - - if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) { - flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; - } else { - flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; - } - - memset(&bh_got, 0, sizeof(struct buffer_head)); - eh = get_ext4_header(&Mcb->Inode); - - if (eh->eh_magic != EXT4_EXT_MAGIC) { - ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); - } - - if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index, - *Number, &bh_got, 1, flags)) < 0) { - DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u," - " err: %d\n", *Number, rc)); - DbgBreak(); - return Ext2WinntError(rc); - } - - if (Number) - *Number = rc ? rc : 1; - if (Block) - *Block = (ULONG)bh_got.b_blocknr; - - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - - return STATUS_SUCCESS; -} - - -NTSTATUS -Ext2ExpandExtent( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - ULONG Start, - ULONG End, - PLARGE_INTEGER Size - ) -{ - ULONG Count = 0, Number = 0, Block = 0; - NTSTATUS Status = STATUS_SUCCESS; - - if (End <= Start) - return Status; - - while (End > Start + Count) { - - Number = End - Start - Count; - Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count, - &Block, &Number); - if (!NT_SUCCESS(Status)) { - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - if (Number == 0) { - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - if (Block && IsZoneInited(Mcb)) { - if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) { - DbgBreak(); - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - Ext2ClearAllExtents(&Mcb->Extents); - } - } - Count += Number; - } - - Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS; - - /* save inode whatever it succeeds to expand or not */ - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - - return Status; -} - - -NTSTATUS -Ext2TruncateExtent( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - PLARGE_INTEGER Size - ) -{ - NTSTATUS Status = STATUS_SUCCESS; - - ULONG Extra = 0; - ULONG Wanted = 0; - ULONG End; - ULONG Removed; - int err; - - /* translate file size to block */ - End = Vcb->max_data_blocks; - Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); - - /* calculate blocks to be freed */ - Extra = End - Wanted; - - err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted); - if (err == 0) { - if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) { - ClearFlag(Mcb->Flags, MCB_ZONE_INITED); - Ext2ClearAllExtents(&Mcb->Extents); - } - Extra = 0; - } else { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - - if (!NT_SUCCESS(Status)) { - Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS); - } - - if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart)) - Mcb->Inode.i_size = (loff_t)(Size->QuadPart); - - /* Save modifications on i_blocks field and i_size field of the inode. */ - Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: extents.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS *****************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +#ifdef ALLOC_PRAGMA +#endif + + +NTSTATUS +Ext2MapExtent( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Index, + IN BOOLEAN Alloc, + OUT PULONG Block, + OUT PULONG Number +) +{ + EXT4_EXTENT_HEADER *eh; + struct buffer_head bh_got = {0}; + int flags, rc; + ULONG max_blocks = 0; + + memset(&bh_got, 0, sizeof(struct buffer_head)); + eh = get_ext4_header(&Mcb->Inode); + + if (eh->eh_magic != EXT4_EXT_MAGIC) { + if (Alloc) { + /* now initialize inode extent root node */ + ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); + } else { + /* return empty-mapping when inode extent isn't initialized */ + if (Block) + *Block = 0; + if (Number) { + LONGLONG _len = _len = Mcb->Inode.i_size; + if (Mcb->Fcb) + _len = Mcb->Fcb->Header.AllocationSize.QuadPart; + *Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS); + } + return STATUS_SUCCESS; + } + } + + /* IrpContext is NULL when called during journal initialization */ + if (IsMcbDirectory(Mcb) || IrpContext == NULL || + IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){ + flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; + max_blocks = EXT_INIT_MAX_LEN; + } else { + flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; + max_blocks = EXT_UNWRITTEN_MAX_LEN; + } + + if (Alloc) { + if (Number && !*Number) { + if (max_blocks > *Number) { + max_blocks = *Number; + } + } else { + max_blocks = 1; + } + } + + if ((rc = ext4_ext_get_blocks( + IrpContext, + NULL, + &Mcb->Inode, + Index, + max_blocks, + &bh_got, + Alloc, + flags)) < 0) { + DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc)); + return Ext2WinntError(rc); + } + if (Alloc) + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + if (Number) + *Number = rc ? rc : 1; + if (Block) + *Block = (ULONG)bh_got.b_blocknr; + + return STATUS_SUCCESS; +} + + +NTSTATUS +Ext2DoExtentExpand( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Index, + IN OUT PULONG Block, + IN OUT PULONG Number +) +{ + EXT4_EXTENT_HEADER *eh; + struct buffer_head bh_got; + int rc, flags; + + if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) { + flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; + } else { + flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; + } + + memset(&bh_got, 0, sizeof(struct buffer_head)); + eh = get_ext4_header(&Mcb->Inode); + + if (eh->eh_magic != EXT4_EXT_MAGIC) { + ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); + } + + if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index, + *Number, &bh_got, 1, flags)) < 0) { + DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u," + " err: %d\n", *Number, rc)); + DbgBreak(); + return Ext2WinntError(rc); + } + + if (Number) + *Number = rc ? rc : 1; + if (Block) + *Block = (ULONG)bh_got.b_blocknr; + + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + return STATUS_SUCCESS; +} + + +NTSTATUS +Ext2ExpandExtent( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Start, + ULONG End, + PLARGE_INTEGER Size + ) +{ + ULONG Count = 0, Number = 0, Block = 0; + NTSTATUS Status = STATUS_SUCCESS; + + if (End <= Start) + return Status; + + while (End > Start + Count) { + + Number = End - Start - Count; + Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count, + &Block, &Number); + if (!NT_SUCCESS(Status)) { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + if (Number == 0) { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + if (Block && IsZoneInited(Mcb)) { + if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) { + DbgBreak(); + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + Ext2ClearAllExtents(&Mcb->Extents); + } + } + Count += Number; + } + + Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS; + + /* save inode whatever it succeeds to expand or not */ + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + return Status; +} + + +NTSTATUS +Ext2TruncateExtent( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + PLARGE_INTEGER Size + ) +{ + NTSTATUS Status = STATUS_SUCCESS; + + ULONG Extra = 0; + ULONG Wanted = 0; + ULONG End; + ULONG Removed; + int err; + + /* translate file size to block */ + End = Vcb->max_data_blocks; + Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); + + /* calculate blocks to be freed */ + Extra = End - Wanted; + + err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted); + if (err == 0) { + if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) { + ClearFlag(Mcb->Flags, MCB_ZONE_INITED); + Ext2ClearAllExtents(&Mcb->Extents); + } + Extra = 0; + } else { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + if (!NT_SUCCESS(Status)) { + Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS); + } + + if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart)) + Mcb->Inode.i_size = (loff_t)(Size->QuadPart); + + /* Save modifications on i_blocks field and i_size field of the inode. */ + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + return Status; +} diff --git a/Ext4Fsd/fastio.c b/Ext4Fsd/fastio.c index ca0d765..e750d40 100644 --- a/Ext4Fsd/fastio.c +++ b/Ext4Fsd/fastio.c @@ -1,1125 +1,1125 @@ -/* - * 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 *************************************************************/ - -#define FASTIO_DEBUG_LEVEL DL_NVR - - -#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 -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; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - /* do nothing if target fie was deleted */ - if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { - __leave; - } - - if (IsDirectory(Fcb)) { - __leave; - } - - Ccb = (PEXT2_CCB) FileObject->FsContext2; - if (Ccb == NULL) { - __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 - - } __except (EXCEPTION_EXECUTE_HANDLER) { - bPossible = FastIoIsNotPossible; - } - - } __finally { - - FsRtlExitFileSystem(); - } - - return bPossible; -} - - -BOOLEAN -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 -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; - - __try { - - FsRtlEnterFileSystem(); - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (IsVcbReadOnly(Fcb->Vcb)) { - __leave; - } - - if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) { - __leave; - } - Locked = TRUE; - - if (IsWritingToEof(*FileOffset) || - Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length || - Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) { - Status = FALSE; - __leave; - } - - if (Locked) { - ExReleaseResourceLite(Fcb->Header.Resource); - Locked = FALSE; - } - - Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, - LockKey, Buffer, IoStatus, DeviceObject); - if (Status) { - if (IoStatus) - Length = (ULONG)IoStatus->Information; - } - - } __finally { - - if (Locked) { - ExReleaseResourceLite(Fcb->Header.Resource); - } - - FsRtlExitFileSystem(); - } - - 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 -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; - PEXT2_CCB Ccb = NULL; - PEXT2_MCB Mcb = NULL; - BOOLEAN Status = FALSE; - BOOLEAN FcbMainResourceAcquired = FALSE; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - IoStatus->Status = STATUS_INVALID_PARAMETER; - __leave; - } - Ccb = (PEXT2_CCB) FileObject->FsContext2; - Mcb = Fcb->Mcb; - 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)) { - __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; - */ - - Buffer->CreationTime = Mcb->CreationTime; - Buffer->LastAccessTime = Mcb->LastAccessTime; - Buffer->LastWriteTime = Mcb->LastWriteTime; - Buffer->ChangeTime = Mcb->ChangeTime; - Buffer->FileAttributes = Mcb->FileAttr; - if (Buffer->FileAttributes == 0) { - Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL; - } - - IoStatus->Information = sizeof(FILE_BASIC_INFORMATION); - IoStatus->Status = STATUS_SUCCESS; - - Status = TRUE; - - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoStatus->Status = GetExceptionCode(); - } - - } __finally { - - if (FcbMainResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - FsRtlExitFileSystem(); - } - -#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 -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 = NULL; - PEXT2_FCB Fcb = NULL; - BOOLEAN FcbMainResourceAcquired = FALSE; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - IoStatus->Status = STATUS_INVALID_PARAMETER; - __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 )) { - __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; - - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoStatus->Status = GetExceptionCode(); - } - - } __finally { - - if (FcbMainResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - FsRtlExitFileSystem(); - } - -#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 -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; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - IoStatus->Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (IsDirectory(Fcb)) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __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)) { - __leave; - } - - Status = FsRtlFastLock( - &Fcb->FileLockAnchor, - FileObject, - FileOffset, - Length, - Process, - Key, - FailImmediately, - ExclusiveLock, - IoStatus, - NULL, - FALSE); - - if (Status) { - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - } - - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoStatus->Status = GetExceptionCode(); - } - - } __finally { - - FsRtlExitFileSystem(); - } - -#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 -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; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (IsDirectory(Fcb)) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __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)) { - __leave; - } - - IoStatus->Status = FsRtlFastUnlockSingle( - &Fcb->FileLockAnchor, - FileObject, - FileOffset, - Length, - Process, - Key, - NULL, - FALSE); - - IoStatus->Information = 0; - Status = TRUE; - - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoStatus->Status = GetExceptionCode(); - } - - } __finally { - - FsRtlExitFileSystem(); - } - -#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 -Ext2FastIoUnlockAll ( - IN PFILE_OBJECT FileObject, - IN PEPROCESS Process, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject) -{ - BOOLEAN Status = FALSE; - PEXT2_FCB Fcb; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (IsDirectory(Fcb)) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __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)) { - __leave; - } - - IoStatus->Status = FsRtlFastUnlockAll( - &Fcb->FileLockAnchor, - FileObject, - Process, - NULL ); - - IoStatus->Information = 0; - Status = TRUE; - - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoStatus->Status = GetExceptionCode(); - } - - } __finally { - - FsRtlExitFileSystem(); - } - -#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 -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; - - __try { - - FsRtlEnterFileSystem(); - - __try { - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (IsDirectory(Fcb)) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __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)) { - __leave; - } - - IoStatus->Status = FsRtlFastUnlockAllByKey( - &Fcb->FileLockAnchor, - FileObject, - Process, - Key, - NULL - ); - - IoStatus->Information = 0; - Status = TRUE; - - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - - } __except (EXCEPTION_EXECUTE_HANDLER) { - IoStatus->Status = GetExceptionCode(); - } - - } __finally { - - FsRtlExitFileSystem(); - } - -#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 -Ext2FastIoQueryNetworkOpenInfo ( - IN PFILE_OBJECT FileObject, - IN BOOLEAN Wait, - IN OUT PFILE_NETWORK_OPEN_INFORMATION PFNOI, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject -) -{ - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PEXT2_MCB Mcb = NULL; - - BOOLEAN bResult = FALSE; - BOOLEAN FcbResourceAcquired = FALSE; - - __try { - - FsRtlEnterFileSystem(); - - if (IsExt2FsDevice(DeviceObject)) { - IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { - DbgBreak(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - Ccb = (PEXT2_CCB) FileObject->FsContext2; - Mcb = Fcb->Mcb; - -#if EXT2_DEBUG - DEBUG(DL_INF, ( - "%-31s %wZ\n", - "FASTIO_QUERY_NETWORK_OPEN_INFO", - &Fcb->Mcb->FullName - )); -#endif - - if (!Ccb) { - __leave; - } - - if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) { - - if (!ExAcquireResourceSharedLite( - &Fcb->MainResource, - Wait - )) { - __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 = Mcb->FileAttr; - 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; - - bResult = TRUE; - - IoStatus->Status = STATUS_SUCCESS; - IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION); - - } __finally { - - if (FcbResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - FsRtlExitFileSystem(); - } - - return bResult; -} - - -VOID -Ext2AcquireForCreateSection ( - IN PFILE_OBJECT FileObject -) - -{ - PEXT2_FCB Fcb = FileObject->FsContext; - - if (Fcb->Header.Resource != NULL) { - ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE); - } - - DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireForCreateSection: Fcb=%p\n", Fcb)); -} - -VOID -Ext2ReleaseForCreateSection ( - IN PFILE_OBJECT FileObject -) -{ - PEXT2_FCB Fcb = FileObject->FsContext; - - DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseForCreateSection: Fcb=%p\n", Fcb)); - - if (Fcb->Header.Resource != NULL) { - ExReleaseResourceLite(Fcb->Header.Resource); - } -} - - -NTSTATUS -Ext2AcquireFileForModWrite ( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER EndingOffset, - OUT PERESOURCE *ResourceToRelease, - IN PDEVICE_OBJECT DeviceObject -) - -{ - BOOLEAN ResourceAcquired = FALSE; - - PEXT2_FCB Fcb = FileObject->FsContext; - - *ResourceToRelease = Fcb->Header.Resource; - ResourceAcquired = ExAcquireResourceExclusiveLite(*ResourceToRelease, FALSE); - if (!ResourceAcquired) { - *ResourceToRelease = NULL; - } - - DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForModWrite: Fcb=%p Acquired=%d\n", - Fcb, ResourceAcquired)); - - return (ResourceAcquired ? STATUS_SUCCESS : STATUS_CANT_WAIT); -} - -NTSTATUS -Ext2ReleaseFileForModWrite ( - IN PFILE_OBJECT FileObject, - IN PERESOURCE ResourceToRelease, - IN PDEVICE_OBJECT DeviceObject -) -{ - PEXT2_FCB Fcb = FileObject->FsContext; - - DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForModWrite: Fcb=%p\n", Fcb)); - - if (ResourceToRelease != NULL) { - ASSERT(ResourceToRelease == Fcb->Header.Resource); - ExReleaseResourceLite(ResourceToRelease); - } else { - DbgBreak(); - } - - return STATUS_SUCCESS; -} - -NTSTATUS -Ext2AcquireFileForCcFlush ( - IN PFILE_OBJECT FileObject, - IN PDEVICE_OBJECT DeviceObject -) -{ - PEXT2_FCB Fcb = FileObject->FsContext; - - if (Fcb->Header.Resource != NULL) { - ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE); - } - - DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForCcFlush: Fcb=%p\n", Fcb)); - - return STATUS_SUCCESS; -} - -NTSTATUS -Ext2ReleaseFileForCcFlush ( - IN PFILE_OBJECT FileObject, - IN PDEVICE_OBJECT DeviceObject -) -{ - PEXT2_FCB Fcb = FileObject->FsContext; - - DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForCcFlush: Fcb=%p\n", Fcb)); - - if (Fcb->Header.Resource != NULL) { - ExReleaseResourceLite(Fcb->Header.Resource); - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -Ext2PreAcquireForCreateSection( - IN PFS_FILTER_CALLBACK_DATA cd, - OUT PVOID *cc - ) -{ - PEXT2_FCB Fcb = (PEXT2_FCB)cd->FileObject->FsContext; - NTSTATUS status; - - ASSERT(cd->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION); - ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE); - if (cd->Parameters.AcquireForSectionSynchronization.SyncType != SyncTypeCreateSection) { - status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY; - } else if (Fcb->ShareAccess.Writers == 0) { - status = STATUS_FILE_LOCKED_WITH_ONLY_READERS; - } else { - status = STATUS_FILE_LOCKED_WITH_WRITERS; - } - - return status; -} +/* + * 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 *************************************************************/ + +#define FASTIO_DEBUG_LEVEL DL_NVR + + +#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 +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; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + /* do nothing if target fie was deleted */ + if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { + __leave; + } + + if (IsDirectory(Fcb)) { + __leave; + } + + Ccb = (PEXT2_CCB) FileObject->FsContext2; + if (Ccb == NULL) { + __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 + + } __except (EXCEPTION_EXECUTE_HANDLER) { + bPossible = FastIoIsNotPossible; + } + + } __finally { + + FsRtlExitFileSystem(); + } + + return bPossible; +} + + +BOOLEAN +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 +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; + + __try { + + FsRtlEnterFileSystem(); + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (IsVcbReadOnly(Fcb->Vcb)) { + __leave; + } + + if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) { + __leave; + } + Locked = TRUE; + + if (IsWritingToEof(*FileOffset) || + Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length || + Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) { + Status = FALSE; + __leave; + } + + if (Locked) { + ExReleaseResourceLite(Fcb->Header.Resource); + Locked = FALSE; + } + + Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, + LockKey, Buffer, IoStatus, DeviceObject); + if (Status) { + if (IoStatus) + Length = (ULONG)IoStatus->Information; + } + + } __finally { + + if (Locked) { + ExReleaseResourceLite(Fcb->Header.Resource); + } + + FsRtlExitFileSystem(); + } + + 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 +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; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + BOOLEAN Status = FALSE; + BOOLEAN FcbMainResourceAcquired = FALSE; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + IoStatus->Status = STATUS_INVALID_PARAMETER; + __leave; + } + Ccb = (PEXT2_CCB) FileObject->FsContext2; + Mcb = Fcb->Mcb; + 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)) { + __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; + */ + + Buffer->CreationTime = Mcb->CreationTime; + Buffer->LastAccessTime = Mcb->LastAccessTime; + Buffer->LastWriteTime = Mcb->LastWriteTime; + Buffer->ChangeTime = Mcb->ChangeTime; + Buffer->FileAttributes = Mcb->FileAttr; + if (Buffer->FileAttributes == 0) { + Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL; + } + + IoStatus->Information = sizeof(FILE_BASIC_INFORMATION); + IoStatus->Status = STATUS_SUCCESS; + + Status = TRUE; + + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoStatus->Status = GetExceptionCode(); + } + + } __finally { + + if (FcbMainResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + FsRtlExitFileSystem(); + } + +#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 +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 = NULL; + PEXT2_FCB Fcb = NULL; + BOOLEAN FcbMainResourceAcquired = FALSE; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + IoStatus->Status = STATUS_INVALID_PARAMETER; + __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 )) { + __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; + + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoStatus->Status = GetExceptionCode(); + } + + } __finally { + + if (FcbMainResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + FsRtlExitFileSystem(); + } + +#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 +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; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + IoStatus->Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (IsDirectory(Fcb)) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __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)) { + __leave; + } + + Status = FsRtlFastLock( + &Fcb->FileLockAnchor, + FileObject, + FileOffset, + Length, + Process, + Key, + FailImmediately, + ExclusiveLock, + IoStatus, + NULL, + FALSE); + + if (Status) { + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + } + + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoStatus->Status = GetExceptionCode(); + } + + } __finally { + + FsRtlExitFileSystem(); + } + +#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 +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; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (IsDirectory(Fcb)) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __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)) { + __leave; + } + + IoStatus->Status = FsRtlFastUnlockSingle( + &Fcb->FileLockAnchor, + FileObject, + FileOffset, + Length, + Process, + Key, + NULL, + FALSE); + + IoStatus->Information = 0; + Status = TRUE; + + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoStatus->Status = GetExceptionCode(); + } + + } __finally { + + FsRtlExitFileSystem(); + } + +#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 +Ext2FastIoUnlockAll ( + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PEXT2_FCB Fcb; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (IsDirectory(Fcb)) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __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)) { + __leave; + } + + IoStatus->Status = FsRtlFastUnlockAll( + &Fcb->FileLockAnchor, + FileObject, + Process, + NULL ); + + IoStatus->Information = 0; + Status = TRUE; + + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoStatus->Status = GetExceptionCode(); + } + + } __finally { + + FsRtlExitFileSystem(); + } + +#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 +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; + + __try { + + FsRtlEnterFileSystem(); + + __try { + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (IsDirectory(Fcb)) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __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)) { + __leave; + } + + IoStatus->Status = FsRtlFastUnlockAllByKey( + &Fcb->FileLockAnchor, + FileObject, + Process, + Key, + NULL + ); + + IoStatus->Information = 0; + Status = TRUE; + + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + + } __except (EXCEPTION_EXECUTE_HANDLER) { + IoStatus->Status = GetExceptionCode(); + } + + } __finally { + + FsRtlExitFileSystem(); + } + +#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 +Ext2FastIoQueryNetworkOpenInfo ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + IN OUT PFILE_NETWORK_OPEN_INFORMATION PFNOI, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +) +{ + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + + BOOLEAN bResult = FALSE; + BOOLEAN FcbResourceAcquired = FALSE; + + __try { + + FsRtlEnterFileSystem(); + + if (IsExt2FsDevice(DeviceObject)) { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { + DbgBreak(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + Ccb = (PEXT2_CCB) FileObject->FsContext2; + Mcb = Fcb->Mcb; + +#if EXT2_DEBUG + DEBUG(DL_INF, ( + "%-31s %wZ\n", + "FASTIO_QUERY_NETWORK_OPEN_INFO", + &Fcb->Mcb->FullName + )); +#endif + + if (!Ccb) { + __leave; + } + + if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) { + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + Wait + )) { + __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 = Mcb->FileAttr; + 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; + + bResult = TRUE; + + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION); + + } __finally { + + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + FsRtlExitFileSystem(); + } + + return bResult; +} + + +VOID +Ext2AcquireForCreateSection ( + IN PFILE_OBJECT FileObject +) + +{ + PEXT2_FCB Fcb = FileObject->FsContext; + + if (Fcb->Header.Resource != NULL) { + ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE); + } + + DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireForCreateSection: Fcb=%p\n", Fcb)); +} + +VOID +Ext2ReleaseForCreateSection ( + IN PFILE_OBJECT FileObject +) +{ + PEXT2_FCB Fcb = FileObject->FsContext; + + DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseForCreateSection: Fcb=%p\n", Fcb)); + + if (Fcb->Header.Resource != NULL) { + ExReleaseResourceLite(Fcb->Header.Resource); + } +} + + +NTSTATUS +Ext2AcquireFileForModWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT PERESOURCE *ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject +) + +{ + BOOLEAN ResourceAcquired = FALSE; + + PEXT2_FCB Fcb = FileObject->FsContext; + + *ResourceToRelease = Fcb->Header.Resource; + ResourceAcquired = ExAcquireResourceExclusiveLite(*ResourceToRelease, FALSE); + if (!ResourceAcquired) { + *ResourceToRelease = NULL; + } + + DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForModWrite: Fcb=%p Acquired=%d\n", + Fcb, ResourceAcquired)); + + return (ResourceAcquired ? STATUS_SUCCESS : STATUS_CANT_WAIT); +} + +NTSTATUS +Ext2ReleaseFileForModWrite ( + IN PFILE_OBJECT FileObject, + IN PERESOURCE ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject +) +{ + PEXT2_FCB Fcb = FileObject->FsContext; + + DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForModWrite: Fcb=%p\n", Fcb)); + + if (ResourceToRelease != NULL) { + ASSERT(ResourceToRelease == Fcb->Header.Resource); + ExReleaseResourceLite(ResourceToRelease); + } else { + DbgBreak(); + } + + return STATUS_SUCCESS; +} + +NTSTATUS +Ext2AcquireFileForCcFlush ( + IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject +) +{ + PEXT2_FCB Fcb = FileObject->FsContext; + + if (Fcb->Header.Resource != NULL) { + ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE); + } + + DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForCcFlush: Fcb=%p\n", Fcb)); + + return STATUS_SUCCESS; +} + +NTSTATUS +Ext2ReleaseFileForCcFlush ( + IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject +) +{ + PEXT2_FCB Fcb = FileObject->FsContext; + + DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForCcFlush: Fcb=%p\n", Fcb)); + + if (Fcb->Header.Resource != NULL) { + ExReleaseResourceLite(Fcb->Header.Resource); + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +Ext2PreAcquireForCreateSection( + IN PFS_FILTER_CALLBACK_DATA cd, + OUT PVOID *cc + ) +{ + PEXT2_FCB Fcb = (PEXT2_FCB)cd->FileObject->FsContext; + NTSTATUS status; + + ASSERT(cd->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION); + ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE); + if (cd->Parameters.AcquireForSectionSynchronization.SyncType != SyncTypeCreateSection) { + status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY; + } else if (Fcb->ShareAccess.Writers == 0) { + status = STATUS_FILE_LOCKED_WITH_ONLY_READERS; + } else { + status = STATUS_FILE_LOCKED_WITH_WRITERS; + } + + return status; +} diff --git a/Ext4Fsd/fileinfo.c b/Ext4Fsd/fileinfo.c index e9cbe89..d2c6d06 100644 --- a/Ext4Fsd/fileinfo.c +++ b/Ext4Fsd/fileinfo.c @@ -1,2089 +1,2089 @@ -/* - * 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 "linux\ext4.h" -#include "linux\ext4_xattr.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Ext2QueryFileInformation) -#pragma alloc_text(PAGE, Ext2SetFileInformation) -#pragma alloc_text(PAGE, Ext2ExpandFile) -#pragma alloc_text(PAGE, Ext2TruncateFile) -#pragma alloc_text(PAGE, Ext2SetDispositionInfo) -#pragma alloc_text(PAGE, Ext2SetRenameInfo) -#pragma alloc_text(PAGE, Ext2SetLinkInfo) -#pragma alloc_text(PAGE, Ext2DeleteFile) -#endif - -static int Ext2IterateAllEa(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item, BOOL is_last) -{ - PULONG EaSize = xattr_ref->iter_arg; - ULONG EaEntrySize = 4 + 1 + 1 + 2 + item->name_len + 1 + item->data_size; - - *EaSize += EaEntrySize - 4; - return EXT4_XATTR_ITERATE_CONT; -} - -NTSTATUS -Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PFILE_OBJECT FileObject; - PEXT2_VCB Vcb = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_MCB Mcb = NULL; - PEXT2_CCB Ccb = NULL; - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation; - FILE_INFORMATION_CLASS FileInformationClass; - ULONG Length; - PVOID Buffer; - BOOLEAN FcbResourceAcquired = FALSE; - - __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; - __leave; - } - - FileObject = IrpContext->FileObject; - Fcb = (PEXT2_FCB) FileObject->FsContext; - if (Fcb == NULL) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - // - // This request is not allowed on volumes - // - if (Fcb->Identifier.Type == EXT2VCB) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (!((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB)))) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - Vcb = Fcb->Vcb; - - { - if (!ExAcquireResourceSharedLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) - )) { - - Status = STATUS_PENDING; - __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; - __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; - __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; - __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: - { - struct ext4_xattr_ref xattr_ref; - PFILE_EA_INFORMATION FileEaInformation; - - if (Length < sizeof(FILE_EA_INFORMATION)) { - Status = STATUS_BUFFER_OVERFLOW; - __leave; - } - - FileEaInformation = (PFILE_EA_INFORMATION) Buffer; - FileEaInformation->EaSize = 0; - - Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); - if (!NT_SUCCESS(Status)) - __leave; - - xattr_ref.iter_arg = &FileEaInformation->EaSize; - ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); - ext4_fs_put_xattr_ref(&xattr_ref); - - if (FileEaInformation->EaSize) - FileEaInformation->EaSize += 4; - - 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; - __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; - __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) - ); - __leave; - } - - RtlCopyMemory( - FileNameInformation->FileName, - Mcb->ShortName.Buffer, - Mcb->ShortName.Length - ); - - Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) + - Mcb->ShortName.Length - sizeof(WCHAR); - - 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; - __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; - __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; - } - - } __finally { - - if (FcbResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (!IrpContext->ExceptionInProgress) { - if (Status == STATUS_PENDING || - Status == STATUS_CANT_WAIT) { - Status = Ext2QueueRequest(IrpContext); - } else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} - - -NTSTATUS -Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb = NULL; - PFILE_OBJECT FileObject = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PEXT2_MCB Mcb = NULL; - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - FILE_INFORMATION_CLASS FileInformationClass; - - ULONG NotifyFilter = 0; - - ULONG Length; - PVOID Buffer; - - BOOLEAN FcbMainResourceAcquired = FALSE; - BOOLEAN FcbPagingIoResourceAcquired = FALSE; - - __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; - __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; - __leave; - } - - if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { - Status = STATUS_ACCESS_DENIED; - __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; - __leave; - } - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { - Status = STATUS_FILE_DELETED; - __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; - __leave; - } - } else { - Mcb = Fcb->Mcb; - } - - if (FileInformationClass != FilePositionInformation) { - if (IsVcbReadOnly(Vcb)) { - Status = STATUS_MEDIA_WRITE_PROTECTED; - __leave; - } - if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) { - Status = STATUS_ACCESS_DENIED; - __leave; - } - } - - 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) { - __leave; - } - - // - // Set the flag indicating if Fast I/O is possible - // - - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - } - - /* for renaming or set link, we must not grab any Fcb locks, - and later we will get Dcb or Fcb resources exclusively. */ - if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) && - FileInformationClass != FileRenameInformation && - FileInformationClass != FileLinkInformation) { - - if (!ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { - Status = STATUS_PENDING; - __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(); - __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; - __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(); - __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; - __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)) { - __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; - } - - __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(); - __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; - __leave; - } else { - Status = STATUS_SUCCESS; - } - - NewVDL = FVDL->ValidDataLength; - if ((NewVDL.QuadPart < Fcb->Header.ValidDataLength.QuadPart)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - if (NewVDL.QuadPart > Fcb->Header.FileSize.QuadPart) - NewVDL = Fcb->Header.FileSize; - - if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, - &NewVDL)) { - Status = STATUS_USER_MAPPED_FILE; - __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; - - - case FileLinkInformation: - { - Status = Ext2SetLinkInfo(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; - __leave; - } - - FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer; - - if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) && - (FilePositionInformation->CurrentByteOffset.LowPart & - DeviceObject->AlignmentRequirement) ) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - FileObject->CurrentByteOffset = - FilePositionInformation->CurrentByteOffset; - - Status = STATUS_SUCCESS; - __leave; - } - - break; - - default: - DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n", - FileInformationClass)); - Status = STATUS_INVALID_PARAMETER;/* STATUS_INVALID_INFO_CLASS; */ - } - - } __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 (!IrpContext->ExceptionInProgress) { - if (Status == STATUS_PENDING || - Status == STATUS_CANT_WAIT ) { - DbgBreak(); - Status = Ext2QueueRequest(IrpContext); - } else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - 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)); - - if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { - /* always allow deleting on symlinks */ - } else { - 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 bFcbLockAcquired = 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; - } - - if (!bFcbLockAcquired) { - ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); - bFcbLockAcquired = TRUE; - } - - TargetDcb = TargetMcb->Fcb; - if (TargetDcb == NULL) { - TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); - } - if (TargetDcb) { - Ext2ReferXcb(&TargetDcb->ReferenceCount); - } - - 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); - } - - if (bFcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - bFcbLockAcquired = FALSE; - } - - 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 (bFcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - bFcbLockAcquired = FALSE; - } - - if (NewEntry) - Ext2FreeEntry(NewEntry); - - if (TargetDcb) { - Ext2ReleaseFcb(TargetDcb); - } - - if (ParentDcb) { - Ext2ReleaseFcb(ParentDcb); - } - - if (ExistingMcb) - Ext2DerefMcb(ExistingMcb); - - return Status; -} - -NTSTATUS -Ext2SetLinkInfo( - 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; - PEXT2_MCB LinkMcb = NULL; /* Mcb for new hardlink */ - - UNICODE_STRING FileName; - - NTSTATUS Status; - - PIRP Irp; - PIO_STACK_LOCATION IrpSp; - - PFILE_OBJECT FileObject; - PFILE_OBJECT TargetObject; - - BOOLEAN ReplaceIfExists; - BOOLEAN bTargetRemoved = FALSE; - - BOOLEAN bFcbLockAcquired = FALSE; - - PFILE_LINK_INFORMATION FLI; - - if (Ccb->SymLink) { - Mcb = Ccb->SymLink; - } - - if (IsMcbDirectory(Mcb)) { - 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; - - FLI = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - if (TargetObject == NULL) { - - UNICODE_STRING NewName; - - NewName.Buffer = FLI->FileName; - NewName.MaximumLength = NewName.Length = (USHORT)FLI->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)(FLI->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; - } - } - - ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); - bFcbLockAcquired = TRUE; - - TargetDcb = TargetMcb->Fcb; - if (TargetDcb == NULL) { - TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); - } - if (TargetDcb) { - Ext2ReferXcb(&TargetDcb->ReferenceCount); - } - - 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); - } - - if (bFcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - bFcbLockAcquired = FALSE; - } - - if (!TargetDcb || !ParentDcb) { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; - } - - DEBUG(DL_RES, ("Ext2SetLinkInfo: %wZ\\%wZ -> %wZ\n", - &TargetMcb->FullName, &FileName, &Mcb->FullName)); - - 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; - } - } - - /* add new entry for new target name */ - Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, NULL); - if (!NT_SUCCESS(Status)) { - DEBUG(DL_REN, ("Ext2SetLinkInfo: Failed to add entry for %wZ with status: %xh.\n", - &FileName, Status)); - goto errorout; - } - - 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)) { - - Ext2LookupFile(IrpContext, Vcb, &FileName, TargetMcb, &LinkMcb, 0); - if (!LinkMcb) - goto errorout; - - Ext2NotifyReportChange( - IrpContext, - Vcb, - LinkMcb, - FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_ADDED); - } - -errorout: - - if (bFcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - bFcbLockAcquired = FALSE; - } - - if (TargetDcb) { - Ext2ReleaseFcb(TargetDcb); - } - - if (ParentDcb) { - Ext2ReleaseFcb(ParentDcb); - } - - if (ExistingMcb) - Ext2DerefMcb(ExistingMcb); - - if (LinkMcb) - Ext2DerefMcb(LinkMcb); - - 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 bFcbLockAcquired = 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; - } - } - - __try { - - Ext2ReferMcb(Mcb); - - ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); - VcbResourceAcquired = TRUE; - - ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); - bFcbLockAcquired = TRUE; - - /* Mcb->Parent could be NULL when working with layered file systems */ - if (Mcb->Parent) { - Dcb = Mcb->Parent->Fcb; - if (!Dcb) - Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent); - } - if (Dcb) - Ext2ReferXcb(&Dcb->ReferenceCount); - - if (bFcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - bFcbLockAcquired = FALSE; - } - - if (Dcb) { - 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; - __leave; - } - } else if (!IsMcbDirectory(Mcb)) { - if (Mcb->Inode.i_nlink > 0) { - __leave; - } - } else { - if (Mcb->Inode.i_nlink >= 2) { - __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)); - } - - } __finally { - - if (FcbPagingIoAcquired) { - ExReleaseResourceLite(&Fcb->PagingIoResource); - } - - if (FcbResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (DcbResourceAcquired) { - ExReleaseResourceLite(&Dcb->MainResource); - } - - if (bFcbLockAcquired) { - ExReleaseResourceLite(&Vcb->FcbLock); - } - - if (VcbResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - - if (Dcb) { - Ext2ReleaseFcb(Dcb); - } - - Ext2DerefMcb(Mcb); - } - - DEBUG(DL_INF, ( "Ext2DeleteFile: %wZ Succeed... EXT2SB->S_FREE_BLOCKS = %I64xh .\n", - &Mcb->FullName, ext3_free_blocks_count(SUPER_BLOCK))); - - return Status; -} +/* + * 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 "linux\ext4.h" +#include "linux\ext4_xattr.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, Ext2QueryFileInformation) +#pragma alloc_text(PAGE, Ext2SetFileInformation) +#pragma alloc_text(PAGE, Ext2ExpandFile) +#pragma alloc_text(PAGE, Ext2TruncateFile) +#pragma alloc_text(PAGE, Ext2SetDispositionInfo) +#pragma alloc_text(PAGE, Ext2SetRenameInfo) +#pragma alloc_text(PAGE, Ext2SetLinkInfo) +#pragma alloc_text(PAGE, Ext2DeleteFile) +#endif + +static int Ext2IterateAllEa(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item, BOOL is_last) +{ + PULONG EaSize = xattr_ref->iter_arg; + ULONG EaEntrySize = 4 + 1 + 1 + 2 + item->name_len + 1 + item->data_size; + + *EaSize += EaEntrySize - 4; + return EXT4_XATTR_ITERATE_CONT; +} + +NTSTATUS +Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFILE_OBJECT FileObject; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_MCB Mcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG Length; + PVOID Buffer; + BOOLEAN FcbResourceAcquired = FALSE; + + __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; + __leave; + } + + FileObject = IrpContext->FileObject; + Fcb = (PEXT2_FCB) FileObject->FsContext; + if (Fcb == NULL) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + // + // This request is not allowed on volumes + // + if (Fcb->Identifier.Type == EXT2VCB) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (!((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB)))) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + Vcb = Fcb->Vcb; + + { + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) + )) { + + Status = STATUS_PENDING; + __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; + __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; + __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; + __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: + { + struct ext4_xattr_ref xattr_ref; + PFILE_EA_INFORMATION FileEaInformation; + + if (Length < sizeof(FILE_EA_INFORMATION)) { + Status = STATUS_BUFFER_OVERFLOW; + __leave; + } + + FileEaInformation = (PFILE_EA_INFORMATION) Buffer; + FileEaInformation->EaSize = 0; + + Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); + if (!NT_SUCCESS(Status)) + __leave; + + xattr_ref.iter_arg = &FileEaInformation->EaSize; + ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); + ext4_fs_put_xattr_ref(&xattr_ref); + + if (FileEaInformation->EaSize) + FileEaInformation->EaSize += 4; + + 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; + __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; + __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) + ); + __leave; + } + + RtlCopyMemory( + FileNameInformation->FileName, + Mcb->ShortName.Buffer, + Mcb->ShortName.Length + ); + + Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) + + Mcb->ShortName.Length - sizeof(WCHAR); + + 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; + __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; + __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; + } + + } __finally { + + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (!IrpContext->ExceptionInProgress) { + if (Status == STATUS_PENDING || + Status == STATUS_CANT_WAIT) { + Status = Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} + + +NTSTATUS +Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PEXT2_VCB Vcb = NULL; + PFILE_OBJECT FileObject = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + FILE_INFORMATION_CLASS FileInformationClass; + + ULONG NotifyFilter = 0; + + ULONG Length; + PVOID Buffer; + + BOOLEAN FcbMainResourceAcquired = FALSE; + BOOLEAN FcbPagingIoResourceAcquired = FALSE; + + __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; + __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; + __leave; + } + + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { + Status = STATUS_ACCESS_DENIED; + __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; + __leave; + } + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { + Status = STATUS_FILE_DELETED; + __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; + __leave; + } + } else { + Mcb = Fcb->Mcb; + } + + if (FileInformationClass != FilePositionInformation) { + if (IsVcbReadOnly(Vcb)) { + Status = STATUS_MEDIA_WRITE_PROTECTED; + __leave; + } + if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) { + Status = STATUS_ACCESS_DENIED; + __leave; + } + } + + 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) { + __leave; + } + + // + // Set the flag indicating if Fast I/O is possible + // + + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + } + + /* for renaming or set link, we must not grab any Fcb locks, + and later we will get Dcb or Fcb resources exclusively. */ + if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) && + FileInformationClass != FileRenameInformation && + FileInformationClass != FileLinkInformation) { + + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + __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(); + __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; + __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(); + __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; + __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)) { + __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; + } + + __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(); + __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; + __leave; + } else { + Status = STATUS_SUCCESS; + } + + NewVDL = FVDL->ValidDataLength; + if ((NewVDL.QuadPart < Fcb->Header.ValidDataLength.QuadPart)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + if (NewVDL.QuadPart > Fcb->Header.FileSize.QuadPart) + NewVDL = Fcb->Header.FileSize; + + if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, + &NewVDL)) { + Status = STATUS_USER_MAPPED_FILE; + __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; + + + case FileLinkInformation: + { + Status = Ext2SetLinkInfo(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; + __leave; + } + + FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer; + + if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) && + (FilePositionInformation->CurrentByteOffset.LowPart & + DeviceObject->AlignmentRequirement) ) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + FileObject->CurrentByteOffset = + FilePositionInformation->CurrentByteOffset; + + Status = STATUS_SUCCESS; + __leave; + } + + break; + + default: + DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n", + FileInformationClass)); + Status = STATUS_INVALID_PARAMETER;/* STATUS_INVALID_INFO_CLASS; */ + } + + } __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 (!IrpContext->ExceptionInProgress) { + if (Status == STATUS_PENDING || + Status == STATUS_CANT_WAIT ) { + DbgBreak(); + Status = Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + 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)); + + if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { + /* always allow deleting on symlinks */ + } else { + 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 bFcbLockAcquired = 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; + } + + if (!bFcbLockAcquired) { + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + } + + TargetDcb = TargetMcb->Fcb; + if (TargetDcb == NULL) { + TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); + } + if (TargetDcb) { + Ext2ReferXcb(&TargetDcb->ReferenceCount); + } + + 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); + } + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } + + 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 (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } + + if (NewEntry) + Ext2FreeEntry(NewEntry); + + if (TargetDcb) { + Ext2ReleaseFcb(TargetDcb); + } + + if (ParentDcb) { + Ext2ReleaseFcb(ParentDcb); + } + + if (ExistingMcb) + Ext2DerefMcb(ExistingMcb); + + return Status; +} + +NTSTATUS +Ext2SetLinkInfo( + 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; + PEXT2_MCB LinkMcb = NULL; /* Mcb for new hardlink */ + + UNICODE_STRING FileName; + + NTSTATUS Status; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + PFILE_OBJECT FileObject; + PFILE_OBJECT TargetObject; + + BOOLEAN ReplaceIfExists; + BOOLEAN bTargetRemoved = FALSE; + + BOOLEAN bFcbLockAcquired = FALSE; + + PFILE_LINK_INFORMATION FLI; + + if (Ccb->SymLink) { + Mcb = Ccb->SymLink; + } + + if (IsMcbDirectory(Mcb)) { + 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; + + FLI = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + if (TargetObject == NULL) { + + UNICODE_STRING NewName; + + NewName.Buffer = FLI->FileName; + NewName.MaximumLength = NewName.Length = (USHORT)FLI->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)(FLI->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; + } + } + + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + + TargetDcb = TargetMcb->Fcb; + if (TargetDcb == NULL) { + TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); + } + if (TargetDcb) { + Ext2ReferXcb(&TargetDcb->ReferenceCount); + } + + 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); + } + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } + + if (!TargetDcb || !ParentDcb) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + + DEBUG(DL_RES, ("Ext2SetLinkInfo: %wZ\\%wZ -> %wZ\n", + &TargetMcb->FullName, &FileName, &Mcb->FullName)); + + 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; + } + } + + /* add new entry for new target name */ + Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, NULL); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_REN, ("Ext2SetLinkInfo: Failed to add entry for %wZ with status: %xh.\n", + &FileName, Status)); + goto errorout; + } + + 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)) { + + Ext2LookupFile(IrpContext, Vcb, &FileName, TargetMcb, &LinkMcb, 0); + if (!LinkMcb) + goto errorout; + + Ext2NotifyReportChange( + IrpContext, + Vcb, + LinkMcb, + FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_ADDED); + } + +errorout: + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } + + if (TargetDcb) { + Ext2ReleaseFcb(TargetDcb); + } + + if (ParentDcb) { + Ext2ReleaseFcb(ParentDcb); + } + + if (ExistingMcb) + Ext2DerefMcb(ExistingMcb); + + if (LinkMcb) + Ext2DerefMcb(LinkMcb); + + 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 bFcbLockAcquired = 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; + } + } + + __try { + + Ext2ReferMcb(Mcb); + + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + VcbResourceAcquired = TRUE; + + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + + /* Mcb->Parent could be NULL when working with layered file systems */ + if (Mcb->Parent) { + Dcb = Mcb->Parent->Fcb; + if (!Dcb) + Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent); + } + if (Dcb) + Ext2ReferXcb(&Dcb->ReferenceCount); + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } + + if (Dcb) { + 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; + __leave; + } + } else if (!IsMcbDirectory(Mcb)) { + if (Mcb->Inode.i_nlink > 0) { + __leave; + } + } else { + if (Mcb->Inode.i_nlink >= 2) { + __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)); + } + + } __finally { + + if (FcbPagingIoAcquired) { + ExReleaseResourceLite(&Fcb->PagingIoResource); + } + + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (DcbResourceAcquired) { + ExReleaseResourceLite(&Dcb->MainResource); + } + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + } + + if (VcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + } + + if (Dcb) { + Ext2ReleaseFcb(Dcb); + } + + Ext2DerefMcb(Mcb); + } + + 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/Ext4Fsd/flush.c b/Ext4Fsd/flush.c index 65d6bf5..999e3d7 100644 --- a/Ext4Fsd/flush.c +++ b/Ext4Fsd/flush.c @@ -1,277 +1,277 @@ -/* - * 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 -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 -Ext2FlushVolume ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN BOOLEAN bShutDown -) -{ - DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n")); - - ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); - ExReleaseResourceLite(&Vcb->PagingIoResource); - - return Ext2FlushVcb(Vcb); -} - -NTSTATUS -Ext2FlushFile ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_FCB Fcb, - IN PEXT2_CCB Ccb -) -{ - IO_STATUS_BLOCK IoStatus = {0}; - - ASSERT(Fcb != NULL); - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - __try { - - /* do nothing if target fie was deleted */ - if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { - IoStatus.Status = STATUS_FILE_DELETED; - __leave; - } - - /* 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)) { - IoStatus.Status = STATUS_SUCCESS; - __leave; - } - - 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); - - } __finally { - - /* do cleanup here */ - } - - return IoStatus.Status; -} - -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); - Ext2FlushFile(IrpContext, Fcb, NULL); - ExReleaseResourceLite(&Fcb->MainResource); - } - - 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; - - __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; - __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; - __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; - __leave; - } - - MainResourceAcquired = - ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE); - 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)) { - __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))); - - - } __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); - } - } - - return Status; +/* + * 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 +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 +Ext2FlushVolume ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN BOOLEAN bShutDown +) +{ + DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n")); + + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + return Ext2FlushVcb(Vcb); +} + +NTSTATUS +Ext2FlushFile ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_FCB Fcb, + IN PEXT2_CCB Ccb +) +{ + IO_STATUS_BLOCK IoStatus = {0}; + + ASSERT(Fcb != NULL); + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + __try { + + /* do nothing if target fie was deleted */ + if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { + IoStatus.Status = STATUS_FILE_DELETED; + __leave; + } + + /* 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)) { + IoStatus.Status = STATUS_SUCCESS; + __leave; + } + + 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); + + } __finally { + + /* do cleanup here */ + } + + return IoStatus.Status; +} + +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); + Ext2FlushFile(IrpContext, Fcb, NULL); + ExReleaseResourceLite(&Fcb->MainResource); + } + + 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; + + __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; + __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; + __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; + __leave; + } + + MainResourceAcquired = + ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE); + 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)) { + __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))); + + + } __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); + } + } + + return Status; } \ No newline at end of file diff --git a/Ext4Fsd/include/common.h b/Ext4Fsd/include/common.h index a62513f..ccc6902 100644 --- a/Ext4Fsd/include/common.h +++ b/Ext4Fsd/include/common.h @@ -1,261 +1,261 @@ -#ifndef _EXT2_COMMON_INCLUDE_ -#define _EXT2_COMMON_INCLUDE_ - -/* global ioctl */ -#define IOCTL_APP_VOLUME_PROPERTY \ -CTL_CODE(FILE_DEVICE_UNKNOWN, 2000, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_APP_QUERY_PERFSTAT \ -CTL_CODE(FILE_DEVICE_UNKNOWN, 2001, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_APP_MOUNT_POINT \ -CTL_CODE(FILE_DEVICE_UNKNOWN, 2002, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -/* performance / memory allocaiton statistics */ -#define PS_IRP_CONTEXT 0x00 -#define PS_VCB 0x01 -#define PS_FCB 0x02 -#define PS_CCB 0x03 -#define PS_MCB 0x04 -#define PS_EXTENT 0x05 -#define PS_RW_CONTEXT 0x06 -#define PS_VPB 0x07 -#define PS_FILE_NAME 0x08 -#define PS_MCB_NAME 0x09 -#define PS_INODE_NAME 0x0A -#define PS_DIR_ENTRY 0x0B -#define PS_DIR_PATTERN 0x0C -#define PS_DISK_EVENT 0x0D -#define PS_DISK_BUFFER 0x0E -#define PS_BLOCK_DATA 0x0F - -#define PS_EXT2_INODE 0x10 -#define PS_DENTRY 0x11 -#define PS_BUFF_HEAD 0x12 - -#define PS_MAX_TYPE_V1 (0x10) -#define PS_MAX_TYPE_V2 (0x30) - -typedef union { - - ULONG Slot[PS_MAX_TYPE_V1]; - - struct { - ULONG IrpContext; - ULONG Vcb; - ULONG Fcb; - ULONG Ccb; - ULONG Mcb; - ULONG Extent; - ULONG RwContext; /* rw context */ - ULONG Vpb; - ULONG FileName; - ULONG McbName; - ULONG InodeName; - ULONG DirEntry; /* pDir */ - ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */ - ULONG ReadDiskEvent; - ULONG ReadDiskBuffer; - ULONG BlockData; /* Ext2Expand&TruncateFile*/ - }; - -} EXT2_STAT_ARRAY_V1; - -typedef union { - - ULONG Slot[PS_MAX_TYPE_V2]; - - struct { - ULONG IrpContext; - ULONG Vcb; - ULONG Fcb; - ULONG Ccb; - ULONG Mcb; - ULONG Extent; - ULONG RwContext; /* rw context */ - ULONG Vpb; - ULONG FileName; - ULONG McbName; - ULONG InodeName; - ULONG DirEntry; /* pDir */ - ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */ - ULONG ReadDiskEvent; - ULONG ReadDiskBuffer; - ULONG BlockData; /* Ext2Expand&TruncateFile*/ - ULONG Inodes; /* inodes */ - ULONG NameEntries; /* name dentry */ - ULONG BufferHead; /* Buffer Header allocations */ - }; - -} EXT2_STAT_ARRAY_V2; - -typedef struct _EXT2_PERF_STATISTICS_V1 { - - /* totoal number of processed/being processed requests */ - struct { - ULONG Processed; - ULONG Current; - } Irps [IRP_MJ_MAXIMUM_FUNCTION + 1]; - - /* structure size */ - EXT2_STAT_ARRAY_V1 Unit; - - /* current memory allocation statistics */ - EXT2_STAT_ARRAY_V1 Current; - - /* memory allocated in bytes */ - EXT2_STAT_ARRAY_V1 Size; - - /* totoal memory allocation statistics */ - EXT2_STAT_ARRAY_V1 Total; - -} EXT2_PERF_STATISTICS_V1, *PEXT2_PERF_STATISTICS_V1; - -#define EXT2_PERF_STAT_MAGIC '2SPE' -#define EXT2_PERF_STAT_VER2 2 - -typedef struct _EXT2_PERF_STATISTICS_V2 { - - ULONG Magic; /* EPS2 */ - USHORT Version; /* 02 */ - USHORT Length; /* sizeof(EXT2_PERF_STATISTICS_V2) */ - - /* totoal number of processed/being processed requests */ - struct { - ULONG Processed; - ULONG Current; - } Irps [IRP_MJ_MAXIMUM_FUNCTION + 1]; - - /* structure size */ - EXT2_STAT_ARRAY_V2 Unit; - - /* current memory allocation statistics */ - EXT2_STAT_ARRAY_V2 Current; - - /* memory allocated in bytes */ - EXT2_STAT_ARRAY_V2 Size; - - /* totoal memory allocation statistics */ - EXT2_STAT_ARRAY_V2 Total; - -} EXT2_PERF_STATISTICS_V2, *PEXT2_PERF_STATISTICS_V2; - -/* volume property ... */ - -#define EXT2_VOLUME_PROPERTY_MAGIC 'EVPM' - -#define EXT2_FLAG_VP_SET_GLOBAL 0x00000001 - -#define APP_CMD_QUERY_VERSION 0x00000000 /* with global flag set */ -#define APP_CMD_QUERY_CODEPAGES 0x00000001 -#define APP_CMD_QUERY_PROPERTY 0x00000002 -#define APP_CMD_SET_PROPERTY 0x00000003 -#define APP_CMD_QUERY_PROPERTY2 0x00000004 -#define APP_CMD_SET_PROPERTY2 0x00000005 -#define APP_CMD_QUERY_PROPERTY3 0x00000006 -#define APP_CMD_SET_PROPERTY3 0x00000007 - -#define CODEPAGE_MAXLEN 0x20 -#define HIDINGPAT_LEN 0x20 - -typedef struct _EXT2_VOLUME_PROPERTY { - ULONG Magic; - ULONG Flags; - ULONG Command; - BOOLEAN bReadonly; - BOOLEAN bExt3Writable; - BOOLEAN bExt2; - BOOLEAN bExt3; - CHAR Codepage[CODEPAGE_MAXLEN]; -} EXT2_VOLUME_PROPERTY, *PEXT2_VOLUME_PROPERTY; - -#ifdef __cplusplus -typedef struct _EXT2_VOLUME_PROPERTY2:EXT2_VOLUME_PROPERTY { -#else // __cplusplus -typedef struct _EXT2_VOLUME_PROPERTY2 { - EXT2_VOLUME_PROPERTY ; -#endif // __cplusplus - - /* new volume properties added after version 0.35 */ - - /* volume uuid */ - __u8 UUID[16]; - - /* mount point: driver letter only */ - UCHAR DrvLetter; - - /* checking bitmap */ - BOOLEAN bCheckBitmap; - - /* global hiding patterns */ - BOOLEAN bHidingPrefix; - BOOLEAN bHidingSuffix; - CHAR sHidingPrefix[HIDINGPAT_LEN]; - CHAR sHidingSuffix[HIDINGPAT_LEN]; - -} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2; - -#define EXT2_VPROP3_AUTOMOUNT (1ui64 << 0) -#define EXT2_VPROP3_USERIDS (1ui64 << 1) - -#ifdef __cplusplus -typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 { -#else // __cplusplus -typedef struct _EXT2_VOLUME_PROPERTY3 { - EXT2_VOLUME_PROPERTY2 ; -#endif // __cplusplus - unsigned __int64 Flags2; - ULONG AutoMount:1; - ULONG EIDS:1; - ULONG Reserved1:30; - USHORT uid; - USHORT gid; - USHORT euid; - USHORT egid; - ULONG Reserved2[29]; -} EXT2_VOLUME_PROPERTY3, *PEXT2_VOLUME_PROPERTY3; - -/* Ext2Fsd driver version and built time */ -typedef struct _EXT2_VOLUME_PROPERTY_VERSION { - ULONG Magic; - ULONG Flags; - ULONG Command; - CHAR Version[0x1C]; - CHAR Time[0x20]; - CHAR Date[0x20]; -} EXT2_VOLUME_PROPERTY_VERSION, *PEXT2_VOLUME_PROPERTY_VERSION; - -/* performance statistics */ -#define EXT2_QUERY_PERFSTAT_MAGIC 'EVPM' -#define EXT2_QUERY_PERFSTAT_VER2 0x8000000 - -typedef struct _EXT2_QUERY_PERFSTAT { - ULONG Magic; - ULONG Flags; - ULONG Command; - union { - EXT2_PERF_STATISTICS_V1 PerfStatV1; - EXT2_PERF_STATISTICS_V2 PerfStatV2; - }; -} EXT2_QUERY_PERFSTAT, *PEXT2_QUERY_PERFSTAT; - -#define EXT2_QUERY_PERFSTAT_SZV1 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V1)) -#define EXT2_QUERY_PERFSTAT_SZV2 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V2)) - -/* mountpoint management */ -#define EXT2_APP_MOUNTPOINT_MAGIC 'EAMM' -typedef struct _EXT2_MOUNT_POINT { - ULONG Magic; - ULONG Flags; - ULONG Size; - ULONG Command; - USHORT Link[256]; - USHORT Name[256]; -} EXT2_MOUNT_POINT, *PEXT2_MOUNT_POINT; - -#define APP_CMD_ADD_DOS_SYMLINK 0x00000001 -#define APP_CMD_DEL_DOS_SYMLINK 0x00000002 - - -#endif /* _EXT2_COMMON_INCLUDE_ */ +#ifndef _EXT2_COMMON_INCLUDE_ +#define _EXT2_COMMON_INCLUDE_ + +/* global ioctl */ +#define IOCTL_APP_VOLUME_PROPERTY \ +CTL_CODE(FILE_DEVICE_UNKNOWN, 2000, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_APP_QUERY_PERFSTAT \ +CTL_CODE(FILE_DEVICE_UNKNOWN, 2001, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_APP_MOUNT_POINT \ +CTL_CODE(FILE_DEVICE_UNKNOWN, 2002, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +/* performance / memory allocaiton statistics */ +#define PS_IRP_CONTEXT 0x00 +#define PS_VCB 0x01 +#define PS_FCB 0x02 +#define PS_CCB 0x03 +#define PS_MCB 0x04 +#define PS_EXTENT 0x05 +#define PS_RW_CONTEXT 0x06 +#define PS_VPB 0x07 +#define PS_FILE_NAME 0x08 +#define PS_MCB_NAME 0x09 +#define PS_INODE_NAME 0x0A +#define PS_DIR_ENTRY 0x0B +#define PS_DIR_PATTERN 0x0C +#define PS_DISK_EVENT 0x0D +#define PS_DISK_BUFFER 0x0E +#define PS_BLOCK_DATA 0x0F + +#define PS_EXT2_INODE 0x10 +#define PS_DENTRY 0x11 +#define PS_BUFF_HEAD 0x12 + +#define PS_MAX_TYPE_V1 (0x10) +#define PS_MAX_TYPE_V2 (0x30) + +typedef union { + + ULONG Slot[PS_MAX_TYPE_V1]; + + struct { + ULONG IrpContext; + ULONG Vcb; + ULONG Fcb; + ULONG Ccb; + ULONG Mcb; + ULONG Extent; + ULONG RwContext; /* rw context */ + ULONG Vpb; + ULONG FileName; + ULONG McbName; + ULONG InodeName; + ULONG DirEntry; /* pDir */ + ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */ + ULONG ReadDiskEvent; + ULONG ReadDiskBuffer; + ULONG BlockData; /* Ext2Expand&TruncateFile*/ + }; + +} EXT2_STAT_ARRAY_V1; + +typedef union { + + ULONG Slot[PS_MAX_TYPE_V2]; + + struct { + ULONG IrpContext; + ULONG Vcb; + ULONG Fcb; + ULONG Ccb; + ULONG Mcb; + ULONG Extent; + ULONG RwContext; /* rw context */ + ULONG Vpb; + ULONG FileName; + ULONG McbName; + ULONG InodeName; + ULONG DirEntry; /* pDir */ + ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */ + ULONG ReadDiskEvent; + ULONG ReadDiskBuffer; + ULONG BlockData; /* Ext2Expand&TruncateFile*/ + ULONG Inodes; /* inodes */ + ULONG NameEntries; /* name dentry */ + ULONG BufferHead; /* Buffer Header allocations */ + }; + +} EXT2_STAT_ARRAY_V2; + +typedef struct _EXT2_PERF_STATISTICS_V1 { + + /* totoal number of processed/being processed requests */ + struct { + ULONG Processed; + ULONG Current; + } Irps [IRP_MJ_MAXIMUM_FUNCTION + 1]; + + /* structure size */ + EXT2_STAT_ARRAY_V1 Unit; + + /* current memory allocation statistics */ + EXT2_STAT_ARRAY_V1 Current; + + /* memory allocated in bytes */ + EXT2_STAT_ARRAY_V1 Size; + + /* totoal memory allocation statistics */ + EXT2_STAT_ARRAY_V1 Total; + +} EXT2_PERF_STATISTICS_V1, *PEXT2_PERF_STATISTICS_V1; + +#define EXT2_PERF_STAT_MAGIC '2SPE' +#define EXT2_PERF_STAT_VER2 2 + +typedef struct _EXT2_PERF_STATISTICS_V2 { + + ULONG Magic; /* EPS2 */ + USHORT Version; /* 02 */ + USHORT Length; /* sizeof(EXT2_PERF_STATISTICS_V2) */ + + /* totoal number of processed/being processed requests */ + struct { + ULONG Processed; + ULONG Current; + } Irps [IRP_MJ_MAXIMUM_FUNCTION + 1]; + + /* structure size */ + EXT2_STAT_ARRAY_V2 Unit; + + /* current memory allocation statistics */ + EXT2_STAT_ARRAY_V2 Current; + + /* memory allocated in bytes */ + EXT2_STAT_ARRAY_V2 Size; + + /* totoal memory allocation statistics */ + EXT2_STAT_ARRAY_V2 Total; + +} EXT2_PERF_STATISTICS_V2, *PEXT2_PERF_STATISTICS_V2; + +/* volume property ... */ + +#define EXT2_VOLUME_PROPERTY_MAGIC 'EVPM' + +#define EXT2_FLAG_VP_SET_GLOBAL 0x00000001 + +#define APP_CMD_QUERY_VERSION 0x00000000 /* with global flag set */ +#define APP_CMD_QUERY_CODEPAGES 0x00000001 +#define APP_CMD_QUERY_PROPERTY 0x00000002 +#define APP_CMD_SET_PROPERTY 0x00000003 +#define APP_CMD_QUERY_PROPERTY2 0x00000004 +#define APP_CMD_SET_PROPERTY2 0x00000005 +#define APP_CMD_QUERY_PROPERTY3 0x00000006 +#define APP_CMD_SET_PROPERTY3 0x00000007 + +#define CODEPAGE_MAXLEN 0x20 +#define HIDINGPAT_LEN 0x20 + +typedef struct _EXT2_VOLUME_PROPERTY { + ULONG Magic; + ULONG Flags; + ULONG Command; + BOOLEAN bReadonly; + BOOLEAN bExt3Writable; + BOOLEAN bExt2; + BOOLEAN bExt3; + CHAR Codepage[CODEPAGE_MAXLEN]; +} EXT2_VOLUME_PROPERTY, *PEXT2_VOLUME_PROPERTY; + +#ifdef __cplusplus +typedef struct _EXT2_VOLUME_PROPERTY2:EXT2_VOLUME_PROPERTY { +#else // __cplusplus +typedef struct _EXT2_VOLUME_PROPERTY2 { + EXT2_VOLUME_PROPERTY ; +#endif // __cplusplus + + /* new volume properties added after version 0.35 */ + + /* volume uuid */ + __u8 UUID[16]; + + /* mount point: driver letter only */ + UCHAR DrvLetter; + + /* checking bitmap */ + BOOLEAN bCheckBitmap; + + /* global hiding patterns */ + BOOLEAN bHidingPrefix; + BOOLEAN bHidingSuffix; + CHAR sHidingPrefix[HIDINGPAT_LEN]; + CHAR sHidingSuffix[HIDINGPAT_LEN]; + +} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2; + +#define EXT2_VPROP3_AUTOMOUNT (1ui64 << 0) +#define EXT2_VPROP3_USERIDS (1ui64 << 1) + +#ifdef __cplusplus +typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 { +#else // __cplusplus +typedef struct _EXT2_VOLUME_PROPERTY3 { + EXT2_VOLUME_PROPERTY2 ; +#endif // __cplusplus + unsigned __int64 Flags2; + ULONG AutoMount:1; + ULONG EIDS:1; + ULONG Reserved1:30; + USHORT uid; + USHORT gid; + USHORT euid; + USHORT egid; + ULONG Reserved2[29]; +} EXT2_VOLUME_PROPERTY3, *PEXT2_VOLUME_PROPERTY3; + +/* Ext2Fsd driver version and built time */ +typedef struct _EXT2_VOLUME_PROPERTY_VERSION { + ULONG Magic; + ULONG Flags; + ULONG Command; + CHAR Version[0x1C]; + CHAR Time[0x20]; + CHAR Date[0x20]; +} EXT2_VOLUME_PROPERTY_VERSION, *PEXT2_VOLUME_PROPERTY_VERSION; + +/* performance statistics */ +#define EXT2_QUERY_PERFSTAT_MAGIC 'EVPM' +#define EXT2_QUERY_PERFSTAT_VER2 0x8000000 + +typedef struct _EXT2_QUERY_PERFSTAT { + ULONG Magic; + ULONG Flags; + ULONG Command; + union { + EXT2_PERF_STATISTICS_V1 PerfStatV1; + EXT2_PERF_STATISTICS_V2 PerfStatV2; + }; +} EXT2_QUERY_PERFSTAT, *PEXT2_QUERY_PERFSTAT; + +#define EXT2_QUERY_PERFSTAT_SZV1 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V1)) +#define EXT2_QUERY_PERFSTAT_SZV2 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V2)) + +/* mountpoint management */ +#define EXT2_APP_MOUNTPOINT_MAGIC 'EAMM' +typedef struct _EXT2_MOUNT_POINT { + ULONG Magic; + ULONG Flags; + ULONG Size; + ULONG Command; + USHORT Link[256]; + USHORT Name[256]; +} EXT2_MOUNT_POINT, *PEXT2_MOUNT_POINT; + +#define APP_CMD_ADD_DOS_SYMLINK 0x00000001 +#define APP_CMD_DEL_DOS_SYMLINK 0x00000002 + + +#endif /* _EXT2_COMMON_INCLUDE_ */ diff --git a/Ext4Fsd/include/linux/atomic.h b/Ext4Fsd/include/linux/atomic.h index 1f43294..7677cff 100644 --- a/Ext4Fsd/include/linux/atomic.h +++ b/Ext4Fsd/include/linux/atomic.h @@ -1,155 +1,155 @@ -#ifndef _LINUX_ATOMIC_H -#define _LINUX_ATOMIC_H - -#include - -// -// atomic -// - -typedef struct { - volatile LONG counter; -} atomic_t; - -#define ATOMIC_INIT(i) (i) - -/** - * atomic_read - read atomic variable - * @v: pointer of type atomic_t - * - * Atomically reads the value of @v. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -#define atomic_read(v) ((v)->counter) - -/** - * atomic_set - set atomic variable - * @v: pointer of type atomic_t - * @i: required value - * - * Atomically sets the value of @v to @i. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -#define atomic_set(v,i) InterlockedExchange((PLONG)(&(v)->counter), (LONG)(i)) - -/** - * atomic_add - add integer to atomic variable - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v. Note that the guaranteed useful range - * of an atomic_t is only 24 bits. - */ -static inline void atomic_add(int volatile i, atomic_t volatile *v) -{ - InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i); -} - -/** - * atomic_sub - subtract the atomic variable - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically subtracts @i from @v. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline void atomic_sub(int volatile i, atomic_t volatile *v) -{ - InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) (-1*i)); -} - -/** - * atomic_sub_and_test - subtract value from variable and test result - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically subtracts @i from @v and returns - * true if the result is zero, or false for all - * other cases. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline int atomic_sub_and_test(int volatile i, atomic_t volatile *v) -{ - int counter, result; - - do { - - counter = v->counter; - result = counter - i; - - } while ( InterlockedCompareExchange( - (PLONG) (&v->counter), - (LONG) result, - (LONG) counter) != counter); - - return (result == 0); -} - -/** - * atomic_inc - increment atomic variable - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline void atomic_inc(atomic_t volatile *v) -{ - InterlockedIncrement((PLONG)(&v->counter)); -} - -/** - * atomic_dec - decrement atomic variable - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline void atomic_dec(atomic_t volatile *v) -{ - InterlockedDecrement((PLONG)(&v->counter)); -} - -/** - * atomic_dec_and_test - decrement and test - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline int atomic_dec_and_test(atomic_t volatile *v) -{ - return (0 == InterlockedDecrement((PLONG)(&v->counter))); -} - -/** - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline int atomic_inc_and_test(atomic_t volatile *v) -{ - return (0 == InterlockedIncrement((PLONG)(&v->counter))); -} - -/** - * atomic_add_negative - add and test if negative - * @v: pointer of type atomic_t - * @i: integer value to add - * - * Atomically adds @i to @v and returns true - * if the result is negative, or false when - * result is greater than or equal to zero. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static inline int atomic_add_negative(int volatile i, atomic_t volatile *v) -{ - return (InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i) + i); -} - +#ifndef _LINUX_ATOMIC_H +#define _LINUX_ATOMIC_H + +#include + +// +// atomic +// + +typedef struct { + volatile LONG counter; +} atomic_t; + +#define ATOMIC_INIT(i) (i) + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) InterlockedExchange((PLONG)(&(v)->counter), (LONG)(i)) + +/** + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. + */ +static inline void atomic_add(int volatile i, atomic_t volatile *v) +{ + InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i); +} + +/** + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline void atomic_sub(int volatile i, atomic_t volatile *v) +{ + InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) (-1*i)); +} + +/** + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline int atomic_sub_and_test(int volatile i, atomic_t volatile *v) +{ + int counter, result; + + do { + + counter = v->counter; + result = counter - i; + + } while ( InterlockedCompareExchange( + (PLONG) (&v->counter), + (LONG) result, + (LONG) counter) != counter); + + return (result == 0); +} + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline void atomic_inc(atomic_t volatile *v) +{ + InterlockedIncrement((PLONG)(&v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline void atomic_dec(atomic_t volatile *v) +{ + InterlockedDecrement((PLONG)(&v->counter)); +} + +/** + * atomic_dec_and_test - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline int atomic_dec_and_test(atomic_t volatile *v) +{ + return (0 == InterlockedDecrement((PLONG)(&v->counter))); +} + +/** + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline int atomic_inc_and_test(atomic_t volatile *v) +{ + return (0 == InterlockedIncrement((PLONG)(&v->counter))); +} + +/** + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static inline int atomic_add_negative(int volatile i, atomic_t volatile *v) +{ + return (InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i) + i); +} + #endif /* LINUX_ATOMIC_H */ \ No newline at end of file diff --git a/Ext4Fsd/include/linux/bit_spinlock.h b/Ext4Fsd/include/linux/bit_spinlock.h index d8bd1bf..bb9965a 100644 --- a/Ext4Fsd/include/linux/bit_spinlock.h +++ b/Ext4Fsd/include/linux/bit_spinlock.h @@ -1,95 +1,95 @@ -#ifndef __LINUX_BIT_SPINLOCK_H -#define __LINUX_BIT_SPINLOCK_H - -/* - * bit-based spin_lock() - * - * Don't use this unless you really need to: spin_lock() and spin_unlock() - * are significantly faster. - */ -static inline void bit_spin_lock(int bitnum, unsigned long *addr) -{ - /* - * Assuming the lock is uncontended, this never enters - * the body of the outer loop. If it is contended, then - * within the inner loop a non-atomic test is used to - * busywait with less bus contention for a good time to - * attempt to acquire the lock bit. - */ - preempt_disable(); -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) - while (unlikely(test_and_set_bit_lock(bitnum, addr))) { - while (test_bit(bitnum, addr)) { - preempt_enable(); - cpu_relax(); - preempt_disable(); - } - } -#endif - __acquire(bitlock); -} - -/* - * Return true if it was acquired - */ -static inline int bit_spin_trylock(int bitnum, unsigned long *addr) -{ - preempt_disable(); -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) - if (unlikely(test_and_set_bit_lock(bitnum, addr))) { - preempt_enable(); - return 0; - } -#endif - __acquire(bitlock); - return 1; -} - -/* - * bit-based spin_unlock() - */ -static inline void bit_spin_unlock(int bitnum, unsigned long *addr) -{ -#ifdef CONFIG_DEBUG_SPINLOCK - BUG_ON(!test_bit(bitnum, addr)); -#endif -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) - clear_bit_unlock(bitnum, addr); -#endif - preempt_enable(); - __release(bitlock); -} - -/* - * bit-based spin_unlock() - * non-atomic version, which can be used eg. if the bit lock itself is - * protecting the rest of the flags in the word. - */ -static inline void __bit_spin_unlock(int bitnum, unsigned long *addr) -{ -#ifdef CONFIG_DEBUG_SPINLOCK - BUG_ON(!test_bit(bitnum, addr)); -#endif -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) - __clear_bit_unlock(bitnum, addr); -#endif - preempt_enable(); - __release(bitlock); -} - -/* - * Return true if the lock is held. - */ -static inline int bit_spin_is_locked(int bitnum, unsigned long *addr) -{ -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) - return test_bit(bitnum, addr); -#elif defined CONFIG_PREEMPT - return preempt_count(); -#else - return 1; -#endif -} - -#endif /* __LINUX_BIT_SPINLOCK_H */ - +#ifndef __LINUX_BIT_SPINLOCK_H +#define __LINUX_BIT_SPINLOCK_H + +/* + * bit-based spin_lock() + * + * Don't use this unless you really need to: spin_lock() and spin_unlock() + * are significantly faster. + */ +static inline void bit_spin_lock(int bitnum, unsigned long *addr) +{ + /* + * Assuming the lock is uncontended, this never enters + * the body of the outer loop. If it is contended, then + * within the inner loop a non-atomic test is used to + * busywait with less bus contention for a good time to + * attempt to acquire the lock bit. + */ + preempt_disable(); +#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) + while (unlikely(test_and_set_bit_lock(bitnum, addr))) { + while (test_bit(bitnum, addr)) { + preempt_enable(); + cpu_relax(); + preempt_disable(); + } + } +#endif + __acquire(bitlock); +} + +/* + * Return true if it was acquired + */ +static inline int bit_spin_trylock(int bitnum, unsigned long *addr) +{ + preempt_disable(); +#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) + if (unlikely(test_and_set_bit_lock(bitnum, addr))) { + preempt_enable(); + return 0; + } +#endif + __acquire(bitlock); + return 1; +} + +/* + * bit-based spin_unlock() + */ +static inline void bit_spin_unlock(int bitnum, unsigned long *addr) +{ +#ifdef CONFIG_DEBUG_SPINLOCK + BUG_ON(!test_bit(bitnum, addr)); +#endif +#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) + clear_bit_unlock(bitnum, addr); +#endif + preempt_enable(); + __release(bitlock); +} + +/* + * bit-based spin_unlock() + * non-atomic version, which can be used eg. if the bit lock itself is + * protecting the rest of the flags in the word. + */ +static inline void __bit_spin_unlock(int bitnum, unsigned long *addr) +{ +#ifdef CONFIG_DEBUG_SPINLOCK + BUG_ON(!test_bit(bitnum, addr)); +#endif +#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) + __clear_bit_unlock(bitnum, addr); +#endif + preempt_enable(); + __release(bitlock); +} + +/* + * Return true if the lock is held. + */ +static inline int bit_spin_is_locked(int bitnum, unsigned long *addr) +{ +#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) + return test_bit(bitnum, addr); +#elif defined CONFIG_PREEMPT + return preempt_count(); +#else + return 1; +#endif +} + +#endif /* __LINUX_BIT_SPINLOCK_H */ + diff --git a/Ext4Fsd/include/linux/bitops.h b/Ext4Fsd/include/linux/bitops.h index cf10309..a4d8a11 100644 --- a/Ext4Fsd/include/linux/bitops.h +++ b/Ext4Fsd/include/linux/bitops.h @@ -1,280 +1,280 @@ -#ifndef _LINUX_BITOPS_H -#define _LINUX_BITOPS_H - -#include -#include - -#ifdef __KERNEL__ -#define BIT(nr) (1 << (nr)) -#define BIT_MASK(nr) (1 << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) -#define BITS_PER_BYTE 8 -#endif - -/* - * Include this here because some architectures need generic_ffs/fls in - * scope - */ - -/** - * find_first_zero_bit - find the first zero bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit number of the first zero bit, not the number of the byte - * containing a bit. - */ -#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) - -/** - * find_next_zero_bit - find the first zero bit in a memory region - * @addr: The address to base the search on - * @offset: The bit number to start searching at - * @size: The maximum size to search - */ -int find_next_zero_bit(const unsigned long *addr, int size, int offset); - -/** - * __ffs - find first bit in word. - * @word: The word to search - * - * Undefined if no bit exists, so code should check against 0 first. - */ -static inline unsigned long __ffs(unsigned long word) -{ - int num = 0; - -#if BITS_PER_LONG == 64 - if ((word & 0xffffffff) == 0) { - num += 32; - word >>= 32; - } -#endif - if ((word & 0xffff) == 0) { - num += 16; - word >>= 16; - } - if ((word & 0xff) == 0) { - num += 8; - word >>= 8; - } - if ((word & 0xf) == 0) { - num += 4; - word >>= 4; - } - if ((word & 0x3) == 0) { - num += 2; - word >>= 2; - } - if ((word & 0x1) == 0) - num += 1; - return num; -} - -/** - * find_first_bit - find the first set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit number of the first set bit, not the number of the byte - * containing a bit. - */ -static inline unsigned find_first_bit(const unsigned long *addr, unsigned size) -{ - unsigned x = 0; - - while (x < size) { - unsigned long val = *addr++; - if (val) - return __ffs(val) + x; - x += (sizeof(*addr)<<3); - } - return x; -} - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ - -/* - * ffz - find first zero in word. - * @word: The word to search - * - * Undefined if no zero exists, so code should check against ~0UL first. - */ -#define ffz(x) __ffs(~(x)) - - -/** - * ffs - find first bit set - * @x: the word to search - * - * This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static inline int ffs(int x) -{ - int r = 1; - - if (!x) - return 0; - if (!(x & 0xffff)) { - x >>= 16; - r += 16; - } - if (!(x & 0xff)) { - x >>= 8; - r += 8; - } - if (!(x & 0xf)) { - x >>= 4; - r += 4; - } - if (!(x & 3)) { - x >>= 2; - r += 2; - } - if (!(x & 1)) { - x >>= 1; - r += 1; - } - return r; -} - -/** - * fls - find last (most-significant) bit set - * @x: the word to search - * - * This is defined the same way as ffs. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ - -static inline int fls(int x) -{ - int r = 32; - - if (!x) - return 0; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; -} - -static inline int fls64(__u64 x) -{ - __u32 h = (__u32) (x >> 32); - if (h) - return fls(h) + 32; - return fls((int)x); -} - -#define for_each_bit(bit, addr, size) \ - for ((bit) = find_first_bit((addr), (size)); \ - (bit) < (size); \ - (bit) = find_next_bit((addr), (size), (bit) + 1)) - - -static __inline int get_bitmask_order(unsigned int count) -{ - int order; - - order = fls(count); - return order; /* We could be slightly more clever with -1 here... */ -} - -static __inline int get_count_order(unsigned int count) -{ - int order; - - order = fls(count) - 1; - if (count & (count - 1)) - order++; - return order; -} - - -/** - * rol32 - rotate a 32-bit value left - * @word: value to rotate - * @shift: bits to roll - */ -static inline __u32 rol32(__u32 word, unsigned int shift) -{ - return (word << shift) | (word >> (32 - shift)); -} - -/** - * ror32 - rotate a 32-bit value right - * @word: value to rotate - * @shift: bits to roll - */ -static inline __u32 ror32(__u32 word, unsigned int shift) -{ - return (word >> shift) | (word << (32 - shift)); -} - -static inline unsigned fls_long(unsigned long l) -{ - if (sizeof(l) == 4) - return fls(l); - return fls64(l); -} - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ - -static inline unsigned long hweight32(unsigned long w) -{ - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); -} - -static inline unsigned long hweight64(__u64 w) -{ -#if BITS_PER_LONG < 64 - return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); -#else - u64 res; - res = (w & 0x5555555555555555U) + ((w >> 1) & 0x5555555555555555U); - res = (res & 0x3333333333333333U) + ((res >> 2) & 0x3333333333333333U); - res = (res & 0x0F0F0F0F0F0F0F0FU) + ((res >> 4) & 0x0F0F0F0F0F0F0F0FU); - res = (res & 0x00FF00FF00FF00FFU) + ((res >> 8) & 0x00FF00FF00FF00FFU); - res = (res & 0x0000FFFF0000FFFFU) + ((res >> 16) & 0x0000FFFF0000FFFFU); - return (res & 0x00000000FFFFFFFFU) + ((res >> 32) & 0x00000000FFFFFFFFU); -#endif -} - -static inline unsigned long hweight_long(unsigned long w) -{ - return sizeof(w) == 4 ? hweight32(w) : hweight64(w); -} - -#endif +#ifndef _LINUX_BITOPS_H +#define _LINUX_BITOPS_H + +#include +#include + +#ifdef __KERNEL__ +#define BIT(nr) (1 << (nr)) +#define BIT_MASK(nr) (1 << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) +#define BITS_PER_BYTE 8 +#endif + +/* + * Include this here because some architectures need generic_ffs/fls in + * scope + */ + +/** + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit number of the first zero bit, not the number of the byte + * containing a bit. + */ +#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) + +/** + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bit number to start searching at + * @size: The maximum size to search + */ +int find_next_zero_bit(const unsigned long *addr, int size, int offset); + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + int num = 0; + +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +/** + * find_first_bit - find the first set bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit number of the first set bit, not the number of the byte + * containing a bit. + */ +static inline unsigned find_first_bit(const unsigned long *addr, unsigned size) +{ + unsigned x = 0; + + while (x < size) { + unsigned long val = *addr++; + if (val) + return __ffs(val) + x; + x += (sizeof(*addr)<<3); + } + return x; +} + +/** + * find_next_bit - find the next set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ + +/* + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +#define ffz(x) __ffs(~(x)) + + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static inline int ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ + +static inline int fls(int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xffff0000u)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000u)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000u)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000u)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000u)) { + x <<= 1; + r -= 1; + } + return r; +} + +static inline int fls64(__u64 x) +{ + __u32 h = (__u32) (x >> 32); + if (h) + return fls(h) + 32; + return fls((int)x); +} + +#define for_each_bit(bit, addr, size) \ + for ((bit) = find_first_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + + +static __inline int get_bitmask_order(unsigned int count) +{ + int order; + + order = fls(count); + return order; /* We could be slightly more clever with -1 here... */ +} + +static __inline int get_count_order(unsigned int count) +{ + int order; + + order = fls(count) - 1; + if (count & (count - 1)) + order++; + return order; +} + + +/** + * rol32 - rotate a 32-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u32 rol32(__u32 word, unsigned int shift) +{ + return (word << shift) | (word >> (32 - shift)); +} + +/** + * ror32 - rotate a 32-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u32 ror32(__u32 word, unsigned int shift) +{ + return (word >> shift) | (word << (32 - shift)); +} + +static inline unsigned fls_long(unsigned long l) +{ + if (sizeof(l) == 4) + return fls(l); + return fls64(l); +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +static inline unsigned long hweight32(unsigned long w) +{ + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +static inline unsigned long hweight64(__u64 w) +{ +#if BITS_PER_LONG < 64 + return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); +#else + u64 res; + res = (w & 0x5555555555555555U) + ((w >> 1) & 0x5555555555555555U); + res = (res & 0x3333333333333333U) + ((res >> 2) & 0x3333333333333333U); + res = (res & 0x0F0F0F0F0F0F0F0FU) + ((res >> 4) & 0x0F0F0F0F0F0F0F0FU); + res = (res & 0x00FF00FF00FF00FFU) + ((res >> 8) & 0x00FF00FF00FF00FFU); + res = (res & 0x0000FFFF0000FFFFU) + ((res >> 16) & 0x0000FFFF0000FFFFU); + return (res & 0x00000000FFFFFFFFU) + ((res >> 32) & 0x00000000FFFFFFFFU); +#endif +} + +static inline unsigned long hweight_long(unsigned long w) +{ + return sizeof(w) == 4 ? hweight32(w) : hweight64(w); +} + +#endif diff --git a/Ext4Fsd/include/linux/config.h b/Ext4Fsd/include/linux/config.h index 1d0a4be..ada125d 100644 --- a/Ext4Fsd/include/linux/config.h +++ b/Ext4Fsd/include/linux/config.h @@ -1,7 +1,7 @@ -#ifndef LINUX_CONFIG_H -#define LINUX_CONFIG_H - -#define EXT2_HTREE_INDEX 1 -//#undef EXT2_HTREE_INDEX - +#ifndef LINUX_CONFIG_H +#define LINUX_CONFIG_H + +#define EXT2_HTREE_INDEX 1 +//#undef EXT2_HTREE_INDEX + #endif /* LINUX_CONFIG_H */ \ No newline at end of file diff --git a/Ext4Fsd/include/linux/errno.h b/Ext4Fsd/include/linux/errno.h index 692ee86..b18a3f5 100644 --- a/Ext4Fsd/include/linux/errno.h +++ b/Ext4Fsd/include/linux/errno.h @@ -1,147 +1,147 @@ -#ifndef _I386_ERRNO_H -#define _I386_ERRNO_H - -#include - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ - -/* Should never be seen by user programs */ -#define ERESTARTSYS 512 -#define ERESTARTNOINTR 513 -#define ERESTARTNOHAND 514 /* restart if no handler.. */ -#define ENOIOCTLCMD 515 /* No ioctl command */ - -/* Defined for the NFSv3 protocol */ -#define EBADHANDLE 521 /* Illegal NFS file handle */ -#define ENOTSYNC 522 /* Update synchronization mismatch */ -#define EBADCOOKIE 523 /* Cookie is stale */ -#define ENOTSUPP 524 /* Operation is not supported */ -#define ETOOSMALL 525 /* Buffer or request is too small */ -#define ESERVERFAULT 526 /* An untranslatable error occurred */ -#define EBADTYPE 527 /* Type not supported by server */ -#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ -#if _MSC_VER > 1900 -#define ENAMETOOLONG 1024; -#endif - -#endif +#ifndef _I386_ERRNO_H +#define _I386_ERRNO_H + +#include + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ + +/* Defined for the NFSv3 protocol */ +#define EBADHANDLE 521 /* Illegal NFS file handle */ +#define ENOTSYNC 522 /* Update synchronization mismatch */ +#define EBADCOOKIE 523 /* Cookie is stale */ +#define ENOTSUPP 524 /* Operation is not supported */ +#define ETOOSMALL 525 /* Buffer or request is too small */ +#define ESERVERFAULT 526 /* An untranslatable error occurred */ +#define EBADTYPE 527 /* Type not supported by server */ +#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ +#if _MSC_VER > 1900 +#define ENAMETOOLONG 1024; +#endif + +#endif diff --git a/Ext4Fsd/include/linux/ext4_ext.h b/Ext4Fsd/include/linux/ext4_ext.h index fedf491..2378349 100644 --- a/Ext4Fsd/include/linux/ext4_ext.h +++ b/Ext4Fsd/include/linux/ext4_ext.h @@ -1,257 +1,257 @@ -#ifndef _LINUX_EXT4_EXT -#define _LINUX_EXT4_EXT - -/* - * This is the extent tail on-disk structure. - * All other extent structures are 12 bytes long. It turns out that - * block_size % 12 >= 4 for at least all powers of 2 greater than 512, which - * covers all valid ext4 block sizes. Therefore, this tail structure can be - * crammed into the end of the block without having to rebalance the tree. - */ -struct ext4_extent_tail { - uint32_t et_checksum; /* crc32c(uuid+inum+extent_block) */ -}; - -/* - * This is the extent on-disk structure. - * It's used at the bottom of the tree. - */ -typedef struct ext4_extent { - uint32_t ee_block; /* first logical block extent covers */ - uint16_t ee_len; /* number of blocks covered by extent */ - uint16_t ee_start_hi; /* high 16 bits of physical block */ - uint32_t ee_start_lo; /* low 32 bits of physical block */ -} __attribute__ ((__packed__)) EXT4_EXTENT; - -/* - * This is index on-disk structure. - * It's used at all the levels except the bottom. - */ -typedef struct ext4_extent_idx { - uint32_t ei_block; /* index covers logical blocks from 'block' */ - uint32_t ei_leaf_lo; /* pointer to the physical block of the next * - * level. leaf or next index could be there */ - uint16_t ei_leaf_hi; /* high 16 bits of physical block */ - uint16_t ei_unused; -}__attribute__ ((__packed__)) EXT4_EXTENT_IDX; - -/* - * Each block (leaves and indexes), even inode-stored has header. - */ -typedef struct ext4_extent_header { - uint16_t eh_magic; /* probably will support different formats */ - uint16_t eh_entries; /* number of valid entries */ - uint16_t eh_max; /* capacity of store in entries */ - uint16_t eh_depth; /* has tree real underlying blocks? */ - uint32_t eh_generation; /* generation of the tree */ -}__attribute__ ((__packed__)) EXT4_EXTENT_HEADER; - - -#define EXT4_EXT_MAGIC 0xf30a -#define get_ext4_header(i) ((struct ext4_extent_header *) (i)->i_block) - -#define EXT4_EXTENT_TAIL_OFFSET(hdr) \ - (sizeof(struct ext4_extent_header) + \ - (sizeof(struct ext4_extent) * (hdr)->eh_max)) - -static inline struct ext4_extent_tail * -find_ext4_extent_tail(struct ext4_extent_header *eh) -{ - return (struct ext4_extent_tail *)(((char *)eh) + - EXT4_EXTENT_TAIL_OFFSET(eh)); -} - -/* - * Array of ext4_ext_path contains path to some extent. - * Creation/lookup routines use it for traversal/splitting/etc. - * Truncate uses it to simulate recursive walking. - */ -struct ext4_ext_path -{ - ext4_fsblk_t p_block; - int p_depth; - int p_maxdepth; - struct ext4_extent *p_ext; - struct ext4_extent_idx *p_idx; - struct ext4_extent_header *p_hdr; - struct buffer_head *p_bh; -}; - -/* - * structure for external API - */ - -/* - * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an - * initialized extent. This is 2^15 and not (2^16 - 1), since we use the - * MSB of ee_len field in the extent datastructure to signify if this - * particular extent is an initialized extent or an uninitialized (i.e. - * preallocated). - * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an - * uninitialized extent. - * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an - * uninitialized one. In other words, if MSB of ee_len is set, it is an - * uninitialized extent with only one special scenario when ee_len = 0x8000. - * In this case we can not have an uninitialized extent of zero length and - * thus we make it as a special case of initialized extent with 0x8000 length. - * This way we get better extent-to-group alignment for initialized extents. - * Hence, the maximum number of blocks we can have in an *initialized* - * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767). - */ -#define EXT_INIT_MAX_LEN (1UL << 15) -#define EXT_UNWRITTEN_MAX_LEN (EXT_INIT_MAX_LEN - 1) - -#define EXT_EXTENT_SIZE sizeof(struct ext4_extent) -#define EXT_INDEX_SIZE sizeof(struct ext4_extent_idx) - -#define EXT_FIRST_EXTENT(__hdr__) \ - ((struct ext4_extent *)(((char *)(__hdr__)) + \ - sizeof(struct ext4_extent_header))) -#define EXT_FIRST_INDEX(__hdr__) \ - ((struct ext4_extent_idx *)(((char *)(__hdr__)) + \ - sizeof(struct ext4_extent_header))) -#define EXT_HAS_FREE_INDEX(__path__) \ - ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) -#define EXT_LAST_EXTENT(__hdr__) \ - (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) -#define EXT_LAST_INDEX(__hdr__) \ - (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) -#define EXT_MAX_EXTENT(__hdr__) \ - (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) -#define EXT_MAX_INDEX(__hdr__) \ - (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) - -static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode) -{ - return get_ext4_header(inode); -} - -static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh) -{ - return (struct ext4_extent_header *)bh->b_data; -} - -static inline unsigned short ext_depth(struct inode *inode) -{ - return ext_inode_hdr(inode)->eh_depth; -} - -static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext) -{ - /* We can not have an uninitialized extent of zero length! */ - ext->ee_len |= EXT_INIT_MAX_LEN; -} - -static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext) -{ - /* Extent with ee_len of 0x8000 is treated as an initialized extent */ - return (ext->ee_len > EXT_INIT_MAX_LEN); -} - -static inline uint16_t ext4_ext_get_actual_len(struct ext4_extent *ext) -{ - return (ext->ee_len <= EXT_INIT_MAX_LEN - ? ext->ee_len - : (ext->ee_len - EXT_INIT_MAX_LEN)); -} - -static inline void ext4_ext_mark_initialized(struct ext4_extent *ext) -{ - ext->ee_len = ext4_ext_get_actual_len(ext); -} - -static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext) -{ - /* We can not have an unwritten extent of zero length! */ - ext->ee_len |= EXT_INIT_MAX_LEN; -} - -static inline int ext4_ext_is_unwritten(struct ext4_extent *ext) -{ - /* Extent with ee_len of 0x8000 is treated as an initialized extent */ - return (ext->ee_len > EXT_INIT_MAX_LEN); -} - -/* - * ext4_ext_pblock: - * combine low and high parts of physical block number into ext4_fsblk_t - */ -static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex) -{ - ext4_fsblk_t block; - - block = ex->ee_start_lo; - block |= ((ext4_fsblk_t)ex->ee_start_hi << 31) << 1; - return block; -} - -/* - * ext4_idx_pblock: - * combine low and high parts of a leaf physical block number into ext4_fsblk_t - */ -static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix) -{ - ext4_fsblk_t block; - - block = ix->ei_leaf_lo; - block |= ((ext4_fsblk_t)ix->ei_leaf_hi << 31) << 1; - return block; -} - -/* - * ext4_ext_store_pblock: - * stores a large physical block number into an extent struct, - * breaking it into parts - */ -static inline void ext4_ext_store_pblock(struct ext4_extent *ex, - ext4_fsblk_t pb) -{ - ex->ee_start_lo = (uint32_t)(pb & 0xffffffff); - ex->ee_start_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff; -} - -/* - * ext4_idx_store_pblock: - * stores a large physical block number into an index struct, - * breaking it into parts - */ -static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix, - ext4_fsblk_t pb) -{ - ix->ei_leaf_lo = (uint32_t)(pb & 0xffffffff); - ix->ei_leaf_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff; -} - -#define ext4_ext_dirty(icb, handle, inode, path) \ - __ext4_ext_dirty("", __LINE__, (icb), (handle), (inode), (path)) - -#define INODE_HAS_EXTENT(i) ((i)->i_flags & EXT2_EXTENTS_FL) - -static inline uint64_t ext_to_block(EXT4_EXTENT *extent) -{ - uint64_t block; - - block = (uint64_t)extent->ee_start_lo; - block |= ((uint64_t) extent->ee_start_hi << 31) << 1; - - return block; -} - -static inline uint64_t idx_to_block(EXT4_EXTENT_IDX *idx) -{ - uint64_t block; - - block = (uint64_t)idx->ei_leaf_lo; - block |= ((uint64_t) idx->ei_leaf_hi << 31) << 1; - - return block; -} - - -int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock, - unsigned long max_blocks, struct buffer_head *bh_result, - int create, int flags); -int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode); -int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start); - -#endif /* _LINUX_EXT4_EXT */ +#ifndef _LINUX_EXT4_EXT +#define _LINUX_EXT4_EXT + +/* + * This is the extent tail on-disk structure. + * All other extent structures are 12 bytes long. It turns out that + * block_size % 12 >= 4 for at least all powers of 2 greater than 512, which + * covers all valid ext4 block sizes. Therefore, this tail structure can be + * crammed into the end of the block without having to rebalance the tree. + */ +struct ext4_extent_tail { + uint32_t et_checksum; /* crc32c(uuid+inum+extent_block) */ +}; + +/* + * This is the extent on-disk structure. + * It's used at the bottom of the tree. + */ +typedef struct ext4_extent { + uint32_t ee_block; /* first logical block extent covers */ + uint16_t ee_len; /* number of blocks covered by extent */ + uint16_t ee_start_hi; /* high 16 bits of physical block */ + uint32_t ee_start_lo; /* low 32 bits of physical block */ +} __attribute__ ((__packed__)) EXT4_EXTENT; + +/* + * This is index on-disk structure. + * It's used at all the levels except the bottom. + */ +typedef struct ext4_extent_idx { + uint32_t ei_block; /* index covers logical blocks from 'block' */ + uint32_t ei_leaf_lo; /* pointer to the physical block of the next * + * level. leaf or next index could be there */ + uint16_t ei_leaf_hi; /* high 16 bits of physical block */ + uint16_t ei_unused; +}__attribute__ ((__packed__)) EXT4_EXTENT_IDX; + +/* + * Each block (leaves and indexes), even inode-stored has header. + */ +typedef struct ext4_extent_header { + uint16_t eh_magic; /* probably will support different formats */ + uint16_t eh_entries; /* number of valid entries */ + uint16_t eh_max; /* capacity of store in entries */ + uint16_t eh_depth; /* has tree real underlying blocks? */ + uint32_t eh_generation; /* generation of the tree */ +}__attribute__ ((__packed__)) EXT4_EXTENT_HEADER; + + +#define EXT4_EXT_MAGIC 0xf30a +#define get_ext4_header(i) ((struct ext4_extent_header *) (i)->i_block) + +#define EXT4_EXTENT_TAIL_OFFSET(hdr) \ + (sizeof(struct ext4_extent_header) + \ + (sizeof(struct ext4_extent) * (hdr)->eh_max)) + +static inline struct ext4_extent_tail * +find_ext4_extent_tail(struct ext4_extent_header *eh) +{ + return (struct ext4_extent_tail *)(((char *)eh) + + EXT4_EXTENT_TAIL_OFFSET(eh)); +} + +/* + * Array of ext4_ext_path contains path to some extent. + * Creation/lookup routines use it for traversal/splitting/etc. + * Truncate uses it to simulate recursive walking. + */ +struct ext4_ext_path +{ + ext4_fsblk_t p_block; + int p_depth; + int p_maxdepth; + struct ext4_extent *p_ext; + struct ext4_extent_idx *p_idx; + struct ext4_extent_header *p_hdr; + struct buffer_head *p_bh; +}; + +/* + * structure for external API + */ + +/* + * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an + * initialized extent. This is 2^15 and not (2^16 - 1), since we use the + * MSB of ee_len field in the extent datastructure to signify if this + * particular extent is an initialized extent or an uninitialized (i.e. + * preallocated). + * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an + * uninitialized extent. + * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an + * uninitialized one. In other words, if MSB of ee_len is set, it is an + * uninitialized extent with only one special scenario when ee_len = 0x8000. + * In this case we can not have an uninitialized extent of zero length and + * thus we make it as a special case of initialized extent with 0x8000 length. + * This way we get better extent-to-group alignment for initialized extents. + * Hence, the maximum number of blocks we can have in an *initialized* + * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767). + */ +#define EXT_INIT_MAX_LEN (1UL << 15) +#define EXT_UNWRITTEN_MAX_LEN (EXT_INIT_MAX_LEN - 1) + +#define EXT_EXTENT_SIZE sizeof(struct ext4_extent) +#define EXT_INDEX_SIZE sizeof(struct ext4_extent_idx) + +#define EXT_FIRST_EXTENT(__hdr__) \ + ((struct ext4_extent *)(((char *)(__hdr__)) + \ + sizeof(struct ext4_extent_header))) +#define EXT_FIRST_INDEX(__hdr__) \ + ((struct ext4_extent_idx *)(((char *)(__hdr__)) + \ + sizeof(struct ext4_extent_header))) +#define EXT_HAS_FREE_INDEX(__path__) \ + ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) +#define EXT_LAST_EXTENT(__hdr__) \ + (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) +#define EXT_LAST_INDEX(__hdr__) \ + (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) +#define EXT_MAX_EXTENT(__hdr__) \ + (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) +#define EXT_MAX_INDEX(__hdr__) \ + (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) + +static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode) +{ + return get_ext4_header(inode); +} + +static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh) +{ + return (struct ext4_extent_header *)bh->b_data; +} + +static inline unsigned short ext_depth(struct inode *inode) +{ + return ext_inode_hdr(inode)->eh_depth; +} + +static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext) +{ + /* We can not have an uninitialized extent of zero length! */ + ext->ee_len |= EXT_INIT_MAX_LEN; +} + +static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext) +{ + /* Extent with ee_len of 0x8000 is treated as an initialized extent */ + return (ext->ee_len > EXT_INIT_MAX_LEN); +} + +static inline uint16_t ext4_ext_get_actual_len(struct ext4_extent *ext) +{ + return (ext->ee_len <= EXT_INIT_MAX_LEN + ? ext->ee_len + : (ext->ee_len - EXT_INIT_MAX_LEN)); +} + +static inline void ext4_ext_mark_initialized(struct ext4_extent *ext) +{ + ext->ee_len = ext4_ext_get_actual_len(ext); +} + +static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext) +{ + /* We can not have an unwritten extent of zero length! */ + ext->ee_len |= EXT_INIT_MAX_LEN; +} + +static inline int ext4_ext_is_unwritten(struct ext4_extent *ext) +{ + /* Extent with ee_len of 0x8000 is treated as an initialized extent */ + return (ext->ee_len > EXT_INIT_MAX_LEN); +} + +/* + * ext4_ext_pblock: + * combine low and high parts of physical block number into ext4_fsblk_t + */ +static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex) +{ + ext4_fsblk_t block; + + block = ex->ee_start_lo; + block |= ((ext4_fsblk_t)ex->ee_start_hi << 31) << 1; + return block; +} + +/* + * ext4_idx_pblock: + * combine low and high parts of a leaf physical block number into ext4_fsblk_t + */ +static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix) +{ + ext4_fsblk_t block; + + block = ix->ei_leaf_lo; + block |= ((ext4_fsblk_t)ix->ei_leaf_hi << 31) << 1; + return block; +} + +/* + * ext4_ext_store_pblock: + * stores a large physical block number into an extent struct, + * breaking it into parts + */ +static inline void ext4_ext_store_pblock(struct ext4_extent *ex, + ext4_fsblk_t pb) +{ + ex->ee_start_lo = (uint32_t)(pb & 0xffffffff); + ex->ee_start_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff; +} + +/* + * ext4_idx_store_pblock: + * stores a large physical block number into an index struct, + * breaking it into parts + */ +static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix, + ext4_fsblk_t pb) +{ + ix->ei_leaf_lo = (uint32_t)(pb & 0xffffffff); + ix->ei_leaf_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff; +} + +#define ext4_ext_dirty(icb, handle, inode, path) \ + __ext4_ext_dirty("", __LINE__, (icb), (handle), (inode), (path)) + +#define INODE_HAS_EXTENT(i) ((i)->i_flags & EXT2_EXTENTS_FL) + +static inline uint64_t ext_to_block(EXT4_EXTENT *extent) +{ + uint64_t block; + + block = (uint64_t)extent->ee_start_lo; + block |= ((uint64_t) extent->ee_start_hi << 31) << 1; + + return block; +} + +static inline uint64_t idx_to_block(EXT4_EXTENT_IDX *idx) +{ + uint64_t block; + + block = (uint64_t)idx->ei_leaf_lo; + block |= ((uint64_t) idx->ei_leaf_hi << 31) << 1; + + return block; +} + + +int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock, + unsigned long max_blocks, struct buffer_head *bh_result, + int create, int flags); +int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode); +int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start); + +#endif /* _LINUX_EXT4_EXT */ diff --git a/Ext4Fsd/include/linux/ext4_jbd2.h b/Ext4Fsd/include/linux/ext4_jbd2.h index d6c6fea..0dd7d37 100644 --- a/Ext4Fsd/include/linux/ext4_jbd2.h +++ b/Ext4Fsd/include/linux/ext4_jbd2.h @@ -1,65 +1,65 @@ -#ifndef _EXT4_JBD2_H -#define _EXT4_JBD2_H - -/* - * Wrapper functions with which ext4 calls into JBD. - */ -void ext4_journal_abort_handle(const char *caller, unsigned int line, - const char *err_fn, struct buffer_head *bh, - handle_t *handle, int err); - -int __ext4_handle_dirty_super(const char *where, unsigned int line, - handle_t *handle, struct super_block *sb); - -int __ext4_journal_get_write_access(const char *where, unsigned int line, - void *icb, handle_t *handle, struct buffer_head *bh); - -int __ext4_forget(const char *where, unsigned int line, void *icb, handle_t *handle, - int is_metadata, struct inode *inode, - struct buffer_head *bh, ext4_fsblk_t blocknr); - -int __ext4_journal_get_create_access(const char *where, unsigned int line, - void *icb, handle_t *handle, struct buffer_head *bh); - -int __ext4_handle_dirty_metadata(const char *where, unsigned int line, - void *icb, handle_t *handle, struct inode *inode, - struct buffer_head *bh); - -#define ext4_journal_get_write_access(handle, icb, bh) \ - __ext4_journal_get_write_access("", __LINE__, (icb), (handle), (bh)) -#define ext4_forget(handle, icb, is_metadata, inode, bh, block_nr) \ - __ext4_forget("", __LINE__, (icb), (handle), (is_metadata), (inode), \ - (bh), (block_nr)) -#define ext4_journal_get_create_access(handle, icb, bh) \ - __ext4_journal_get_create_access("", __LINE__, (icb), (handle), (bh)) -#define ext4_handle_dirty_metadata(handle, icb, inode, bh) \ - __ext4_handle_dirty_metadata("", __LINE__, (icb), (handle), (inode), \ - (bh)) - -handle_t *__ext4_journal_start_sb(void *icb, struct super_block *sb, unsigned int line, - int type, int blocks, int rsv_blocks); -int __ext4_journal_stop(const char *where, unsigned int line, void *icb, handle_t *handle); - -#define ext4_journal_start_sb(icb, sb, type, nblocks) \ - __ext4_journal_start_sb((icb), (sb), __LINE__, (type), (nblocks), 0) - -#define ext4_journal_start(icb, inode, type, nblocks) \ - __ext4_journal_start((icb), (inode), __LINE__, (type), (nblocks), 0) - -static inline handle_t *__ext4_journal_start(void *icb, struct inode *inode, - unsigned int line, int type, - int blocks, int rsv_blocks) -{ - return __ext4_journal_start_sb(icb, inode->i_sb, line, type, blocks, - rsv_blocks); -} - -#define ext4_journal_stop(icb, handle) \ - __ext4_journal_stop("", __LINE__, (icb), (handle)) - -static inline int ext4_journal_extend(void *icb, handle_t *handle, int nblocks) -{ - return 0; -} - -#endif +#ifndef _EXT4_JBD2_H +#define _EXT4_JBD2_H + +/* + * Wrapper functions with which ext4 calls into JBD. + */ +void ext4_journal_abort_handle(const char *caller, unsigned int line, + const char *err_fn, struct buffer_head *bh, + handle_t *handle, int err); + +int __ext4_handle_dirty_super(const char *where, unsigned int line, + handle_t *handle, struct super_block *sb); + +int __ext4_journal_get_write_access(const char *where, unsigned int line, + void *icb, handle_t *handle, struct buffer_head *bh); + +int __ext4_forget(const char *where, unsigned int line, void *icb, handle_t *handle, + int is_metadata, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t blocknr); + +int __ext4_journal_get_create_access(const char *where, unsigned int line, + void *icb, handle_t *handle, struct buffer_head *bh); + +int __ext4_handle_dirty_metadata(const char *where, unsigned int line, + void *icb, handle_t *handle, struct inode *inode, + struct buffer_head *bh); + +#define ext4_journal_get_write_access(handle, icb, bh) \ + __ext4_journal_get_write_access("", __LINE__, (icb), (handle), (bh)) +#define ext4_forget(handle, icb, is_metadata, inode, bh, block_nr) \ + __ext4_forget("", __LINE__, (icb), (handle), (is_metadata), (inode), \ + (bh), (block_nr)) +#define ext4_journal_get_create_access(handle, icb, bh) \ + __ext4_journal_get_create_access("", __LINE__, (icb), (handle), (bh)) +#define ext4_handle_dirty_metadata(handle, icb, inode, bh) \ + __ext4_handle_dirty_metadata("", __LINE__, (icb), (handle), (inode), \ + (bh)) + +handle_t *__ext4_journal_start_sb(void *icb, struct super_block *sb, unsigned int line, + int type, int blocks, int rsv_blocks); +int __ext4_journal_stop(const char *where, unsigned int line, void *icb, handle_t *handle); + +#define ext4_journal_start_sb(icb, sb, type, nblocks) \ + __ext4_journal_start_sb((icb), (sb), __LINE__, (type), (nblocks), 0) + +#define ext4_journal_start(icb, inode, type, nblocks) \ + __ext4_journal_start((icb), (inode), __LINE__, (type), (nblocks), 0) + +static inline handle_t *__ext4_journal_start(void *icb, struct inode *inode, + unsigned int line, int type, + int blocks, int rsv_blocks) +{ + return __ext4_journal_start_sb(icb, inode->i_sb, line, type, blocks, + rsv_blocks); +} + +#define ext4_journal_stop(icb, handle) \ + __ext4_journal_stop("", __LINE__, (icb), (handle)) + +static inline int ext4_journal_extend(void *icb, handle_t *handle, int nblocks) +{ + return 0; +} + +#endif diff --git a/Ext4Fsd/include/linux/ext4_xattr.h b/Ext4Fsd/include/linux/ext4_xattr.h index 44d5f91..d5c3442 100644 --- a/Ext4Fsd/include/linux/ext4_xattr.h +++ b/Ext4Fsd/include/linux/ext4_xattr.h @@ -1,205 +1,205 @@ -/* - * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com) - * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @addtogroup lwext4 - * @{ - */ -/** - * @file ext4_xattr.h - * @brief Extended Attribute manipulation. - */ - -#ifndef EXT4_XATTR_H_ -#define EXT4_XATTR_H_ - -#include -#include - -/* Extended Attribute(EA) */ - -/* Magic value in attribute blocks */ -#define EXT4_XATTR_MAGIC 0xEA020000 - -/* Maximum number of references to one attribute block */ -#define EXT4_XATTR_REFCOUNT_MAX 1024 - -/* Name indexes */ -#define EXT4_XATTR_INDEX_USER 1 -#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2 -#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -#define EXT4_XATTR_INDEX_TRUSTED 4 -#define EXT4_XATTR_INDEX_LUSTRE 5 -#define EXT4_XATTR_INDEX_SECURITY 6 -#define EXT4_XATTR_INDEX_SYSTEM 7 -#define EXT4_XATTR_INDEX_RICHACL 8 -#define EXT4_XATTR_INDEX_ENCRYPTION 9 - -#pragma pack(push, 1) - -struct ext4_xattr_header { - __le32 h_magic; /* magic number for identification */ - __le32 h_refcount; /* reference count */ - __le32 h_blocks; /* number of disk blocks used */ - __le32 h_hash; /* hash value of all attributes */ - __le32 h_checksum; /* crc32c(uuid+id+xattrblock) */ - /* id = inum if refcount=1, blknum otherwise */ - __le32 h_reserved[3]; /* zero right now */ -}; - -struct ext4_xattr_ibody_header { - __le32 h_magic; /* magic number for identification */ -}; - -struct ext4_xattr_entry { - __u8 e_name_len; /* length of name */ - __u8 e_name_index; /* attribute name index */ - __le16 e_value_offs; /* offset in disk block of value */ - __le32 e_value_block; /* disk block attribute is stored on (n/i) */ - __le32 e_value_size; /* size of attribute value */ - __le32 e_hash; /* hash value of name and value */ -}; - -#pragma pack(pop) - -//#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE - -#define EXT4_XATTR_PAD_BITS 2 -#define EXT4_XATTR_PAD (1<e_name_len))) -#define EXT4_XATTR_SIZE(size) \ - (((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND) -#define EXT4_XATTR_NAME(entry) \ - ((char *)((entry) + 1)) - -#define EXT4_XATTR_IHDR(raw_inode) \ - ((struct ext4_xattr_ibody_header *) \ - ((char *)raw_inode + \ - EXT4_GOOD_OLD_INODE_SIZE + \ - (raw_inode)->i_extra_isize)) -#define EXT4_XATTR_IFIRST(hdr) \ - ((struct ext4_xattr_entry *)((hdr)+1)) - -#define EXT4_XATTR_BHDR(block) \ - ((struct ext4_xattr_header *)((block)->b_data)) -#define EXT4_XATTR_ENTRY(ptr) \ - ((struct ext4_xattr_entry *)(ptr)) -#define EXT4_XATTR_BFIRST(block) \ - EXT4_XATTR_ENTRY(EXT4_XATTR_BHDR(block)+1) -#define EXT4_XATTR_IS_LAST_ENTRY(entry) \ - (*(__le32 *)(entry) == 0) - -#define EXT4_ZERO_XATTR_VALUE ((void *)-1) - - -struct ext4_xattr_item { - /* This attribute should be stored in inode body */ - BOOL in_inode; - BOOL is_data; - - __u8 name_index; - char *name; - size_t name_len; - void *data; - size_t data_size; - - struct rb_node node; - struct list_head list_node; -}; - -struct ext4_xattr_ref { - PEXT2_IRP_CONTEXT IrpContext; - BOOL block_loaded; - struct buffer_head *block_bh; - PEXT2_MCB inode_ref; - - PEXT2_INODE OnDiskInode; - BOOL IsOnDiskInodeDirty; - - BOOL dirty; - size_t ea_size; - size_t inode_size_rem; - size_t block_size_rem; - PEXT2_VCB fs; - - void *iter_arg; - struct ext4_xattr_item *iter_from; - - struct rb_root root; - struct list_head ordered_list; -}; - -#define EXT4_XATTR_ITERATE_CONT 0 -#define EXT4_XATTR_ITERATE_STOP 1 -#define EXT4_XATTR_ITERATE_PAUSE 2 - -int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref, - struct ext4_xattr_ref *ref); - -int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref); - -int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index, - const char *name, size_t name_len, const void *data, - size_t data_size, BOOL replace); - -int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index, - const char *name, size_t name_len, const void *data, - size_t data_size); - -int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index, - const char *name, size_t name_len); - -int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index, - const char *name, size_t name_len, void *buf, - size_t buf_size, size_t *data_size); - -void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref, - int(*iter)(struct ext4_xattr_ref *ref, - struct ext4_xattr_item *item, - BOOL is_last)); - -void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref); - -const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len, - __u8 *name_index, size_t *name_len, - BOOL *found); - -const char *ext4_get_xattr_name_prefix(__u8 name_index, - size_t *ret_prefix_len); - -void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref); - -#endif -/** - * @} - */ +/* + * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com) + * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** @addtogroup lwext4 + * @{ + */ +/** + * @file ext4_xattr.h + * @brief Extended Attribute manipulation. + */ + +#ifndef EXT4_XATTR_H_ +#define EXT4_XATTR_H_ + +#include +#include + +/* Extended Attribute(EA) */ + +/* Magic value in attribute blocks */ +#define EXT4_XATTR_MAGIC 0xEA020000 + +/* Maximum number of references to one attribute block */ +#define EXT4_XATTR_REFCOUNT_MAX 1024 + +/* Name indexes */ +#define EXT4_XATTR_INDEX_USER 1 +#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2 +#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3 +#define EXT4_XATTR_INDEX_TRUSTED 4 +#define EXT4_XATTR_INDEX_LUSTRE 5 +#define EXT4_XATTR_INDEX_SECURITY 6 +#define EXT4_XATTR_INDEX_SYSTEM 7 +#define EXT4_XATTR_INDEX_RICHACL 8 +#define EXT4_XATTR_INDEX_ENCRYPTION 9 + +#pragma pack(push, 1) + +struct ext4_xattr_header { + __le32 h_magic; /* magic number for identification */ + __le32 h_refcount; /* reference count */ + __le32 h_blocks; /* number of disk blocks used */ + __le32 h_hash; /* hash value of all attributes */ + __le32 h_checksum; /* crc32c(uuid+id+xattrblock) */ + /* id = inum if refcount=1, blknum otherwise */ + __le32 h_reserved[3]; /* zero right now */ +}; + +struct ext4_xattr_ibody_header { + __le32 h_magic; /* magic number for identification */ +}; + +struct ext4_xattr_entry { + __u8 e_name_len; /* length of name */ + __u8 e_name_index; /* attribute name index */ + __le16 e_value_offs; /* offset in disk block of value */ + __le32 e_value_block; /* disk block attribute is stored on (n/i) */ + __le32 e_value_size; /* size of attribute value */ + __le32 e_hash; /* hash value of name and value */ +}; + +#pragma pack(pop) + +//#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE + +#define EXT4_XATTR_PAD_BITS 2 +#define EXT4_XATTR_PAD (1<e_name_len))) +#define EXT4_XATTR_SIZE(size) \ + (((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND) +#define EXT4_XATTR_NAME(entry) \ + ((char *)((entry) + 1)) + +#define EXT4_XATTR_IHDR(raw_inode) \ + ((struct ext4_xattr_ibody_header *) \ + ((char *)raw_inode + \ + EXT4_GOOD_OLD_INODE_SIZE + \ + (raw_inode)->i_extra_isize)) +#define EXT4_XATTR_IFIRST(hdr) \ + ((struct ext4_xattr_entry *)((hdr)+1)) + +#define EXT4_XATTR_BHDR(block) \ + ((struct ext4_xattr_header *)((block)->b_data)) +#define EXT4_XATTR_ENTRY(ptr) \ + ((struct ext4_xattr_entry *)(ptr)) +#define EXT4_XATTR_BFIRST(block) \ + EXT4_XATTR_ENTRY(EXT4_XATTR_BHDR(block)+1) +#define EXT4_XATTR_IS_LAST_ENTRY(entry) \ + (*(__le32 *)(entry) == 0) + +#define EXT4_ZERO_XATTR_VALUE ((void *)-1) + + +struct ext4_xattr_item { + /* This attribute should be stored in inode body */ + BOOL in_inode; + BOOL is_data; + + __u8 name_index; + char *name; + size_t name_len; + void *data; + size_t data_size; + + struct rb_node node; + struct list_head list_node; +}; + +struct ext4_xattr_ref { + PEXT2_IRP_CONTEXT IrpContext; + BOOL block_loaded; + struct buffer_head *block_bh; + PEXT2_MCB inode_ref; + + PEXT2_INODE OnDiskInode; + BOOL IsOnDiskInodeDirty; + + BOOL dirty; + size_t ea_size; + size_t inode_size_rem; + size_t block_size_rem; + PEXT2_VCB fs; + + void *iter_arg; + struct ext4_xattr_item *iter_from; + + struct rb_root root; + struct list_head ordered_list; +}; + +#define EXT4_XATTR_ITERATE_CONT 0 +#define EXT4_XATTR_ITERATE_STOP 1 +#define EXT4_XATTR_ITERATE_PAUSE 2 + +int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref, + struct ext4_xattr_ref *ref); + +int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref); + +int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index, + const char *name, size_t name_len, const void *data, + size_t data_size, BOOL replace); + +int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index, + const char *name, size_t name_len, const void *data, + size_t data_size); + +int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index, + const char *name, size_t name_len); + +int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index, + const char *name, size_t name_len, void *buf, + size_t buf_size, size_t *data_size); + +void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref, + int(*iter)(struct ext4_xattr_ref *ref, + struct ext4_xattr_item *item, + BOOL is_last)); + +void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref); + +const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len, + __u8 *name_index, size_t *name_len, + BOOL *found); + +const char *ext4_get_xattr_name_prefix(__u8 name_index, + size_t *ret_prefix_len); + +void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref); + +#endif +/** + * @} + */ diff --git a/Ext4Fsd/include/linux/fs.h b/Ext4Fsd/include/linux/fs.h index 5da58f9..d3540db 100644 --- a/Ext4Fsd/include/linux/fs.h +++ b/Ext4Fsd/include/linux/fs.h @@ -1,160 +1,160 @@ -#ifndef _LINUX_FS_INCLUDE_ -#define _LINUX_FS_INCLUDE_ - -#include -#include -#include - -// -// kdev -// - -#define NODEV 0 - -typedef struct block_device * kdev_t; - -#define MINORBITS 8 -#define MINORMASK ((1U << MINORBITS) - 1) - -#define MAJOR(dev) ((unsigned int)((int)(dev) >> MINORBITS)) -#define MINOR(dev) ((unsigned int)((int)(dev) & MINORMASK)) - -static inline unsigned int kdev_t_to_nr(kdev_t dev) { - /*return (unsigned int)(MAJOR(dev)<<8) | MINOR(dev);*/ - return 0; -} - -#define NODEV 0 -#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) - -static inline kdev_t to_kdev_t(int dev) -{ -#if 0 - int major, minor; -#if 0 - major = (dev >> 16); - if (!major) { - major = (dev >> 8); - minor = (dev & 0xff); - } else - minor = (dev & 0xffff); -#else - major = (dev >> 8); - minor = (dev & 0xff); -#endif - return (kdev_t) MKDEV(major, minor); -#endif - return 0; -} - - -// -// file system specific structures -// - -/* - * Kernel pointers have redundant information, so we can use a - * scheme where we can return either an error code or a dentry - * pointer with the same return value. - * - * This should be a per-architecture thing, to allow different - * error and pointer decisions. - */ - -struct super_block { - unsigned long s_magic; - unsigned long s_flags; - unsigned long s_blocksize; /* blocksize */ - unsigned long long s_maxbytes; - unsigned char s_blocksize_bits; /* bits of blocksize */ - unsigned char s_dirt; /* any thing */ - char s_id[30]; /* id string */ - kdev_t s_bdev; /* block_device */ - void * s_priv; /* EXT2_VCB */ - struct dentry *s_root; - void *s_fs_info; -}; - -struct inode { - __u32 i_ino; /* inode number */ - loff_t i_size; /* size */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* Creation time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* Deletion Time */ - __u64 i_blocks; - __u32 i_block[15]; - umode_t i_mode; /* mode */ - uid_t i_uid; - gid_t i_gid; - atomic_t i_count; /* ref count */ - __u16 i_nlink; - __u32 i_generation; - __u32 i_version; - __u32 i_flags; - - struct super_block *i_sb; /* super_block */ - void *i_priv; /* EXT2_MCB */ - - __u16 i_extra_isize; /* extra fields' size */ - __u64 i_file_acl; -}; - -// -// Inode state bits -// - -#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ -#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ -#define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ -#define I_LOCK 8 -#define I_FREEING 16 -#define I_CLEAR 32 - -#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) - - -struct dentry { - atomic_t d_count; - struct { - int len; - char *name; - } d_name; - struct inode *d_inode; - struct dentry *d_parent; - void *d_fsdata; - struct super_block *d_sb; -}; - -struct file { - - unsigned int f_flags; - umode_t f_mode; - __u32 f_version; - __int64 f_size; - loff_t f_pos; - struct dentry *f_dentry; - void *private_data; -}; - -/* - * File types - * - * NOTE! These match bits 12..15 of stat.st_mode - * (ie "(i_mode >> 12) & 15"). - */ -#define DT_UNKNOWN 0 -#define DT_FIFO 1 -#define DT_CHR 2 -#define DT_DIR 4 -#define DT_BLK 6 -#define DT_REG 8 -#define DT_LNK 10 -#define DT_SOCK 12 -#define DT_WHT 14 - -void iget(struct inode *inode); -void iput(struct inode *inode); -ULONGLONG bmap(struct inode *i, ULONGLONG b); - -#endif /*_LINUX_FS_INCLUDE_*/ +#ifndef _LINUX_FS_INCLUDE_ +#define _LINUX_FS_INCLUDE_ + +#include +#include +#include + +// +// kdev +// + +#define NODEV 0 + +typedef struct block_device * kdev_t; + +#define MINORBITS 8 +#define MINORMASK ((1U << MINORBITS) - 1) + +#define MAJOR(dev) ((unsigned int)((int)(dev) >> MINORBITS)) +#define MINOR(dev) ((unsigned int)((int)(dev) & MINORMASK)) + +static inline unsigned int kdev_t_to_nr(kdev_t dev) { + /*return (unsigned int)(MAJOR(dev)<<8) | MINOR(dev);*/ + return 0; +} + +#define NODEV 0 +#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) + +static inline kdev_t to_kdev_t(int dev) +{ +#if 0 + int major, minor; +#if 0 + major = (dev >> 16); + if (!major) { + major = (dev >> 8); + minor = (dev & 0xff); + } else + minor = (dev & 0xffff); +#else + major = (dev >> 8); + minor = (dev & 0xff); +#endif + return (kdev_t) MKDEV(major, minor); +#endif + return 0; +} + + +// +// file system specific structures +// + +/* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ + +struct super_block { + unsigned long s_magic; + unsigned long s_flags; + unsigned long s_blocksize; /* blocksize */ + unsigned long long s_maxbytes; + unsigned char s_blocksize_bits; /* bits of blocksize */ + unsigned char s_dirt; /* any thing */ + char s_id[30]; /* id string */ + kdev_t s_bdev; /* block_device */ + void * s_priv; /* EXT2_VCB */ + struct dentry *s_root; + void *s_fs_info; +}; + +struct inode { + __u32 i_ino; /* inode number */ + loff_t i_size; /* size */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* Creation time */ + __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* Deletion Time */ + __u64 i_blocks; + __u32 i_block[15]; + umode_t i_mode; /* mode */ + uid_t i_uid; + gid_t i_gid; + atomic_t i_count; /* ref count */ + __u16 i_nlink; + __u32 i_generation; + __u32 i_version; + __u32 i_flags; + + struct super_block *i_sb; /* super_block */ + void *i_priv; /* EXT2_MCB */ + + __u16 i_extra_isize; /* extra fields' size */ + __u64 i_file_acl; +}; + +// +// Inode state bits +// + +#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ +#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ +#define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ +#define I_LOCK 8 +#define I_FREEING 16 +#define I_CLEAR 32 + +#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) + + +struct dentry { + atomic_t d_count; + struct { + int len; + char *name; + } d_name; + struct inode *d_inode; + struct dentry *d_parent; + void *d_fsdata; + struct super_block *d_sb; +}; + +struct file { + + unsigned int f_flags; + umode_t f_mode; + __u32 f_version; + __int64 f_size; + loff_t f_pos; + struct dentry *f_dentry; + void *private_data; +}; + +/* + * File types + * + * NOTE! These match bits 12..15 of stat.st_mode + * (ie "(i_mode >> 12) & 15"). + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +void iget(struct inode *inode); +void iput(struct inode *inode); +ULONGLONG bmap(struct inode *i, ULONGLONG b); + +#endif /*_LINUX_FS_INCLUDE_*/ diff --git a/Ext4Fsd/include/linux/group.h b/Ext4Fsd/include/linux/group.h index 32614cf..afae31a 100644 --- a/Ext4Fsd/include/linux/group.h +++ b/Ext4Fsd/include/linux/group.h @@ -1,29 +1,29 @@ -/* - * linux/fs/ext4/group.h - * - * Copyright (C) 2007 Cluster File Systems, Inc - * - * Author: Andreas Dilger - */ - -#ifndef _LINUX_EXT4_GROUP_H -#define _LINUX_EXT4_GROUP_H - -extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, - struct ext4_group_desc *gdp); -extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, - struct ext4_group_desc *gdp); -struct buffer_head *ext4_read_block_bitmap(struct super_block *sb, - ext4_group_t block_group); -extern unsigned ext4_init_block_bitmap(struct super_block *sb, - struct buffer_head *bh, - ext4_group_t group, - struct ext4_group_desc *desc); -#define ext4_free_blocks_after_init(sb, group, desc) \ - ext4_init_block_bitmap(sb, NULL, group, desc) -extern unsigned ext4_init_inode_bitmap(struct super_block *sb, - struct buffer_head *bh, - ext4_group_t group, - struct ext4_group_desc *desc); -extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); -#endif /* _LINUX_EXT4_GROUP_H */ +/* + * linux/fs/ext4/group.h + * + * Copyright (C) 2007 Cluster File Systems, Inc + * + * Author: Andreas Dilger + */ + +#ifndef _LINUX_EXT4_GROUP_H +#define _LINUX_EXT4_GROUP_H + +extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, + struct ext4_group_desc *gdp); +extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, + struct ext4_group_desc *gdp); +struct buffer_head *ext4_read_block_bitmap(struct super_block *sb, + ext4_group_t block_group); +extern unsigned ext4_init_block_bitmap(struct super_block *sb, + struct buffer_head *bh, + ext4_group_t group, + struct ext4_group_desc *desc); +#define ext4_free_blocks_after_init(sb, group, desc) \ + ext4_init_block_bitmap(sb, NULL, group, desc) +extern unsigned ext4_init_inode_bitmap(struct super_block *sb, + struct buffer_head *bh, + ext4_group_t group, + struct ext4_group_desc *desc); +extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); +#endif /* _LINUX_EXT4_GROUP_H */ diff --git a/Ext4Fsd/include/linux/journal-head.h b/Ext4Fsd/include/linux/journal-head.h index 7171777..ec6905b 100644 --- a/Ext4Fsd/include/linux/journal-head.h +++ b/Ext4Fsd/include/linux/journal-head.h @@ -1,92 +1,92 @@ -/* - * include/linux/journal-head.h - * - * buffer_head fields for JBD - * - * 27 May 2001 Andrew Morton - * Created - pulled out of fs.h - */ - -#ifndef JOURNAL_HEAD_H_INCLUDED -#define JOURNAL_HEAD_H_INCLUDED - -typedef unsigned int tid_t; /* Unique transaction ID */ -typedef struct transaction_s transaction_t; /* Compound transaction type */ -struct buffer_head; - -struct journal_head { - /* - * Points back to our buffer_head. [jbd_lock_bh_journal_head()] - */ - struct buffer_head *b_bh; - - /* - * Reference count - see description in journal.c - * [jbd_lock_bh_journal_head()] - */ - int b_jcount; - - /* - * Journalling list for this buffer [jbd_lock_bh_state()] - */ - unsigned b_jlist; - - /* - * This flag signals the buffer has been modified by - * the currently running transaction - * [jbd_lock_bh_state()] - */ - unsigned b_modified; - - /* - * Copy of the buffer data frozen for writing to the log. - * [jbd_lock_bh_state()] - */ - char *b_frozen_data; - - /* - * Pointer to a saved copy of the buffer containing no uncommitted - * deallocation references, so that allocations can avoid overwriting - * uncommitted deletes. [jbd_lock_bh_state()] - */ - char *b_committed_data; - - /* - * Pointer to the compound transaction which owns this buffer's - * metadata: either the running transaction or the committing - * transaction (if there is one). Only applies to buffers on a - * transaction's data or metadata journaling list. - * [j_list_lock] [jbd_lock_bh_state()] - */ - transaction_t *b_transaction; - - /* - * Pointer to the running compound transaction which is currently - * modifying the buffer's metadata, if there was already a transaction - * committing it when the new transaction touched it. - * [t_list_lock] [jbd_lock_bh_state()] - */ - transaction_t *b_next_transaction; - - /* - * Doubly-linked list of buffers on a transaction's data, metadata or - * forget queue. [t_list_lock] [jbd_lock_bh_state()] - */ - struct journal_head *b_tnext, *b_tprev; - - /* - * Pointer to the compound transaction against which this buffer - * is checkpointed. Only dirty buffers can be checkpointed. - * [j_list_lock] - */ - transaction_t *b_cp_transaction; - - /* - * Doubly-linked list of buffers still remaining to be flushed - * before an old transaction can be checkpointed. - * [j_list_lock] - */ - struct journal_head *b_cpnext, *b_cpprev; -}; - -#endif /* JOURNAL_HEAD_H_INCLUDED */ +/* + * include/linux/journal-head.h + * + * buffer_head fields for JBD + * + * 27 May 2001 Andrew Morton + * Created - pulled out of fs.h + */ + +#ifndef JOURNAL_HEAD_H_INCLUDED +#define JOURNAL_HEAD_H_INCLUDED + +typedef unsigned int tid_t; /* Unique transaction ID */ +typedef struct transaction_s transaction_t; /* Compound transaction type */ +struct buffer_head; + +struct journal_head { + /* + * Points back to our buffer_head. [jbd_lock_bh_journal_head()] + */ + struct buffer_head *b_bh; + + /* + * Reference count - see description in journal.c + * [jbd_lock_bh_journal_head()] + */ + int b_jcount; + + /* + * Journalling list for this buffer [jbd_lock_bh_state()] + */ + unsigned b_jlist; + + /* + * This flag signals the buffer has been modified by + * the currently running transaction + * [jbd_lock_bh_state()] + */ + unsigned b_modified; + + /* + * Copy of the buffer data frozen for writing to the log. + * [jbd_lock_bh_state()] + */ + char *b_frozen_data; + + /* + * Pointer to a saved copy of the buffer containing no uncommitted + * deallocation references, so that allocations can avoid overwriting + * uncommitted deletes. [jbd_lock_bh_state()] + */ + char *b_committed_data; + + /* + * Pointer to the compound transaction which owns this buffer's + * metadata: either the running transaction or the committing + * transaction (if there is one). Only applies to buffers on a + * transaction's data or metadata journaling list. + * [j_list_lock] [jbd_lock_bh_state()] + */ + transaction_t *b_transaction; + + /* + * Pointer to the running compound transaction which is currently + * modifying the buffer's metadata, if there was already a transaction + * committing it when the new transaction touched it. + * [t_list_lock] [jbd_lock_bh_state()] + */ + transaction_t *b_next_transaction; + + /* + * Doubly-linked list of buffers on a transaction's data, metadata or + * forget queue. [t_list_lock] [jbd_lock_bh_state()] + */ + struct journal_head *b_tnext, *b_tprev; + + /* + * Pointer to the compound transaction against which this buffer + * is checkpointed. Only dirty buffers can be checkpointed. + * [j_list_lock] + */ + transaction_t *b_cp_transaction; + + /* + * Doubly-linked list of buffers still remaining to be flushed + * before an old transaction can be checkpointed. + * [j_list_lock] + */ + struct journal_head *b_cpnext, *b_cpprev; +}; + +#endif /* JOURNAL_HEAD_H_INCLUDED */ diff --git a/Ext4Fsd/include/linux/list.h b/Ext4Fsd/include/linux/list.h index 62bf07d..f48cdcb 100644 --- a/Ext4Fsd/include/linux/list.h +++ b/Ext4Fsd/include/linux/list.h @@ -1,255 +1,255 @@ -#ifndef __LINUX_LIST_H__ -#define __LINUX_LIST_H__ - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -#define prefetch(a) ((void *)a) - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head * new, - struct list_head * prev, - struct list_head * next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(struct list_head *head) -{ - return head->next == head; -} - -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(char *)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#ifndef list_for_each_prev -/** - * list_for_each_prev - iterate over a list in reverse order - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -#endif /* list_for_each_prev */ - -#ifndef list_for_each_entry -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, type, member) \ - for (pos = list_entry((head)->next, type, member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member), \ - prefetch(pos->member.next)) -#endif /* list_for_each_entry */ - -#ifndef list_for_each_entry_safe -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, type, member) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) -#endif /* list_for_each_entry_safe */ - -#endif /* __LINUX_LIST_H__ */ +#ifndef __LINUX_LIST_H__ +#define __LINUX_LIST_H__ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#define prefetch(a) ((void *)a) + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(char *)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +#ifndef list_for_each_prev +/** + * list_for_each_prev - iterate over a list in reverse order + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +#endif /* list_for_each_prev */ + +#ifndef list_for_each_entry +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, type, member) \ + for (pos = list_entry((head)->next, type, member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, type, member), \ + prefetch(pos->member.next)) +#endif /* list_for_each_entry */ + +#ifndef list_for_each_entry_safe +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, type, member) \ + for (pos = list_entry((head)->next, type, member), \ + n = list_entry(pos->member.next, type, member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, type, member)) +#endif /* list_for_each_entry_safe */ + +#endif /* __LINUX_LIST_H__ */ diff --git a/Ext4Fsd/include/linux/log2.h b/Ext4Fsd/include/linux/log2.h index f5bd56a..5df0613 100644 --- a/Ext4Fsd/include/linux/log2.h +++ b/Ext4Fsd/include/linux/log2.h @@ -1,140 +1,140 @@ -/* Integer base 2 logarithm calculation - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _LINUX_LOG2_H -#define _LINUX_LOG2_H - -#include -#include - -/* - * deal with unrepresentable constant logarithms - */ -int ____ilog2_NaN(void); - -/* - * non-constant log of base 2 calculators - * - the arch may override these in asm/bitops.h if they can be implemented - * more efficiently than using fls() and fls64() - * - the arch is not required to handle n==0 if implementing the fallback - */ -#ifndef CONFIG_ARCH_HAS_ILOG2_U32 -static inline __attribute__((const)) -int __ilog2_u32(u32 n) -{ - return fls(n) - 1; -} -#endif - -#ifndef CONFIG_ARCH_HAS_ILOG2_U64 -static inline __attribute__((const)) -int __ilog2_u64(u64 n) -{ - return fls64(n) - 1; -} -#endif - -/* - * Determine whether some value is a power of two, where zero is - * *not* considered a power of two. - */ - -static inline __attribute__((const)) -bool is_power_of_2(unsigned long n) -{ - return (n != 0 && ((n & (n - 1)) == 0)); -} - -/* - * round up to nearest power of two - */ -static inline __attribute__((const)) -unsigned long __roundup_pow_of_two(unsigned long n) -{ - return 1UL << fls_long(n - 1); -} - -/* - * round down to nearest power of two - */ -static inline __attribute__((const)) -unsigned long __rounddown_pow_of_two(unsigned long n) -{ - return 1UL << (fls_long(n) - 1); -} - -/** - * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value - * @n - parameter - * - * constant-capable log of base 2 calculation - * - this can be used to initialise global variables from constant data, hence - * the massive ternary operator construction - * - * selects the appropriately-sized optimised version depending on sizeof(n) - */ -#define ilog2(n) \ -( \ - (sizeof(n) <= 4) ? \ - __ilog2_u32(n) : \ - __ilog2_u64(n) \ - ) - -/** - * roundup_pow_of_two - round the given value up to nearest power of two - * @n - parameter - * - * round the given value up to the nearest power of two - * - the result is undefined when n == 0 - * - this can be used to initialise global variables from constant data - */ -#define roundup_pow_of_two(n) \ -( \ - __builtin_constant_p(n) ? ( \ - (n == 1) ? 1 : \ - (1UL << (ilog2((n) - 1) + 1)) \ - ) : \ - __roundup_pow_of_two(n) \ - ) - -/** - * rounddown_pow_of_two - round the given value down to nearest power of two - * @n - parameter - * - * round the given value down to the nearest power of two - * - the result is undefined when n == 0 - * - this can be used to initialise global variables from constant data - */ -#define rounddown_pow_of_two(n) \ -( \ - __builtin_constant_p(n) ? ( \ - (n == 1) ? 0 : \ - (1UL << ilog2(n))) : \ - __rounddown_pow_of_two(n) \ - ) - -/** - * order_base_2 - calculate the (rounded up) base 2 order of the argument - * @n: parameter - * - * The first few values calculated by this routine: - * ob2(0) = 0 - * ob2(1) = 0 - * ob2(2) = 1 - * ob2(3) = 2 - * ob2(4) = 2 - * ob2(5) = 3 - * ... and so on. - */ - -#define order_base_2(n) ilog2(roundup_pow_of_two(n)) - -#endif /* _LINUX_LOG2_H */ +/* Integer base 2 logarithm calculation + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_LOG2_H +#define _LINUX_LOG2_H + +#include +#include + +/* + * deal with unrepresentable constant logarithms + */ +int ____ilog2_NaN(void); + +/* + * non-constant log of base 2 calculators + * - the arch may override these in asm/bitops.h if they can be implemented + * more efficiently than using fls() and fls64() + * - the arch is not required to handle n==0 if implementing the fallback + */ +#ifndef CONFIG_ARCH_HAS_ILOG2_U32 +static inline __attribute__((const)) +int __ilog2_u32(u32 n) +{ + return fls(n) - 1; +} +#endif + +#ifndef CONFIG_ARCH_HAS_ILOG2_U64 +static inline __attribute__((const)) +int __ilog2_u64(u64 n) +{ + return fls64(n) - 1; +} +#endif + +/* + * Determine whether some value is a power of two, where zero is + * *not* considered a power of two. + */ + +static inline __attribute__((const)) +bool is_power_of_2(unsigned long n) +{ + return (n != 0 && ((n & (n - 1)) == 0)); +} + +/* + * round up to nearest power of two + */ +static inline __attribute__((const)) +unsigned long __roundup_pow_of_two(unsigned long n) +{ + return 1UL << fls_long(n - 1); +} + +/* + * round down to nearest power of two + */ +static inline __attribute__((const)) +unsigned long __rounddown_pow_of_two(unsigned long n) +{ + return 1UL << (fls_long(n) - 1); +} + +/** + * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value + * @n - parameter + * + * constant-capable log of base 2 calculation + * - this can be used to initialise global variables from constant data, hence + * the massive ternary operator construction + * + * selects the appropriately-sized optimised version depending on sizeof(n) + */ +#define ilog2(n) \ +( \ + (sizeof(n) <= 4) ? \ + __ilog2_u32(n) : \ + __ilog2_u64(n) \ + ) + +/** + * roundup_pow_of_two - round the given value up to nearest power of two + * @n - parameter + * + * round the given value up to the nearest power of two + * - the result is undefined when n == 0 + * - this can be used to initialise global variables from constant data + */ +#define roundup_pow_of_two(n) \ +( \ + __builtin_constant_p(n) ? ( \ + (n == 1) ? 1 : \ + (1UL << (ilog2((n) - 1) + 1)) \ + ) : \ + __roundup_pow_of_two(n) \ + ) + +/** + * rounddown_pow_of_two - round the given value down to nearest power of two + * @n - parameter + * + * round the given value down to the nearest power of two + * - the result is undefined when n == 0 + * - this can be used to initialise global variables from constant data + */ +#define rounddown_pow_of_two(n) \ +( \ + __builtin_constant_p(n) ? ( \ + (n == 1) ? 0 : \ + (1UL << ilog2(n))) : \ + __rounddown_pow_of_two(n) \ + ) + +/** + * order_base_2 - calculate the (rounded up) base 2 order of the argument + * @n: parameter + * + * The first few values calculated by this routine: + * ob2(0) = 0 + * ob2(1) = 0 + * ob2(2) = 1 + * ob2(3) = 2 + * ob2(4) = 2 + * ob2(5) = 3 + * ... and so on. + */ + +#define order_base_2(n) ilog2(roundup_pow_of_two(n)) + +#endif /* _LINUX_LOG2_H */ diff --git a/Ext4Fsd/include/linux/module.h b/Ext4Fsd/include/linux/module.h index 7385c03..5274425 100644 --- a/Ext4Fsd/include/linux/module.h +++ b/Ext4Fsd/include/linux/module.h @@ -1,1215 +1,1215 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: Modules.h - * PURPOSE: Header file: nls structures & linux kernel ... - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -#ifndef _EXT2_MODULE_HEADER_ -#define _EXT2_MODULE_HEADER_ - -/* INCLUDES *************************************************************/ - -#include -#include -#include -#include -#include - -#if _WIN32_WINNT <= 0x500 -#define _WIN2K_TARGET_ 1 -#endif - -/* STRUCTS ******************************************************/ - -#ifndef offsetof -# define offsetof(type, member) ((ULONG_PTR)&(((type *)0)->member)) -#endif - -#ifndef container_of -#define container_of(ptr, type, member) \ - ((type *)((char *)ptr - (char *)offsetof(type, member))) -#endif - -// -// Byte order swapping routines -// - -/* use the runtime routine or compiler's implementation */ -#if (defined(_M_IX86) && (_MSC_FULL_VER > 13009037)) || \ - ((defined(_M_AMD64) || defined(_M_IA64)) && \ - (_MSC_FULL_VER > 13009175)) -#ifdef __cplusplus -extern "C" { -#endif - unsigned short __cdecl _byteswap_ushort(unsigned short); - unsigned long __cdecl _byteswap_ulong (unsigned long); - unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64); -#ifdef __cplusplus -} -#endif -#pragma intrinsic(_byteswap_ushort) -#pragma intrinsic(_byteswap_ulong) -#pragma intrinsic(_byteswap_uint64) - -#define RtlUshortByteSwap(_x) _byteswap_ushort((USHORT)(_x)) -#define RtlUlongByteSwap(_x) _byteswap_ulong((_x)) -#define RtlUlonglongByteSwap(_x) _byteswap_uint64((_x)) - -#else - -USHORT -FASTCALL -RtlUshortByteSwap( - IN USHORT Source -); - -ULONG -FASTCALL -RtlUlongByteSwap( - IN ULONG Source -); - -ULONGLONG -FASTCALL -RtlUlonglongByteSwap( - IN ULONGLONG Source -); -#endif - -#define __swab16(x) RtlUshortByteSwap(x) -#define __swab32(x) RtlUlongByteSwap(x) -#define __swab64(x) RtlUlonglongByteSwap(x) - -#define __constant_swab32 __swab32 -#define __constant_swab64 __swab64 - -#define __constant_htonl(x) __constant_swab32((x)) -#define __constant_ntohl(x) __constant_swab32((x)) -#define __constant_htons(x) __constant_swab16((x)) -#define __constant_ntohs(x) __constant_swab16((x)) -#define __constant_cpu_to_le64(x) ((__u64)(x)) -#define __constant_le64_to_cpu(x) ((__u64)(x)) -#define __constant_cpu_to_le32(x) ((__u32)(x)) -#define __constant_le32_to_cpu(x) ((__u32)(x)) -#define __constant_cpu_to_le16(x) ((__u16)(x)) -#define __constant_le16_to_cpu(x) ((__u16)(x)) -#define __constant_cpu_to_be64(x) __constant_swab64((x)) -#define __constant_be64_to_cpu(x) __constant_swab64((x)) -#define __constant_cpu_to_be32(x) __constant_swab32((x)) -#define __constant_be32_to_cpu(x) __constant_swab32((x)) -#define __constant_cpu_to_be16(x) __constant_swab16((x)) -#define __constant_be16_to_cpu(x) __constant_swab16((x)) -#define __cpu_to_le64(x) ((__u64)(x)) -#define __le64_to_cpu(x) ((__u64)(x)) -#define __cpu_to_le32(x) ((__u32)(x)) -#define __le32_to_cpu(x) ((__u32)(x)) -#define __cpu_to_le16(x) ((__u16)(x)) -#define __le16_to_cpu(x) ((__u16)(x)) -#define __cpu_to_be64(x) __swab64((x)) -#define __be64_to_cpu(x) __swab64((x)) -#define __cpu_to_be32(x) __swab32((x)) -#define __be32_to_cpu(x) __swab32((x)) -#define __cpu_to_be16(x) __swab16((x)) -#define __be16_to_cpu(x) __swab16((x)) -#define __cpu_to_le64p(x) (*(__u64*)(x)) -#define __le64_to_cpup(x) (*(__u64*)(x)) -#define __cpu_to_le32p(x) (*(__u32*)(x)) -#define __le32_to_cpup(x) (*(__u32*)(x)) -#define __cpu_to_le16p(x) (*(__u16*)(x)) -#define __le16_to_cpup(x) (*(__u16*)(x)) -#define __cpu_to_be64p(x) __swab64p((x)) -#define __be64_to_cpup(x) __swab64p((x)) -#define __cpu_to_be32p(x) __swab32p((x)) -#define __be32_to_cpup(x) __swab32p((x)) -#define __cpu_to_be16p(x) __swab16p((x)) -#define __be16_to_cpup(x) __swab16p((x)) -#define __cpu_to_le64s(x) ((__s64)(x)) -#define __le64_to_cpus(x) ((__s64)(x)) -#define __cpu_to_le32s(x) ((__s32)(x)) -#define __le32_to_cpus(x) ((__s32)(x)) -#define __cpu_to_le16s(x) ((__s16)(x)) -#define __le16_to_cpus(x) ((__s16)(x)) -#define __cpu_to_be64s(x) __swab64s((x)) -#define __be64_to_cpus(x) __swab64s((x)) -#define __cpu_to_be32s(x) __swab32s((x)) -#define __be32_to_cpus(x) __swab32s((x)) -#define __cpu_to_be16s(x) __swab16s((x)) -#define __be16_to_cpus(x) __swab16s((x)) - -#ifndef cpu_to_le64 -#define cpu_to_le64 __cpu_to_le64 -#define le64_to_cpu __le64_to_cpu -#define cpu_to_le32 __cpu_to_le32 -#define le32_to_cpu __le32_to_cpu -#define cpu_to_le16 __cpu_to_le16 -#define le16_to_cpu __le16_to_cpu -#endif - -#define cpu_to_be64 __cpu_to_be64 -#define be64_to_cpu __be64_to_cpu -#define cpu_to_be32 __cpu_to_be32 -#define be32_to_cpu __be32_to_cpu -#define cpu_to_be16 __cpu_to_be16 -#define be16_to_cpu __be16_to_cpu -#define cpu_to_le64p __cpu_to_le64p -#define le64_to_cpup __le64_to_cpup -#define cpu_to_le32p __cpu_to_le32p -#define le32_to_cpup __le32_to_cpup -#define cpu_to_le16p __cpu_to_le16p -#define le16_to_cpup __le16_to_cpup -#define cpu_to_be64p __cpu_to_be64p -#define be64_to_cpup __be64_to_cpup -#define cpu_to_be32p __cpu_to_be32p -#define be32_to_cpup __be32_to_cpup -#define cpu_to_be16p __cpu_to_be16p -#define be16_to_cpup __be16_to_cpup -#define cpu_to_le64s __cpu_to_le64s -#define le64_to_cpus __le64_to_cpus -#define cpu_to_le32s __cpu_to_le32s -#define le32_to_cpus __le32_to_cpus -#define cpu_to_le16s __cpu_to_le16s -#define le16_to_cpus __le16_to_cpus -#define cpu_to_be64s __cpu_to_be64s -#define be64_to_cpus __be64_to_cpus -#define cpu_to_be32s __cpu_to_be32s -#define be32_to_cpus __be32_to_cpus -#define cpu_to_be16s __cpu_to_be16s -#define be16_to_cpus __be16_to_cpus - - -static inline void le16_add_cpu(__le16 *var, u16 val) -{ - *var = cpu_to_le16(le16_to_cpu(*var) + val); -} - -static inline void le32_add_cpu(__le32 *var, u32 val) -{ - *var = cpu_to_le32(le32_to_cpu(*var) + val); -} - -static inline void le64_add_cpu(__le64 *var, u64 val) -{ - *var = cpu_to_le64(le64_to_cpu(*var) + val); -} - -// -// Network to host byte swap functions -// - -#define ntohl(x) ( ( ( ( x ) & 0x000000ff ) << 24 ) | \ - ( ( ( x ) & 0x0000ff00 ) << 8 ) | \ - ( ( ( x ) & 0x00ff0000 ) >> 8 ) | \ - ( ( ( x ) & 0xff000000 ) >> 24 ) ) - -#define ntohs(x) ( ( ( ( x ) & 0xff00 ) >> 8 ) | \ - ( ( ( x ) & 0x00ff ) << 8 ) ) - - -#define htonl(x) ntohl(x) -#define htons(x) ntohs(x) - - -// -// kernel printk flags -// - -#define KERN_EMERG "<0>" /* system is unusable */ -#define KERN_ALERT "<1>" /* action must be taken immediately */ -#define KERN_CRIT "<2>" /* critical conditions */ -#define KERN_ERR "<3>" /* error conditions */ -#define KERN_WARNING "<4>" /* warning conditions */ -#define KERN_NOTICE "<5>" /* normal but significant condition */ -#define KERN_INFO "<6>" /* informational */ -#define KERN_DEBUG "<7>" /* debug-level messages */ - -#define printk DbgPrint - -/* - * error pointer - */ -#define MAX_ERRNO 4095 -#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) - -static inline void *ERR_PTR(long error) -{ - return (void *)(long_ptr_t) error; -} - -static inline long PTR_ERR(const void *ptr) -{ - return (long)(long_ptr_t) ptr; -} - -static inline long IS_ERR(const void *ptr) -{ - return IS_ERR_VALUE((unsigned long)(long_ptr_t)ptr); -} - - -#define BUG_ON(c) assert(!(c)) - -#define WARN_ON(c) BUG_ON(c) - -// -// Linux module definitions -// - -#define likely -#define unlikely - -#define __init -#define __exit - -#define THIS_MODULE NULL -#define MODULE_LICENSE(x) -#define MODULE_ALIAS_NLS(x) -#define EXPORT_SYMBOL(x) - - -#define try_module_get(x) (TRUE) -#define module_put(x) - -#define module_init(X) int __init module_##X() {return X();} -#define module_exit(X) void __exit module_##X() {X();} - -#define DECLARE_INIT(X) int __init module_##X(void) -#define DECLARE_EXIT(X) void __exit module_##X(void) - -#define LOAD_MODULE(X) do { \ - rc = module_##X(); \ - } while(0) - -#define UNLOAD_MODULE(X) do { \ - module_##X(); \ - } while(0) - -#define LOAD_NLS LOAD_MODULE -#define UNLOAD_NLS UNLOAD_MODULE - -// -// spinlocks ..... -// - -typedef struct _spinlock_t { - - KSPIN_LOCK lock; - KIRQL irql; -} spinlock_t; - -#define spin_lock_init(sl) KeInitializeSpinLock(&((sl)->lock)) -#define spin_lock(sl) KeAcquireSpinLock(&((sl)->lock), &((sl)->irql)) -#define spin_unlock(sl) KeReleaseSpinLock(&((sl)->lock), (sl)->irql) -#define spin_lock_irqsave(sl, flags) do {spin_lock(sl); flags=(sl)->irql;} while(0) -#define spin_unlock_irqrestore(sl, flags) do {ASSERT((KIRQL)(flags)==(sl)->irql); spin_unlock(sl);} while(0) - -#define assert_spin_locked(x) do {} while(0) - -/* - * Does a critical section need to be broken due to another - * task waiting?: (technically does not depend on CONFIG_PREEMPT, - * but a general need for low latency) - */ -static inline int spin_needbreak(spinlock_t *lock) -{ -#ifdef CONFIG_PREEMPT - return spin_is_contended(lock); -#else - return 0; -#endif -} - -// -// bit operations -// - -/** - * __set_bit - Set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Unlike set_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ -static inline int set_bit(int nr, volatile unsigned long *addr) -{ - addr += (nr >> ORDER_PER_LONG); - nr &= (BITS_PER_LONG - 1); - - return !!(InterlockedOr(addr, (1 << nr)) & (1 << nr)); -} - - -/** - * clear_bit - Clears a bit in memory - * @nr: Bit to clear - * @addr: Address to start counting from - * - * clear_bit() is atomic and may not be reordered. However, it does - * not contain a memory barrier, so if it is used for locking purposes, - * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() - * in order to ensure changes are visible on other processors. - */ -static inline int clear_bit(int nr, volatile unsigned long *addr) -{ - addr += (nr >> ORDER_PER_LONG); - nr &= (BITS_PER_LONG - 1); - - return !!(InterlockedAnd(addr, ~(1 << nr)) & (1 << nr)); -} - -/** - * test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to clear - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) -{ - return clear_bit(nr, addr); -} - -/* - * test - */ -static int test_bit(int nr, volatile const unsigned long *addr) -{ - return !!((1 << (nr & (BITS_PER_LONG - 1))) & - (addr[nr >> ORDER_PER_LONG])); -} - -/** - * test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static inline int test_and_set_bit(int nr, volatile unsigned long *addr) -{ - return set_bit(nr, addr); -} - -// -// list definition ... -// - -#include - - -/********************************************* - * linux scheduler related structures * -*********************************************/ - -// -// task structure -// - -#define TASK_INTERRUPTIBLE 1 -#define TASK_UNINTERRUPTIBLE 2 - -struct task_struct { - pid_t pid; - pid_t tid; - char comm[32]; - void * journal_info; -}; - -extern struct task_struct *current; - -// -// scheduler routines -// - - -static inline cond_resched() { - return FALSE; -} -static inline need_resched() { - return FALSE; -} - -#define yield() do {} while(0) -#define might_sleep() do {} while(0) - -// -// mutex -// - -typedef struct mutex { - FAST_MUTEX lock; -} mutex_t; - -#define mutex_init(x) ExInitializeFastMutex(&((x)->lock)) -#define mutex_lock(x) ExAcquireFastMutex(&((x)->lock)) -#define mutex_unlock(x) ExReleaseFastMutex(&((x)->lock)) - - -// -// wait_queue -// - - -typedef PVOID wait_queue_t; - -#define WQ_FLAG_EXCLUSIVE 0x01 -#define WQ_FLAG_AUTO_REMOVAL 0x02 - -struct __wait_queue { - unsigned int flags; - void * private; - KEVENT event; - struct list_head task_list; -}; - - -#define DEFINE_WAIT(name) \ - wait_queue_t name = (PVOID)wait_queue_create(); - -/* -struct wait_bit_key { - void *flags; - int bit_nr; -}; - -struct wait_bit_queue { - struct wait_bit_key key; - wait_queue_t wait; -}; -*/ - -struct __wait_queue_head { - spinlock_t lock; - struct list_head task_list; -}; -typedef struct __wait_queue_head wait_queue_head_t; - -#define is_sync_wait(wait) (TRUE) -#define set_current_state(state) do {} while(0) -#define __set_current_state(state) do {} while(0) - -void init_waitqueue_head(wait_queue_head_t *q); -int wake_up(wait_queue_head_t *queue); - - -/* - * Waitqueues which are removed from the waitqueue_head at wakeup time - */ -struct __wait_queue * wait_queue_create(); -void wait_queue_destroy(struct __wait_queue *); - -void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state); -void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state); -void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); -int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); -int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); - - -// -// timer structure -// - -struct timer_list { - struct list_head entry; - unsigned long expires; - - void (*function)(unsigned long); - unsigned long data; - -#ifdef CONFIG_TIMER_STATS - void *start_site; - char start_comm[16]; - int start_pid; -#endif -}; - - -typedef struct kmem_cache kmem_cache_t; - -struct block_device { - - unsigned long bd_flags; /* flags */ - atomic_t bd_count; /* reference count */ - PDEVICE_OBJECT bd_dev; /* device object */ - ANSI_STRING bd_name; /* name in ansi string */ - DISK_GEOMETRY bd_geo; /* disk geometry */ - PARTITION_INFORMATION bd_part; /* partition information */ - void * bd_priv; /* pointers to EXT2_VCB - NULL if it's a journal dev */ - PFILE_OBJECT bd_volume; /* streaming object file */ - LARGE_MCB bd_extents; /* dirty extents */ - - kmem_cache_t * bd_bh_cache;/* memory cache for buffer_head */ - ERESOURCE bd_bh_lock; /* lock for bh tree and reaper list */ - struct rb_root bd_bh_root; /* buffer_head red-black tree root */ - LIST_ENTRY bd_bh_free; /* reaper list */ - KEVENT bd_bh_notify; /* notification event for cleanup */ -}; - -// -// page information -// - -// vom trata paginile in felul urmator: -// alocam la sfarsitul structurii inca PAGE_SIZE octeti cand alocam o structura -// de tip pagina - acolo vor veni toate buffer-headurile -// deci -> page_address(page) = page + sizeof(page) -#define page_address(_page) ((char*)_page + sizeof(struct page)) - -typedef struct page { - void *addr; - void *mapping; - void *private; - atomic_t count; - __u32 index; - __u32 flags; -} mem_map_t; - -#define get_page(p) atomic_inc(&(p)->count) - -#define PG_locked 0 /* Page is locked. Don't touch. */ -#define PG_error 1 -#define PG_referenced 2 -#define PG_uptodate 3 -#define PG_dirty 4 -#define PG_unused 5 -#define PG_lru 6 -#define PG_active 7 -#define PG_slab 8 -#define PG_skip 10 -#define PG_highmem 11 -#define PG_checked 12 /* kill me in 2.5.. */ -#define PG_arch_1 13 -#define PG_reserved 14 -#define PG_launder 15 /* written out by VM pressure.. */ -#define PG_fs_1 16 /* Filesystem specific */ - -#ifndef arch_set_page_uptodate -#define arch_set_page_uptodate(page) -#endif - -/* Make it prettier to test the above... */ -#define UnlockPage(page) unlock_page(page) -#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) -#define SetPageUptodate(page) \ - do { \ - arch_set_page_uptodate(page); \ - set_bit(PG_uptodate, &(page)->flags); \ - } while (0) -#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) -#define PageDirty(page) test_bit(PG_dirty, &(page)->flags) -#define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags) -#define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags) -#define PageLocked(page) test_bit(PG_locked, &(page)->flags) -#define LockPage(page) set_bit(PG_locked, &(page)->flags) -#define TryLockPage(page) test_and_set_bit(PG_locked, &(page)->flags) -#define PageChecked(page) test_bit(PG_checked, &(page)->flags) -#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags) -#define ClearPageChecked(page) clear_bit(PG_checked, &(page)->flags) -#define PageLaunder(page) test_bit(PG_launder, &(page)->flags) -#define SetPageLaunder(page) set_bit(PG_launder, &(page)->flags) -#define ClearPageLaunder(page) clear_bit(PG_launder, &(page)->flags) -#define ClearPageArch1(page) clear_bit(PG_arch_1, &(page)->flags) - -#define PageError(page) test_bit(PG_error, &(page)->flags) -#define SetPageError(page) set_bit(PG_error, &(page)->flags) -#define ClearPageError(page) clear_bit(PG_error, &(page)->flags) -#define PageReferenced(page) test_bit(PG_referenced, &(page)->flags) -#define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags) -#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags) - -#define PageActive(page) test_bit(PG_active, &(page)->flags) -#define SetPageActive(page) set_bit(PG_active, &(page)->flags) -#define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) - - -extern unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order); -#define __get_free_page(gfp_mask) \ - __get_free_pages((gfp_mask),0) - -extern void __free_pages(struct page *page, unsigned int order); -extern void free_pages(unsigned long addr, unsigned int order); - -#define __free_page(page) __free_pages((page), 0) -#define free_page(addr) free_pages((addr),0) - -extern void truncate_inode_pages(struct address_space *, loff_t); - -#define __GFP_HIGHMEM 0x02 - -#define __GFP_WAIT 0x10 /* Can wait and reschedule? */ -#define __GFP_HIGH 0x20 /* Should access emergency pools? */ -#define __GFP_IO 0x40 /* Can start low memory physical IO? */ -#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */ -#define __GFP_FS 0x100 /* Can call down to low-level FS? */ - -#define GFP_ATOMIC (__GFP_HIGH) -#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) -#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS | __GFP_HIGHMEM) -#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) -#define GFP_NOFS 0 -#define __GFP_NOFAIL 0 - - -#define KM_USER0 0 - -// -// buffer head definitions -// - -enum bh_state_bits { - BH_Uptodate, /* Contains valid data */ - BH_Dirty, /* Is dirty */ - BH_Verified, /* Is verified */ - BH_Lock, /* Is locked */ - BH_Req, /* Has been submitted for I/O */ - BH_Uptodate_Lock, /* Used by the first bh in a page, to serialise - * IO completion of other buffers in the page - */ - - BH_Mapped, /* Has a disk mapping */ - BH_New, /* Disk mapping was newly created by get_block */ - BH_Async_Read, /* Is under end_buffer_async_read I/O */ - BH_Async_Write, /* Is under end_buffer_async_write I/O */ - BH_Delay, /* Buffer is not yet allocated on disk */ - BH_Boundary, /* Block is followed by a discontiguity */ - BH_Write_EIO, /* I/O error on write */ - BH_Ordered, /* ordered write */ - BH_Eopnotsupp, /* operation not supported (barrier) */ - BH_Unwritten, /* Buffer is allocated on disk but not written */ - - BH_PrivateStart, /* not a state bit, but the first bit available - * for private allocation by other entities - */ -}; - -#define PAGE_CACHE_SIZE (PAGE_SIZE) -#define PAGE_CACHE_SHIFT (12) -#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512) - -typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate); - -/* - * Historically, a buffer_head was used to map a single block - * within a page, and of course as the unit of I/O through the - * filesystem and block layers. Nowadays the basic I/O unit - * is the bio, and buffer_heads are used for extracting block - * mappings (via a get_block_t call), for tracking state within - * a page (via a page_mapping) and for wrapping bio submission - * for backward compatibility reasons (e.g. submit_bh). - */ -struct buffer_head { - LIST_ENTRY b_link; /* to be added to reaper list */ - unsigned long b_state; /* buffer state bitmap (see above) */ - struct page *b_page; /* the page this bh is mapped to */ - PMDL b_mdl; /* MDL of the locked buffer */ - void *b_bcb; /* BCB of the buffer */ - - // kdev_t b_dev; /* device (B_FREE = free) */ - struct block_device *b_bdev; /* block device object */ - - blkcnt_t b_blocknr; /* start block number */ - size_t b_size; /* size of mapping */ - char * b_data; /* pointer to data within the page */ - bh_end_io_t *b_end_io; /* I/O completion */ - void *b_private; /* reserved for b_end_io */ - // struct list_head b_assoc_buffers; /* associated with another mapping */ - // struct address_space *b_assoc_map; /* mapping this buffer is associated with */ - atomic_t b_count; /* users using this buffer_head */ - struct rb_node b_rb_node; /* Red-black tree node entry */ - - LARGE_INTEGER b_ts_creat; /* creation time*/ - LARGE_INTEGER b_ts_drop; /* drop time (to be released) */ -}; - - -/* - * macro tricks to expand the set_buffer_foo(), clear_buffer_foo() - * and buffer_foo() functions. - */ -#define BUFFER_FNS(bit, name) \ -static inline void set_buffer_##name(struct buffer_head *bh) \ -{ \ - set_bit(BH_##bit, &(bh)->b_state); \ -} \ -static inline void clear_buffer_##name(struct buffer_head *bh) \ -{ \ - clear_bit(BH_##bit, &(bh)->b_state); \ -} \ -static inline int buffer_##name(const struct buffer_head *bh) \ -{ \ - return test_bit(BH_##bit, &(bh)->b_state); \ -} - -/* - * test_set_buffer_foo() and test_clear_buffer_foo() - */ -#define TAS_BUFFER_FNS(bit, name) \ -static inline int test_set_buffer_##name(struct buffer_head *bh) \ -{ \ - return test_and_set_bit(BH_##bit, &(bh)->b_state); \ -} \ -static inline int test_clear_buffer_##name(struct buffer_head *bh) \ -{ \ - return test_and_clear_bit(BH_##bit, &(bh)->b_state); \ -} \ - -/* - * Emit the buffer bitops functions. Note that there are also functions - * of the form "mark_buffer_foo()". These are higher-level functions which - * do something in addition to setting a b_state bit. - */ -BUFFER_FNS(Uptodate, uptodate) -BUFFER_FNS(Dirty, dirty) -TAS_BUFFER_FNS(Dirty, dirty) -BUFFER_FNS(Verified, verified) -BUFFER_FNS(Lock, locked) -TAS_BUFFER_FNS(Lock, locked) -BUFFER_FNS(Req, req) -TAS_BUFFER_FNS(Req, req) -BUFFER_FNS(Mapped, mapped) -BUFFER_FNS(New, new) -BUFFER_FNS(Async_Read, async_read) -BUFFER_FNS(Async_Write, async_write) -BUFFER_FNS(Delay, delay) -BUFFER_FNS(Boundary, boundary) -BUFFER_FNS(Write_EIO, write_io_error) -BUFFER_FNS(Ordered, ordered) -BUFFER_FNS(Eopnotsupp, eopnotsupp) -BUFFER_FNS(Unwritten, unwritten) - -#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK) -#define touch_buffer(bh) mark_page_accessed(bh->b_page) - -/* If we *know* page->private refers to buffer_heads */ - -#define page_buffers(page) \ - ( \ - BUG_ON(!PagePrivate(page)), \ - ((struct buffer_head *)page_private(page)) \ - ) -#define page_has_buffers(page) PagePrivate(page) - - -/* - * Declarations - */ - -void mark_buffer_dirty(struct buffer_head *bh); -void init_buffer(struct buffer_head *, bh_end_io_t *, void *); -void set_bh_page(struct buffer_head *bh, - struct page *page, unsigned long offset); -int try_to_free_buffers(struct page *); -struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size, - int retry); -void create_empty_buffers(struct page *, unsigned long, - unsigned long b_state); - -/* Things to do with buffers at mapping->private_list */ -void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode); -int inode_has_buffers(struct inode *); -void invalidate_inode_buffers(struct inode *); -int remove_inode_buffers(struct inode *inode); -int sync_mapping_buffers(struct address_space *mapping); -void unmap_underlying_metadata(struct block_device *bdev, sector_t block); - -void mark_buffer_async_write(struct buffer_head *bh); -void invalidate_bdev(struct block_device *); -int sync_blockdev(struct block_device *bdev); -void __wait_on_buffer(struct buffer_head *); -wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); -int fsync_bdev(struct block_device *); -struct super_block *freeze_bdev(struct block_device *); -void thaw_bdev(struct block_device *, struct super_block *); -int fsync_super(struct super_block *); -int fsync_no_super(struct block_device *); -struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, - unsigned long size); -struct buffer_head *get_block_bh(struct block_device *bdev, sector_t block, - unsigned long size, int zero); -struct buffer_head *__getblk(struct block_device *bdev, sector_t block, - unsigned long size); -void __brelse(struct buffer_head *); -void __bforget(struct buffer_head *); -void __breadahead(struct block_device *, sector_t block, unsigned int size); -struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size); -void invalidate_bh_lrus(void); -struct buffer_head *alloc_buffer_head(gfp_t gfp_flags); -void free_buffer_head(struct buffer_head * bh); -void unlock_buffer(struct buffer_head *bh); -void __lock_buffer(struct buffer_head *bh); -void ll_rw_block(int, int, struct buffer_head * bh[]); -int sync_dirty_buffer(struct buffer_head *bh); -int submit_bh(int, struct buffer_head *); -void write_boundary_block(struct block_device *bdev, - sector_t bblock, unsigned blocksize); -int bh_uptodate_or_lock(struct buffer_head *bh); -int bh_submit_read(struct buffer_head *bh); -/* They are separately managed */ -struct buffer_head *extents_bread(struct super_block *sb, sector_t block); -struct buffer_head *extents_bwrite(struct super_block *sb, sector_t block); -void extents_mark_buffer_dirty(struct buffer_head *bh); -void extents_brelse(struct buffer_head *bh); -void extents_bforget(struct buffer_head *bh); -void buffer_head_remove(struct block_device *bdev, struct buffer_head *bh); - -extern int buffer_heads_over_limit; - -/* - * Generic address_space_operations implementations for buffer_head-backed - * address_spaces. - */ - -#if 0 - -int block_write_full_page(struct page *page, get_block_t *get_block, - struct writeback_control *wbc); -int block_read_full_page(struct page*, get_block_t*); -int block_write_begin(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page **, void **, get_block_t*); -int block_write_end(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page *, void *); -int generic_write_end(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page *, void *); - -int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); -int cont_write_begin(struct file *, struct address_space *, loff_t, - unsigned, unsigned, struct page **, void **, - get_block_t *, loff_t *); -int block_page_mkwrite(struct vm_area_struct *vma, struct page *page, - get_block_t get_block); -sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); -int generic_commit_write(struct file *, struct page *, unsigned, unsigned); -int block_truncate_page(struct address_space *, loff_t, get_block_t *); -int file_fsync(struct file *, struct dentry *, int); -int nobh_write_begin(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page **, void **, get_block_t*); -int nobh_write_end(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page *, void *); -int nobh_truncate_page(struct address_space *, loff_t, get_block_t *); -int nobh_writepage(struct page *page, get_block_t *get_block, - struct writeback_control *wbc); -int generic_cont_expand_simple(struct inode *inode, loff_t size); -#endif - -void block_invalidatepage(struct page *page, unsigned long offset); -void page_zero_new_buffers(struct page *page, unsigned from, unsigned to); -int block_commit_write(struct page *page, unsigned from, unsigned to); -void block_sync_page(struct page *); - -void buffer_init(void); - -/* - * inline definitions - */ -#if 0 -static inline void attach_page_buffers(struct page *page, - struct buffer_head *head) -{ - page_cache_get(page); - SetPagePrivate(page); - set_page_private(page, (unsigned long)head); -} -#endif - -static inline void get_bh(struct buffer_head *bh) -{ - atomic_inc(&bh->b_count); -} - -static inline void put_bh(struct buffer_head *bh) -{ - if (bh) - __brelse(bh); -} - -static inline void brelse(struct buffer_head *bh) -{ - if (bh) - __brelse(bh); -} - -static inline void fini_bh(struct buffer_head **bh) -{ - if (bh && *bh) { - brelse(*bh); - *bh = NULL; - } -} - -static inline void bforget(struct buffer_head *bh) -{ - if (bh) - __bforget(bh); -} - -static inline struct buffer_head * - sb_getblk(struct super_block *sb, sector_t block) -{ - return get_block_bh(sb->s_bdev, block, sb->s_blocksize, 0); -} - -static inline struct buffer_head * - sb_getblk_zero(struct super_block *sb, sector_t block) -{ - return get_block_bh(sb->s_bdev, block, sb->s_blocksize, 1); -} - -static inline struct buffer_head * - sb_bread(struct super_block *sb, sector_t block) -{ - struct buffer_head *bh = __getblk(sb->s_bdev, block, sb->s_blocksize); - if (!bh) - return NULL; - if (!buffer_uptodate(bh) && (bh_submit_read(bh) < 0)) { - brelse(bh); - return NULL; - } - return bh; -} - -static inline struct buffer_head * - sb_find_get_block(struct super_block *sb, sector_t block) -{ - return __find_get_block(sb->s_bdev, block, sb->s_blocksize); -} - -static inline void -map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block) -{ - set_buffer_mapped(bh); - bh->b_bdev = sb->s_bdev; - bh->b_blocknr = block; - bh->b_size = sb->s_blocksize; -} - -/* - * Calling wait_on_buffer() for a zero-ref buffer is illegal, so we call into - * __wait_on_buffer() just to trip a debug check. Because debug code in inline - * functions is bloaty. - */ - -static inline void wait_on_buffer(struct buffer_head *bh) -{ - might_sleep(); - if (buffer_locked(bh) || atomic_read(&bh->b_count) == 0) - __wait_on_buffer(bh); -} - -static inline void lock_buffer(struct buffer_head *bh) -{ - might_sleep(); - if (test_set_buffer_locked(bh)) - __lock_buffer(bh); -} - -extern int __set_page_dirty_buffers(struct page *page); - -// -// unicode character -// - -struct nls_table { - char *charset; - char *alias; - int (*uni2char) (wchar_t uni, unsigned char *out, int boundlen); - int (*char2uni) (const unsigned char *rawstring, int boundlen, - wchar_t *uni); - unsigned char *charset2lower; - unsigned char *charset2upper; - struct module *owner; - struct nls_table *next; -}; - -/* this value hold the maximum octet of charset */ -#define NLS_MAX_CHARSET_SIZE 6 /* for UTF-8 */ - -/* nls.c */ -extern int register_nls(struct nls_table *); -extern int unregister_nls(struct nls_table *); -extern struct nls_table *load_nls(char *); -extern void unload_nls(struct nls_table *); -extern struct nls_table *load_nls_default(void); - -extern int utf8_mbtowc(wchar_t *, const __u8 *, int); -extern int utf8_mbstowcs(wchar_t *, const __u8 *, int); -extern int utf8_wctomb(__u8 *, wchar_t, int); -extern int utf8_wcstombs(__u8 *, const wchar_t *, int); - -// -// kernel jiffies -// - -#define HZ (100) - -static inline __u32 JIFFIES() -{ - LARGE_INTEGER Tick; - - KeQueryTickCount(&Tick); - Tick.QuadPart *= KeQueryTimeIncrement(); - Tick.QuadPart /= (10000000 / HZ); - - return Tick.LowPart; -} - -#define jiffies JIFFIES() - -// -// memory routines -// - -#ifdef _WIN2K_TARGET_ - -typedef GUID UUID; -NTKERNELAPI -NTSTATUS -ExUuidCreate( - OUT UUID *Uuid -); - -NTKERNELAPI -PVOID -NTAPI -ExAllocatePoolWithTag( - IN POOL_TYPE PoolType, - IN SIZE_T NumberOfBytes, - IN ULONG Tag -); - -#define ExFreePoolWithTag(_P, _T) ExFreePool(_P) -#endif - -PVOID Ext2AllocatePool( - IN POOL_TYPE PoolType, - IN SIZE_T NumberOfBytes, - IN ULONG Tag -); - -VOID -Ext2FreePool( - IN PVOID P, - IN ULONG Tag -); - -void *kzalloc(int size, int flags); -#define kmalloc(size, gfp) Ext2AllocatePool(NonPagedPool, size, 'JBDM') -#define kfree(p) Ext2FreePool(p, 'JBDM') - - -/* memory slab */ - -#define SLAB_HWCACHE_ALIGN 0x00002000U /* align objs on a h/w cache lines */ -#define SLAB_KERNEL 0x00000001U -#define SLAB_TEMPORARY 0x00000002U - -typedef void (*kmem_cache_cb_t)(void*, kmem_cache_t *, unsigned long); - -struct kmem_cache { - CHAR name[32]; - ULONG flags; - ULONG size; - atomic_t count; - atomic_t acount; - NPAGED_LOOKASIDE_LIST la; - kmem_cache_cb_t constructor; -}; - - -kmem_cache_t * -kmem_cache_create( - const char *name, - size_t size, - size_t offset, - unsigned long flags, - kmem_cache_cb_t ctor -); - -void* kmem_cache_alloc(kmem_cache_t *kc, int flags); -void kmem_cache_free(kmem_cache_t *kc, void *p); -int kmem_cache_destroy(kmem_cache_t *kc); - - -// -// block device -// - -#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ - -// -// ll_rw_block .... -// - - -#define RW_MASK 1 -#define RWA_MASK 2 -#define READ 0 -#define WRITE 1 -#define READA 2 /* read-ahead - don't block if no resources */ -#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ -#define READ_SYNC (READ | (1 << BIO_RW_SYNC)) -#define READ_META (READ | (1 << BIO_RW_META)) -#define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) -#define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) - -// -// timer routines -// - -/* - * These inlines deal with timer wrapping correctly. You are - * strongly encouraged to use them - * 1. Because people otherwise forget - * 2. Because if the timer wrap changes in future you won't have to - * alter your driver code. - * - * time_after(a,b) returns true if the time a is after time b. - * - * Do this with "<0" and ">=0" to only test the sign of the result. A - * good compiler would generate better code (and a really good compiler - * wouldn't care). Gcc is currently neither. - */ -#define typecheck(x, y) (TRUE) - -#define time_after(a,b) \ - (typecheck(unsigned long, a) && \ - typecheck(unsigned long, b) && \ - ((long)(b) - (long)(a) < 0)) -#define time_before(a,b) time_after(b,a) - -#define time_after_eq(a,b) \ - (typecheck(unsigned long, a) && \ - typecheck(unsigned long, b) && \ - ((long)(a) - (long)(b) >= 0)) -#define time_before_eq(a,b) time_after_eq(b,a) - -#define time_in_range(a,b,c) \ - (time_after_eq(a,b) && \ - time_before_eq(a,c)) - -#define smp_rmb() do {}while(0) - - -static inline __u32 do_div64 (__u64 * n, __u64 b) -{ - __u64 mod; - - mod = *n % b; - *n = *n / b; - return (__u32) mod; -} -#define do_div(n, b) do_div64(&(n), (__u64)b) - -#endif // _EXT2_MODULE_HEADER_ +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: Modules.h + * PURPOSE: Header file: nls structures & linux kernel ... + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +#ifndef _EXT2_MODULE_HEADER_ +#define _EXT2_MODULE_HEADER_ + +/* INCLUDES *************************************************************/ + +#include +#include +#include +#include +#include + +#if _WIN32_WINNT <= 0x500 +#define _WIN2K_TARGET_ 1 +#endif + +/* STRUCTS ******************************************************/ + +#ifndef offsetof +# define offsetof(type, member) ((ULONG_PTR)&(((type *)0)->member)) +#endif + +#ifndef container_of +#define container_of(ptr, type, member) \ + ((type *)((char *)ptr - (char *)offsetof(type, member))) +#endif + +// +// Byte order swapping routines +// + +/* use the runtime routine or compiler's implementation */ +#if (defined(_M_IX86) && (_MSC_FULL_VER > 13009037)) || \ + ((defined(_M_AMD64) || defined(_M_IA64)) && \ + (_MSC_FULL_VER > 13009175)) +#ifdef __cplusplus +extern "C" { +#endif + unsigned short __cdecl _byteswap_ushort(unsigned short); + unsigned long __cdecl _byteswap_ulong (unsigned long); + unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64); +#ifdef __cplusplus +} +#endif +#pragma intrinsic(_byteswap_ushort) +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) + +#define RtlUshortByteSwap(_x) _byteswap_ushort((USHORT)(_x)) +#define RtlUlongByteSwap(_x) _byteswap_ulong((_x)) +#define RtlUlonglongByteSwap(_x) _byteswap_uint64((_x)) + +#else + +USHORT +FASTCALL +RtlUshortByteSwap( + IN USHORT Source +); + +ULONG +FASTCALL +RtlUlongByteSwap( + IN ULONG Source +); + +ULONGLONG +FASTCALL +RtlUlonglongByteSwap( + IN ULONGLONG Source +); +#endif + +#define __swab16(x) RtlUshortByteSwap(x) +#define __swab32(x) RtlUlongByteSwap(x) +#define __swab64(x) RtlUlonglongByteSwap(x) + +#define __constant_swab32 __swab32 +#define __constant_swab64 __swab64 + +#define __constant_htonl(x) __constant_swab32((x)) +#define __constant_ntohl(x) __constant_swab32((x)) +#define __constant_htons(x) __constant_swab16((x)) +#define __constant_ntohs(x) __constant_swab16((x)) +#define __constant_cpu_to_le64(x) ((__u64)(x)) +#define __constant_le64_to_cpu(x) ((__u64)(x)) +#define __constant_cpu_to_le32(x) ((__u32)(x)) +#define __constant_le32_to_cpu(x) ((__u32)(x)) +#define __constant_cpu_to_le16(x) ((__u16)(x)) +#define __constant_le16_to_cpu(x) ((__u16)(x)) +#define __constant_cpu_to_be64(x) __constant_swab64((x)) +#define __constant_be64_to_cpu(x) __constant_swab64((x)) +#define __constant_cpu_to_be32(x) __constant_swab32((x)) +#define __constant_be32_to_cpu(x) __constant_swab32((x)) +#define __constant_cpu_to_be16(x) __constant_swab16((x)) +#define __constant_be16_to_cpu(x) __constant_swab16((x)) +#define __cpu_to_le64(x) ((__u64)(x)) +#define __le64_to_cpu(x) ((__u64)(x)) +#define __cpu_to_le32(x) ((__u32)(x)) +#define __le32_to_cpu(x) ((__u32)(x)) +#define __cpu_to_le16(x) ((__u16)(x)) +#define __le16_to_cpu(x) ((__u16)(x)) +#define __cpu_to_be64(x) __swab64((x)) +#define __be64_to_cpu(x) __swab64((x)) +#define __cpu_to_be32(x) __swab32((x)) +#define __be32_to_cpu(x) __swab32((x)) +#define __cpu_to_be16(x) __swab16((x)) +#define __be16_to_cpu(x) __swab16((x)) +#define __cpu_to_le64p(x) (*(__u64*)(x)) +#define __le64_to_cpup(x) (*(__u64*)(x)) +#define __cpu_to_le32p(x) (*(__u32*)(x)) +#define __le32_to_cpup(x) (*(__u32*)(x)) +#define __cpu_to_le16p(x) (*(__u16*)(x)) +#define __le16_to_cpup(x) (*(__u16*)(x)) +#define __cpu_to_be64p(x) __swab64p((x)) +#define __be64_to_cpup(x) __swab64p((x)) +#define __cpu_to_be32p(x) __swab32p((x)) +#define __be32_to_cpup(x) __swab32p((x)) +#define __cpu_to_be16p(x) __swab16p((x)) +#define __be16_to_cpup(x) __swab16p((x)) +#define __cpu_to_le64s(x) ((__s64)(x)) +#define __le64_to_cpus(x) ((__s64)(x)) +#define __cpu_to_le32s(x) ((__s32)(x)) +#define __le32_to_cpus(x) ((__s32)(x)) +#define __cpu_to_le16s(x) ((__s16)(x)) +#define __le16_to_cpus(x) ((__s16)(x)) +#define __cpu_to_be64s(x) __swab64s((x)) +#define __be64_to_cpus(x) __swab64s((x)) +#define __cpu_to_be32s(x) __swab32s((x)) +#define __be32_to_cpus(x) __swab32s((x)) +#define __cpu_to_be16s(x) __swab16s((x)) +#define __be16_to_cpus(x) __swab16s((x)) + +#ifndef cpu_to_le64 +#define cpu_to_le64 __cpu_to_le64 +#define le64_to_cpu __le64_to_cpu +#define cpu_to_le32 __cpu_to_le32 +#define le32_to_cpu __le32_to_cpu +#define cpu_to_le16 __cpu_to_le16 +#define le16_to_cpu __le16_to_cpu +#endif + +#define cpu_to_be64 __cpu_to_be64 +#define be64_to_cpu __be64_to_cpu +#define cpu_to_be32 __cpu_to_be32 +#define be32_to_cpu __be32_to_cpu +#define cpu_to_be16 __cpu_to_be16 +#define be16_to_cpu __be16_to_cpu +#define cpu_to_le64p __cpu_to_le64p +#define le64_to_cpup __le64_to_cpup +#define cpu_to_le32p __cpu_to_le32p +#define le32_to_cpup __le32_to_cpup +#define cpu_to_le16p __cpu_to_le16p +#define le16_to_cpup __le16_to_cpup +#define cpu_to_be64p __cpu_to_be64p +#define be64_to_cpup __be64_to_cpup +#define cpu_to_be32p __cpu_to_be32p +#define be32_to_cpup __be32_to_cpup +#define cpu_to_be16p __cpu_to_be16p +#define be16_to_cpup __be16_to_cpup +#define cpu_to_le64s __cpu_to_le64s +#define le64_to_cpus __le64_to_cpus +#define cpu_to_le32s __cpu_to_le32s +#define le32_to_cpus __le32_to_cpus +#define cpu_to_le16s __cpu_to_le16s +#define le16_to_cpus __le16_to_cpus +#define cpu_to_be64s __cpu_to_be64s +#define be64_to_cpus __be64_to_cpus +#define cpu_to_be32s __cpu_to_be32s +#define be32_to_cpus __be32_to_cpus +#define cpu_to_be16s __cpu_to_be16s +#define be16_to_cpus __be16_to_cpus + + +static inline void le16_add_cpu(__le16 *var, u16 val) +{ + *var = cpu_to_le16(le16_to_cpu(*var) + val); +} + +static inline void le32_add_cpu(__le32 *var, u32 val) +{ + *var = cpu_to_le32(le32_to_cpu(*var) + val); +} + +static inline void le64_add_cpu(__le64 *var, u64 val) +{ + *var = cpu_to_le64(le64_to_cpu(*var) + val); +} + +// +// Network to host byte swap functions +// + +#define ntohl(x) ( ( ( ( x ) & 0x000000ff ) << 24 ) | \ + ( ( ( x ) & 0x0000ff00 ) << 8 ) | \ + ( ( ( x ) & 0x00ff0000 ) >> 8 ) | \ + ( ( ( x ) & 0xff000000 ) >> 24 ) ) + +#define ntohs(x) ( ( ( ( x ) & 0xff00 ) >> 8 ) | \ + ( ( ( x ) & 0x00ff ) << 8 ) ) + + +#define htonl(x) ntohl(x) +#define htons(x) ntohs(x) + + +// +// kernel printk flags +// + +#define KERN_EMERG "<0>" /* system is unusable */ +#define KERN_ALERT "<1>" /* action must be taken immediately */ +#define KERN_CRIT "<2>" /* critical conditions */ +#define KERN_ERR "<3>" /* error conditions */ +#define KERN_WARNING "<4>" /* warning conditions */ +#define KERN_NOTICE "<5>" /* normal but significant condition */ +#define KERN_INFO "<6>" /* informational */ +#define KERN_DEBUG "<7>" /* debug-level messages */ + +#define printk DbgPrint + +/* + * error pointer + */ +#define MAX_ERRNO 4095 +#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) + +static inline void *ERR_PTR(long error) +{ + return (void *)(long_ptr_t) error; +} + +static inline long PTR_ERR(const void *ptr) +{ + return (long)(long_ptr_t) ptr; +} + +static inline long IS_ERR(const void *ptr) +{ + return IS_ERR_VALUE((unsigned long)(long_ptr_t)ptr); +} + + +#define BUG_ON(c) assert(!(c)) + +#define WARN_ON(c) BUG_ON(c) + +// +// Linux module definitions +// + +#define likely +#define unlikely + +#define __init +#define __exit + +#define THIS_MODULE NULL +#define MODULE_LICENSE(x) +#define MODULE_ALIAS_NLS(x) +#define EXPORT_SYMBOL(x) + + +#define try_module_get(x) (TRUE) +#define module_put(x) + +#define module_init(X) int __init module_##X() {return X();} +#define module_exit(X) void __exit module_##X() {X();} + +#define DECLARE_INIT(X) int __init module_##X(void) +#define DECLARE_EXIT(X) void __exit module_##X(void) + +#define LOAD_MODULE(X) do { \ + rc = module_##X(); \ + } while(0) + +#define UNLOAD_MODULE(X) do { \ + module_##X(); \ + } while(0) + +#define LOAD_NLS LOAD_MODULE +#define UNLOAD_NLS UNLOAD_MODULE + +// +// spinlocks ..... +// + +typedef struct _spinlock_t { + + KSPIN_LOCK lock; + KIRQL irql; +} spinlock_t; + +#define spin_lock_init(sl) KeInitializeSpinLock(&((sl)->lock)) +#define spin_lock(sl) KeAcquireSpinLock(&((sl)->lock), &((sl)->irql)) +#define spin_unlock(sl) KeReleaseSpinLock(&((sl)->lock), (sl)->irql) +#define spin_lock_irqsave(sl, flags) do {spin_lock(sl); flags=(sl)->irql;} while(0) +#define spin_unlock_irqrestore(sl, flags) do {ASSERT((KIRQL)(flags)==(sl)->irql); spin_unlock(sl);} while(0) + +#define assert_spin_locked(x) do {} while(0) + +/* + * Does a critical section need to be broken due to another + * task waiting?: (technically does not depend on CONFIG_PREEMPT, + * but a general need for low latency) + */ +static inline int spin_needbreak(spinlock_t *lock) +{ +#ifdef CONFIG_PREEMPT + return spin_is_contended(lock); +#else + return 0; +#endif +} + +// +// bit operations +// + +/** + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static inline int set_bit(int nr, volatile unsigned long *addr) +{ + addr += (nr >> ORDER_PER_LONG); + nr &= (BITS_PER_LONG - 1); + + return !!(InterlockedOr(addr, (1 << nr)) & (1 << nr)); +} + + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static inline int clear_bit(int nr, volatile unsigned long *addr) +{ + addr += (nr >> ORDER_PER_LONG); + nr &= (BITS_PER_LONG - 1); + + return !!(InterlockedAnd(addr, ~(1 << nr)) & (1 << nr)); +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) +{ + return clear_bit(nr, addr); +} + +/* + * test + */ +static int test_bit(int nr, volatile const unsigned long *addr) +{ + return !!((1 << (nr & (BITS_PER_LONG - 1))) & + (addr[nr >> ORDER_PER_LONG])); +} + +/** + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_set_bit(int nr, volatile unsigned long *addr) +{ + return set_bit(nr, addr); +} + +// +// list definition ... +// + +#include + + +/********************************************* + * linux scheduler related structures * +*********************************************/ + +// +// task structure +// + +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 + +struct task_struct { + pid_t pid; + pid_t tid; + char comm[32]; + void * journal_info; +}; + +extern struct task_struct *current; + +// +// scheduler routines +// + + +static inline cond_resched() { + return FALSE; +} +static inline need_resched() { + return FALSE; +} + +#define yield() do {} while(0) +#define might_sleep() do {} while(0) + +// +// mutex +// + +typedef struct mutex { + FAST_MUTEX lock; +} mutex_t; + +#define mutex_init(x) ExInitializeFastMutex(&((x)->lock)) +#define mutex_lock(x) ExAcquireFastMutex(&((x)->lock)) +#define mutex_unlock(x) ExReleaseFastMutex(&((x)->lock)) + + +// +// wait_queue +// + + +typedef PVOID wait_queue_t; + +#define WQ_FLAG_EXCLUSIVE 0x01 +#define WQ_FLAG_AUTO_REMOVAL 0x02 + +struct __wait_queue { + unsigned int flags; + void * private; + KEVENT event; + struct list_head task_list; +}; + + +#define DEFINE_WAIT(name) \ + wait_queue_t name = (PVOID)wait_queue_create(); + +/* +struct wait_bit_key { + void *flags; + int bit_nr; +}; + +struct wait_bit_queue { + struct wait_bit_key key; + wait_queue_t wait; +}; +*/ + +struct __wait_queue_head { + spinlock_t lock; + struct list_head task_list; +}; +typedef struct __wait_queue_head wait_queue_head_t; + +#define is_sync_wait(wait) (TRUE) +#define set_current_state(state) do {} while(0) +#define __set_current_state(state) do {} while(0) + +void init_waitqueue_head(wait_queue_head_t *q); +int wake_up(wait_queue_head_t *queue); + + +/* + * Waitqueues which are removed from the waitqueue_head at wakeup time + */ +struct __wait_queue * wait_queue_create(); +void wait_queue_destroy(struct __wait_queue *); + +void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state); +void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state); +void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); +int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); +int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); + + +// +// timer structure +// + +struct timer_list { + struct list_head entry; + unsigned long expires; + + void (*function)(unsigned long); + unsigned long data; + +#ifdef CONFIG_TIMER_STATS + void *start_site; + char start_comm[16]; + int start_pid; +#endif +}; + + +typedef struct kmem_cache kmem_cache_t; + +struct block_device { + + unsigned long bd_flags; /* flags */ + atomic_t bd_count; /* reference count */ + PDEVICE_OBJECT bd_dev; /* device object */ + ANSI_STRING bd_name; /* name in ansi string */ + DISK_GEOMETRY bd_geo; /* disk geometry */ + PARTITION_INFORMATION bd_part; /* partition information */ + void * bd_priv; /* pointers to EXT2_VCB + NULL if it's a journal dev */ + PFILE_OBJECT bd_volume; /* streaming object file */ + LARGE_MCB bd_extents; /* dirty extents */ + + kmem_cache_t * bd_bh_cache;/* memory cache for buffer_head */ + ERESOURCE bd_bh_lock; /* lock for bh tree and reaper list */ + struct rb_root bd_bh_root; /* buffer_head red-black tree root */ + LIST_ENTRY bd_bh_free; /* reaper list */ + KEVENT bd_bh_notify; /* notification event for cleanup */ +}; + +// +// page information +// + +// vom trata paginile in felul urmator: +// alocam la sfarsitul structurii inca PAGE_SIZE octeti cand alocam o structura +// de tip pagina - acolo vor veni toate buffer-headurile +// deci -> page_address(page) = page + sizeof(page) +#define page_address(_page) ((char*)_page + sizeof(struct page)) + +typedef struct page { + void *addr; + void *mapping; + void *private; + atomic_t count; + __u32 index; + __u32 flags; +} mem_map_t; + +#define get_page(p) atomic_inc(&(p)->count) + +#define PG_locked 0 /* Page is locked. Don't touch. */ +#define PG_error 1 +#define PG_referenced 2 +#define PG_uptodate 3 +#define PG_dirty 4 +#define PG_unused 5 +#define PG_lru 6 +#define PG_active 7 +#define PG_slab 8 +#define PG_skip 10 +#define PG_highmem 11 +#define PG_checked 12 /* kill me in 2.5.. */ +#define PG_arch_1 13 +#define PG_reserved 14 +#define PG_launder 15 /* written out by VM pressure.. */ +#define PG_fs_1 16 /* Filesystem specific */ + +#ifndef arch_set_page_uptodate +#define arch_set_page_uptodate(page) +#endif + +/* Make it prettier to test the above... */ +#define UnlockPage(page) unlock_page(page) +#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) +#define SetPageUptodate(page) \ + do { \ + arch_set_page_uptodate(page); \ + set_bit(PG_uptodate, &(page)->flags); \ + } while (0) +#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) +#define PageDirty(page) test_bit(PG_dirty, &(page)->flags) +#define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags) +#define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags) +#define PageLocked(page) test_bit(PG_locked, &(page)->flags) +#define LockPage(page) set_bit(PG_locked, &(page)->flags) +#define TryLockPage(page) test_and_set_bit(PG_locked, &(page)->flags) +#define PageChecked(page) test_bit(PG_checked, &(page)->flags) +#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags) +#define ClearPageChecked(page) clear_bit(PG_checked, &(page)->flags) +#define PageLaunder(page) test_bit(PG_launder, &(page)->flags) +#define SetPageLaunder(page) set_bit(PG_launder, &(page)->flags) +#define ClearPageLaunder(page) clear_bit(PG_launder, &(page)->flags) +#define ClearPageArch1(page) clear_bit(PG_arch_1, &(page)->flags) + +#define PageError(page) test_bit(PG_error, &(page)->flags) +#define SetPageError(page) set_bit(PG_error, &(page)->flags) +#define ClearPageError(page) clear_bit(PG_error, &(page)->flags) +#define PageReferenced(page) test_bit(PG_referenced, &(page)->flags) +#define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags) +#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags) + +#define PageActive(page) test_bit(PG_active, &(page)->flags) +#define SetPageActive(page) set_bit(PG_active, &(page)->flags) +#define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) + + +extern unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order); +#define __get_free_page(gfp_mask) \ + __get_free_pages((gfp_mask),0) + +extern void __free_pages(struct page *page, unsigned int order); +extern void free_pages(unsigned long addr, unsigned int order); + +#define __free_page(page) __free_pages((page), 0) +#define free_page(addr) free_pages((addr),0) + +extern void truncate_inode_pages(struct address_space *, loff_t); + +#define __GFP_HIGHMEM 0x02 + +#define __GFP_WAIT 0x10 /* Can wait and reschedule? */ +#define __GFP_HIGH 0x20 /* Should access emergency pools? */ +#define __GFP_IO 0x40 /* Can start low memory physical IO? */ +#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */ +#define __GFP_FS 0x100 /* Can call down to low-level FS? */ + +#define GFP_ATOMIC (__GFP_HIGH) +#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) +#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS | __GFP_HIGHMEM) +#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) +#define GFP_NOFS 0 +#define __GFP_NOFAIL 0 + + +#define KM_USER0 0 + +// +// buffer head definitions +// + +enum bh_state_bits { + BH_Uptodate, /* Contains valid data */ + BH_Dirty, /* Is dirty */ + BH_Verified, /* Is verified */ + BH_Lock, /* Is locked */ + BH_Req, /* Has been submitted for I/O */ + BH_Uptodate_Lock, /* Used by the first bh in a page, to serialise + * IO completion of other buffers in the page + */ + + BH_Mapped, /* Has a disk mapping */ + BH_New, /* Disk mapping was newly created by get_block */ + BH_Async_Read, /* Is under end_buffer_async_read I/O */ + BH_Async_Write, /* Is under end_buffer_async_write I/O */ + BH_Delay, /* Buffer is not yet allocated on disk */ + BH_Boundary, /* Block is followed by a discontiguity */ + BH_Write_EIO, /* I/O error on write */ + BH_Ordered, /* ordered write */ + BH_Eopnotsupp, /* operation not supported (barrier) */ + BH_Unwritten, /* Buffer is allocated on disk but not written */ + + BH_PrivateStart, /* not a state bit, but the first bit available + * for private allocation by other entities + */ +}; + +#define PAGE_CACHE_SIZE (PAGE_SIZE) +#define PAGE_CACHE_SHIFT (12) +#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512) + +typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate); + +/* + * Historically, a buffer_head was used to map a single block + * within a page, and of course as the unit of I/O through the + * filesystem and block layers. Nowadays the basic I/O unit + * is the bio, and buffer_heads are used for extracting block + * mappings (via a get_block_t call), for tracking state within + * a page (via a page_mapping) and for wrapping bio submission + * for backward compatibility reasons (e.g. submit_bh). + */ +struct buffer_head { + LIST_ENTRY b_link; /* to be added to reaper list */ + unsigned long b_state; /* buffer state bitmap (see above) */ + struct page *b_page; /* the page this bh is mapped to */ + PMDL b_mdl; /* MDL of the locked buffer */ + void *b_bcb; /* BCB of the buffer */ + + // kdev_t b_dev; /* device (B_FREE = free) */ + struct block_device *b_bdev; /* block device object */ + + blkcnt_t b_blocknr; /* start block number */ + size_t b_size; /* size of mapping */ + char * b_data; /* pointer to data within the page */ + bh_end_io_t *b_end_io; /* I/O completion */ + void *b_private; /* reserved for b_end_io */ + // struct list_head b_assoc_buffers; /* associated with another mapping */ + // struct address_space *b_assoc_map; /* mapping this buffer is associated with */ + atomic_t b_count; /* users using this buffer_head */ + struct rb_node b_rb_node; /* Red-black tree node entry */ + + LARGE_INTEGER b_ts_creat; /* creation time*/ + LARGE_INTEGER b_ts_drop; /* drop time (to be released) */ +}; + + +/* + * macro tricks to expand the set_buffer_foo(), clear_buffer_foo() + * and buffer_foo() functions. + */ +#define BUFFER_FNS(bit, name) \ +static inline void set_buffer_##name(struct buffer_head *bh) \ +{ \ + set_bit(BH_##bit, &(bh)->b_state); \ +} \ +static inline void clear_buffer_##name(struct buffer_head *bh) \ +{ \ + clear_bit(BH_##bit, &(bh)->b_state); \ +} \ +static inline int buffer_##name(const struct buffer_head *bh) \ +{ \ + return test_bit(BH_##bit, &(bh)->b_state); \ +} + +/* + * test_set_buffer_foo() and test_clear_buffer_foo() + */ +#define TAS_BUFFER_FNS(bit, name) \ +static inline int test_set_buffer_##name(struct buffer_head *bh) \ +{ \ + return test_and_set_bit(BH_##bit, &(bh)->b_state); \ +} \ +static inline int test_clear_buffer_##name(struct buffer_head *bh) \ +{ \ + return test_and_clear_bit(BH_##bit, &(bh)->b_state); \ +} \ + +/* + * Emit the buffer bitops functions. Note that there are also functions + * of the form "mark_buffer_foo()". These are higher-level functions which + * do something in addition to setting a b_state bit. + */ +BUFFER_FNS(Uptodate, uptodate) +BUFFER_FNS(Dirty, dirty) +TAS_BUFFER_FNS(Dirty, dirty) +BUFFER_FNS(Verified, verified) +BUFFER_FNS(Lock, locked) +TAS_BUFFER_FNS(Lock, locked) +BUFFER_FNS(Req, req) +TAS_BUFFER_FNS(Req, req) +BUFFER_FNS(Mapped, mapped) +BUFFER_FNS(New, new) +BUFFER_FNS(Async_Read, async_read) +BUFFER_FNS(Async_Write, async_write) +BUFFER_FNS(Delay, delay) +BUFFER_FNS(Boundary, boundary) +BUFFER_FNS(Write_EIO, write_io_error) +BUFFER_FNS(Ordered, ordered) +BUFFER_FNS(Eopnotsupp, eopnotsupp) +BUFFER_FNS(Unwritten, unwritten) + +#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK) +#define touch_buffer(bh) mark_page_accessed(bh->b_page) + +/* If we *know* page->private refers to buffer_heads */ + +#define page_buffers(page) \ + ( \ + BUG_ON(!PagePrivate(page)), \ + ((struct buffer_head *)page_private(page)) \ + ) +#define page_has_buffers(page) PagePrivate(page) + + +/* + * Declarations + */ + +void mark_buffer_dirty(struct buffer_head *bh); +void init_buffer(struct buffer_head *, bh_end_io_t *, void *); +void set_bh_page(struct buffer_head *bh, + struct page *page, unsigned long offset); +int try_to_free_buffers(struct page *); +struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size, + int retry); +void create_empty_buffers(struct page *, unsigned long, + unsigned long b_state); + +/* Things to do with buffers at mapping->private_list */ +void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode); +int inode_has_buffers(struct inode *); +void invalidate_inode_buffers(struct inode *); +int remove_inode_buffers(struct inode *inode); +int sync_mapping_buffers(struct address_space *mapping); +void unmap_underlying_metadata(struct block_device *bdev, sector_t block); + +void mark_buffer_async_write(struct buffer_head *bh); +void invalidate_bdev(struct block_device *); +int sync_blockdev(struct block_device *bdev); +void __wait_on_buffer(struct buffer_head *); +wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); +int fsync_bdev(struct block_device *); +struct super_block *freeze_bdev(struct block_device *); +void thaw_bdev(struct block_device *, struct super_block *); +int fsync_super(struct super_block *); +int fsync_no_super(struct block_device *); +struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, + unsigned long size); +struct buffer_head *get_block_bh(struct block_device *bdev, sector_t block, + unsigned long size, int zero); +struct buffer_head *__getblk(struct block_device *bdev, sector_t block, + unsigned long size); +void __brelse(struct buffer_head *); +void __bforget(struct buffer_head *); +void __breadahead(struct block_device *, sector_t block, unsigned int size); +struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size); +void invalidate_bh_lrus(void); +struct buffer_head *alloc_buffer_head(gfp_t gfp_flags); +void free_buffer_head(struct buffer_head * bh); +void unlock_buffer(struct buffer_head *bh); +void __lock_buffer(struct buffer_head *bh); +void ll_rw_block(int, int, struct buffer_head * bh[]); +int sync_dirty_buffer(struct buffer_head *bh); +int submit_bh(int, struct buffer_head *); +void write_boundary_block(struct block_device *bdev, + sector_t bblock, unsigned blocksize); +int bh_uptodate_or_lock(struct buffer_head *bh); +int bh_submit_read(struct buffer_head *bh); +/* They are separately managed */ +struct buffer_head *extents_bread(struct super_block *sb, sector_t block); +struct buffer_head *extents_bwrite(struct super_block *sb, sector_t block); +void extents_mark_buffer_dirty(struct buffer_head *bh); +void extents_brelse(struct buffer_head *bh); +void extents_bforget(struct buffer_head *bh); +void buffer_head_remove(struct block_device *bdev, struct buffer_head *bh); + +extern int buffer_heads_over_limit; + +/* + * Generic address_space_operations implementations for buffer_head-backed + * address_spaces. + */ + +#if 0 + +int block_write_full_page(struct page *page, get_block_t *get_block, + struct writeback_control *wbc); +int block_read_full_page(struct page*, get_block_t*); +int block_write_begin(struct file *, struct address_space *, + loff_t, unsigned, unsigned, + struct page **, void **, get_block_t*); +int block_write_end(struct file *, struct address_space *, + loff_t, unsigned, unsigned, + struct page *, void *); +int generic_write_end(struct file *, struct address_space *, + loff_t, unsigned, unsigned, + struct page *, void *); + +int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); +int cont_write_begin(struct file *, struct address_space *, loff_t, + unsigned, unsigned, struct page **, void **, + get_block_t *, loff_t *); +int block_page_mkwrite(struct vm_area_struct *vma, struct page *page, + get_block_t get_block); +sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); +int generic_commit_write(struct file *, struct page *, unsigned, unsigned); +int block_truncate_page(struct address_space *, loff_t, get_block_t *); +int file_fsync(struct file *, struct dentry *, int); +int nobh_write_begin(struct file *, struct address_space *, + loff_t, unsigned, unsigned, + struct page **, void **, get_block_t*); +int nobh_write_end(struct file *, struct address_space *, + loff_t, unsigned, unsigned, + struct page *, void *); +int nobh_truncate_page(struct address_space *, loff_t, get_block_t *); +int nobh_writepage(struct page *page, get_block_t *get_block, + struct writeback_control *wbc); +int generic_cont_expand_simple(struct inode *inode, loff_t size); +#endif + +void block_invalidatepage(struct page *page, unsigned long offset); +void page_zero_new_buffers(struct page *page, unsigned from, unsigned to); +int block_commit_write(struct page *page, unsigned from, unsigned to); +void block_sync_page(struct page *); + +void buffer_init(void); + +/* + * inline definitions + */ +#if 0 +static inline void attach_page_buffers(struct page *page, + struct buffer_head *head) +{ + page_cache_get(page); + SetPagePrivate(page); + set_page_private(page, (unsigned long)head); +} +#endif + +static inline void get_bh(struct buffer_head *bh) +{ + atomic_inc(&bh->b_count); +} + +static inline void put_bh(struct buffer_head *bh) +{ + if (bh) + __brelse(bh); +} + +static inline void brelse(struct buffer_head *bh) +{ + if (bh) + __brelse(bh); +} + +static inline void fini_bh(struct buffer_head **bh) +{ + if (bh && *bh) { + brelse(*bh); + *bh = NULL; + } +} + +static inline void bforget(struct buffer_head *bh) +{ + if (bh) + __bforget(bh); +} + +static inline struct buffer_head * + sb_getblk(struct super_block *sb, sector_t block) +{ + return get_block_bh(sb->s_bdev, block, sb->s_blocksize, 0); +} + +static inline struct buffer_head * + sb_getblk_zero(struct super_block *sb, sector_t block) +{ + return get_block_bh(sb->s_bdev, block, sb->s_blocksize, 1); +} + +static inline struct buffer_head * + sb_bread(struct super_block *sb, sector_t block) +{ + struct buffer_head *bh = __getblk(sb->s_bdev, block, sb->s_blocksize); + if (!bh) + return NULL; + if (!buffer_uptodate(bh) && (bh_submit_read(bh) < 0)) { + brelse(bh); + return NULL; + } + return bh; +} + +static inline struct buffer_head * + sb_find_get_block(struct super_block *sb, sector_t block) +{ + return __find_get_block(sb->s_bdev, block, sb->s_blocksize); +} + +static inline void +map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block) +{ + set_buffer_mapped(bh); + bh->b_bdev = sb->s_bdev; + bh->b_blocknr = block; + bh->b_size = sb->s_blocksize; +} + +/* + * Calling wait_on_buffer() for a zero-ref buffer is illegal, so we call into + * __wait_on_buffer() just to trip a debug check. Because debug code in inline + * functions is bloaty. + */ + +static inline void wait_on_buffer(struct buffer_head *bh) +{ + might_sleep(); + if (buffer_locked(bh) || atomic_read(&bh->b_count) == 0) + __wait_on_buffer(bh); +} + +static inline void lock_buffer(struct buffer_head *bh) +{ + might_sleep(); + if (test_set_buffer_locked(bh)) + __lock_buffer(bh); +} + +extern int __set_page_dirty_buffers(struct page *page); + +// +// unicode character +// + +struct nls_table { + char *charset; + char *alias; + int (*uni2char) (wchar_t uni, unsigned char *out, int boundlen); + int (*char2uni) (const unsigned char *rawstring, int boundlen, + wchar_t *uni); + unsigned char *charset2lower; + unsigned char *charset2upper; + struct module *owner; + struct nls_table *next; +}; + +/* this value hold the maximum octet of charset */ +#define NLS_MAX_CHARSET_SIZE 6 /* for UTF-8 */ + +/* nls.c */ +extern int register_nls(struct nls_table *); +extern int unregister_nls(struct nls_table *); +extern struct nls_table *load_nls(char *); +extern void unload_nls(struct nls_table *); +extern struct nls_table *load_nls_default(void); + +extern int utf8_mbtowc(wchar_t *, const __u8 *, int); +extern int utf8_mbstowcs(wchar_t *, const __u8 *, int); +extern int utf8_wctomb(__u8 *, wchar_t, int); +extern int utf8_wcstombs(__u8 *, const wchar_t *, int); + +// +// kernel jiffies +// + +#define HZ (100) + +static inline __u32 JIFFIES() +{ + LARGE_INTEGER Tick; + + KeQueryTickCount(&Tick); + Tick.QuadPart *= KeQueryTimeIncrement(); + Tick.QuadPart /= (10000000 / HZ); + + return Tick.LowPart; +} + +#define jiffies JIFFIES() + +// +// memory routines +// + +#ifdef _WIN2K_TARGET_ + +typedef GUID UUID; +NTKERNELAPI +NTSTATUS +ExUuidCreate( + OUT UUID *Uuid +); + +NTKERNELAPI +PVOID +NTAPI +ExAllocatePoolWithTag( + IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag +); + +#define ExFreePoolWithTag(_P, _T) ExFreePool(_P) +#endif + +PVOID Ext2AllocatePool( + IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag +); + +VOID +Ext2FreePool( + IN PVOID P, + IN ULONG Tag +); + +void *kzalloc(int size, int flags); +#define kmalloc(size, gfp) Ext2AllocatePool(NonPagedPool, size, 'JBDM') +#define kfree(p) Ext2FreePool(p, 'JBDM') + + +/* memory slab */ + +#define SLAB_HWCACHE_ALIGN 0x00002000U /* align objs on a h/w cache lines */ +#define SLAB_KERNEL 0x00000001U +#define SLAB_TEMPORARY 0x00000002U + +typedef void (*kmem_cache_cb_t)(void*, kmem_cache_t *, unsigned long); + +struct kmem_cache { + CHAR name[32]; + ULONG flags; + ULONG size; + atomic_t count; + atomic_t acount; + NPAGED_LOOKASIDE_LIST la; + kmem_cache_cb_t constructor; +}; + + +kmem_cache_t * +kmem_cache_create( + const char *name, + size_t size, + size_t offset, + unsigned long flags, + kmem_cache_cb_t ctor +); + +void* kmem_cache_alloc(kmem_cache_t *kc, int flags); +void kmem_cache_free(kmem_cache_t *kc, void *p); +int kmem_cache_destroy(kmem_cache_t *kc); + + +// +// block device +// + +#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ + +// +// ll_rw_block .... +// + + +#define RW_MASK 1 +#define RWA_MASK 2 +#define READ 0 +#define WRITE 1 +#define READA 2 /* read-ahead - don't block if no resources */ +#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ +#define READ_SYNC (READ | (1 << BIO_RW_SYNC)) +#define READ_META (READ | (1 << BIO_RW_META)) +#define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) +#define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) + +// +// timer routines +// + +/* + * These inlines deal with timer wrapping correctly. You are + * strongly encouraged to use them + * 1. Because people otherwise forget + * 2. Because if the timer wrap changes in future you won't have to + * alter your driver code. + * + * time_after(a,b) returns true if the time a is after time b. + * + * Do this with "<0" and ">=0" to only test the sign of the result. A + * good compiler would generate better code (and a really good compiler + * wouldn't care). Gcc is currently neither. + */ +#define typecheck(x, y) (TRUE) + +#define time_after(a,b) \ + (typecheck(unsigned long, a) && \ + typecheck(unsigned long, b) && \ + ((long)(b) - (long)(a) < 0)) +#define time_before(a,b) time_after(b,a) + +#define time_after_eq(a,b) \ + (typecheck(unsigned long, a) && \ + typecheck(unsigned long, b) && \ + ((long)(a) - (long)(b) >= 0)) +#define time_before_eq(a,b) time_after_eq(b,a) + +#define time_in_range(a,b,c) \ + (time_after_eq(a,b) && \ + time_before_eq(a,c)) + +#define smp_rmb() do {}while(0) + + +static inline __u32 do_div64 (__u64 * n, __u64 b) +{ + __u64 mod; + + mod = *n % b; + *n = *n / b; + return (__u32) mod; +} +#define do_div(n, b) do_div64(&(n), (__u64)b) + +#endif // _EXT2_MODULE_HEADER_ diff --git a/Ext4Fsd/include/linux/rbtree.h b/Ext4Fsd/include/linux/rbtree.h index 39b9039..08c7b60 100644 --- a/Ext4Fsd/include/linux/rbtree.h +++ b/Ext4Fsd/include/linux/rbtree.h @@ -1,161 +1,161 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/include/linux/rbtree.h - - To use rbtrees you'll have to implement your own insert and search cores. - This will avoid us to use callbacks and to drop drammatically performances. - I know it's not the cleaner way, but in C (not in C++) to get - performances and genericity... - - Some example of insert and search follows here. The search is a plain - normal search over an ordered tree. The insert instead must be implemented - int two steps: as first thing the code must insert the element in - order as a red leaf in the tree, then the support library function - rb_insert_color() must be called. Such function will do the - not trivial work to rebalance the rbtree if necessary. - ------------------------------------------------------------------------ -static inline struct page * rb_search_page_cache(struct inode * inode, - unsigned long offset) -{ - struct rb_node * n = inode->i_rb_page_cache.rb_node; - struct page * page; - - while (n) - { - page = rb_entry(n, struct page, rb_page_cache); - - if (offset < page->offset) - n = n->rb_left; - else if (offset > page->offset) - n = n->rb_right; - else - return page; - } - return NULL; -} - -static inline struct page * __rb_insert_page_cache(struct inode * inode, - unsigned long offset, - struct rb_node * node) -{ - struct rb_node ** p = &inode->i_rb_page_cache.rb_node; - struct rb_node * parent = NULL; - struct page * page; - - while (*p) - { - parent = *p; - page = rb_entry(parent, struct page, rb_page_cache); - - if (offset < page->offset) - p = &(*p)->rb_left; - else if (offset > page->offset) - p = &(*p)->rb_right; - else - return page; - } - - rb_link_node(node, parent, p); - - return NULL; -} - -static inline struct page * rb_insert_page_cache(struct inode * inode, - unsigned long offset, - struct rb_node * node) -{ - struct page * ret; - if ((ret = __rb_insert_page_cache(inode, offset, node))) - goto out; - rb_insert_color(node, &inode->i_rb_page_cache); - out: - return ret; -} ------------------------------------------------------------------------ -*/ - -#ifndef _LINUX_RBTREE_H -#define _LINUX_RBTREE_H - -struct rb_node -{ - ULONG_PTR rb_parent_color; -#define RB_RED 0 -#define RB_BLACK 1 - struct rb_node *rb_right; - struct rb_node *rb_left; -} __attribute__((aligned(sizeof(long)))); -/* The alignment might seem pointless, but allegedly CRIS needs it */ - -struct rb_root -{ - struct rb_node *rb_node; -}; - - -#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) -#define rb_color(r) ((r)->rb_parent_color & 1) -#define rb_is_red(r) (!rb_color(r)) -#define rb_is_black(r) rb_color(r) -#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) -#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) - -static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) -{ - rb->rb_parent_color = (rb->rb_parent_color & 3) | (ULONG_PTR)p; -} -static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color) -{ - rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; -} - -#define RB_ROOT (struct rb_root) { NULL, } -#define rb_entry(ptr, type, member) container_of(ptr, type, member) - -#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) -#define RB_EMPTY_NODE(node) (rb_parent(node) != node) -#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) - -extern void rb_insert_color(struct rb_node *, struct rb_root *); -extern void rb_erase(struct rb_node *, struct rb_root *); - -/* Find logical next and previous nodes in a tree */ -extern struct rb_node *rb_next(struct rb_node *); -extern struct rb_node *rb_prev(struct rb_node *); -extern struct rb_node *rb_first(struct rb_root *); -extern struct rb_node *rb_last(struct rb_root *); - -/* Fast replacement of a single node without remove/rebalance/add/rebalance */ -extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root); - -static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, - struct rb_node ** rb_link) -{ - node->rb_parent_color = (ULONG_PTR )parent; - node->rb_left = node->rb_right = NULL; - - *rb_link = node; -} - -extern void rb_insert(struct rb_root *root, struct rb_node *node, - int (*cmp)(struct rb_node *, struct rb_node *)); - -#endif /* _LINUX_RBTREE_H */ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop drammatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + Some example of insert and search follows here. The search is a plain + normal search over an ordered tree. The insert instead must be implemented + int two steps: as first thing the code must insert the element in + order as a red leaf in the tree, then the support library function + rb_insert_color() must be called. Such function will do the + not trivial work to rebalance the rbtree if necessary. + +----------------------------------------------------------------------- +static inline struct page * rb_search_page_cache(struct inode * inode, + unsigned long offset) +{ + struct rb_node * n = inode->i_rb_page_cache.rb_node; + struct page * page; + + while (n) + { + page = rb_entry(n, struct page, rb_page_cache); + + if (offset < page->offset) + n = n->rb_left; + else if (offset > page->offset) + n = n->rb_right; + else + return page; + } + return NULL; +} + +static inline struct page * __rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct rb_node ** p = &inode->i_rb_page_cache.rb_node; + struct rb_node * parent = NULL; + struct page * page; + + while (*p) + { + parent = *p; + page = rb_entry(parent, struct page, rb_page_cache); + + if (offset < page->offset) + p = &(*p)->rb_left; + else if (offset > page->offset) + p = &(*p)->rb_right; + else + return page; + } + + rb_link_node(node, parent, p); + + return NULL; +} + +static inline struct page * rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct page * ret; + if ((ret = __rb_insert_page_cache(inode, offset, node))) + goto out; + rb_insert_color(node, &inode->i_rb_page_cache); + out: + return ret; +} +----------------------------------------------------------------------- +*/ + +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + +struct rb_node +{ + ULONG_PTR rb_parent_color; +#define RB_RED 0 +#define RB_BLACK 1 + struct rb_node *rb_right; + struct rb_node *rb_left; +} __attribute__((aligned(sizeof(long)))); +/* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root +{ + struct rb_node *rb_node; +}; + + +#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) +#define rb_color(r) ((r)->rb_parent_color & 1) +#define rb_is_red(r) (!rb_color(r)) +#define rb_is_black(r) rb_color(r) +#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) +#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) + +static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->rb_parent_color = (rb->rb_parent_color & 3) | (ULONG_PTR)p; +} +static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color) +{ + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; +} + +#define RB_ROOT (struct rb_root) { NULL, } +#define rb_entry(ptr, type, member) container_of(ptr, type, member) + +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) +#define RB_EMPTY_NODE(node) (rb_parent(node) != node) +#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) + +extern void rb_insert_color(struct rb_node *, struct rb_root *); +extern void rb_erase(struct rb_node *, struct rb_root *); + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *rb_next(struct rb_node *); +extern struct rb_node *rb_prev(struct rb_node *); +extern struct rb_node *rb_first(struct rb_root *); +extern struct rb_node *rb_last(struct rb_root *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->rb_parent_color = (ULONG_PTR )parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +extern void rb_insert(struct rb_root *root, struct rb_node *node, + int (*cmp)(struct rb_node *, struct rb_node *)); + +#endif /* _LINUX_RBTREE_H */ diff --git a/Ext4Fsd/include/linux/stddef.h b/Ext4Fsd/include/linux/stddef.h index ace1692..c036c6a 100644 --- a/Ext4Fsd/include/linux/stddef.h +++ b/Ext4Fsd/include/linux/stddef.h @@ -1,13 +1,13 @@ -#ifndef _LINUX_STDDEF_H -#define _LINUX_STDDEF_H - -enum { - false = 0, - true = 1 -}; - -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - -#endif /* _LINUX_STDDEF_H */ +#ifndef _LINUX_STDDEF_H +#define _LINUX_STDDEF_H + +enum { + false = 0, + true = 1 +}; + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#endif /* _LINUX_STDDEF_H */ diff --git a/Ext4Fsd/include/resource.h b/Ext4Fsd/include/resource.h index f330897..fe4676d 100644 --- a/Ext4Fsd/include/resource.h +++ b/Ext4Fsd/include/resource.h @@ -1,15 +1,15 @@ -//{{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 +//{{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/Ext4Fsd/lock.c b/Ext4Fsd/lock.c index 3219f60..b5ee19e 100644 --- a/Ext4Fsd/lock.c +++ b/Ext4Fsd/lock.c @@ -1,125 +1,125 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: lock.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, Ext2LockControl) -#endif - -NTSTATUS -Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject = NULL; - PFILE_OBJECT FileObject = NULL; - PEXT2_FCB Fcb = NULL; - PIRP Irp = NULL; - - NTSTATUS Status = STATUS_UNSUCCESSFUL; - BOOLEAN CompleteContext = TRUE; - BOOLEAN CompleteIrp = TRUE; - BOOLEAN bFcbAcquired = FALSE; - - __try { - - ASSERT(IrpContext != NULL); - - ASSERT((IrpContext->Identifier.Type == EXT2ICX) && - (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); - - DeviceObject = IrpContext->DeviceObject; - - if (IsExt2FsDevice(DeviceObject)) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - FileObject = IrpContext->FileObject; - - Fcb = (PEXT2_FCB) FileObject->FsContext; - ASSERT(Fcb != NULL); - if (Fcb->Identifier.Type == EXT2VCB) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ASSERT((Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - - if (FlagOn(Fcb->Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE); - bFcbAcquired = TRUE; - - Irp = IrpContext->Irp; - - CompleteIrp = FALSE; - - Status = FsRtlCheckOplock( &Fcb->Oplock, - Irp, - IrpContext, - Ext2OplockComplete, - NULL ); - - if (Status != STATUS_SUCCESS) { - CompleteContext = FALSE; - __leave; - } - - // - // FsRtlProcessFileLock acquires FileObject->FsContext->Resource while - // modifying the file locks and calls IoCompleteRequest when it's done. - // - - Status = FsRtlProcessFileLock( - &Fcb->FileLockAnchor, - Irp, - NULL ); -#if EXT2_DEBUG - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ( - "Ext2LockControl: %-16.16s %-31s Status: %#x ***\n", - Ext2GetCurrentProcessName(), - "IRP_MJ_LOCK_CONTROL", - Status )); - } -#endif - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - - } __finally { - - if (bFcbAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - } - - if (!IrpContext->ExceptionInProgress) { - - if (!CompleteIrp) { - IrpContext->Irp = NULL; - } - - if (CompleteContext) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: lock.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, Ext2LockControl) +#endif + +NTSTATUS +Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject = NULL; + PFILE_OBJECT FileObject = NULL; + PEXT2_FCB Fcb = NULL; + PIRP Irp = NULL; + + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN CompleteContext = TRUE; + BOOLEAN CompleteIrp = TRUE; + BOOLEAN bFcbAcquired = FALSE; + + __try { + + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == EXT2ICX) && + (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + if (IsExt2FsDevice(DeviceObject)) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + FileObject = IrpContext->FileObject; + + Fcb = (PEXT2_FCB) FileObject->FsContext; + ASSERT(Fcb != NULL); + if (Fcb->Identifier.Type == EXT2VCB) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ASSERT((Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + + if (FlagOn(Fcb->Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE); + bFcbAcquired = TRUE; + + Irp = IrpContext->Irp; + + CompleteIrp = FALSE; + + Status = FsRtlCheckOplock( &Fcb->Oplock, + Irp, + IrpContext, + Ext2OplockComplete, + NULL ); + + if (Status != STATUS_SUCCESS) { + CompleteContext = FALSE; + __leave; + } + + // + // FsRtlProcessFileLock acquires FileObject->FsContext->Resource while + // modifying the file locks and calls IoCompleteRequest when it's done. + // + + Status = FsRtlProcessFileLock( + &Fcb->FileLockAnchor, + Irp, + NULL ); +#if EXT2_DEBUG + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ( + "Ext2LockControl: %-16.16s %-31s Status: %#x ***\n", + Ext2GetCurrentProcessName(), + "IRP_MJ_LOCK_CONTROL", + Status )); + } +#endif + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + + } __finally { + + if (bFcbAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (!IrpContext->ExceptionInProgress) { + + if (!CompleteIrp) { + IrpContext->Irp = NULL; + } + + if (CompleteContext) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} diff --git a/Ext4Fsd/misc.c b/Ext4Fsd/misc.c index d78f5b8..f5abdab 100644 --- a/Ext4Fsd/misc.c +++ b/Ext4Fsd/misc.c @@ -1,533 +1,533 @@ -/* - * 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_CANT_WAIT: - case STATUS_PENDING: - return (-EAGAIN); - - case STATUS_DEVICE_NOT_READY: - return (-EIO); - - 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_CANT_WAIT; - - 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'.'); +/* + * 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_CANT_WAIT: + case STATUS_PENDING: + return (-EAGAIN); + + case STATUS_DEVICE_NOT_READY: + return (-EIO); + + 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_CANT_WAIT; + + 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/Ext4Fsd/nls.c b/Ext4Fsd/nls.c index f51d380..11bb875 100644 --- a/Ext4Fsd/nls.c +++ b/Ext4Fsd/nls.c @@ -1,232 +1,232 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: nls.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GOBALS** ****************************************************************/ - -extern struct nls_table *tables; -extern spinlock_t nls_lock; - -/* DECLARES ****************************************************************/ - -#define FULL_CODEPAGES_SUPPORT - -#ifdef FULL_CODEPAGES_SUPPORT - -DECLARE_INIT(init_nls_ascii); -DECLARE_EXIT(exit_nls_ascii); -DECLARE_INIT(init_nls_cp1250); -DECLARE_EXIT(exit_nls_cp1250); -DECLARE_INIT(init_nls_cp1251); -DECLARE_EXIT(exit_nls_cp1251); -DECLARE_INIT(init_nls_cp1255); -DECLARE_EXIT(exit_nls_cp1255); -DECLARE_INIT(init_nls_cp437); -DECLARE_EXIT(exit_nls_cp437); -DECLARE_INIT(init_nls_cp737); -DECLARE_EXIT(exit_nls_cp737); -DECLARE_INIT(init_nls_cp775); -DECLARE_EXIT(exit_nls_cp775); -DECLARE_INIT(init_nls_cp850); -DECLARE_EXIT(exit_nls_cp850); -DECLARE_INIT(init_nls_cp852); -DECLARE_EXIT(exit_nls_cp852); -DECLARE_INIT(init_nls_cp855); -DECLARE_EXIT(exit_nls_cp855); -DECLARE_INIT(init_nls_cp857); -DECLARE_EXIT(exit_nls_cp857); -DECLARE_INIT(init_nls_cp860); -DECLARE_EXIT(exit_nls_cp860); -DECLARE_INIT(init_nls_cp861); -DECLARE_EXIT(exit_nls_cp861); -DECLARE_INIT(init_nls_cp862); -DECLARE_EXIT(exit_nls_cp862); -DECLARE_INIT(init_nls_cp863); -DECLARE_EXIT(exit_nls_cp863); -DECLARE_INIT(init_nls_cp864); -DECLARE_EXIT(exit_nls_cp864); -DECLARE_INIT(init_nls_cp865); -DECLARE_EXIT(exit_nls_cp865); -DECLARE_INIT(init_nls_cp866); -DECLARE_EXIT(exit_nls_cp866); -DECLARE_INIT(init_nls_cp869); -DECLARE_EXIT(exit_nls_cp869); -DECLARE_INIT(init_nls_cp874); -DECLARE_EXIT(exit_nls_cp874); -DECLARE_INIT(init_nls_cp932); -DECLARE_EXIT(exit_nls_cp932); -DECLARE_INIT(init_nls_cp949); -DECLARE_EXIT(exit_nls_cp949); -DECLARE_INIT(init_nls_euc_jp); -DECLARE_EXIT(exit_nls_euc_jp); -DECLARE_INIT(init_nls_iso8859_1); -DECLARE_EXIT(exit_nls_iso8859_1); -DECLARE_INIT(init_nls_iso8859_13); -DECLARE_EXIT(exit_nls_iso8859_13); -DECLARE_INIT(init_nls_iso8859_14); -DECLARE_EXIT(exit_nls_iso8859_14); -DECLARE_INIT(init_nls_iso8859_15); -DECLARE_EXIT(exit_nls_iso8859_15); -DECLARE_INIT(init_nls_iso8859_2); -DECLARE_EXIT(exit_nls_iso8859_2); -DECLARE_INIT(init_nls_iso8859_3); -DECLARE_EXIT(exit_nls_iso8859_3); -DECLARE_INIT(init_nls_iso8859_4); -DECLARE_EXIT(exit_nls_iso8859_4); -DECLARE_INIT(init_nls_iso8859_5); -DECLARE_EXIT(exit_nls_iso8859_5); -DECLARE_INIT(init_nls_iso8859_6); -DECLARE_EXIT(exit_nls_iso8859_6); -DECLARE_INIT(init_nls_iso8859_7); -DECLARE_EXIT(exit_nls_iso8859_7); -DECLARE_INIT(init_nls_iso8859_9); -DECLARE_EXIT(exit_nls_iso8859_9); -DECLARE_INIT(init_nls_koi8_r); -DECLARE_EXIT(exit_nls_koi8_r); -DECLARE_INIT(init_nls_koi8_ru); -DECLARE_EXIT(exit_nls_koi8_ru); -DECLARE_INIT(init_nls_koi8_u); -DECLARE_EXIT(exit_nls_koi8_u); -#endif //FULL_CODEPAGES_SUPPORT - -/* gb2312 */ -DECLARE_INIT(init_nls_cp936); -DECLARE_EXIT(exit_nls_cp936); - -/* big5 */ -DECLARE_INIT(init_nls_cp950); -DECLARE_EXIT(exit_nls_cp950); - -/* utf8 */ -DECLARE_INIT(init_nls_utf8); -DECLARE_EXIT(exit_nls_utf8); - - -/* FUNCTIONS ****************************************************************/ - - -int -Ext2LoadAllNls() -{ - int rc; - - tables = NULL; - spin_lock_init(&nls_lock); - - /* loading utf8 ... */ - LOAD_NLS(init_nls_utf8); - -#ifdef FULL_CODEPAGES_SUPPORT - - /* loading chinese gb2312 and big5... */ - LOAD_NLS(init_nls_cp936); - LOAD_NLS(init_nls_cp950); - - /* loading all others */ - - LOAD_NLS(init_nls_ascii); - LOAD_NLS(init_nls_cp1250); - LOAD_NLS(init_nls_cp1251); - LOAD_NLS(init_nls_cp1255); - LOAD_NLS(init_nls_cp437); - LOAD_NLS(init_nls_cp737); - LOAD_NLS(init_nls_cp775); - LOAD_NLS(init_nls_cp850); - LOAD_NLS(init_nls_cp852); - LOAD_NLS(init_nls_cp855); - LOAD_NLS(init_nls_cp857); - LOAD_NLS(init_nls_cp860); - LOAD_NLS(init_nls_cp861); - LOAD_NLS(init_nls_cp862); - LOAD_NLS(init_nls_cp863); - LOAD_NLS(init_nls_cp864); - LOAD_NLS(init_nls_cp865); - LOAD_NLS(init_nls_cp866); - LOAD_NLS(init_nls_cp869); - LOAD_NLS(init_nls_cp874); - LOAD_NLS(init_nls_cp932); - LOAD_NLS(init_nls_euc_jp); - LOAD_NLS(init_nls_cp949); - LOAD_NLS(init_nls_iso8859_1); - LOAD_NLS(init_nls_iso8859_13); - LOAD_NLS(init_nls_iso8859_14); - LOAD_NLS(init_nls_iso8859_15); - LOAD_NLS(init_nls_iso8859_2); - LOAD_NLS(init_nls_iso8859_3); - LOAD_NLS(init_nls_iso8859_4); - LOAD_NLS(init_nls_iso8859_5); - LOAD_NLS(init_nls_iso8859_6); - LOAD_NLS(init_nls_iso8859_7); - LOAD_NLS(init_nls_iso8859_9); - LOAD_NLS(init_nls_koi8_r); - LOAD_NLS(init_nls_koi8_u); - LOAD_NLS(init_nls_koi8_ru); - -#endif //FULL_CODEPAGES_SUPPORT - - return rc; -} - - -VOID -Ext2UnloadAllNls() -{ - -#ifdef FULL_CODEPAGES_SUPPORT - - UNLOAD_NLS(init_nls_ascii); - UNLOAD_NLS(init_nls_cp1250); - UNLOAD_NLS(exit_nls_cp1251); - UNLOAD_NLS(exit_nls_cp1255); - UNLOAD_NLS(exit_nls_cp437); - UNLOAD_NLS(exit_nls_cp737); - UNLOAD_NLS(exit_nls_cp775); - UNLOAD_NLS(exit_nls_cp850); - UNLOAD_NLS(exit_nls_cp852); - UNLOAD_NLS(exit_nls_cp855); - UNLOAD_NLS(exit_nls_cp857); - UNLOAD_NLS(exit_nls_cp860); - UNLOAD_NLS(exit_nls_cp861); - UNLOAD_NLS(exit_nls_cp862); - UNLOAD_NLS(exit_nls_cp863); - UNLOAD_NLS(exit_nls_cp864); - UNLOAD_NLS(exit_nls_cp865); - UNLOAD_NLS(exit_nls_cp866); - UNLOAD_NLS(exit_nls_cp869); - UNLOAD_NLS(exit_nls_cp874); - UNLOAD_NLS(exit_nls_euc_jp); - UNLOAD_NLS(exit_nls_cp932); - UNLOAD_NLS(exit_nls_cp949); - UNLOAD_NLS(exit_nls_iso8859_1); - UNLOAD_NLS(exit_nls_iso8859_13); - UNLOAD_NLS(exit_nls_iso8859_14); - UNLOAD_NLS(exit_nls_iso8859_15); - UNLOAD_NLS(exit_nls_iso8859_2); - UNLOAD_NLS(exit_nls_iso8859_3); - UNLOAD_NLS(exit_nls_iso8859_4); - UNLOAD_NLS(exit_nls_iso8859_5); - UNLOAD_NLS(exit_nls_iso8859_6); - UNLOAD_NLS(exit_nls_iso8859_7); - UNLOAD_NLS(exit_nls_iso8859_9); - UNLOAD_NLS(exit_nls_koi8_ru); - UNLOAD_NLS(exit_nls_koi8_r); - UNLOAD_NLS(exit_nls_koi8_u); - - /* unloading chinese codepages */ - UNLOAD_NLS(exit_nls_cp950); - UNLOAD_NLS(exit_nls_cp936); - -#endif //FULL_CODEPAGES_SUPPORT - - /* unloading nls of utf8 */ - UNLOAD_NLS(exit_nls_utf8); +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: nls.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GOBALS** ****************************************************************/ + +extern struct nls_table *tables; +extern spinlock_t nls_lock; + +/* DECLARES ****************************************************************/ + +#define FULL_CODEPAGES_SUPPORT + +#ifdef FULL_CODEPAGES_SUPPORT + +DECLARE_INIT(init_nls_ascii); +DECLARE_EXIT(exit_nls_ascii); +DECLARE_INIT(init_nls_cp1250); +DECLARE_EXIT(exit_nls_cp1250); +DECLARE_INIT(init_nls_cp1251); +DECLARE_EXIT(exit_nls_cp1251); +DECLARE_INIT(init_nls_cp1255); +DECLARE_EXIT(exit_nls_cp1255); +DECLARE_INIT(init_nls_cp437); +DECLARE_EXIT(exit_nls_cp437); +DECLARE_INIT(init_nls_cp737); +DECLARE_EXIT(exit_nls_cp737); +DECLARE_INIT(init_nls_cp775); +DECLARE_EXIT(exit_nls_cp775); +DECLARE_INIT(init_nls_cp850); +DECLARE_EXIT(exit_nls_cp850); +DECLARE_INIT(init_nls_cp852); +DECLARE_EXIT(exit_nls_cp852); +DECLARE_INIT(init_nls_cp855); +DECLARE_EXIT(exit_nls_cp855); +DECLARE_INIT(init_nls_cp857); +DECLARE_EXIT(exit_nls_cp857); +DECLARE_INIT(init_nls_cp860); +DECLARE_EXIT(exit_nls_cp860); +DECLARE_INIT(init_nls_cp861); +DECLARE_EXIT(exit_nls_cp861); +DECLARE_INIT(init_nls_cp862); +DECLARE_EXIT(exit_nls_cp862); +DECLARE_INIT(init_nls_cp863); +DECLARE_EXIT(exit_nls_cp863); +DECLARE_INIT(init_nls_cp864); +DECLARE_EXIT(exit_nls_cp864); +DECLARE_INIT(init_nls_cp865); +DECLARE_EXIT(exit_nls_cp865); +DECLARE_INIT(init_nls_cp866); +DECLARE_EXIT(exit_nls_cp866); +DECLARE_INIT(init_nls_cp869); +DECLARE_EXIT(exit_nls_cp869); +DECLARE_INIT(init_nls_cp874); +DECLARE_EXIT(exit_nls_cp874); +DECLARE_INIT(init_nls_cp932); +DECLARE_EXIT(exit_nls_cp932); +DECLARE_INIT(init_nls_cp949); +DECLARE_EXIT(exit_nls_cp949); +DECLARE_INIT(init_nls_euc_jp); +DECLARE_EXIT(exit_nls_euc_jp); +DECLARE_INIT(init_nls_iso8859_1); +DECLARE_EXIT(exit_nls_iso8859_1); +DECLARE_INIT(init_nls_iso8859_13); +DECLARE_EXIT(exit_nls_iso8859_13); +DECLARE_INIT(init_nls_iso8859_14); +DECLARE_EXIT(exit_nls_iso8859_14); +DECLARE_INIT(init_nls_iso8859_15); +DECLARE_EXIT(exit_nls_iso8859_15); +DECLARE_INIT(init_nls_iso8859_2); +DECLARE_EXIT(exit_nls_iso8859_2); +DECLARE_INIT(init_nls_iso8859_3); +DECLARE_EXIT(exit_nls_iso8859_3); +DECLARE_INIT(init_nls_iso8859_4); +DECLARE_EXIT(exit_nls_iso8859_4); +DECLARE_INIT(init_nls_iso8859_5); +DECLARE_EXIT(exit_nls_iso8859_5); +DECLARE_INIT(init_nls_iso8859_6); +DECLARE_EXIT(exit_nls_iso8859_6); +DECLARE_INIT(init_nls_iso8859_7); +DECLARE_EXIT(exit_nls_iso8859_7); +DECLARE_INIT(init_nls_iso8859_9); +DECLARE_EXIT(exit_nls_iso8859_9); +DECLARE_INIT(init_nls_koi8_r); +DECLARE_EXIT(exit_nls_koi8_r); +DECLARE_INIT(init_nls_koi8_ru); +DECLARE_EXIT(exit_nls_koi8_ru); +DECLARE_INIT(init_nls_koi8_u); +DECLARE_EXIT(exit_nls_koi8_u); +#endif //FULL_CODEPAGES_SUPPORT + +/* gb2312 */ +DECLARE_INIT(init_nls_cp936); +DECLARE_EXIT(exit_nls_cp936); + +/* big5 */ +DECLARE_INIT(init_nls_cp950); +DECLARE_EXIT(exit_nls_cp950); + +/* utf8 */ +DECLARE_INIT(init_nls_utf8); +DECLARE_EXIT(exit_nls_utf8); + + +/* FUNCTIONS ****************************************************************/ + + +int +Ext2LoadAllNls() +{ + int rc; + + tables = NULL; + spin_lock_init(&nls_lock); + + /* loading utf8 ... */ + LOAD_NLS(init_nls_utf8); + +#ifdef FULL_CODEPAGES_SUPPORT + + /* loading chinese gb2312 and big5... */ + LOAD_NLS(init_nls_cp936); + LOAD_NLS(init_nls_cp950); + + /* loading all others */ + + LOAD_NLS(init_nls_ascii); + LOAD_NLS(init_nls_cp1250); + LOAD_NLS(init_nls_cp1251); + LOAD_NLS(init_nls_cp1255); + LOAD_NLS(init_nls_cp437); + LOAD_NLS(init_nls_cp737); + LOAD_NLS(init_nls_cp775); + LOAD_NLS(init_nls_cp850); + LOAD_NLS(init_nls_cp852); + LOAD_NLS(init_nls_cp855); + LOAD_NLS(init_nls_cp857); + LOAD_NLS(init_nls_cp860); + LOAD_NLS(init_nls_cp861); + LOAD_NLS(init_nls_cp862); + LOAD_NLS(init_nls_cp863); + LOAD_NLS(init_nls_cp864); + LOAD_NLS(init_nls_cp865); + LOAD_NLS(init_nls_cp866); + LOAD_NLS(init_nls_cp869); + LOAD_NLS(init_nls_cp874); + LOAD_NLS(init_nls_cp932); + LOAD_NLS(init_nls_euc_jp); + LOAD_NLS(init_nls_cp949); + LOAD_NLS(init_nls_iso8859_1); + LOAD_NLS(init_nls_iso8859_13); + LOAD_NLS(init_nls_iso8859_14); + LOAD_NLS(init_nls_iso8859_15); + LOAD_NLS(init_nls_iso8859_2); + LOAD_NLS(init_nls_iso8859_3); + LOAD_NLS(init_nls_iso8859_4); + LOAD_NLS(init_nls_iso8859_5); + LOAD_NLS(init_nls_iso8859_6); + LOAD_NLS(init_nls_iso8859_7); + LOAD_NLS(init_nls_iso8859_9); + LOAD_NLS(init_nls_koi8_r); + LOAD_NLS(init_nls_koi8_u); + LOAD_NLS(init_nls_koi8_ru); + +#endif //FULL_CODEPAGES_SUPPORT + + return rc; +} + + +VOID +Ext2UnloadAllNls() +{ + +#ifdef FULL_CODEPAGES_SUPPORT + + UNLOAD_NLS(init_nls_ascii); + UNLOAD_NLS(init_nls_cp1250); + UNLOAD_NLS(exit_nls_cp1251); + UNLOAD_NLS(exit_nls_cp1255); + UNLOAD_NLS(exit_nls_cp437); + UNLOAD_NLS(exit_nls_cp737); + UNLOAD_NLS(exit_nls_cp775); + UNLOAD_NLS(exit_nls_cp850); + UNLOAD_NLS(exit_nls_cp852); + UNLOAD_NLS(exit_nls_cp855); + UNLOAD_NLS(exit_nls_cp857); + UNLOAD_NLS(exit_nls_cp860); + UNLOAD_NLS(exit_nls_cp861); + UNLOAD_NLS(exit_nls_cp862); + UNLOAD_NLS(exit_nls_cp863); + UNLOAD_NLS(exit_nls_cp864); + UNLOAD_NLS(exit_nls_cp865); + UNLOAD_NLS(exit_nls_cp866); + UNLOAD_NLS(exit_nls_cp869); + UNLOAD_NLS(exit_nls_cp874); + UNLOAD_NLS(exit_nls_euc_jp); + UNLOAD_NLS(exit_nls_cp932); + UNLOAD_NLS(exit_nls_cp949); + UNLOAD_NLS(exit_nls_iso8859_1); + UNLOAD_NLS(exit_nls_iso8859_13); + UNLOAD_NLS(exit_nls_iso8859_14); + UNLOAD_NLS(exit_nls_iso8859_15); + UNLOAD_NLS(exit_nls_iso8859_2); + UNLOAD_NLS(exit_nls_iso8859_3); + UNLOAD_NLS(exit_nls_iso8859_4); + UNLOAD_NLS(exit_nls_iso8859_5); + UNLOAD_NLS(exit_nls_iso8859_6); + UNLOAD_NLS(exit_nls_iso8859_7); + UNLOAD_NLS(exit_nls_iso8859_9); + UNLOAD_NLS(exit_nls_koi8_ru); + UNLOAD_NLS(exit_nls_koi8_r); + UNLOAD_NLS(exit_nls_koi8_u); + + /* unloading chinese codepages */ + UNLOAD_NLS(exit_nls_cp950); + UNLOAD_NLS(exit_nls_cp936); + +#endif //FULL_CODEPAGES_SUPPORT + + /* unloading nls of utf8 */ + UNLOAD_NLS(exit_nls_utf8); } \ No newline at end of file diff --git a/Ext4Fsd/pnp.c b/Ext4Fsd/pnp.c index f7f70e1..08371a5 100644 --- a/Ext4Fsd/pnp.c +++ b/Ext4Fsd/pnp.c @@ -1,397 +1,397 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: pnp.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -#if (_WIN32_WINNT >= 0x0500) - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -extern PEXT2_GLOBAL Ext2Global; - -/* DEFINITIONS *************************************************************/ - -NTSTATUS -Ext2PnpCompletionRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Contxt ); - - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Ext2Pnp) -#pragma alloc_text(PAGE, Ext2PnpQueryRemove) -#pragma alloc_text(PAGE, Ext2PnpRemove) -#pragma alloc_text(PAGE, Ext2PnpCancelRemove) -#pragma alloc_text(PAGE, Ext2PnpSurpriseRemove) -#endif - - -/* FUNCTIONS *************************************************************/ - - -NTSTATUS -Ext2PnpCompletionRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Contxt -) -{ - PKEVENT Event = (PKEVENT) Contxt; - - KeSetEvent( Event, 0, FALSE ); - - return STATUS_MORE_PROCESSING_REQUIRED; - - UNREFERENCED_PARAMETER( DeviceObject ); - UNREFERENCED_PARAMETER( Contxt ); -} - - -NTSTATUS -Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext) -{ - NTSTATUS Status = STATUS_INVALID_PARAMETER; - - PIRP Irp; - PIO_STACK_LOCATION IrpSp; - PEXT2_VCB Vcb = NULL; - PDEVICE_OBJECT DeviceObject; - - __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); - - if ( !((Vcb->Identifier.Type == EXT2VCB) && - (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { - __leave; // Status = STATUS_INVALID_PARAMETER - } - - Irp = IrpContext->Irp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); - - switch ( IrpSp->MinorFunction ) { - - case IRP_MN_QUERY_REMOVE_DEVICE: - - DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n")); - Status = Ext2PnpQueryRemove(IrpContext, Vcb); - - break; - - case IRP_MN_REMOVE_DEVICE: - - DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n")); - Status = Ext2PnpRemove(IrpContext, Vcb); - break; - - case IRP_MN_CANCEL_REMOVE_DEVICE: - - DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n")); - Status = Ext2PnpCancelRemove(IrpContext, Vcb); - break; - - case IRP_MN_SURPRISE_REMOVAL: - - DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n")); - Status = Ext2PnpSurpriseRemove(IrpContext, Vcb); - break; - - default: - break; - } - - } __finally { - - if (!IrpContext->ExceptionInProgress) { - Irp = IrpContext->Irp; - - if (Irp) { - - // - // Here we need pass the IRP to the disk driver. - // - - IoSkipCurrentIrpStackLocation( Irp ); - - Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); - - IrpContext->Irp = NULL; - } - - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - return Status; -} - - -NTSTATUS -Ext2PnpQueryRemove ( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb -) -{ - NTSTATUS Status = STATUS_SUCCESS; - KEVENT Event; - BOOLEAN bDeleted = FALSE; - BOOLEAN VcbAcquired = FALSE; - - __try { - - CcWaitForCurrentLazyWriterActivity(); - - VcbAcquired = ExAcquireResourceExclusiveLite( - &Vcb->MainResource, TRUE ); - - Ext2FlushFiles(IrpContext, Vcb, FALSE); - Ext2FlushVolume(IrpContext, Vcb, FALSE); - - DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n", - Vcb, IrpContext->FileObject)); - Status = Ext2LockVcb(Vcb, IrpContext->FileObject); - - if (VcbAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - VcbAcquired = FALSE; - } - - DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n")); - Ext2PurgeVolume(Vcb, TRUE); - - if (!NT_SUCCESS(Status)) { - __leave; - } - - IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); - - KeInitializeEvent( &Event, NotificationEvent, FALSE ); - IoSetCompletionRoutine( IrpContext->Irp, - Ext2PnpCompletionRoutine, - &Event, - TRUE, - TRUE, - TRUE ); - - DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n")); - Status = IoCallDriver( Vcb->TargetDeviceObject, - IrpContext->Irp); - - if (Status == STATUS_PENDING) { - KeWaitForSingleObject( &Event, - Executive, - KernelMode, - FALSE, - NULL ); - Status = IrpContext->Irp->IoStatus.Status; - } - - if (NT_SUCCESS(Status)) { - ASSERT(!VcbAcquired); - DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n")); - bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); - DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted)); - } - - } __finally { - - if (VcbAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - - IrpContext->Irp->IoStatus.Status = Status; - Ext2CompleteRequest( - IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? - IO_DISK_INCREMENT : IO_NO_INCREMENT) ); - - IrpContext->Irp = NULL; - } - - return Status; -} - -NTSTATUS -Ext2PnpRemove ( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb ) -{ - NTSTATUS Status = STATUS_SUCCESS; - KEVENT Event; - BOOLEAN bDeleted; - - __try { - - DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n")); - - CcWaitForCurrentLazyWriterActivity(); - ExAcquireResourceExclusiveLite( - &Vcb->MainResource, TRUE ); - Status = Ext2LockVcb(Vcb, IrpContext->FileObject); - ExReleaseResourceLite(&Vcb->MainResource); - - // - // Setup the Irp. We'll send it to the lower disk driver. - // - - IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); - - KeInitializeEvent( &Event, NotificationEvent, FALSE ); - IoSetCompletionRoutine( IrpContext->Irp, - Ext2PnpCompletionRoutine, - &Event, - TRUE, - TRUE, - TRUE ); - - Status = IoCallDriver( Vcb->TargetDeviceObject, - IrpContext->Irp); - - if (Status == STATUS_PENDING) { - - KeWaitForSingleObject( &Event, - Executive, - KernelMode, - FALSE, - NULL ); - - Status = IrpContext->Irp->IoStatus.Status; - } - - /* purge volume cache */ - Ext2PurgeVolume(Vcb, FALSE); - - /* dismount volume */ - bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); - SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); - - } __finally { - - IrpContext->Irp->IoStatus.Status = Status; - Ext2CompleteRequest( - IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? - IO_DISK_INCREMENT : IO_NO_INCREMENT) ); - - IrpContext->Irp = NULL; - } - - return Status; -} - - -NTSTATUS -Ext2PnpSurpriseRemove ( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb ) -{ - NTSTATUS Status; - KEVENT Event; - BOOLEAN bDeleted; - - __try { - - DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n")); - - CcWaitForCurrentLazyWriterActivity(); - ExAcquireResourceExclusiveLite( - &Vcb->MainResource, TRUE ); - - Status = Ext2LockVcb(Vcb, IrpContext->FileObject); - - ExReleaseResourceLite(&Vcb->MainResource); - - // - // Setup the Irp. We'll send it to the lower disk driver. - // - - IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); - - KeInitializeEvent( &Event, NotificationEvent, FALSE ); - IoSetCompletionRoutine( IrpContext->Irp, - Ext2PnpCompletionRoutine, - &Event, - TRUE, - TRUE, - TRUE ); - - Status = IoCallDriver( Vcb->TargetDeviceObject, - IrpContext->Irp); - - if (Status == STATUS_PENDING) { - - KeWaitForSingleObject( &Event, - Executive, - KernelMode, - FALSE, - NULL ); - - Status = IrpContext->Irp->IoStatus.Status; - } - - /* purge volume cache */ - Ext2PurgeVolume(Vcb, FALSE); - - /* dismount volume */ - bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); - SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); - - } __finally { - - IrpContext->Irp->IoStatus.Status = Status; - Ext2CompleteRequest( - IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? - IO_DISK_INCREMENT : IO_NO_INCREMENT) ); - - IrpContext->Irp = NULL; - } - - return Status; -} - - -NTSTATUS -Ext2PnpCancelRemove ( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb -) -{ - NTSTATUS Status; - - DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n")); - - ExAcquireResourceExclusiveLite( - &Vcb->MainResource, TRUE ); - - Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject); - - ExReleaseResourceLite(&Vcb->MainResource); - - IoSkipCurrentIrpStackLocation(IrpContext->Irp); - - Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); - - IrpContext->Irp = NULL; - - return Status; -} - +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: pnp.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +#if (_WIN32_WINNT >= 0x0500) + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +NTSTATUS +Ext2PnpCompletionRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, Ext2Pnp) +#pragma alloc_text(PAGE, Ext2PnpQueryRemove) +#pragma alloc_text(PAGE, Ext2PnpRemove) +#pragma alloc_text(PAGE, Ext2PnpCancelRemove) +#pragma alloc_text(PAGE, Ext2PnpSurpriseRemove) +#endif + + +/* FUNCTIONS *************************************************************/ + + +NTSTATUS +Ext2PnpCompletionRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt +) +{ + PKEVENT Event = (PKEVENT) Contxt; + + KeSetEvent( Event, 0, FALSE ); + + return STATUS_MORE_PROCESSING_REQUIRED; + + UNREFERENCED_PARAMETER( DeviceObject ); + UNREFERENCED_PARAMETER( Contxt ); +} + + +NTSTATUS +Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PEXT2_VCB Vcb = NULL; + PDEVICE_OBJECT DeviceObject; + + __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); + + if ( !((Vcb->Identifier.Type == EXT2VCB) && + (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { + __leave; // Status = STATUS_INVALID_PARAMETER + } + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + switch ( IrpSp->MinorFunction ) { + + case IRP_MN_QUERY_REMOVE_DEVICE: + + DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n")); + Status = Ext2PnpQueryRemove(IrpContext, Vcb); + + break; + + case IRP_MN_REMOVE_DEVICE: + + DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n")); + Status = Ext2PnpRemove(IrpContext, Vcb); + break; + + case IRP_MN_CANCEL_REMOVE_DEVICE: + + DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n")); + Status = Ext2PnpCancelRemove(IrpContext, Vcb); + break; + + case IRP_MN_SURPRISE_REMOVAL: + + DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n")); + Status = Ext2PnpSurpriseRemove(IrpContext, Vcb); + break; + + default: + break; + } + + } __finally { + + if (!IrpContext->ExceptionInProgress) { + Irp = IrpContext->Irp; + + if (Irp) { + + // + // Here we need pass the IRP to the disk driver. + // + + IoSkipCurrentIrpStackLocation( Irp ); + + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + IrpContext->Irp = NULL; + } + + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + return Status; +} + + +NTSTATUS +Ext2PnpQueryRemove ( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb +) +{ + NTSTATUS Status = STATUS_SUCCESS; + KEVENT Event; + BOOLEAN bDeleted = FALSE; + BOOLEAN VcbAcquired = FALSE; + + __try { + + CcWaitForCurrentLazyWriterActivity(); + + VcbAcquired = ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE ); + + Ext2FlushFiles(IrpContext, Vcb, FALSE); + Ext2FlushVolume(IrpContext, Vcb, FALSE); + + DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n", + Vcb, IrpContext->FileObject)); + Status = Ext2LockVcb(Vcb, IrpContext->FileObject); + + if (VcbAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + VcbAcquired = FALSE; + } + + DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n")); + Ext2PurgeVolume(Vcb, TRUE); + + if (!NT_SUCCESS(Status)) { + __leave; + } + + IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); + + KeInitializeEvent( &Event, NotificationEvent, FALSE ); + IoSetCompletionRoutine( IrpContext->Irp, + Ext2PnpCompletionRoutine, + &Event, + TRUE, + TRUE, + TRUE ); + + DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n")); + Status = IoCallDriver( Vcb->TargetDeviceObject, + IrpContext->Irp); + + if (Status == STATUS_PENDING) { + KeWaitForSingleObject( &Event, + Executive, + KernelMode, + FALSE, + NULL ); + Status = IrpContext->Irp->IoStatus.Status; + } + + if (NT_SUCCESS(Status)) { + ASSERT(!VcbAcquired); + DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n")); + bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); + DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted)); + } + + } __finally { + + if (VcbAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + } + + IrpContext->Irp->IoStatus.Status = Status; + Ext2CompleteRequest( + IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? + IO_DISK_INCREMENT : IO_NO_INCREMENT) ); + + IrpContext->Irp = NULL; + } + + return Status; +} + +NTSTATUS +Ext2PnpRemove ( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb ) +{ + NTSTATUS Status = STATUS_SUCCESS; + KEVENT Event; + BOOLEAN bDeleted; + + __try { + + DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n")); + + CcWaitForCurrentLazyWriterActivity(); + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE ); + Status = Ext2LockVcb(Vcb, IrpContext->FileObject); + ExReleaseResourceLite(&Vcb->MainResource); + + // + // Setup the Irp. We'll send it to the lower disk driver. + // + + IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); + + KeInitializeEvent( &Event, NotificationEvent, FALSE ); + IoSetCompletionRoutine( IrpContext->Irp, + Ext2PnpCompletionRoutine, + &Event, + TRUE, + TRUE, + TRUE ); + + Status = IoCallDriver( Vcb->TargetDeviceObject, + IrpContext->Irp); + + if (Status == STATUS_PENDING) { + + KeWaitForSingleObject( &Event, + Executive, + KernelMode, + FALSE, + NULL ); + + Status = IrpContext->Irp->IoStatus.Status; + } + + /* purge volume cache */ + Ext2PurgeVolume(Vcb, FALSE); + + /* dismount volume */ + bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); + SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); + + } __finally { + + IrpContext->Irp->IoStatus.Status = Status; + Ext2CompleteRequest( + IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? + IO_DISK_INCREMENT : IO_NO_INCREMENT) ); + + IrpContext->Irp = NULL; + } + + return Status; +} + + +NTSTATUS +Ext2PnpSurpriseRemove ( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb ) +{ + NTSTATUS Status; + KEVENT Event; + BOOLEAN bDeleted; + + __try { + + DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n")); + + CcWaitForCurrentLazyWriterActivity(); + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE ); + + Status = Ext2LockVcb(Vcb, IrpContext->FileObject); + + ExReleaseResourceLite(&Vcb->MainResource); + + // + // Setup the Irp. We'll send it to the lower disk driver. + // + + IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); + + KeInitializeEvent( &Event, NotificationEvent, FALSE ); + IoSetCompletionRoutine( IrpContext->Irp, + Ext2PnpCompletionRoutine, + &Event, + TRUE, + TRUE, + TRUE ); + + Status = IoCallDriver( Vcb->TargetDeviceObject, + IrpContext->Irp); + + if (Status == STATUS_PENDING) { + + KeWaitForSingleObject( &Event, + Executive, + KernelMode, + FALSE, + NULL ); + + Status = IrpContext->Irp->IoStatus.Status; + } + + /* purge volume cache */ + Ext2PurgeVolume(Vcb, FALSE); + + /* dismount volume */ + bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); + SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); + + } __finally { + + IrpContext->Irp->IoStatus.Status = Status; + Ext2CompleteRequest( + IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? + IO_DISK_INCREMENT : IO_NO_INCREMENT) ); + + IrpContext->Irp = NULL; + } + + return Status; +} + + +NTSTATUS +Ext2PnpCancelRemove ( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb +) +{ + NTSTATUS Status; + + DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n")); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE ); + + Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject); + + ExReleaseResourceLite(&Vcb->MainResource); + + IoSkipCurrentIrpStackLocation(IrpContext->Irp); + + Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); + + IrpContext->Irp = NULL; + + return Status; +} + #endif //(_WIN32_WINNT >= 0x0500) \ No newline at end of file diff --git a/Ext4Fsd/rbtree.c b/Ext4Fsd/rbtree.c index b97f950..d80273d 100644 --- a/Ext4Fsd/rbtree.c +++ b/Ext4Fsd/rbtree.c @@ -1,415 +1,415 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli - (C) 2002 David Woodhouse - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -*/ - -#include - -static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *right = node->rb_right; - struct rb_node *parent = rb_parent(node); - - if ((node->rb_right = right->rb_left)) - rb_set_parent(right->rb_left, node); - right->rb_left = node; - - rb_set_parent(right, parent); - - if (parent) - { - if (node == parent->rb_left) - parent->rb_left = right; - else - parent->rb_right = right; - } - else - root->rb_node = right; - rb_set_parent(node, right); -} - -static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *left = node->rb_left; - struct rb_node *parent = rb_parent(node); - - if ((node->rb_left = left->rb_right)) - rb_set_parent(left->rb_right, node); - left->rb_right = node; - - rb_set_parent(left, parent); - - if (parent) - { - if (node == parent->rb_right) - parent->rb_right = left; - else - parent->rb_left = left; - } - else - root->rb_node = left; - rb_set_parent(node, left); -} - -void rb_insert_color(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *parent, *gparent; - - while ((parent = rb_parent(node)) && rb_is_red(parent)) - { - gparent = rb_parent(parent); - - if (parent == gparent->rb_left) - { - { - register struct rb_node *uncle = gparent->rb_right; - if (uncle && rb_is_red(uncle)) - { - rb_set_black(uncle); - rb_set_black(parent); - rb_set_red(gparent); - node = gparent; - continue; - } - } - - if (parent->rb_right == node) - { - register struct rb_node *tmp; - __rb_rotate_left(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - rb_set_black(parent); - rb_set_red(gparent); - __rb_rotate_right(gparent, root); - } else { - { - register struct rb_node *uncle = gparent->rb_left; - if (uncle && rb_is_red(uncle)) - { - rb_set_black(uncle); - rb_set_black(parent); - rb_set_red(gparent); - node = gparent; - continue; - } - } - - if (parent->rb_left == node) - { - register struct rb_node *tmp; - __rb_rotate_right(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - rb_set_black(parent); - rb_set_red(gparent); - __rb_rotate_left(gparent, root); - } - } - - rb_set_black(root->rb_node); -} -EXPORT_SYMBOL(rb_insert_color); - -static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, - struct rb_root *root) -{ - struct rb_node *other; - - while ((!node || rb_is_black(node)) && node != root->rb_node) - { - if (parent->rb_left == node) - { - other = parent->rb_right; - if (rb_is_red(other)) - { - rb_set_black(other); - rb_set_red(parent); - __rb_rotate_left(parent, root); - other = parent->rb_right; - } - if ((!other->rb_left || rb_is_black(other->rb_left)) && - (!other->rb_right || rb_is_black(other->rb_right))) - { - rb_set_red(other); - node = parent; - parent = rb_parent(node); - } - else - { - if (!other->rb_right || rb_is_black(other->rb_right)) - { - struct rb_node *o_left; - if ((o_left = other->rb_left)) - rb_set_black(o_left); - rb_set_red(other); - __rb_rotate_right(other, root); - other = parent->rb_right; - } - rb_set_color(other, rb_color(parent)); - rb_set_black(parent); - if (other->rb_right) - rb_set_black(other->rb_right); - __rb_rotate_left(parent, root); - node = root->rb_node; - break; - } - } - else - { - other = parent->rb_left; - if (rb_is_red(other)) - { - rb_set_black(other); - rb_set_red(parent); - __rb_rotate_right(parent, root); - other = parent->rb_left; - } - if ((!other->rb_left || rb_is_black(other->rb_left)) && - (!other->rb_right || rb_is_black(other->rb_right))) - { - rb_set_red(other); - node = parent; - parent = rb_parent(node); - } - else - { - if (!other->rb_left || rb_is_black(other->rb_left)) - { - register struct rb_node *o_right; - if ((o_right = other->rb_right)) - rb_set_black(o_right); - rb_set_red(other); - __rb_rotate_left(other, root); - other = parent->rb_left; - } - rb_set_color(other, rb_color(parent)); - rb_set_black(parent); - if (other->rb_left) - rb_set_black(other->rb_left); - __rb_rotate_right(parent, root); - node = root->rb_node; - break; - } - } - } - if (node) - rb_set_black(node); -} - -void rb_erase(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *child, *parent; - ULONG_PTR color; - - if (!node->rb_left) - child = node->rb_right; - else if (!node->rb_right) - child = node->rb_left; - else - { - struct rb_node *old = node, *left; - - node = node->rb_right; - while ((left = node->rb_left) != NULL) - node = left; - child = node->rb_right; - parent = rb_parent(node); - color = rb_color(node); - - if (child) - rb_set_parent(child, parent); - if (parent == old) { - parent->rb_right = child; - parent = node; - } else - parent->rb_left = child; - - node->rb_parent_color = old->rb_parent_color; - node->rb_right = old->rb_right; - node->rb_left = old->rb_left; - - if (rb_parent(old)) - { - if (rb_parent(old)->rb_left == old) - rb_parent(old)->rb_left = node; - else - rb_parent(old)->rb_right = node; - } else - root->rb_node = node; - - rb_set_parent(old->rb_left, node); - if (old->rb_right) - rb_set_parent(old->rb_right, node); - goto color; - } - - parent = rb_parent(node); - color = rb_color(node); - - if (child) - rb_set_parent(child, parent); - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - -color: - if (color == RB_BLACK) - __rb_erase_color(child, parent, root); -} -EXPORT_SYMBOL(rb_erase); - -/* - * This function returns the first node (in sort order) of the tree. - */ -struct rb_node *rb_first(struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return NULL; - while (n->rb_left) - n = n->rb_left; - return n; -} -EXPORT_SYMBOL(rb_first); - -struct rb_node *rb_last(struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return NULL; - while (n->rb_right) - n = n->rb_right; - return n; -} -EXPORT_SYMBOL(rb_last); - -struct rb_node *rb_next(struct rb_node *node) -{ - struct rb_node *parent; - - /* If we have a right-hand child, go down and then left as far - as we can. */ - if (node->rb_right) { - node = node->rb_right; - while (node->rb_left) - node=node->rb_left; - return node; - } - - /* No right-hand children. Everything down and left is - smaller than us, so any 'next' node must be in the general - direction of our parent. Go up the tree; any time the - ancestor is a right-hand child of its parent, keep going - up. First time it's a left-hand child of its parent, said - parent is our 'next' node. */ - while ((parent = rb_parent(node)) && node == parent->rb_right) - node = parent; - - return parent; -} -EXPORT_SYMBOL(rb_next); - -struct rb_node *rb_prev(struct rb_node *node) -{ - struct rb_node *parent; - - /* If we have a left-hand child, go down and then right as far - as we can. */ - if (node->rb_left) { - node = node->rb_left; - while (node->rb_right) - node=node->rb_right; - return node; - } - - /* No left-hand children. Go up till we find an ancestor which - is a right-hand child of its parent */ - while ((parent = rb_parent(node)) && node == parent->rb_left) - node = parent; - - return parent; -} -EXPORT_SYMBOL(rb_prev); - -void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root) -{ - struct rb_node *parent = rb_parent(victim); - - /* Set the surrounding nodes to point to the replacement */ - if (parent) { - if (victim == parent->rb_left) - parent->rb_left = new; - else - parent->rb_right = new; - } else { - root->rb_node = new; - } - if (victim->rb_left) - rb_set_parent(victim->rb_left, new); - if (victim->rb_right) - rb_set_parent(victim->rb_right, new); - - /* Copy the pointers/colour from the victim to the replacement */ - *new = *victim; -} -EXPORT_SYMBOL(rb_replace_node); - -void rb_insert(struct rb_root *root, struct rb_node *node, - int (*cmp)(struct rb_node *, struct rb_node *)) -{ - struct rb_node **new = &(root->rb_node), *parent = NULL; - - /* Figure out where to put new node */ - while (*new) { - int result = cmp(node, *new); - - parent = *new; - if (result < 0) - new = &((*new)->rb_left); - else if (result > 0) - new = &((*new)->rb_right); - else - return; - - } - - /* Add new node and rebalance tree. */ - rb_link_node(node, parent, new); - rb_insert_color(node, root); -} -EXPORT_SYMBOL(rb_insert); +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + (C) 2002 David Woodhouse + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/lib/rbtree.c +*/ + +#include + +static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *right = node->rb_right; + struct rb_node *parent = rb_parent(node); + + if ((node->rb_right = right->rb_left)) + rb_set_parent(right->rb_left, node); + right->rb_left = node; + + rb_set_parent(right, parent); + + if (parent) + { + if (node == parent->rb_left) + parent->rb_left = right; + else + parent->rb_right = right; + } + else + root->rb_node = right; + rb_set_parent(node, right); +} + +static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *left = node->rb_left; + struct rb_node *parent = rb_parent(node); + + if ((node->rb_left = left->rb_right)) + rb_set_parent(left->rb_right, node); + left->rb_right = node; + + rb_set_parent(left, parent); + + if (parent) + { + if (node == parent->rb_right) + parent->rb_right = left; + else + parent->rb_left = left; + } + else + root->rb_node = left; + rb_set_parent(node, left); +} + +void rb_insert_color(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *parent, *gparent; + + while ((parent = rb_parent(node)) && rb_is_red(parent)) + { + gparent = rb_parent(parent); + + if (parent == gparent->rb_left) + { + { + register struct rb_node *uncle = gparent->rb_right; + if (uncle && rb_is_red(uncle)) + { + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->rb_right == node) + { + register struct rb_node *tmp; + __rb_rotate_left(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + rb_set_black(parent); + rb_set_red(gparent); + __rb_rotate_right(gparent, root); + } else { + { + register struct rb_node *uncle = gparent->rb_left; + if (uncle && rb_is_red(uncle)) + { + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->rb_left == node) + { + register struct rb_node *tmp; + __rb_rotate_right(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + rb_set_black(parent); + rb_set_red(gparent); + __rb_rotate_left(gparent, root); + } + } + + rb_set_black(root->rb_node); +} +EXPORT_SYMBOL(rb_insert_color); + +static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, + struct rb_root *root) +{ + struct rb_node *other; + + while ((!node || rb_is_black(node)) && node != root->rb_node) + { + if (parent->rb_left == node) + { + other = parent->rb_right; + if (rb_is_red(other)) + { + rb_set_black(other); + rb_set_red(parent); + __rb_rotate_left(parent, root); + other = parent->rb_right; + } + if ((!other->rb_left || rb_is_black(other->rb_left)) && + (!other->rb_right || rb_is_black(other->rb_right))) + { + rb_set_red(other); + node = parent; + parent = rb_parent(node); + } + else + { + if (!other->rb_right || rb_is_black(other->rb_right)) + { + struct rb_node *o_left; + if ((o_left = other->rb_left)) + rb_set_black(o_left); + rb_set_red(other); + __rb_rotate_right(other, root); + other = parent->rb_right; + } + rb_set_color(other, rb_color(parent)); + rb_set_black(parent); + if (other->rb_right) + rb_set_black(other->rb_right); + __rb_rotate_left(parent, root); + node = root->rb_node; + break; + } + } + else + { + other = parent->rb_left; + if (rb_is_red(other)) + { + rb_set_black(other); + rb_set_red(parent); + __rb_rotate_right(parent, root); + other = parent->rb_left; + } + if ((!other->rb_left || rb_is_black(other->rb_left)) && + (!other->rb_right || rb_is_black(other->rb_right))) + { + rb_set_red(other); + node = parent; + parent = rb_parent(node); + } + else + { + if (!other->rb_left || rb_is_black(other->rb_left)) + { + register struct rb_node *o_right; + if ((o_right = other->rb_right)) + rb_set_black(o_right); + rb_set_red(other); + __rb_rotate_left(other, root); + other = parent->rb_left; + } + rb_set_color(other, rb_color(parent)); + rb_set_black(parent); + if (other->rb_left) + rb_set_black(other->rb_left); + __rb_rotate_right(parent, root); + node = root->rb_node; + break; + } + } + } + if (node) + rb_set_black(node); +} + +void rb_erase(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *child, *parent; + ULONG_PTR color; + + if (!node->rb_left) + child = node->rb_right; + else if (!node->rb_right) + child = node->rb_left; + else + { + struct rb_node *old = node, *left; + + node = node->rb_right; + while ((left = node->rb_left) != NULL) + node = left; + child = node->rb_right; + parent = rb_parent(node); + color = rb_color(node); + + if (child) + rb_set_parent(child, parent); + if (parent == old) { + parent->rb_right = child; + parent = node; + } else + parent->rb_left = child; + + node->rb_parent_color = old->rb_parent_color; + node->rb_right = old->rb_right; + node->rb_left = old->rb_left; + + if (rb_parent(old)) + { + if (rb_parent(old)->rb_left == old) + rb_parent(old)->rb_left = node; + else + rb_parent(old)->rb_right = node; + } else + root->rb_node = node; + + rb_set_parent(old->rb_left, node); + if (old->rb_right) + rb_set_parent(old->rb_right, node); + goto color; + } + + parent = rb_parent(node); + color = rb_color(node); + + if (child) + rb_set_parent(child, parent); + if (parent) + { + if (parent->rb_left == node) + parent->rb_left = child; + else + parent->rb_right = child; + } + else + root->rb_node = child; + +color: + if (color == RB_BLACK) + __rb_erase_color(child, parent, root); +} +EXPORT_SYMBOL(rb_erase); + +/* + * This function returns the first node (in sort order) of the tree. + */ +struct rb_node *rb_first(struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_left) + n = n->rb_left; + return n; +} +EXPORT_SYMBOL(rb_first); + +struct rb_node *rb_last(struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_right) + n = n->rb_right; + return n; +} +EXPORT_SYMBOL(rb_last); + +struct rb_node *rb_next(struct rb_node *node) +{ + struct rb_node *parent; + + /* If we have a right-hand child, go down and then left as far + as we can. */ + if (node->rb_right) { + node = node->rb_right; + while (node->rb_left) + node=node->rb_left; + return node; + } + + /* No right-hand children. Everything down and left is + smaller than us, so any 'next' node must be in the general + direction of our parent. Go up the tree; any time the + ancestor is a right-hand child of its parent, keep going + up. First time it's a left-hand child of its parent, said + parent is our 'next' node. */ + while ((parent = rb_parent(node)) && node == parent->rb_right) + node = parent; + + return parent; +} +EXPORT_SYMBOL(rb_next); + +struct rb_node *rb_prev(struct rb_node *node) +{ + struct rb_node *parent; + + /* If we have a left-hand child, go down and then right as far + as we can. */ + if (node->rb_left) { + node = node->rb_left; + while (node->rb_right) + node=node->rb_right; + return node; + } + + /* No left-hand children. Go up till we find an ancestor which + is a right-hand child of its parent */ + while ((parent = rb_parent(node)) && node == parent->rb_left) + node = parent; + + return parent; +} +EXPORT_SYMBOL(rb_prev); + +void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root) +{ + struct rb_node *parent = rb_parent(victim); + + /* Set the surrounding nodes to point to the replacement */ + if (parent) { + if (victim == parent->rb_left) + parent->rb_left = new; + else + parent->rb_right = new; + } else { + root->rb_node = new; + } + if (victim->rb_left) + rb_set_parent(victim->rb_left, new); + if (victim->rb_right) + rb_set_parent(victim->rb_right, new); + + /* Copy the pointers/colour from the victim to the replacement */ + *new = *victim; +} +EXPORT_SYMBOL(rb_replace_node); + +void rb_insert(struct rb_root *root, struct rb_node *node, + int (*cmp)(struct rb_node *, struct rb_node *)) +{ + struct rb_node **new = &(root->rb_node), *parent = NULL; + + /* Figure out where to put new node */ + while (*new) { + int result = cmp(node, *new); + + parent = *new; + if (result < 0) + new = &((*new)->rb_left); + else if (result > 0) + new = &((*new)->rb_right); + else + return; + + } + + /* Add new node and rebalance tree. */ + rb_link_node(node, parent, new); + rb_insert_color(node, root); +} +EXPORT_SYMBOL(rb_insert); diff --git a/Ext4Fsd/read.c b/Ext4Fsd/read.c index 16b6c2f..4d5d986 100644 --- a/Ext4Fsd/read.c +++ b/Ext4Fsd/read.c @@ -1,945 +1,945 @@ -/* - * 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 = NULL; - PEXT2_CCB Ccb = NULL; - PEXT2_FCBVCB FcbOrVcb = NULL; - PFILE_OBJECT FileObject = NULL; - - PDEVICE_OBJECT DeviceObject = NULL; - - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - - ULONG Length; - LARGE_INTEGER ByteOffset; - - BOOLEAN PagingIo; - BOOLEAN Nocache; - BOOLEAN SynchronousIo; - BOOLEAN MainResourceAcquired = FALSE; - - PUCHAR Buffer = NULL; - EXT2_EXTENT BlockArray; - - __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; - __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; - __leave; - } - - if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { - ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); - Status = STATUS_PENDING; - __leave; - } - - if (ByteOffset.QuadPart >= - Vcb->PartitionInformation.PartitionLength.QuadPart ) { - Irp->IoStatus.Information = 0; - Status = STATUS_END_OF_FILE; - __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; - __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; - __leave; - } - - if (!CcCopyRead( - Vcb->Volume, - &ByteOffset, - Length, - Ext2CanIWait(), - Buffer, - &Irp->IoStatus )) { - Status = STATUS_PENDING; - __leave; - } - - Status = Irp->IoStatus.Status; - } - - } else { - - Length &= ~((ULONG)SECTOR_SIZE - 1); - Status = Ext2LockUserBuffer( - IrpContext->Irp, - Length, - IoWriteAccess ); - - if (!NT_SUCCESS(Status)) { - __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) { - __leave; - } - } - - } __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); - } - } - } - - return Status; -} - - -#define SafeZeroMemory(AT,BYTE_COUNT) { \ - __try { \ - if (AT) \ - RtlZeroMemory((AT), (BYTE_COUNT)); \ - } __except(EXCEPTION_EXECUTE_HANDLER) { \ - Ext2RaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \ - } \ -} - -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; - } - - __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))) { - __leave; - } - - if (Buffer == NULL && IrpContext != NULL) - Buffer = Ext2GetUserBuffer(IrpContext->Irp); - - - /* handle fast symlinks */ - if (S_ISLNK(Mcb->Inode.i_mode) && 0 == Mcb->Inode.i_blocks) { - - PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]); - if (!Buffer) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __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; - } - __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)) { - __leave; - } - - if (Chain == NULL) { - SafeZeroMemory((PCHAR)Buffer, Size); - Status = STATUS_SUCCESS; - __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; - } - } - } - - } __finally { - - if (Chain) { - Ext2DestroyExtentChain(Chain); - } - - Ext2DerefMcb(Mcb); - } - - if (NT_SUCCESS(Status)) { - if (BytesRead) - *BytesRead = Size; - } - - return Status; -} - -NTSTATUS -Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) -{ - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - PEXT2_VCB Vcb = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PFILE_OBJECT FileObject = NULL; - - PDEVICE_OBJECT DeviceObject = NULL; - - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - - 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; - - __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 (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) || - IsFileDeleted(Fcb->Mcb)) { - Status = STATUS_FILE_DELETED; - __leave; - } - - if (Length == 0) { - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; - __leave; - } - - if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && - ByteOffset.HighPart == -1) { - ByteOffset = FileObject->CurrentByteOffset; - } - - if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || - Length & (SECTOR_SIZE - 1))) { - Status = STATUS_INVALID_PARAMETER; - DbgBreak(); - __leave; - } - - if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { - ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); - Status = STATUS_PENDING; - DbgBreak(); - __leave; - } - - ReturnedLength = Length; - - if (PagingIo) { - - if (!ExAcquireResourceSharedLite( - &Fcb->PagingIoResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { - Status = STATUS_PENDING; - __leave; - } - PagingIoResourceAcquired = TRUE; - - } else { - - if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject) { - - if (!ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { - Status = STATUS_PENDING; - __leave; - } - MainResourceAcquired = TRUE; - - CcFlushCache(&Fcb->SectionObject, - &ByteOffset, - Length, - &Irp->IoStatus ); - if (!NT_SUCCESS(Irp->IoStatus.Status)) - __leave; - ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); - - if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { - ExReleaseResourceLite(&(Fcb->PagingIoResource)); - } - CcPurgeCacheSection( &Fcb->SectionObject, - NULL, - 0, - FALSE ); - - ExConvertExclusiveToShared(&Fcb->MainResource); - - } else { - - if (!ExAcquireResourceSharedLite( - &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { - Status = STATUS_PENDING; - __leave; - } - MainResourceAcquired = TRUE; - } - - if (!FsRtlCheckLockForReadAccess( - &Fcb->FileLockAnchor, - Irp )) { - Status = STATUS_FILE_LOCK_CONFLICT; - __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; - __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; - __leave; - } - - // - // Set the flag indicating if Fast I/O is possible - // - - Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); - } - - if (!Nocache) { - - if (IsDirectory(Fcb)) { - __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(); - __leave; - } - - if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength, - Ext2CanIWait(), Buffer, &Irp->IoStatus)) { - - if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset, - ReturnedLength, TRUE, - Buffer, &Irp->IoStatus)) { - Status = STATUS_PENDING; - DbgBreak(); - __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; - __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)) { - __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)) { - __leave; - } - - /* pended by low level device */ - if (Status == STATUS_PENDING) { - IrpContext->Irp = Irp = NULL; - __leave; - } - - Irp = IrpContext->Irp; - ASSERT(Irp); - Status = Irp->IoStatus.Status; - - if (!NT_SUCCESS(Status)) { - Ext2NormalizeAndRaiseStatus(IrpContext, Status); - } - } - - Irp->IoStatus.Information = ReturnedLength; - - } __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); - } - } - } - - 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; - - __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; - - } __finally { - - if (!IrpContext->ExceptionInProgress) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - 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))); - - __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; - __leave; - } - - Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; - if (Vcb->Identifier.Type != EXT2VCB || - Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { - Status = STATUS_INVALID_DEVICE_REQUEST; - bCompleteRequest = TRUE; - - __leave; - } - - FileObject = IrpContext->FileObject; - - if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && - Vcb->LockFile != FileObject ) { - Status = STATUS_ACCESS_DENIED; - __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; - __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; - } - } - - } __finally { - if (bCompleteRequest) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - return Status; -} +/* + * 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 = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_FCBVCB FcbOrVcb = NULL; + PFILE_OBJECT FileObject = NULL; + + PDEVICE_OBJECT DeviceObject = NULL; + + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + + ULONG Length; + LARGE_INTEGER ByteOffset; + + BOOLEAN PagingIo; + BOOLEAN Nocache; + BOOLEAN SynchronousIo; + BOOLEAN MainResourceAcquired = FALSE; + + PUCHAR Buffer = NULL; + EXT2_EXTENT BlockArray; + + __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; + __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; + __leave; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + __leave; + } + + if (ByteOffset.QuadPart >= + Vcb->PartitionInformation.PartitionLength.QuadPart ) { + Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + __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; + __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; + __leave; + } + + if (!CcCopyRead( + Vcb->Volume, + &ByteOffset, + Length, + Ext2CanIWait(), + Buffer, + &Irp->IoStatus )) { + Status = STATUS_PENDING; + __leave; + } + + Status = Irp->IoStatus.Status; + } + + } else { + + Length &= ~((ULONG)SECTOR_SIZE - 1); + Status = Ext2LockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess ); + + if (!NT_SUCCESS(Status)) { + __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) { + __leave; + } + } + + } __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); + } + } + } + + return Status; +} + + +#define SafeZeroMemory(AT,BYTE_COUNT) { \ + __try { \ + if (AT) \ + RtlZeroMemory((AT), (BYTE_COUNT)); \ + } __except(EXCEPTION_EXECUTE_HANDLER) { \ + Ext2RaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \ + } \ +} + +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; + } + + __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))) { + __leave; + } + + if (Buffer == NULL && IrpContext != NULL) + Buffer = Ext2GetUserBuffer(IrpContext->Irp); + + + /* handle fast symlinks */ + if (S_ISLNK(Mcb->Inode.i_mode) && 0 == Mcb->Inode.i_blocks) { + + PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]); + if (!Buffer) { + Status = STATUS_INSUFFICIENT_RESOURCES; + __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; + } + __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)) { + __leave; + } + + if (Chain == NULL) { + SafeZeroMemory((PCHAR)Buffer, Size); + Status = STATUS_SUCCESS; + __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; + } + } + } + + } __finally { + + if (Chain) { + Ext2DestroyExtentChain(Chain); + } + + Ext2DerefMcb(Mcb); + } + + if (NT_SUCCESS(Status)) { + if (BytesRead) + *BytesRead = Size; + } + + return Status; +} + +NTSTATUS +Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PFILE_OBJECT FileObject = NULL; + + PDEVICE_OBJECT DeviceObject = NULL; + + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + + 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; + + __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 (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) || + IsFileDeleted(Fcb->Mcb)) { + Status = STATUS_FILE_DELETED; + __leave; + } + + if (Length == 0) { + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + __leave; + } + + if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && + ByteOffset.HighPart == -1) { + ByteOffset = FileObject->CurrentByteOffset; + } + + if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || + Length & (SECTOR_SIZE - 1))) { + Status = STATUS_INVALID_PARAMETER; + DbgBreak(); + __leave; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + DbgBreak(); + __leave; + } + + ReturnedLength = Length; + + if (PagingIo) { + + if (!ExAcquireResourceSharedLite( + &Fcb->PagingIoResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + __leave; + } + PagingIoResourceAcquired = TRUE; + + } else { + + if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject) { + + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + __leave; + } + MainResourceAcquired = TRUE; + + CcFlushCache(&Fcb->SectionObject, + &ByteOffset, + Length, + &Irp->IoStatus ); + if (!NT_SUCCESS(Irp->IoStatus.Status)) + __leave; + ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); + + if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { + ExReleaseResourceLite(&(Fcb->PagingIoResource)); + } + CcPurgeCacheSection( &Fcb->SectionObject, + NULL, + 0, + FALSE ); + + ExConvertExclusiveToShared(&Fcb->MainResource); + + } else { + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + __leave; + } + MainResourceAcquired = TRUE; + } + + if (!FsRtlCheckLockForReadAccess( + &Fcb->FileLockAnchor, + Irp )) { + Status = STATUS_FILE_LOCK_CONFLICT; + __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; + __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; + __leave; + } + + // + // Set the flag indicating if Fast I/O is possible + // + + Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); + } + + if (!Nocache) { + + if (IsDirectory(Fcb)) { + __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(); + __leave; + } + + if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength, + Ext2CanIWait(), Buffer, &Irp->IoStatus)) { + + if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset, + ReturnedLength, TRUE, + Buffer, &Irp->IoStatus)) { + Status = STATUS_PENDING; + DbgBreak(); + __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; + __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)) { + __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)) { + __leave; + } + + /* pended by low level device */ + if (Status == STATUS_PENDING) { + IrpContext->Irp = Irp = NULL; + __leave; + } + + Irp = IrpContext->Irp; + ASSERT(Irp); + Status = Irp->IoStatus.Status; + + if (!NT_SUCCESS(Status)) { + Ext2NormalizeAndRaiseStatus(IrpContext, Status); + } + } + + Irp->IoStatus.Information = ReturnedLength; + + } __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); + } + } + } + + 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; + + __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; + + } __finally { + + if (!IrpContext->ExceptionInProgress) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + 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))); + + __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; + __leave; + } + + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + if (Vcb->Identifier.Type != EXT2VCB || + Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { + Status = STATUS_INVALID_DEVICE_REQUEST; + bCompleteRequest = TRUE; + + __leave; + } + + FileObject = IrpContext->FileObject; + + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && + Vcb->LockFile != FileObject ) { + Status = STATUS_ACCESS_DENIED; + __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; + __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; + } + } + + } __finally { + if (bCompleteRequest) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + return Status; +} diff --git a/Ext4Fsd/shutdown.c b/Ext4Fsd/shutdown.c index 6b5ba46..3a34eb1 100644 --- a/Ext4Fsd/shutdown.c +++ b/Ext4Fsd/shutdown.c @@ -1,118 +1,118 @@ -/* - * 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; - - __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; - __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); - */ - - } __finally { - - if (GlobalResourceAcquired) { - ExReleaseResourceLite(&Ext2Global->Resource); - } - - if (!IrpContext->ExceptionInProgress) { - if (Status == STATUS_PENDING) { - Ext2QueueRequest(IrpContext); - } else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; +/* + * 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; + + __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; + __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); + */ + + } __finally { + + if (GlobalResourceAcquired) { + ExReleaseResourceLite(&Ext2Global->Resource); + } + + if (!IrpContext->ExceptionInProgress) { + if (Status == STATUS_PENDING) { + Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; } \ No newline at end of file diff --git a/Ext4Fsd/volinfo.c b/Ext4Fsd/volinfo.c index 483d9c9..0eaf362 100644 --- a/Ext4Fsd/volinfo.c +++ b/Ext4Fsd/volinfo.c @@ -1,409 +1,409 @@ -/* - * 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; - PEXT2_VCB Vcb = NULL; - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - PVOID Buffer; - ULONG Length; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - FS_INFORMATION_CLASS FsInformationClass; - BOOLEAN VcbResourceAcquired = FALSE; - - __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; - __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; - __leave; - } - - if (!ExAcquireResourceSharedLite( - &Vcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) - )) { - - Status = STATUS_PENDING; - __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; - __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; - __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; - __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; - __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; - __leave; - } - - FsAttrInfo = - (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer; - FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS | - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | - FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES; - 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; - __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; - __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; - } - - } __finally { - - if (VcbResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - - if (!IrpContext->ExceptionInProgress) { - if (Status == STATUS_PENDING) { - Ext2QueueRequest(IrpContext); - } else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; -} - -NTSTATUS -Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb = NULL; - PIRP Irp; - PIO_STACK_LOCATION IoStackLocation; - FS_INFORMATION_CLASS FsInformationClass; - BOOLEAN VcbResourceAcquired = FALSE; - - __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; - __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; - __leave; - } - - if (!ExAcquireResourceExclusiveLite( - &Vcb->MainResource, TRUE)) { - Status = STATUS_PENDING; - __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; - __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; - } - - } __finally { - - if (VcbResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - - if (!IrpContext->ExceptionInProgress) { - if (Status == STATUS_PENDING) { - Ext2QueueRequest(IrpContext); - } else { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - } - - return Status; +/* + * 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; + PEXT2_VCB Vcb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + PVOID Buffer; + ULONG Length; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + FS_INFORMATION_CLASS FsInformationClass; + BOOLEAN VcbResourceAcquired = FALSE; + + __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; + __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; + __leave; + } + + if (!ExAcquireResourceSharedLite( + &Vcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) + )) { + + Status = STATUS_PENDING; + __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; + __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; + __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; + __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; + __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; + __leave; + } + + FsAttrInfo = + (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer; + FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS | + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | + FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES; + 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; + __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; + __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; + } + + } __finally { + + if (VcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + } + + if (!IrpContext->ExceptionInProgress) { + if (Status == STATUS_PENDING) { + Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; +} + +NTSTATUS +Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PEXT2_VCB Vcb = NULL; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + FS_INFORMATION_CLASS FsInformationClass; + BOOLEAN VcbResourceAcquired = FALSE; + + __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; + __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; + __leave; + } + + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE)) { + Status = STATUS_PENDING; + __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; + __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; + } + + } __finally { + + if (VcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->MainResource); + } + + if (!IrpContext->ExceptionInProgress) { + if (Status == STATUS_PENDING) { + Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } + + return Status; } \ No newline at end of file diff --git a/Ext4Fsd/write.c b/Ext4Fsd/write.c index f2528d4..5d9b108 100644 --- a/Ext4Fsd/write.c +++ b/Ext4Fsd/write.c @@ -1,1423 +1,1423 @@ -/* - * 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 -Ext2FloppyFlush(IN PVOID Parameter); - -VOID -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 -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); - ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); - ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); - ExReleaseResourceLite(&Fcb->PagingIoResource); - - CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL); - ExReleaseResourceLite(&Fcb->MainResource); - - ObDereferenceObject(FileObject); - } - - if (Vcb) { - ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); - - ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); - ExReleaseResourceLite(&Vcb->PagingIoResource); - - Ext2FlushVcb(Vcb); - ExReleaseResourceLite(&Vcb->MainResource); - } - - IoSetTopLevelIrp(NULL); - Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC); -} - -VOID -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; - BOOLEAN rc = TRUE; - - 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) */ - __try { - rc = CcZeroData(FileObject, Start, End, Ext2CanIWait()); - } __except (EXCEPTION_EXECUTE_HANDLER) { - DbgBreak(); - } - - return rc; -} - -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 = NULL; - PEXT2_CCB Ccb = NULL; - PEXT2_FCBVCB FcbOrVcb = NULL; - PFILE_OBJECT FileObject = NULL; - - PDEVICE_OBJECT DeviceObject = NULL; - - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - - 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; - - __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; - __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; - __leave; - } - - if (Nocache && - (ByteOffset.LowPart & (SECTOR_SIZE - 1) || - Length & (SECTOR_SIZE - 1))) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { - ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); - Status = STATUS_PENDING; - __leave; - } - - if (ByteOffset.QuadPart >= - Vcb->PartitionInformation.PartitionLength.QuadPart ) { - Irp->IoStatus.Information = 0; - Status = STATUS_END_OF_FILE; - __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; - - __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; - __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; - __leave; - } - - if (!CcCopyWrite( Vcb->Volume, - (PLARGE_INTEGER)(&ByteOffset), - Length, - TRUE, - Buffer )) { - Status = STATUS_PENDING; - __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)) { - __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; - __leave; - } - - Extent->Irp = NULL; - Extent->Lba = DirtyStart; - 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 = RemainLength - Extent->Length; -/* - RemainLength = (DirtyStart + RemainLength) - - (DirtyLba + DirtyLength); -*/ - ASSERT(RemainLength <= (LONGLONG)Length); - ASSERT(Extent->Length <= Length); - } - - ASSERT(Extent->Length >= SECTOR_SIZE); - DirtyLba = DirtyStart + Extent->Length; - - 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) { - __leave; - } - - } else { - - Irp->IoStatus.Information = Length; - Status = STATUS_SUCCESS; - __leave; - } - - } else { - - Length &= ~((ULONG)SECTOR_SIZE - 1); - - Status = Ext2LockUserBuffer( - IrpContext->Irp, - Length, - IoWriteAccess ); - - if (!NT_SUCCESS(Status)) { - __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) { - __leave; - } - } - - } __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); - } - } - - 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; - - __try { - - if (BytesWritten) { - *BytesWritten = 0; - } - - Status = Ext2BuildExtents ( - IrpContext, - Vcb, - Mcb, - Offset, - Size, - S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE, - &Chain - ); - - if (!NT_SUCCESS(Status)) { - __leave; - } - - if (Chain == NULL) { - Status = STATUS_SUCCESS; - __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) - )) { - __leave; - } - } - - if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { - - DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n")); - Ext2StartFloppyFlushDpc(Vcb, NULL, NULL); - } - - Status = STATUS_SUCCESS; - } - - } __finally { - - if (Chain) { - Ext2DestroyExtentChain(Chain); - } - - if (NT_SUCCESS(Status) && BytesWritten) { - *BytesWritten = Size; - } - } - - return Status; -} - - -NTSTATUS -Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) -{ - PEXT2_VCB Vcb = NULL; - PEXT2_FCB Fcb = NULL; - PEXT2_CCB Ccb = NULL; - PFILE_OBJECT FileObject = NULL; - - PDEVICE_OBJECT DeviceObject = NULL; - - PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation = NULL; - PUCHAR Buffer = NULL; - - 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; - BOOLEAN UpdateFileValidSize = FALSE; - BOOLEAN FileSizesChanged = FALSE; - BOOLEAN rc; - - - __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) || IsInodeSymLink(Fcb->Inode) ) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __leave; - } - - if (IsFileDeleted(Fcb->Mcb) || - (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) { - Status = STATUS_FILE_DELETED; - __leave; - } - - if (Length == 0) { - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; - __leave; - } - - if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && - ByteOffset.HighPart == -1) { - ByteOffset = FileObject->CurrentByteOffset; - } else if (IsWritingToEof(ByteOffset)) { - ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; - } - - if (Nocache && !PagingIo && - ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) || - (Length & (SECTOR_SIZE - 1))) ) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { - ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); - Status = STATUS_PENDING; - __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; - __leave; - } - } - } - - if (IsDirectory(Fcb) && !PagingIo) { - Status = STATUS_INVALID_DEVICE_REQUEST; - __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; - __leave; - } - PagingIoResourceAcquired = TRUE; - - if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { - - if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { - - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - __leave; - - } else { - - ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); - if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) - Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); - } - - } else { - - ReturnedLength = Length; - } - - } else { - - if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) { - Status = STATUS_ACCESS_DENIED; - __leave; - } - - if (IsDirectory(Fcb)) { - __leave; - } - - if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) { - Status = STATUS_PENDING; - __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; - __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; - __leave; - } - - if (Ccb != NULL) { - - Status = FsRtlCheckOplock( &Fcb->Oplock, - Irp, - IrpContext, - Ext2OplockComplete, - Ext2LockIrp ); - - if (Status != STATUS_SUCCESS) { - OpPostIrp = TRUE; - __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; - __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; - } - __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; - __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(); - __leave; - } - } - - if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) { - if (Ext2CanIWait() || - !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) { - Status = STATUS_PENDING; - DbgBreak(); - __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 > 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(); - __leave; - } - } - } - - Status = Ext2LockUserBuffer( - IrpContext->Irp, - Length, - IoReadAccess ); - - if (!NT_SUCCESS(Status)) { - __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) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { - - if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { - - FileSizesChanged = TRUE; - - if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { - if (!PagingIo) - 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 (!PagingIo && 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 ); - } - - } __finally { - - /* - * in case we got excpetions, we need revert MajorFunction - * back to IRP_MJ_WRITE. The reason we do this, is 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); - } - } - } - - 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; - - __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; - - } __finally { - - if (!IrpContext->ExceptionInProgress) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - 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))); - - __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; - __leave; - } - FileObject = IrpContext->FileObject; - - Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; - - if (Vcb->Identifier.Type != EXT2VCB || - Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { - Status = STATUS_INVALID_PARAMETER; - __leave; - } - - if (IsVcbReadOnly(Vcb)) { - Status = STATUS_MEDIA_WRITE_PROTECTED; - __leave; - } - - if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && - Vcb->LockFile != FileObject ) { - Status = STATUS_ACCESS_DENIED; - __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; - __leave; - } - - Status = Ext2WriteFile(IrpContext); - if (!NT_SUCCESS(Status)) { - DbgBreak(); - } - - bCompleteRequest = FALSE; - } else { - Status = STATUS_INVALID_PARAMETER; - } - } - - } __finally { - - if (bCompleteRequest) { - Ext2CompleteIrpContext(IrpContext, Status); - } - } - - return Status; -} +/* + * 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 +Ext2FloppyFlush(IN PVOID Parameter); + +VOID +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 +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); + ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); + ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Fcb->PagingIoResource); + + CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL); + ExReleaseResourceLite(&Fcb->MainResource); + + ObDereferenceObject(FileObject); + } + + if (Vcb) { + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + Ext2FlushVcb(Vcb); + ExReleaseResourceLite(&Vcb->MainResource); + } + + IoSetTopLevelIrp(NULL); + Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC); +} + +VOID +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; + BOOLEAN rc = TRUE; + + 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) */ + __try { + rc = CcZeroData(FileObject, Start, End, Ext2CanIWait()); + } __except (EXCEPTION_EXECUTE_HANDLER) { + DbgBreak(); + } + + return rc; +} + +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 = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_FCBVCB FcbOrVcb = NULL; + PFILE_OBJECT FileObject = NULL; + + PDEVICE_OBJECT DeviceObject = NULL; + + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + + 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; + + __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; + __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; + __leave; + } + + if (Nocache && + (ByteOffset.LowPart & (SECTOR_SIZE - 1) || + Length & (SECTOR_SIZE - 1))) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + __leave; + } + + if (ByteOffset.QuadPart >= + Vcb->PartitionInformation.PartitionLength.QuadPart ) { + Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + __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; + + __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; + __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; + __leave; + } + + if (!CcCopyWrite( Vcb->Volume, + (PLARGE_INTEGER)(&ByteOffset), + Length, + TRUE, + Buffer )) { + Status = STATUS_PENDING; + __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)) { + __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; + __leave; + } + + Extent->Irp = NULL; + Extent->Lba = DirtyStart; + 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 = RemainLength - Extent->Length; +/* + RemainLength = (DirtyStart + RemainLength) - + (DirtyLba + DirtyLength); +*/ + ASSERT(RemainLength <= (LONGLONG)Length); + ASSERT(Extent->Length <= Length); + } + + ASSERT(Extent->Length >= SECTOR_SIZE); + DirtyLba = DirtyStart + Extent->Length; + + 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) { + __leave; + } + + } else { + + Irp->IoStatus.Information = Length; + Status = STATUS_SUCCESS; + __leave; + } + + } else { + + Length &= ~((ULONG)SECTOR_SIZE - 1); + + Status = Ext2LockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess ); + + if (!NT_SUCCESS(Status)) { + __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) { + __leave; + } + } + + } __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); + } + } + + 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; + + __try { + + if (BytesWritten) { + *BytesWritten = 0; + } + + Status = Ext2BuildExtents ( + IrpContext, + Vcb, + Mcb, + Offset, + Size, + S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE, + &Chain + ); + + if (!NT_SUCCESS(Status)) { + __leave; + } + + if (Chain == NULL) { + Status = STATUS_SUCCESS; + __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) + )) { + __leave; + } + } + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { + + DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n")); + Ext2StartFloppyFlushDpc(Vcb, NULL, NULL); + } + + Status = STATUS_SUCCESS; + } + + } __finally { + + if (Chain) { + Ext2DestroyExtentChain(Chain); + } + + if (NT_SUCCESS(Status) && BytesWritten) { + *BytesWritten = Size; + } + } + + return Status; +} + + +NTSTATUS +Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) +{ + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PFILE_OBJECT FileObject = NULL; + + PDEVICE_OBJECT DeviceObject = NULL; + + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + PUCHAR Buffer = NULL; + + 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; + BOOLEAN UpdateFileValidSize = FALSE; + BOOLEAN FileSizesChanged = FALSE; + BOOLEAN rc; + + + __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) || IsInodeSymLink(Fcb->Inode) ) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __leave; + } + + if (IsFileDeleted(Fcb->Mcb) || + (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) { + Status = STATUS_FILE_DELETED; + __leave; + } + + if (Length == 0) { + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + __leave; + } + + if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && + ByteOffset.HighPart == -1) { + ByteOffset = FileObject->CurrentByteOffset; + } else if (IsWritingToEof(ByteOffset)) { + ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; + } + + if (Nocache && !PagingIo && + ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) || + (Length & (SECTOR_SIZE - 1))) ) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + __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; + __leave; + } + } + } + + if (IsDirectory(Fcb) && !PagingIo) { + Status = STATUS_INVALID_DEVICE_REQUEST; + __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; + __leave; + } + PagingIoResourceAcquired = TRUE; + + if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { + + if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { + + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + __leave; + + } else { + + ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) + Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); + } + + } else { + + ReturnedLength = Length; + } + + } else { + + if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) { + Status = STATUS_ACCESS_DENIED; + __leave; + } + + if (IsDirectory(Fcb)) { + __leave; + } + + if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) { + Status = STATUS_PENDING; + __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; + __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; + __leave; + } + + if (Ccb != NULL) { + + Status = FsRtlCheckOplock( &Fcb->Oplock, + Irp, + IrpContext, + Ext2OplockComplete, + Ext2LockIrp ); + + if (Status != STATUS_SUCCESS) { + OpPostIrp = TRUE; + __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; + __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; + } + __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; + __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(); + __leave; + } + } + + if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) { + if (Ext2CanIWait() || + !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) { + Status = STATUS_PENDING; + DbgBreak(); + __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 > 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(); + __leave; + } + } + } + + Status = Ext2LockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess ); + + if (!NT_SUCCESS(Status)) { + __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) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { + + if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { + + FileSizesChanged = TRUE; + + if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { + if (!PagingIo) + 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 (!PagingIo && 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 ); + } + + } __finally { + + /* + * in case we got excpetions, we need revert MajorFunction + * back to IRP_MJ_WRITE. The reason we do this, is 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); + } + } + } + + 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; + + __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; + + } __finally { + + if (!IrpContext->ExceptionInProgress) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + 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))); + + __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; + __leave; + } + FileObject = IrpContext->FileObject; + + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + + if (Vcb->Identifier.Type != EXT2VCB || + Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { + Status = STATUS_INVALID_PARAMETER; + __leave; + } + + if (IsVcbReadOnly(Vcb)) { + Status = STATUS_MEDIA_WRITE_PROTECTED; + __leave; + } + + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && + Vcb->LockFile != FileObject ) { + Status = STATUS_ACCESS_DENIED; + __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; + __leave; + } + + Status = Ext2WriteFile(IrpContext); + if (!NT_SUCCESS(Status)) { + DbgBreak(); + } + + bCompleteRequest = FALSE; + } else { + Status = STATUS_INVALID_PARAMETER; + } + } + + } __finally { + + if (bCompleteRequest) { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + return Status; +}