- COMPUTE_PAGES_SPANNED is deprecated, use ADDRESS_AND_SIZE_TO_SPAN_PAGES instead
[reactos.git] / reactos / ntoskrnl / fsrtl / fastio.c
index a4b2dfa..76f5ff8 100644 (file)
@@ -3,7 +3,7 @@
  * 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:     None.\r
+ * PROGRAMMERS:     buzdelabuz2@gmail.com,alex.ionescu@reactos.org\r
  */\r
 \r
 /* INCLUDES ******************************************************************/\r
@@ -55,7 +55,7 @@ FsRtlIncrementCcFastReadNoWait(VOID)
 }\r
 \r
 /*\r
- * @unimplemented\r
+ * @implemented\r
  */\r
 BOOLEAN\r
 NTAPI\r
@@ -68,12 +68,166 @@ FsRtlCopyRead(IN PFILE_OBJECT FileObject,
               OUT PIO_STATUS_BLOCK IoStatus,\r
               IN PDEVICE_OBJECT DeviceObject)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
- * @unimplemented\r
+ * @implemented\r
  */\r
 BOOLEAN\r
 NTAPI\r
@@ -86,8 +240,445 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
                OUT PIO_STATUS_BLOCK IoStatus,\r
                IN PDEVICE_OBJECT DeviceObject)\r
 {\r
-    KEBUGCHECK(0);\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
@@ -98,10 +689,98 @@ NTAPI
 FsRtlGetFileSize(IN PFILE_OBJECT  FileObject,\r
                  IN OUT PLARGE_INTEGER FileSize)\r
 {\r
-    KEBUGCHECK(0);\r
-    return STATUS_UNSUCCESSFUL;\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
@@ -114,8 +793,45 @@ FsRtlMdlRead(IN PFILE_OBJECT FileObject,
              OUT PMDL *MdlChain,\r
              OUT PIO_STATUS_BLOCK IoStatus)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
@@ -126,23 +842,52 @@ NTAPI
 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,\r
                      IN OUT PMDL MdlChain)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
+ BOOLEAN\r
+ NTAPI\r
 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,\r
-                        IN PMDL MdlChain,\r
+                        IN PMDL MemoryDescriptorList,\r
                         IN PDEVICE_OBJECT DeviceObject)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\r
+    /* Call the Cache Manager */\r
+    CcMdlReadComplete2(MemoryDescriptorList, FileObject);\r
+    return TRUE;\r
 }\r
 \r
+\r
 /*\r
  * @implemented\r
  */\r
@@ -156,8 +901,114 @@ FsRtlMdlReadDev(IN PFILE_OBJECT FileObject,
                 OUT PIO_STATUS_BLOCK IoStatus,\r
                 IN PDEVICE_OBJECT DeviceObject)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
@@ -169,8 +1020,39 @@ FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject,
                       IN PLARGE_INTEGER FileOffset,\r
                       IN PMDL MdlChain)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
@@ -183,8 +1065,15 @@ FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject,
                          IN PMDL MdlChain,\r
                          IN PDEVICE_OBJECT DeviceObject)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
@@ -199,12 +1088,49 @@ FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
                      OUT PMDL *MdlChain,\r
                      OUT PIO_STATUS_BLOCK IoStatus)\r
 {\r
-    KEBUGCHECK(0);\r
-    return FALSE;\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
- * @unimplemented\r
+ * @implemented\r
  */\r
 BOOLEAN\r
 NTAPI\r
@@ -216,8 +1142,235 @@ FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
                         OUT PIO_STATUS_BLOCK IoStatus,\r
                         IN PDEVICE_OBJECT DeviceObject)\r
 {\r
-    KEBUGCHECK(0);\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
@@ -227,7 +1380,11 @@ VOID
 NTAPI\r
 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)\r
 {\r
-    KEBUGCHECK(0);\r
+    /*\r
+    PAGED_CODE();\r
+    FsRtlAcquireFileExclusiveCommon(FileObject,0,0);\r
+    */\r
+    KeBugCheck(FILE_SYSTEM);\r
 }\r
 \r
 /*\r
@@ -237,7 +1394,8 @@ VOID
 NTAPI\r
 FsRtlReleaseFile(IN PFILE_OBJECT FileObject)\r
 {\r
-    KEBUGCHECK(0);\r
+\r
+    KeBugCheck(FILE_SYSTEM);\r
 }\r
 \r
 /*++\r