Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784/* * COPYRIGHT: See COPYRIGHT.TXT * PROJECT: Ext2 File System Driver for WinNT/2K/XP * FILE: block.c * PROGRAMMER: Matt Wu <mattwu@163.com> * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
#ifdef __REACTOS__NTSTATUS NTAPI#elseNTSTATUS#endifExt2ReadWriteBlockSyncCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
#ifdef __REACTOS__NTSTATUS NTAPI#elseNTSTATUS#endifExt2ReadWriteBlockAsyncCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
#ifdef __REACTOS__NTSTATUS NTAPI#elseNTSTATUS#endifExt2MediaEjectControlCompletion ( 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 ***************************************************************/
PMDLExt2CreateMdl ( 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 { _SEH2_TRY { if (MmIsNonPagedSystemAddressValid(Buffer)) { MmBuildMdlForNonPagedPool(Mdl); } else { MmProbeAndLockPages(Mdl, KernelMode, op); } Status = STATUS_SUCCESS; } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl (Mdl); Mdl = NULL; DbgBreak(); Status = STATUS_INVALID_USER_BUFFER; } _SEH2_END; } return Mdl;}
VOIDExt2DestroyMdl (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; }}
NTSTATUSExt2LockUserBuffer (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; }
_SEH2_TRY {
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); Status = STATUS_SUCCESS;
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
DbgBreak(); IoFreeMdl(Irp->MdlAddress); Irp->MdlAddress = NULL; Status = STATUS_INVALID_USER_BUFFER; } _SEH2_END;
return Status;}
PVOIDExt2GetUserBuffer (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; }}
#ifdef __REACTOS__NTSTATUS NTAPI#elseNTSTATUS#endifExt2ReadWriteBlockSyncCompletionRoutine ( 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;}
#ifdef __REACTOS__NTSTATUS NTAPI#elseNTSTATUS#endifExt2ReadWriteBlockAsyncCompletionRoutine ( 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;}
NTSTATUSExt2ReadWriteBlocks( 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);
_SEH2_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; _SEH2_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; _SEH2_LEAVE; }
Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer + Extent->Offset, Extent->Length, FALSE, FALSE, Irp );
if (!Mdl) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_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; }
} _SEH2_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; } } } } _SEH2_END;
return Status;}
NTSTATUSExt2ReadSync( 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);
_SEH2_TRY {
Event = Ext2AllocatePool(NonPagedPool, sizeof(KEVENT), 'EK2E');
if (NULL == Event) { DEBUG(DL_ERR, ( "Ex2ReadSync: failed to allocate Event.\n")); _SEH2_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; _SEH2_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; }
} _SEH2_FINALLY {
if (Event) { Ext2FreePool(Event, 'EK2E'); DEC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); } } _SEH2_END;
return Status;}
NTSTATUSExt2ReadDisk( 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;}
NTSTATUSExt2DiskIoControl ( 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;}
#ifdef __REACTOS__NTSTATUS NTAPI#elseNTSTATUS#endifExt2MediaEjectControlCompletion ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Contxt){ PKEVENT Event = (PKEVENT)Contxt;
KeSetEvent( Event, 0, FALSE );
UNREFERENCED_PARAMETER( DeviceObject );
return STATUS_SUCCESS;}
VOIDExt2MediaEjectControl ( 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 ); } }}
NTSTATUSExt2DiskShutDown(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;}