- SVN maintenance.
authorAleksey Bragin <aleksey@reactos.org>
Sun, 18 Jan 2009 10:23:15 +0000 (10:23 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Sun, 18 Jan 2009 10:23:15 +0000 (10:23 +0000)
svn path=/trunk/; revision=38881

reactos/ntoskrnl/fsrtl/fastio.c

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