Author: fireball
Date: Sun Jan 18 04:23:15 2009
New Revision: 38881
URL:
http://svn.reactos.org/svn/reactos?rev=38881&view=rev
Log:
- SVN maintenance.
Modified:
trunk/reactos/ntoskrnl/fsrtl/fastio.c (contents, props changed)
Modified: trunk/reactos/ntoskrnl/fsrtl/fastio.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/fastio.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/fastio.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/fastio.c [iso-8859-1] Sun Jan 18 04:23:15 2009
@@ -1,1426 +1,1426 @@
-/*
- * PROJECT: ReactOS Kernel
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: ntoskrnl/fsrtl/fastio.c
- * PURPOSE: Provides Fast I/O entrypoints to the Cache Manager
- * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-FsRtlIncrementCcFastReadResourceMiss(VOID)
-{
- CcFastReadResourceMiss++;
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-FsRtlIncrementCcFastReadNotPossible(VOID)
-{
- CcFastReadNotPossible++;
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-FsRtlIncrementCcFastReadWait(VOID)
-{
- CcFastReadWait++;
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-FsRtlIncrementCcFastReadNoWait(VOID)
-{
- CcFastReadNoWait++;
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlCopyRead(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)
-{
-
- PFSRTL_COMMON_FCB_HEADER FcbHeader;
- LARGE_INTEGER Offset;
- PFAST_IO_DISPATCH FastIoDispatch;
- PDEVICE_OBJECT Device;
- BOOLEAN Result = TRUE;
- ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset,Length);
-
- PAGED_CODE();
- ASSERT(FileObject);
- ASSERT(FileObject->FsContext);
-
- /* No actual read */
- if (!Length)
- {
- /* Return success */
- IoStatus->Status = STATUS_SUCCESS;
- IoStatus->Information = 0;
- return TRUE;
- }
-
- if (MAXLONGLONG < (LONGLONG) FileOffset->QuadPart + Length) {
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- IoStatus->Information = 0;
- return FALSE;
- }
-
- /* Get the offset and FCB header */
- Offset.QuadPart = FileOffset->QuadPart + Length;
- FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
-
-
- if (Wait) {
- /* Use a Resource Acquire */
- FsRtlEnterFileSystem();
- CcFastReadWait++;
- ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- } else {
- /* Acquire the resource without blocking */
- /* Return false and the I/O manager will retry using the standard IRP method. */
- /* Use a Resource Acquire */
- FsRtlEnterFileSystem();
- if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE)) {
- FsRtlExitFileSystem();
- FsRtlIncrementCcFastReadResourceMiss();
- return FALSE;
- }
- }
-
-
- /* Check if this is a fast I/O cached file */
- if (!(FileObject->PrivateCacheMap) ||
- (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) {
- /* It's not, so fail */
- Result = FALSE;
- goto Cleanup;
- }
-
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
-
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
-
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
-
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffset,
- Length,
- TRUE,
- LockKey,
- TRUE,
- IoStatus,
- Device))
- {
- /* It's not, fail */
- Result = FALSE;
- goto Cleanup;
- }
- }
-
- /* Check if we read too much */
- if (Offset.QuadPart > FcbHeader->FileSize.QuadPart){
- /* We did, check if the file offset is past the end */
- if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart){
- /* Set end of file */
- IoStatus->Status = STATUS_END_OF_FILE;
- IoStatus->Information = 0;
- goto Cleanup;
- }
-
- /* Otherwise, just normalize the length */
- Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
- }
-
- /* Set this as top-level IRP */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
-
- _SEH2_TRY
- {
- /* Make sure the IO and file size is below 4GB */
- if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) {
-
- /* Call the cache controller */
- CcFastCopyRead (FileObject,FileOffset->LowPart,Length,PageCount,Buffer,IoStatus);
- /* File was accessed */
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
- if (IoStatus->Status != STATUS_END_OF_FILE) {
- ASSERT(( FcbHeader->FileSize.QuadPart) >= (FileOffset->QuadPart +
IoStatus->Information));
- }
-
- } else {
-
- /* Call the cache controller */
- Result = CcCopyRead(FileObject, FileOffset, Length, Wait,Buffer, IoStatus);
- /* File was accessed */
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
- if (Result == TRUE) {
- ASSERT( (IoStatus->Status == STATUS_END_OF_FILE) ||
- ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <=
FcbHeader->FileSize.QuadPart)
- );
- }
- }
-
- /* Update the current file offset */
- if (Result == TRUE) {
- FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
- }
- }
- _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
- } _SEH2_END;
-
- PsGetCurrentThread()->TopLevelIrp = 0;
-
- /* Return to caller */
-Cleanup:
-
- ExReleaseResourceLite(FcbHeader->Resource);
- FsRtlExitFileSystem();
-
- if (Result == FALSE) {
- CcFastReadNotPossible += 1;
- }
-
- return Result;
-
-}
-
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- OUT PVOID Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
-
- BOOLEAN Result = TRUE;
- PFAST_IO_DISPATCH FastIoDispatch;
- PDEVICE_OBJECT Device;
- PFSRTL_COMMON_FCB_HEADER FcbHeader;
-
- /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
- BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) &&
(FileOffset->LowPart == 0xffffffff));
- BOOLEAN ResourceAquiredShared = FALSE;
-
- BOOLEAN b_4GB = FALSE;
-
- BOOLEAN FileSizeModified = FALSE;
- LARGE_INTEGER OldFileSize;
- LARGE_INTEGER OldValidDataLength;
-
- LARGE_INTEGER NewSize;
- LARGE_INTEGER Offset;
-
- PAGED_CODE();
-
- ASSERT(FileObject);
- ASSERT(FileObject->FsContext);
-
- /* Initialize some of the vars and pointers */
- NewSize.QuadPart = 0;
- Offset.QuadPart = FileOffset->QuadPart + Length;
- FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
-
- /* Nagar p.544 -- Check with Cc if we can write and check if the IO > 64kB (WDK
macro) */
- if ( (CcCanIWrite(FileObject, Length,Wait, FALSE) == FALSE) ||
- (CcCopyWriteWontFlush(FileObject,FileOffset,Length) == FALSE) ||
- ((FileObject->Flags & FO_WRITE_THROUGH )== TRUE)
- )
- {
- return FALSE;
- }
-
- /* No actual read */
- if (!Length)
- {
- IoStatus->Status = STATUS_SUCCESS;
- IoStatus->Information = Length;
- return TRUE;
- }
-
- FsRtlEnterFileSystem();
-
- /* Nagar p.544/545 -- The CcFastCopyWrite doesn't deal with filesize beyond
4GB*/
- if (Wait && (FcbHeader->AllocationSize.HighPart == 0))
- {
- /* If the file offset is not past the file size, then we can acquire the lock
shared */
- if ((FileOffsetAppend == FALSE) && (Offset.LowPart <=
FcbHeader->ValidDataLength.LowPart)){
- ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
- ResourceAquiredShared = TRUE;
- } else {
- ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
- }
-
- /* Nagar p.544/545 -- If we append, use the file size as offset. Also, check that
we aren't crossing the 4GB boundary */
- if ((FileOffsetAppend == TRUE)) {
- Offset.LowPart = FcbHeader->FileSize.LowPart;
- NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
- b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart);
-
- } else {
- Offset.LowPart = FileOffset->LowPart;
- NewSize.LowPart = FileOffset->LowPart + Length;
- b_4GB = ((NewSize.LowPart < FileOffset->LowPart) ||
(FileOffset->HighPart != 0));
- }
-
- /* Nagar p.544/545
- Make sure that caching is initated.
- That fast are allowed for this file stream.
- That we are not extending past the allocated size
- That we are not creating a hole bigger than 8k
- That we are not crossing the 4GB boundary
- */
- if ( (FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
- (Offset.LowPart < (FcbHeader->ValidDataLength.LowPart + 0x2000) )
&&
- !b_4GB
- )
- {
- /* If we are extending past the file size, we need to release the lock and
acquire it
- exclusively, because we are going to need to update the FcbHeader */
- if (ResourceAquiredShared && (NewSize.LowPart >
(FcbHeader->ValidDataLength.LowPart + 0x2000))) {
- /* Then we need to acquire the resource exclusive */
- ExReleaseResourceLite(FcbHeader->Resource);
- ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
- if (FileOffsetAppend == TRUE) {
- Offset.LowPart = FcbHeader->FileSize.LowPart; // ??
- NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
- /* Make sure we don't cross the 4GB boundary */
- b_4GB = (NewSize.LowPart < Offset.LowPart);
- }
-
- /* Recheck some of the conditions since we let the lock go */
- if ( (FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
- (FcbHeader->AllocationSize.HighPart == 0) &&
- !b_4GB
- )
- {
- } else
- {
- goto FailAndCleanup;
- }
- }
-
- }else
- {
- goto FailAndCleanup;
- }
-
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
-
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
-
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
-
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
-
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffsetAppend?
&FcbHeader->FileSize:FileOffset,
- Length,
- TRUE,
- LockKey,
- FALSE,
- &FastIoCheckIfPossibleStatus,
- Device))
- {
- /* It's not, fail */
- goto FailAndCleanup;
- }
- }
-
- /* If we are going to extend the file then save the old file size
- in case the operation fails
- */
- if (NewSize.LowPart > FcbHeader->FileSize.LowPart) {
- FileSizeModified = TRUE;
- OldFileSize.LowPart = FcbHeader->FileSize.LowPart;
- OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart;
- FcbHeader->FileSize.LowPart = NewSize.LowPart;
- }
-
- /* Set this as top-level IRP */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
-
- _SEH2_TRY
- {
- if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) {
- LARGE_INTEGER OffsetVar;
- OffsetVar.LowPart = Offset.LowPart;
- OffsetVar.HighPart = 0;
- CcZeroData(FileObject,&FcbHeader->ValidDataLength,&OffsetVar,TRUE);
- }
-
- /* Call the cache manager */
- CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer);
- }
- _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
- } _SEH2_END;
-
- /* Remove ourselves at the top level component after the IO is done */
- PsGetCurrentThread()->TopLevelIrp = 0;
-
- /* Did the operation succeed ? */
- if (Result == TRUE) {
- /* Update the valid file size if necessary */
- if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart){
- FcbHeader->ValidDataLength.LowPart = NewSize.LowPart ;
- }
-
- /* Flag the file as modified */
- FileObject->Flags |= FO_FILE_MODIFIED;
-
- /* Update the strucutres if the file size changed */
- if (FileSizeModified) {
- ((SHARED_CACHE_MAP*)
FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.LowPart =
NewSize.LowPart;
- FileObject->Flags |= FO_FILE_SIZE_CHANGED;
- }
-
- /* Update the file object current file offset */
- FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart;
-
- } else {
-
- /* Result == FALSE if we get here. */
- if (FileSizeModified) {
- /* If the file size was modified then restore the old file size */
- if(FcbHeader->PagingIoResource != NULL) {
- // Nagar P.544 Restore the old file size if operation didn't succeed.
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource,TRUE);
- FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
- FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
- /* If there is no lock and do it without */
- FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
- FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
- }
- } else {
- }
- }
-
- goto Cleanup;
-
- } else {
-
- LARGE_INTEGER OldFileSize;
-
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
-
- // Nagar P.544
- /* Check if we need to acquire the resource exclusive */
- if ( (FileOffsetAppend == FALSE) &&
- ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
- )
- {
- /* Acquire the resource shared */
- if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) {
- goto LeaveCriticalAndFail;
- }
- ResourceAquiredShared =TRUE;
- } else {
- /* Acquire the resource exclusive */
- if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) {
- goto LeaveCriticalAndFail;
- }
- }
-
- /* Check if we are appending */
- if (FileOffsetAppend == TRUE) {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- } else {
- Offset.QuadPart = FileOffset->QuadPart;
- NewSize.QuadPart += FileOffset->QuadPart + Length;
- }
-
- /* Nagar p.544/545
- Make sure that caching is initated.
- That fast are allowed for this file stream.
- That we are not extending past the allocated size
- That we are not creating a hole bigger than 8k
- */
- if ( (FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- ((FcbHeader->ValidDataLength.QuadPart + 0x2000) > Offset.QuadPart) &&
- (MAXLONGLONG > (Offset.QuadPart + Length)) &&
- (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart)
- )
- {
- /* Check if we can keep the lock shared */
- if (ResourceAquiredShared && (NewSize.QuadPart >
FcbHeader->ValidDataLength.QuadPart) ) {
- ExReleaseResourceLite(FcbHeader->Resource);
- if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait))
- {
- goto LeaveCriticalAndFail;
- }
-
- /* Compute the offset and the new filesize */
- if (FileOffsetAppend) {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- }
-
- /* Recheck the above points since we released and reacquire the lock
*/
- if ( (FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
- )
- {
- /* Do nothing */
- } else {
- goto FailAndCleanup;
- }
- }
-
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
-
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
-
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
-
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
-
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffsetAppend?
&FcbHeader->FileSize:FileOffset,
- Length,
- TRUE,
- LockKey,
- FALSE,
- &FastIoCheckIfPossibleStatus,
- Device))
- {
- /* It's not, fail */
- goto FailAndCleanup;
- }
- }
-
-
- /* If we are going to modify the filesize, save the old fs in case the
operation fails */
- if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) {
- FileSizeModified = TRUE;
- OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
- OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
-
- /* If the high part of the filesize is going to change, grab the Paging IoResouce */
- if (NewSize.HighPart != FcbHeader->FileSize.HighPart &&
FcbHeader->PagingIoResource) {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- }
- }
-
- /* Nagar p.544 */
- /* Set ourselves as top component */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
- _SEH2_TRY
- {
- BOOLEAN CallCc = TRUE;
- /* Check if there is a gap between the end of the file and the offset
- If yes, then we have to zero the data
- */
- if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- if (!(Result =
CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,Wait))) {
- /* If this operation fails, then we have to exit
- We can jump outside the SEH, so I a using a variable to exit
- normally
- */
- CallCc = FALSE;
- }
- }
-
- /* Unless the CcZeroData failed, call the cache manager */
- if (CallCc) {
- Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer);
- }
- }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
- } _SEH2_END;
-
- /* Reset the top component */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
-
- /* Did the operation suceeded */
- if (Result) {
- /* Check if we need to update the filesize */
- if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart &&
FcbHeader->PagingIoResource) {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- }
- }
-
- /* Flag the file as modified */
- FileObject->Flags |= FO_FILE_MODIFIED;
- /* Check if the filesize has changed */
- if (FileSizeModified) {
- /* Update the file sizes */
- ((SHARED_CACHE_MAP*)
FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart =
NewSize.QuadPart;
- FileObject->Flags |= FO_FILE_SIZE_CHANGED;
- }
- /* Update the current FO byte offset */
- FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;
- }
- else
- {
- /* The operation did not succeed
- Reset the file size to what it should be
- */
- if (FileSizeModified) {
- if (FcbHeader->PagingIoResource) {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- }else{
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- }
- }
- }
- goto Cleanup;
- } else {
- goto FailAndCleanup;
- }
-
- ASSERT(0);
- }
-
-LeaveCriticalAndFail:
- FsRtlExitFileSystem();
- return FALSE;
-
-
-FailAndCleanup:
-
- ExReleaseResourceLite(FcbHeader->Resource);
- FsRtlExitFileSystem();
- return FALSE;
-
-Cleanup:
-
- ExReleaseResourceLite(FcbHeader->Resource);
- FsRtlExitFileSystem();
- return Result;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
- IN OUT PLARGE_INTEGER FileSize)
-{
- FILE_STANDARD_INFORMATION Info;
- NTSTATUS Status;
- IO_STATUS_BLOCK IoStatus;
- PDEVICE_OBJECT DeviceObject;
- PFAST_IO_DISPATCH FastDispatch;
- KEVENT Event;
- PIO_STACK_LOCATION IoStackLocation;
- PIRP Irp;
- BOOLEAN OldHardError;
-
-
- PAGED_CODE();
-
- /* Get Device Object and Fast Calls */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
- FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
-
- /* Check if we support Fast Calls, and check FastIoQueryStandardInfo */
- /* Call the function and see if it succeeds */
- if ( !FastDispatch ||
- !FastDispatch->FastIoQueryStandardInfo ||
- !FastDispatch->FastIoQueryStandardInfo(FileObject,TRUE,
- &Info,&IoStatus,DeviceObject))
- {
- /* If any of the above failed, then we are going to send an IRP to the device
object */
- /* Initialize the even for the IO */
- KeInitializeEvent(&Event,NotificationEvent,FALSE);
- /* Allocate the IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
- if (Irp == NULL)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
-
- /* Don't process hard error */
- OldHardError = IoSetThreadHardErrorMode(FALSE);
-
- /* Setup the IRP */
- Irp->UserIosb = &IoStatus;
- Irp->UserEvent = &Event;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
- Irp->Flags = IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO;
- Irp->RequestorMode = KernelMode;
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->AssociatedIrp.SystemBuffer = &Info;
-
- /* Setup out stack location */
- IoStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
- IoStackLocation--;
- IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;
- IoStackLocation->FileObject = FileObject;
- IoStackLocation->DeviceObject = DeviceObject;
- IoStackLocation->Parameters.QueryFile.Length =
ALIGN_UP(sizeof(FILE_INFORMATION_CLASS),ULONG);
- IoStackLocation->Parameters.QueryFile.FileInformationClass =
FileStandardInformation;
-
- /* Send the IRP to the related device object */
- Status = IofCallDriver(DeviceObject,Irp);
-
- /* Standard DDK IRP result processing */
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
- }
-
- /* If there was a synchronous error, signal it */
- if (!NT_SUCCESS(Status))
- {
- IoStatus.Status = Status;
- }
-
- IoSetThreadHardErrorMode(OldHardError);
- }
-
- /* Check the sync/async IO result */
- if (NT_SUCCESS(IoStatus.Status))
- {
- /* Was the request for a directory ? */
- if (Info.Directory)
- {
- IoStatus.Status = STATUS_FILE_IS_A_DIRECTORY;
- }
- else
- {
- FileSize->QuadPart = Info.EndOfFile.QuadPart;
- }
- }
-
- return IoStatus.Status;
-}
-
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlMdlRead(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN ULONG LockKey,
- OUT PMDL *MdlChain,
- OUT PIO_STATUS_BLOCK IoStatus)
-{
- PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
- PFAST_IO_DISPATCH FastDispatch;
-
- /* Get Device Object and Fast Calls */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
- FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
-
- /* Check if we support Fast Calls, and check this one */
- if (FastDispatch && FastDispatch->MdlRead)
- {
- /* Use the fast path */
- return FastDispatch->MdlRead(FileObject,
- FileOffset,
- Length,
- LockKey,
- MdlChain,
- IoStatus,
- DeviceObject);
- }
-
- /* Get the Base File System (Volume) and Fast Calls */
- BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
- FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
-
- /* If the Base Device Object has its own FastDispatch Routine, fail */
- if (FastDispatch && FastDispatch->MdlRead &&
- BaseDeviceObject != DeviceObject)
- {
- return FALSE;
- }
-
- /* No fast path, use slow path */
- return FsRtlMdlReadDev(FileObject,
- FileOffset,
- Length,
- LockKey,
- MdlChain,
- IoStatus,
- DeviceObject);
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,
- IN OUT PMDL MdlChain)
-{
- PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
- PFAST_IO_DISPATCH FastDispatch;
-
- /* Get Device Object and Fast Calls */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
- FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
-
- /* Check if we support Fast Calls, and check this one */
- if (FastDispatch && FastDispatch->MdlReadComplete)
- {
- /* Use the fast path */
- return FastDispatch->MdlReadComplete(FileObject,
- MdlChain,
- DeviceObject);
- }
-
- /* Get the Base File System (Volume) and Fast Calls */
- BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
- FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
-
- /* If the Base Device Object has its own FastDispatch Routine, fail */
- if ((BaseDeviceObject != DeviceObject) && FastDispatch
- && FastDispatch->MdlReadComplete)
- {
- return FALSE;
- }
-
- /* No fast path, use slow path */
- return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject);
-}
-
-/*
- * @implemented
- */
- BOOLEAN
- NTAPI
-FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,
- IN PMDL MemoryDescriptorList,
- IN PDEVICE_OBJECT DeviceObject)
-{
- /* Call the Cache Manager */
- CcMdlReadComplete2(MemoryDescriptorList, FileObject);
- return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlMdlReadDev(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN ULONG LockKey,
- OUT PMDL *MdlChain,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
- PFSRTL_COMMON_FCB_HEADER FcbHeader;
- BOOLEAN Result = TRUE;
- LARGE_INTEGER Offset;
- PFAST_IO_DISPATCH FastIoDispatch;
- PDEVICE_OBJECT Device;
- PAGED_CODE();
-
- /* No actual read */
- if (!Length)
- {
- /* Return success */
- IoStatus->Status = STATUS_SUCCESS;
- IoStatus->Information = 0;
- return TRUE;
- }
-
- /* Sanity check */
- ASSERT(MAXLONGLONG - FileOffset->QuadPart >= (LONGLONG)Length);
-
- /* Get the offset and FCB header */
- Offset.QuadPart = FileOffset->QuadPart + Length;
- FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
-
- /* Enter the FS */
- FsRtlEnterFileSystem();
- CcFastMdlReadWait++;
-
- /* Lock the FCB */
- ExAcquireResourceShared(FcbHeader->Resource, TRUE);
-
- /* Check if this is a fast I/O cached file */
- if (!(FileObject->PrivateCacheMap) ||
- (FcbHeader->IsFastIoPossible == FastIoIsNotPossible))
- {
- /* It's not, so fail */
- CcFastMdlReadNotPossible += 1;
- Result = FALSE;
- goto Cleanup;
- }
-
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
-
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
-
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffset,
- Length,
- TRUE,
- LockKey,
- TRUE,
- IoStatus,
- Device))
- {
- /* It's not, fail */
- CcFastMdlReadNotPossible += 1;
- Result = FALSE;
- goto Cleanup;
- }
- }
-
- /* Check if we read too much */
- if (Offset.QuadPart > FcbHeader->FileSize.QuadPart)
- {
- /* We did, check if the file offset is past the end */
- if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart)
- {
- /* Set end of file */
- IoStatus->Status = STATUS_END_OF_FILE;
- IoStatus->Information = 0;
- goto Cleanup;
- }
-
- /* Otherwise, just normalize the length */
- Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
- }
-
- /* Set this as top-level IRP */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
-
- _SEH2_TRY
- {
- /* Attempt a read */
- CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus);
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
- }
- _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
- } _SEH2_END;
-
-
- /* Remove the top-level IRP flag */
- PsGetCurrentThread()->TopLevelIrp = 0;
-
- /* Return to caller */
-Cleanup:
- ExReleaseResourceLite(FcbHeader->Resource);
- FsRtlExitFileSystem();
- return Result;
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN PMDL MdlChain)
-{
- PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
- PFAST_IO_DISPATCH FastDispatch;
-
- /* Get Device Object and Fast Calls */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
- FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
-
- /* Check if we support Fast Calls, and check this one */
- if (FastDispatch && FastDispatch->MdlWriteComplete)
- {
- /* Use the fast path */
- return FastDispatch->MdlWriteComplete(FileObject,
- FileOffset,
- MdlChain,
- DeviceObject);
- }
-
- /* Get the Base File System (Volume) and Fast Calls */
- BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
- FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
-
- /* If the Base Device Object has its own FastDispatch Routine, fail */
- if (FastDispatch && FastDispatch->MdlWriteComplete &&
- BaseDeviceObject != DeviceObject)
- {
- return FALSE;
- }
-
- /* No fast path, use slow path */
- return FsRtlMdlWriteCompleteDev(FileObject,
- FileOffset,
- MdlChain,
- DeviceObject);
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN PMDL MdlChain,
- IN PDEVICE_OBJECT DeviceObject)
-{
- if (FileObject->Flags & FO_WRITE_THROUGH)
- {
- return FALSE;
- }
-
-
- /* Call the Cache Manager */
- CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);
- return TRUE;
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN ULONG LockKey,
- OUT PMDL *MdlChain,
- OUT PIO_STATUS_BLOCK IoStatus)
-{
- PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
- PFAST_IO_DISPATCH FastDispatch;
-
- /* Get Device Object and Fast Calls */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
- FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
-
- /* Check if we support Fast Calls, and check this one */
- if (FastDispatch && FastDispatch->PrepareMdlWrite)
- {
- /* Use the fast path */
- return FastDispatch->PrepareMdlWrite(FileObject,
- FileOffset,
- Length,
- LockKey,
- MdlChain,
- IoStatus,
- DeviceObject);
- }
-
- /* Get the Base File System (Volume) and Fast Calls */
- BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
- FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
-
- /* If the Base Device Object has its own FastDispatch Routine, fail */
- if (FastDispatch && FastDispatch->PrepareMdlWrite &&
- BaseDeviceObject != DeviceObject)
- {
- return FALSE;
- }
-
- /* No fast path, use slow path */
- return FsRtlPrepareMdlWriteDev(FileObject,
- FileOffset,
- Length,
- LockKey,
- MdlChain,
- IoStatus,
- DeviceObject);
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN ULONG LockKey,
- OUT PMDL *MdlChain,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
-{
- BOOLEAN Result = TRUE;
- PFAST_IO_DISPATCH FastIoDispatch;
- PDEVICE_OBJECT Device;
- PFSRTL_COMMON_FCB_HEADER FcbHeader;
-
- LARGE_INTEGER OldFileSize;
- LARGE_INTEGER OldValidDataLength;
- LARGE_INTEGER NewSize;
- LARGE_INTEGER Offset;
-
- /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
- BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) &&
(FileOffset->LowPart == 0xffffffff));
- BOOLEAN FileSizeModified = FALSE;
- BOOLEAN ResourceAquiredShared = FALSE;
-
- /* Initialize some of the vars and pointers */
- OldFileSize.QuadPart = 0;
- OldValidDataLength.QuadPart = 0;
-
- PAGED_CODE();
-
- Offset.QuadPart = FileOffset->QuadPart + Length;
-
- /* Nagar p.544 -- Check with Cc if we can write */
- if ( (!CcCanIWrite(FileObject, Length,TRUE,FALSE))||
- (FileObject->Flags & FO_WRITE_THROUGH))
- {
- return FALSE;
- }
-
- IoStatus->Status = STATUS_SUCCESS;
-
- /* No actual read */
- if (!Length)
- {
- return TRUE;
- }
-
- FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
- FsRtlEnterFileSystem();
-
- /* Check we are going to extend the file */
- if ( (FileOffsetAppend == FALSE) &&
- ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
- )
- {
- /* Acquire the resource shared */
- ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
- ResourceAquiredShared =TRUE;
- } else
- {
- /* Acquire the resource exclusive */
- ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
- }
-
- /* Check if we are appending */
- if (FileOffsetAppend == TRUE) {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- } else
- {
- Offset.QuadPart = FileOffset->QuadPart;
- NewSize.QuadPart = FileOffset->QuadPart + Length;
- }
-
- if ( (FileObject->PrivateCacheMap) &&
- (FcbHeader->IsFastIoPossible) &&
- (MAXLONGLONG >= (LONGLONG) FileOffset->QuadPart + Length) &&
- (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart) )
- {
- /* Check if we can keep the lock shared */
- if (ResourceAquiredShared && (NewSize.QuadPart >
FcbHeader->ValidDataLength.QuadPart) ) {
- ExReleaseResourceLite(FcbHeader->Resource);
- ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
-
- /* Compute the offset and the new filesize */
- if (FileOffsetAppend) {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- }
-
- /* Recheck the above points since we released and reacquire the lock */
- if ( (FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
- )
- {
- /* Do nothing */
- } else {
- goto FailAndCleanup;
- }
- }
-
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- /* Sanity check */
- /* ASSERT(!KeIsExecutingDpc()); */
-
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
-
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
-
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffset,
- Length,
- TRUE,
- LockKey,
- FALSE,
- IoStatus,
- Device))
- {
- /* It's not, fail */
- goto FailAndCleanup;
- }
- }
-
- /* If we are going to modify the filesize, save the old fs in case the operation
fails */
- if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
- {
- FileSizeModified = TRUE;
- OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
- OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
-
- /* If the high part of the filesize is going to change, grab the Paging IoResouce */
- if (NewSize.HighPart != FcbHeader->FileSize.HighPart &&
FcbHeader->PagingIoResource)
- {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- }
- }
-
-
- /* Nagar p.544 */
- /* Set ourselves as top component */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
- _SEH2_TRY
- {
- /* Check if there is a gap between the end of the file and the offset
- If yes, then we have to zero the data
- */
- if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,TRUE);
- if (Result)
- {
- CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
- }
- } else {
- CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
- }
-
- }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
- } _SEH2_END;
-
- /* Reset the top component */
- PsGetCurrentThread()->TopLevelIrp = 0;
-
- /* Did the operation suceeded */
- if (Result) {
- /* Check if we need to update the filesize */
- if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart &&
FcbHeader->PagingIoResource) {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- }
- }
-
- /* Flag the file as modified */
- FileObject->Flags |= FO_FILE_MODIFIED;
- /* Check if the filesize has changed */
- if (FileSizeModified) {
- /* Update the file sizes */
- ((SHARED_CACHE_MAP*)
FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart =
NewSize.QuadPart;
- FileObject->Flags |= FO_FILE_SIZE_CHANGED;
- }
-
- }
- else
- {
- /* The operation did not succeed
- Reset the file size to what it should be
- */
- if (FileSizeModified) {
- if (FcbHeader->PagingIoResource) {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
- }else{
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- }
- }
- }
-
- goto Cleanup;
-
- }
- else
- {
- goto FailAndCleanup;
- }
-
-
-FailAndCleanup:
-
- ExReleaseResourceLite(FcbHeader->Resource);
- FsRtlExitFileSystem();
- return FALSE;
-
-Cleanup:
-
- ExReleaseResourceLite(FcbHeader->Resource);
- FsRtlExitFileSystem();
- return Result;
-
-}
-
-/*
-* @implemented
-*/
-VOID
-NTAPI
-FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
-{
- /*
- PAGED_CODE();
- FsRtlAcquireFileExclusiveCommon(FileObject,0,0);
- */
- KeBugCheck(FILE_SYSTEM);
-}
-
-/*
-* @implemented
-*/
-VOID
-NTAPI
-FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
-{
-
- KeBugCheck(FILE_SYSTEM);
-}
-
-/*++
- * @name FsRtlRegisterFileSystemFilterCallbacks
- * @unimplemented
- *
- * FILLME
- *
- * @param FilterDriverObject
- * FILLME
- *
- * @param Callbacks
- * FILLME
- *
- * @return None
- *
- * @remarks None
- *
- *--*/
-NTSTATUS
-NTAPI
-FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject,
- IN PFS_FILTER_CALLBACKS Callbacks)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/fsrtl/fastio.c
+ * PURPOSE: Provides Fast I/O entrypoints to the Cache Manager
+ * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlIncrementCcFastReadResourceMiss(VOID)
+{
+ CcFastReadResourceMiss++;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlIncrementCcFastReadNotPossible(VOID)
+{
+ CcFastReadNotPossible++;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlIncrementCcFastReadWait(VOID)
+{
+ CcFastReadWait++;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlIncrementCcFastReadNoWait(VOID)
+{
+ CcFastReadNoWait++;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlCopyRead(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)
+{
+
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ LARGE_INTEGER Offset;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ PDEVICE_OBJECT Device;
+ BOOLEAN Result = TRUE;
+ ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset,Length);
+
+ PAGED_CODE();
+ ASSERT(FileObject);
+ ASSERT(FileObject->FsContext);
+
+ /* No actual read */
+ if (!Length)
+ {
+ /* Return success */
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = 0;
+ return TRUE;
+ }
+
+ if (MAXLONGLONG < (LONGLONG) FileOffset->QuadPart + Length) {
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ IoStatus->Information = 0;
+ return FALSE;
+ }
+
+ /* Get the offset and FCB header */
+ Offset.QuadPart = FileOffset->QuadPart + Length;
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+
+
+ if (Wait) {
+ /* Use a Resource Acquire */
+ FsRtlEnterFileSystem();
+ CcFastReadWait++;
+ ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
+ } else {
+ /* Acquire the resource without blocking */
+ /* Return false and the I/O manager will retry using the standard IRP method. */
+ /* Use a Resource Acquire */
+ FsRtlEnterFileSystem();
+ if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE)) {
+ FsRtlExitFileSystem();
+ FsRtlIncrementCcFastReadResourceMiss();
+ return FALSE;
+ }
+ }
+
+
+ /* Check if this is a fast I/O cached file */
+ if (!(FileObject->PrivateCacheMap) ||
+ (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) {
+ /* It's not, so fail */
+ Result = FALSE;
+ goto Cleanup;
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
+
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ TRUE,
+ IoStatus,
+ Device))
+ {
+ /* It's not, fail */
+ Result = FALSE;
+ goto Cleanup;
+ }
+ }
+
+ /* Check if we read too much */
+ if (Offset.QuadPart > FcbHeader->FileSize.QuadPart){
+ /* We did, check if the file offset is past the end */
+ if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart){
+ /* Set end of file */
+ IoStatus->Status = STATUS_END_OF_FILE;
+ IoStatus->Information = 0;
+ goto Cleanup;
+ }
+
+ /* Otherwise, just normalize the length */
+ Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
+ }
+
+ /* Set this as top-level IRP */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+
+ _SEH2_TRY
+ {
+ /* Make sure the IO and file size is below 4GB */
+ if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) {
+
+ /* Call the cache controller */
+ CcFastCopyRead (FileObject,FileOffset->LowPart,Length,PageCount,Buffer,IoStatus);
+ /* File was accessed */
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ if (IoStatus->Status != STATUS_END_OF_FILE) {
+ ASSERT(( FcbHeader->FileSize.QuadPart) >= (FileOffset->QuadPart +
IoStatus->Information));
+ }
+
+ } else {
+
+ /* Call the cache controller */
+ Result = CcCopyRead(FileObject, FileOffset, Length, Wait,Buffer, IoStatus);
+ /* File was accessed */
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ if (Result == TRUE) {
+ ASSERT( (IoStatus->Status == STATUS_END_OF_FILE) ||
+ ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <=
FcbHeader->FileSize.QuadPart)
+ );
+ }
+ }
+
+ /* Update the current file offset */
+ if (Result == TRUE) {
+ FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
+ }
+ }
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ Result = FALSE;
+ } _SEH2_END;
+
+ PsGetCurrentThread()->TopLevelIrp = 0;
+
+ /* Return to caller */
+Cleanup:
+
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+
+ if (Result == FALSE) {
+ CcFastReadNotPossible += 1;
+ }
+
+ return Result;
+
+}
+
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN BOOLEAN Wait,
+ IN ULONG LockKey,
+ OUT PVOID Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
+{
+
+ BOOLEAN Result = TRUE;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ PDEVICE_OBJECT Device;
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+
+ /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
+ BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) &&
(FileOffset->LowPart == 0xffffffff));
+ BOOLEAN ResourceAquiredShared = FALSE;
+
+ BOOLEAN b_4GB = FALSE;
+
+ BOOLEAN FileSizeModified = FALSE;
+ LARGE_INTEGER OldFileSize;
+ LARGE_INTEGER OldValidDataLength;
+
+ LARGE_INTEGER NewSize;
+ LARGE_INTEGER Offset;
+
+ PAGED_CODE();
+
+ ASSERT(FileObject);
+ ASSERT(FileObject->FsContext);
+
+ /* Initialize some of the vars and pointers */
+ NewSize.QuadPart = 0;
+ Offset.QuadPart = FileOffset->QuadPart + Length;
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+
+ /* Nagar p.544 -- Check with Cc if we can write and check if the IO > 64kB (WDK
macro) */
+ if ( (CcCanIWrite(FileObject, Length,Wait, FALSE) == FALSE) ||
+ (CcCopyWriteWontFlush(FileObject,FileOffset,Length) == FALSE) ||
+ ((FileObject->Flags & FO_WRITE_THROUGH )== TRUE)
+ )
+ {
+ return FALSE;
+ }
+
+ /* No actual read */
+ if (!Length)
+ {
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = Length;
+ return TRUE;
+ }
+
+ FsRtlEnterFileSystem();
+
+ /* Nagar p.544/545 -- The CcFastCopyWrite doesn't deal with filesize beyond
4GB*/
+ if (Wait && (FcbHeader->AllocationSize.HighPart == 0))
+ {
+ /* If the file offset is not past the file size, then we can acquire the lock
shared */
+ if ((FileOffsetAppend == FALSE) && (Offset.LowPart <=
FcbHeader->ValidDataLength.LowPart)){
+ ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
+ ResourceAquiredShared = TRUE;
+ } else {
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
+ }
+
+ /* Nagar p.544/545 -- If we append, use the file size as offset. Also, check that
we aren't crossing the 4GB boundary */
+ if ((FileOffsetAppend == TRUE)) {
+ Offset.LowPart = FcbHeader->FileSize.LowPart;
+ NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
+ b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart);
+
+ } else {
+ Offset.LowPart = FileOffset->LowPart;
+ NewSize.LowPart = FileOffset->LowPart + Length;
+ b_4GB = ((NewSize.LowPart < FileOffset->LowPart) ||
(FileOffset->HighPart != 0));
+ }
+
+ /* Nagar p.544/545
+ Make sure that caching is initated.
+ That fast are allowed for this file stream.
+ That we are not extending past the allocated size
+ That we are not creating a hole bigger than 8k
+ That we are not crossing the 4GB boundary
+ */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
+ (Offset.LowPart < (FcbHeader->ValidDataLength.LowPart + 0x2000) )
&&
+ !b_4GB
+ )
+ {
+ /* If we are extending past the file size, we need to release the lock and
acquire it
+ exclusively, because we are going to need to update the FcbHeader */
+ if (ResourceAquiredShared && (NewSize.LowPart >
(FcbHeader->ValidDataLength.LowPart + 0x2000))) {
+ /* Then we need to acquire the resource exclusive */
+ ExReleaseResourceLite(FcbHeader->Resource);
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
+ if (FileOffsetAppend == TRUE) {
+ Offset.LowPart = FcbHeader->FileSize.LowPart; // ??
+ NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
+ /* Make sure we don't cross the 4GB boundary */
+ b_4GB = (NewSize.LowPart < Offset.LowPart);
+ }
+
+ /* Recheck some of the conditions since we let the lock go */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
+ (FcbHeader->AllocationSize.HighPart == 0) &&
+ !b_4GB
+ )
+ {
+ } else
+ {
+ goto FailAndCleanup;
+ }
+ }
+
+ }else
+ {
+ goto FailAndCleanup;
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
+
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
+
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffsetAppend?
&FcbHeader->FileSize:FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ FALSE,
+ &FastIoCheckIfPossibleStatus,
+ Device))
+ {
+ /* It's not, fail */
+ goto FailAndCleanup;
+ }
+ }
+
+ /* If we are going to extend the file then save the old file size
+ in case the operation fails
+ */
+ if (NewSize.LowPart > FcbHeader->FileSize.LowPart) {
+ FileSizeModified = TRUE;
+ OldFileSize.LowPart = FcbHeader->FileSize.LowPart;
+ OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart;
+ FcbHeader->FileSize.LowPart = NewSize.LowPart;
+ }
+
+ /* Set this as top-level IRP */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+
+ _SEH2_TRY
+ {
+ if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) {
+ LARGE_INTEGER OffsetVar;
+ OffsetVar.LowPart = Offset.LowPart;
+ OffsetVar.HighPart = 0;
+ CcZeroData(FileObject,&FcbHeader->ValidDataLength,&OffsetVar,TRUE);
+ }
+
+ /* Call the cache manager */
+ CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer);
+ }
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ Result = FALSE;
+ } _SEH2_END;
+
+ /* Remove ourselves at the top level component after the IO is done */
+ PsGetCurrentThread()->TopLevelIrp = 0;
+
+ /* Did the operation succeed ? */
+ if (Result == TRUE) {
+ /* Update the valid file size if necessary */
+ if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart){
+ FcbHeader->ValidDataLength.LowPart = NewSize.LowPart ;
+ }
+
+ /* Flag the file as modified */
+ FileObject->Flags |= FO_FILE_MODIFIED;
+
+ /* Update the strucutres if the file size changed */
+ if (FileSizeModified) {
+ ((SHARED_CACHE_MAP*)
FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.LowPart =
NewSize.LowPart;
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;
+ }
+
+ /* Update the file object current file offset */
+ FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart;
+
+ } else {
+
+ /* Result == FALSE if we get here. */
+ if (FileSizeModified) {
+ /* If the file size was modified then restore the old file size */
+ if(FcbHeader->PagingIoResource != NULL) {
+ // Nagar P.544 Restore the old file size if operation didn't succeed.
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource,TRUE);
+ FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
+ FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ } else {
+ /* If there is no lock and do it without */
+ FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
+ FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
+ }
+ } else {
+ }
+ }
+
+ goto Cleanup;
+
+ } else {
+
+ LARGE_INTEGER OldFileSize;
+
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
+
+ // Nagar P.544
+ /* Check if we need to acquire the resource exclusive */
+ if ( (FileOffsetAppend == FALSE) &&
+ ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
+ )
+ {
+ /* Acquire the resource shared */
+ if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) {
+ goto LeaveCriticalAndFail;
+ }
+ ResourceAquiredShared =TRUE;
+ } else {
+ /* Acquire the resource exclusive */
+ if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) {
+ goto LeaveCriticalAndFail;
+ }
+ }
+
+ /* Check if we are appending */
+ if (FileOffsetAppend == TRUE) {
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ } else {
+ Offset.QuadPart = FileOffset->QuadPart;
+ NewSize.QuadPart += FileOffset->QuadPart + Length;
+ }
+
+ /* Nagar p.544/545
+ Make sure that caching is initated.
+ That fast are allowed for this file stream.
+ That we are not extending past the allocated size
+ That we are not creating a hole bigger than 8k
+ */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ ((FcbHeader->ValidDataLength.QuadPart + 0x2000) > Offset.QuadPart) &&
+ (MAXLONGLONG > (Offset.QuadPart + Length)) &&
+ (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart)
+ )
+ {
+ /* Check if we can keep the lock shared */
+ if (ResourceAquiredShared && (NewSize.QuadPart >
FcbHeader->ValidDataLength.QuadPart) ) {
+ ExReleaseResourceLite(FcbHeader->Resource);
+ if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait))
+ {
+ goto LeaveCriticalAndFail;
+ }
+
+ /* Compute the offset and the new filesize */
+ if (FileOffsetAppend) {
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ }
+
+ /* Recheck the above points since we released and reacquire the lock
*/
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
+ )
+ {
+ /* Do nothing */
+ } else {
+ goto FailAndCleanup;
+ }
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
+
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
+
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffsetAppend?
&FcbHeader->FileSize:FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ FALSE,
+ &FastIoCheckIfPossibleStatus,
+ Device))
+ {
+ /* It's not, fail */
+ goto FailAndCleanup;
+ }
+ }
+
+
+ /* If we are going to modify the filesize, save the old fs in case the
operation fails */
+ if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) {
+ FileSizeModified = TRUE;
+ OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
+ OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
+
+ /* If the high part of the filesize is going to change, grab the Paging IoResouce */
+ if (NewSize.HighPart != FcbHeader->FileSize.HighPart &&
FcbHeader->PagingIoResource) {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ } else {
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ }
+ }
+
+ /* Nagar p.544 */
+ /* Set ourselves as top component */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ _SEH2_TRY
+ {
+ BOOLEAN CallCc = TRUE;
+ /* Check if there is a gap between the end of the file and the offset
+ If yes, then we have to zero the data
+ */
+ if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
+ if (!(Result =
CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,Wait))) {
+ /* If this operation fails, then we have to exit
+ We can jump outside the SEH, so I a using a variable to exit
+ normally
+ */
+ CallCc = FALSE;
+ }
+ }
+
+ /* Unless the CcZeroData failed, call the cache manager */
+ if (CallCc) {
+ Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer);
+ }
+ }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ Result = FALSE;
+ } _SEH2_END;
+
+ /* Reset the top component */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+
+ /* Did the operation suceeded */
+ if (Result) {
+ /* Check if we need to update the filesize */
+ if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
+ if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart &&
FcbHeader->PagingIoResource) {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ } else {
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ }
+ }
+
+ /* Flag the file as modified */
+ FileObject->Flags |= FO_FILE_MODIFIED;
+ /* Check if the filesize has changed */
+ if (FileSizeModified) {
+ /* Update the file sizes */
+ ((SHARED_CACHE_MAP*)
FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart =
NewSize.QuadPart;
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;
+ }
+ /* Update the current FO byte offset */
+ FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;
+ }
+ else
+ {
+ /* The operation did not succeed
+ Reset the file size to what it should be
+ */
+ if (FileSizeModified) {
+ if (FcbHeader->PagingIoResource) {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ }else{
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ }
+ }
+ }
+ goto Cleanup;
+ } else {
+ goto FailAndCleanup;
+ }
+
+ ASSERT(0);
+ }
+
+LeaveCriticalAndFail:
+ FsRtlExitFileSystem();
+ return FALSE;
+
+
+FailAndCleanup:
+
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ return FALSE;
+
+Cleanup:
+
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
+ IN OUT PLARGE_INTEGER FileSize)
+{
+ FILE_STANDARD_INFORMATION Info;
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatus;
+ PDEVICE_OBJECT DeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ KEVENT Event;
+ PIO_STACK_LOCATION IoStackLocation;
+ PIRP Irp;
+ BOOLEAN OldHardError;
+
+
+ PAGED_CODE();
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we support Fast Calls, and check FastIoQueryStandardInfo */
+ /* Call the function and see if it succeeds */
+ if ( !FastDispatch ||
+ !FastDispatch->FastIoQueryStandardInfo ||
+ !FastDispatch->FastIoQueryStandardInfo(FileObject,TRUE,
+ &Info,&IoStatus,DeviceObject))
+ {
+ /* If any of the above failed, then we are going to send an IRP to the device
object */
+ /* Initialize the even for the IO */
+ KeInitializeEvent(&Event,NotificationEvent,FALSE);
+ /* Allocate the IRP */
+ Irp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
+ if (Irp == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ /* Don't process hard error */
+ OldHardError = IoSetThreadHardErrorMode(FALSE);
+
+ /* Setup the IRP */
+ Irp->UserIosb = &IoStatus;
+ Irp->UserEvent = &Event;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Flags = IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO;
+ Irp->RequestorMode = KernelMode;
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->AssociatedIrp.SystemBuffer = &Info;
+
+ /* Setup out stack location */
+ IoStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
+ IoStackLocation--;
+ IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;
+ IoStackLocation->FileObject = FileObject;
+ IoStackLocation->DeviceObject = DeviceObject;
+ IoStackLocation->Parameters.QueryFile.Length =
ALIGN_UP(sizeof(FILE_INFORMATION_CLASS),ULONG);
+ IoStackLocation->Parameters.QueryFile.FileInformationClass =
FileStandardInformation;
+
+ /* Send the IRP to the related device object */
+ Status = IofCallDriver(DeviceObject,Irp);
+
+ /* Standard DDK IRP result processing */
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
+ }
+
+ /* If there was a synchronous error, signal it */
+ if (!NT_SUCCESS(Status))
+ {
+ IoStatus.Status = Status;
+ }
+
+ IoSetThreadHardErrorMode(OldHardError);
+ }
+
+ /* Check the sync/async IO result */
+ if (NT_SUCCESS(IoStatus.Status))
+ {
+ /* Was the request for a directory ? */
+ if (Info.Directory)
+ {
+ IoStatus.Status = STATUS_FILE_IS_A_DIRECTORY;
+ }
+ else
+ {
+ FileSize->QuadPart = Info.EndOfFile.QuadPart;
+ }
+ }
+
+ return IoStatus.Status;
+}
+
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlMdlRead(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN ULONG LockKey,
+ OUT PMDL *MdlChain,
+ OUT PIO_STATUS_BLOCK IoStatus)
+{
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we support Fast Calls, and check this one */
+ if (FastDispatch && FastDispatch->MdlRead)
+ {
+ /* Use the fast path */
+ return FastDispatch->MdlRead(FileObject,
+ FileOffset,
+ Length,
+ LockKey,
+ MdlChain,
+ IoStatus,
+ DeviceObject);
+ }
+
+ /* Get the Base File System (Volume) and Fast Calls */
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
+
+ /* If the Base Device Object has its own FastDispatch Routine, fail */
+ if (FastDispatch && FastDispatch->MdlRead &&
+ BaseDeviceObject != DeviceObject)
+ {
+ return FALSE;
+ }
+
+ /* No fast path, use slow path */
+ return FsRtlMdlReadDev(FileObject,
+ FileOffset,
+ Length,
+ LockKey,
+ MdlChain,
+ IoStatus,
+ DeviceObject);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,
+ IN OUT PMDL MdlChain)
+{
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we support Fast Calls, and check this one */
+ if (FastDispatch && FastDispatch->MdlReadComplete)
+ {
+ /* Use the fast path */
+ return FastDispatch->MdlReadComplete(FileObject,
+ MdlChain,
+ DeviceObject);
+ }
+
+ /* Get the Base File System (Volume) and Fast Calls */
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
+
+ /* If the Base Device Object has its own FastDispatch Routine, fail */
+ if ((BaseDeviceObject != DeviceObject) && FastDispatch
+ && FastDispatch->MdlReadComplete)
+ {
+ return FALSE;
+ }
+
+ /* No fast path, use slow path */
+ return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject);
+}
+
+/*
+ * @implemented
+ */
+ BOOLEAN
+ NTAPI
+FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,
+ IN PMDL MemoryDescriptorList,
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ /* Call the Cache Manager */
+ CcMdlReadComplete2(MemoryDescriptorList, FileObject);
+ return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlMdlReadDev(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN ULONG LockKey,
+ OUT PMDL *MdlChain,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ BOOLEAN Result = TRUE;
+ LARGE_INTEGER Offset;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ PDEVICE_OBJECT Device;
+ PAGED_CODE();
+
+ /* No actual read */
+ if (!Length)
+ {
+ /* Return success */
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = 0;
+ return TRUE;
+ }
+
+ /* Sanity check */
+ ASSERT(MAXLONGLONG - FileOffset->QuadPart >= (LONGLONG)Length);
+
+ /* Get the offset and FCB header */
+ Offset.QuadPart = FileOffset->QuadPart + Length;
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+
+ /* Enter the FS */
+ FsRtlEnterFileSystem();
+ CcFastMdlReadWait++;
+
+ /* Lock the FCB */
+ ExAcquireResourceShared(FcbHeader->Resource, TRUE);
+
+ /* Check if this is a fast I/O cached file */
+ if (!(FileObject->PrivateCacheMap) ||
+ (FcbHeader->IsFastIoPossible == FastIoIsNotPossible))
+ {
+ /* It's not, so fail */
+ CcFastMdlReadNotPossible += 1;
+ Result = FALSE;
+ goto Cleanup;
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ TRUE,
+ IoStatus,
+ Device))
+ {
+ /* It's not, fail */
+ CcFastMdlReadNotPossible += 1;
+ Result = FALSE;
+ goto Cleanup;
+ }
+ }
+
+ /* Check if we read too much */
+ if (Offset.QuadPart > FcbHeader->FileSize.QuadPart)
+ {
+ /* We did, check if the file offset is past the end */
+ if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart)
+ {
+ /* Set end of file */
+ IoStatus->Status = STATUS_END_OF_FILE;
+ IoStatus->Information = 0;
+ goto Cleanup;
+ }
+
+ /* Otherwise, just normalize the length */
+ Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
+ }
+
+ /* Set this as top-level IRP */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+
+ _SEH2_TRY
+ {
+ /* Attempt a read */
+ CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus);
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ }
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ Result = FALSE;
+ } _SEH2_END;
+
+
+ /* Remove the top-level IRP flag */
+ PsGetCurrentThread()->TopLevelIrp = 0;
+
+ /* Return to caller */
+Cleanup:
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN PMDL MdlChain)
+{
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we support Fast Calls, and check this one */
+ if (FastDispatch && FastDispatch->MdlWriteComplete)
+ {
+ /* Use the fast path */
+ return FastDispatch->MdlWriteComplete(FileObject,
+ FileOffset,
+ MdlChain,
+ DeviceObject);
+ }
+
+ /* Get the Base File System (Volume) and Fast Calls */
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
+
+ /* If the Base Device Object has its own FastDispatch Routine, fail */
+ if (FastDispatch && FastDispatch->MdlWriteComplete &&
+ BaseDeviceObject != DeviceObject)
+ {
+ return FALSE;
+ }
+
+ /* No fast path, use slow path */
+ return FsRtlMdlWriteCompleteDev(FileObject,
+ FileOffset,
+ MdlChain,
+ DeviceObject);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN PMDL MdlChain,
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ if (FileObject->Flags & FO_WRITE_THROUGH)
+ {
+ return FALSE;
+ }
+
+
+ /* Call the Cache Manager */
+ CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN ULONG LockKey,
+ OUT PMDL *MdlChain,
+ OUT PIO_STATUS_BLOCK IoStatus)
+{
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we support Fast Calls, and check this one */
+ if (FastDispatch && FastDispatch->PrepareMdlWrite)
+ {
+ /* Use the fast path */
+ return FastDispatch->PrepareMdlWrite(FileObject,
+ FileOffset,
+ Length,
+ LockKey,
+ MdlChain,
+ IoStatus,
+ DeviceObject);
+ }
+
+ /* Get the Base File System (Volume) and Fast Calls */
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
+
+ /* If the Base Device Object has its own FastDispatch Routine, fail */
+ if (FastDispatch && FastDispatch->PrepareMdlWrite &&
+ BaseDeviceObject != DeviceObject)
+ {
+ return FALSE;
+ }
+
+ /* No fast path, use slow path */
+ return FsRtlPrepareMdlWriteDev(FileObject,
+ FileOffset,
+ Length,
+ LockKey,
+ MdlChain,
+ IoStatus,
+ DeviceObject);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN ULONG LockKey,
+ OUT PMDL *MdlChain,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ BOOLEAN Result = TRUE;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ PDEVICE_OBJECT Device;
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+
+ LARGE_INTEGER OldFileSize;
+ LARGE_INTEGER OldValidDataLength;
+ LARGE_INTEGER NewSize;
+ LARGE_INTEGER Offset;
+
+ /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
+ BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) &&
(FileOffset->LowPart == 0xffffffff));
+ BOOLEAN FileSizeModified = FALSE;
+ BOOLEAN ResourceAquiredShared = FALSE;
+
+ /* Initialize some of the vars and pointers */
+ OldFileSize.QuadPart = 0;
+ OldValidDataLength.QuadPart = 0;
+
+ PAGED_CODE();
+
+ Offset.QuadPart = FileOffset->QuadPart + Length;
+
+ /* Nagar p.544 -- Check with Cc if we can write */
+ if ( (!CcCanIWrite(FileObject, Length,TRUE,FALSE))||
+ (FileObject->Flags & FO_WRITE_THROUGH))
+ {
+ return FALSE;
+ }
+
+ IoStatus->Status = STATUS_SUCCESS;
+
+ /* No actual read */
+ if (!Length)
+ {
+ return TRUE;
+ }
+
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ FsRtlEnterFileSystem();
+
+ /* Check we are going to extend the file */
+ if ( (FileOffsetAppend == FALSE) &&
+ ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
+ )
+ {
+ /* Acquire the resource shared */
+ ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
+ ResourceAquiredShared =TRUE;
+ } else
+ {
+ /* Acquire the resource exclusive */
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
+ }
+
+ /* Check if we are appending */
+ if (FileOffsetAppend == TRUE) {
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ } else
+ {
+ Offset.QuadPart = FileOffset->QuadPart;
+ NewSize.QuadPart = FileOffset->QuadPart + Length;
+ }
+
+ if ( (FileObject->PrivateCacheMap) &&
+ (FcbHeader->IsFastIoPossible) &&
+ (MAXLONGLONG >= (LONGLONG) FileOffset->QuadPart + Length) &&
+ (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart) )
+ {
+ /* Check if we can keep the lock shared */
+ if (ResourceAquiredShared && (NewSize.QuadPart >
FcbHeader->ValidDataLength.QuadPart) ) {
+ ExReleaseResourceLite(FcbHeader->Resource);
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
+
+ /* Compute the offset and the new filesize */
+ if (FileOffsetAppend) {
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ }
+
+ /* Recheck the above points since we released and reacquire the lock */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
+ )
+ {
+ /* Do nothing */
+ } else {
+ goto FailAndCleanup;
+ }
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ /* Sanity check */
+ /* ASSERT(!KeIsExecutingDpc()); */
+
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ FALSE,
+ IoStatus,
+ Device))
+ {
+ /* It's not, fail */
+ goto FailAndCleanup;
+ }
+ }
+
+ /* If we are going to modify the filesize, save the old fs in case the operation
fails */
+ if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
+ {
+ FileSizeModified = TRUE;
+ OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
+ OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
+
+ /* If the high part of the filesize is going to change, grab the Paging IoResouce */
+ if (NewSize.HighPart != FcbHeader->FileSize.HighPart &&
FcbHeader->PagingIoResource)
+ {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ } else {
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ }
+ }
+
+
+ /* Nagar p.544 */
+ /* Set ourselves as top component */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ _SEH2_TRY
+ {
+ /* Check if there is a gap between the end of the file and the offset
+ If yes, then we have to zero the data
+ */
+ if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
+ Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,TRUE);
+ if (Result)
+ {
+ CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
+ }
+ } else {
+ CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
+ }
+
+ }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ Result = FALSE;
+ } _SEH2_END;
+
+ /* Reset the top component */
+ PsGetCurrentThread()->TopLevelIrp = 0;
+
+ /* Did the operation suceeded */
+ if (Result) {
+ /* Check if we need to update the filesize */
+ if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
+ if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart &&
FcbHeader->PagingIoResource) {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ } else {
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ }
+ }
+
+ /* Flag the file as modified */
+ FileObject->Flags |= FO_FILE_MODIFIED;
+ /* Check if the filesize has changed */
+ if (FileSizeModified) {
+ /* Update the file sizes */
+ ((SHARED_CACHE_MAP*)
FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart =
NewSize.QuadPart;
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;
+ }
+
+ }
+ else
+ {
+ /* The operation did not succeed
+ Reset the file size to what it should be
+ */
+ if (FileSizeModified) {
+ if (FcbHeader->PagingIoResource) {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ }else{
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ }
+ }
+ }
+
+ goto Cleanup;
+
+ }
+ else
+ {
+ goto FailAndCleanup;
+ }
+
+
+FailAndCleanup:
+
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ return FALSE;
+
+Cleanup:
+
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ return Result;
+
+}
+
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
+{
+ /*
+ PAGED_CODE();
+ FsRtlAcquireFileExclusiveCommon(FileObject,0,0);
+ */
+ KeBugCheck(FILE_SYSTEM);
+}
+
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
+{
+
+ KeBugCheck(FILE_SYSTEM);
+}
+
+/*++
+ * @name FsRtlRegisterFileSystemFilterCallbacks
+ * @unimplemented
+ *
+ * FILLME
+ *
+ * @param FilterDriverObject
+ * FILLME
+ *
+ * @param Callbacks
+ * FILLME
+ *
+ * @return None
+ *
+ * @remarks None
+ *
+ *--*/
+NTSTATUS
+NTAPI
+FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject,
+ IN PFS_FILTER_CALLBACKS Callbacks)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
Propchange: trunk/reactos/ntoskrnl/fsrtl/fastio.c
------------------------------------------------------------------------------
svn:eol-style = native