Sync with trunk r63935.
[reactos.git] / ntoskrnl / cc / copy.c
index d63c36e..ccddd41 100644 (file)
 static PFN_NUMBER CcZeroPage = 0;
 
 #define MAX_ZERO_LENGTH    (256 * 1024)
-#define MAX_RW_LENGTH    (256 * 1024)
-C_ASSERT(MAX_RW_LENGTH <= VACB_MAPPING_GRANULARITY);
+
+typedef enum _CC_COPY_OPERATION
+{
+    CcOperationRead,
+    CcOperationWrite,
+    CcOperationZero
+} CC_COPY_OPERATION;
 
 ULONG CcFastMdlReadWait;
 ULONG CcFastMdlReadNotPossible;
@@ -54,136 +59,6 @@ CcInitCacheZeroPage (
     MiZeroPhysicalPage(CcZeroPage);
 }
 
-NTSTATUS
-NTAPI
-ReadVacbChain (
-    PROS_SHARED_CACHE_MAP SharedCacheMap,
-    ULONG ReadOffset,
-    ULONG Length,
-    PVOID Buffer)
-{
-    PROS_VACB head;
-    PROS_VACB current;
-    PROS_VACB previous;
-    IO_STATUS_BLOCK Iosb;
-    NTSTATUS Status;
-    ULONG TempLength;
-    KEVENT Event;
-    PMDL Mdl;
-
-    Mdl = _alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
-
-    Status = CcRosGetVacbChain(SharedCacheMap, ReadOffset, Length, &head);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    current = head;
-    while (current != NULL)
-    {
-        /*
-         * If the current VACB is valid then copy it into the user buffer.
-         */
-        if (current->Valid)
-        {
-            TempLength = min(VACB_MAPPING_GRANULARITY, Length);
-            RtlCopyMemory(Buffer, current->BaseAddress, TempLength);
-
-            Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-
-            Length = Length - TempLength;
-            previous = current;
-            current = current->NextInChain;
-            CcRosReleaseVacb(SharedCacheMap, previous, TRUE, FALSE, FALSE);
-        }
-        /*
-         * Otherwise read in as much as we can.
-         */
-        else
-        {
-            PROS_VACB current2;
-            ULONG current_size;
-            ULONG i;
-            PPFN_NUMBER MdlPages;
-
-            /*
-             * Count the maximum number of bytes we could read starting
-             * from the current VACB.
-             */
-            current2 = current;
-            current_size = 0;
-            while ((current2 != NULL) && !current2->Valid && (current_size < MAX_RW_LENGTH))
-            {
-                current2 = current2->NextInChain;
-                current_size += VACB_MAPPING_GRANULARITY;
-            }
-
-            /*
-             * Create an MDL which contains all their pages.
-             */
-            MmInitializeMdl(Mdl, NULL, current_size);
-            Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
-            current2 = current;
-            current_size = 0;
-            MdlPages = (PPFN_NUMBER)(Mdl + 1);
-            while ((current2 != NULL) && !current2->Valid && (current_size < MAX_RW_LENGTH))
-            {
-                PVOID address = current2->BaseAddress;
-                for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++, address = RVA(address, PAGE_SIZE))
-                {
-                    *MdlPages++ = MmGetPfnForProcess(NULL, address);
-                }
-                current2 = current2->NextInChain;
-                current_size += VACB_MAPPING_GRANULARITY;
-            }
-
-            /*
-             * Read in the information.
-             */
-            KeInitializeEvent(&Event, NotificationEvent, FALSE);
-            Status = IoPageRead(SharedCacheMap->FileObject,
-                                Mdl,
-                                &current->FileOffset,
-                                &Event,
-                                &Iosb);
-            if (Status == STATUS_PENDING)
-            {
-                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-                Status = Iosb.Status;
-            }
-            if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
-            {
-                MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
-            }
-            if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
-            {
-                while (current != NULL)
-                {
-                    previous = current;
-                    current = current->NextInChain;
-                    CcRosReleaseVacb(SharedCacheMap, previous, FALSE, FALSE, FALSE);
-                }
-                return Status;
-            }
-            current_size = 0;
-            while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH)
-            {
-                previous = current;
-                current = current->NextInChain;
-                TempLength = min(VACB_MAPPING_GRANULARITY, Length);
-                RtlCopyMemory(Buffer, previous->BaseAddress, TempLength);
-
-                Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-
-                Length = Length - TempLength;
-                CcRosReleaseVacb(SharedCacheMap, previous, TRUE, FALSE, FALSE);
-                current_size += VACB_MAPPING_GRANULARITY;
-            }
-        }
-    }
-    return STATUS_SUCCESS;
-}
-
 NTSTATUS
 NTAPI
 CcReadVirtualAddress (
@@ -288,153 +163,213 @@ CcWriteVirtualAddress (
     return STATUS_SUCCESS;
 }
 
-
-/*
- * @unimplemented
- */
-BOOLEAN
-NTAPI
-CcCanIWrite (
-    IN PFILE_OBJECT FileObject,
-    IN ULONG BytesToWrite,
-    IN BOOLEAN Wait,
-    IN BOOLEAN Retrying)
+NTSTATUS
+ReadWriteOrZero(
+    _Inout_ PVOID BaseAddress,
+    _Inout_opt_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ CC_COPY_OPERATION Operation)
 {
-    UNIMPLEMENTED;
-    return FALSE;
-}
+    NTSTATUS Status = STATUS_SUCCESS;
 
+    if (Operation == CcOperationZero)
+    {
+        /* Zero */
+        RtlZeroMemory(BaseAddress, Length);
+    }
+    else
+    {
+        _SEH2_TRY
+        {
+            if (Operation == CcOperationWrite)
+                RtlCopyMemory(BaseAddress, Buffer, Length);
+            else
+                RtlCopyMemory(Buffer, BaseAddress, Length);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+    }
+    return Status;
+}
 
-/*
- * @implemented
- */
 BOOLEAN
-NTAPI
-CcCopyRead (
-    IN PFILE_OBJECT FileObject,
-    IN PLARGE_INTEGER FileOffset,
-    IN ULONG Length,
-    IN BOOLEAN Wait,
-    OUT PVOID Buffer,
-    OUT PIO_STATUS_BLOCK IoStatus)
+CcCopyData (
+    _In_ PFILE_OBJECT FileObject,
+    _In_ LONGLONG FileOffset,
+    _Inout_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ CC_COPY_OPERATION Operation,
+    _In_ BOOLEAN Wait,
+    _Out_ PIO_STATUS_BLOCK IoStatus)
 {
-    ULONG ReadOffset;
-    ULONG TempLength;
-    NTSTATUS Status = STATUS_SUCCESS;
-    PVOID BaseAddress;
+    NTSTATUS Status;
+    LONGLONG CurrentOffset;
+    ULONG BytesCopied;
+    KIRQL OldIrql;
+    PROS_SHARED_CACHE_MAP SharedCacheMap;
+    PLIST_ENTRY ListEntry;
     PROS_VACB Vacb;
+    ULONG PartialLength;
+    PVOID BaseAddress;
     BOOLEAN Valid;
-    ULONG ReadLength = 0;
-    PROS_SHARED_CACHE_MAP SharedCacheMap;
-    KIRQL oldirql;
-    PLIST_ENTRY current_entry;
-    PROS_VACB current;
-
-    DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
-           "Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
-           FileObject, FileOffset->QuadPart, Length, Wait,
-           Buffer, IoStatus);
 
     SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
-    ReadOffset = (ULONG)FileOffset->QuadPart;
+    CurrentOffset = FileOffset;
+    BytesCopied = 0;
 
-    DPRINT("SectionSize %I64d, FileSize %I64d\n",
-           SharedCacheMap->SectionSize.QuadPart,
-           SharedCacheMap->FileSize.QuadPart);
-
-    /*
-     * Check for the nowait case that all the cache VACBs that would
-     * cover this read are in memory.
-     */
     if (!Wait)
     {
-        KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
+        /* test if the requested data is available */
+        KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
         /* FIXME: this loop doesn't take into account areas that don't have
          * a VACB in the list yet */
-        current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
-        while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
+        ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
+        while (ListEntry != &SharedCacheMap->CacheMapVacbListHead)
         {
-            current = CONTAINING_RECORD(current_entry,
-                                        ROS_VACB,
-                                        CacheMapVacbListEntry);
-            if (!current->Valid &&
-                DoRangesIntersect(current->FileOffset.QuadPart,
+            Vacb = CONTAINING_RECORD(ListEntry,
+                                     ROS_VACB,
+                                     CacheMapVacbListEntry);
+            ListEntry = ListEntry->Flink;
+            if (!Vacb->Valid &&
+                DoRangesIntersect(Vacb->FileOffset.QuadPart,
                                   VACB_MAPPING_GRANULARITY,
-                                  ReadOffset, Length))
+                                  CurrentOffset, Length))
             {
-                KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
-                IoStatus->Status = STATUS_UNSUCCESSFUL;
-                IoStatus->Information = 0;
+                KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
+                /* data not available */
                 return FALSE;
             }
-            if (current->FileOffset.QuadPart >= ReadOffset + Length)
+            if (Vacb->FileOffset.QuadPart >= CurrentOffset + Length)
                 break;
-            current_entry = current_entry->Flink;
         }
-        KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
+        KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
     }
 
-    TempLength = ReadOffset % VACB_MAPPING_GRANULARITY;
-    if (TempLength != 0)
+    PartialLength = CurrentOffset % VACB_MAPPING_GRANULARITY;
+    if (PartialLength != 0)
     {
-        TempLength = min(Length, VACB_MAPPING_GRANULARITY - TempLength);
+        PartialLength = min(Length, VACB_MAPPING_GRANULARITY - PartialLength);
         Status = CcRosRequestVacb(SharedCacheMap,
-                                  ROUND_DOWN(ReadOffset,
+                                  ROUND_DOWN(CurrentOffset,
                                              VACB_MAPPING_GRANULARITY),
-                                  &BaseAddress, &Valid, &Vacb);
+                                  &BaseAddress,
+                                  &Valid,
+                                  &Vacb);
         if (!NT_SUCCESS(Status))
-        {
-            IoStatus->Information = 0;
-            IoStatus->Status = Status;
-            DPRINT("CcRosRequestVacb failed, Status %x\n", Status);
-            return FALSE;
-        }
+            ExRaiseStatus(Status);
         if (!Valid)
         {
             Status = CcReadVirtualAddress(Vacb);
             if (!NT_SUCCESS(Status))
             {
-                IoStatus->Information = 0;
-                IoStatus->Status = Status;
                 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
-                return FALSE;
+                ExRaiseStatus(Status);
             }
         }
-        RtlCopyMemory(Buffer,
-                      (char*)BaseAddress + ReadOffset % VACB_MAPPING_GRANULARITY,
-                      TempLength);
-        CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
-        ReadLength += TempLength;
-        Length -= TempLength;
-        ReadOffset += TempLength;
-        Buffer = (PVOID)((char*)Buffer + TempLength);
+        Status = ReadWriteOrZero((PUCHAR)BaseAddress + CurrentOffset % VACB_MAPPING_GRANULARITY,
+                                 Buffer,
+                                 PartialLength,
+                                 Operation);
+
+        CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, Operation != CcOperationRead, FALSE);
+
+        if (!NT_SUCCESS(Status))
+            ExRaiseStatus(STATUS_INVALID_USER_BUFFER);
+
+        Length -= PartialLength;
+        CurrentOffset += PartialLength;
+        BytesCopied += PartialLength;
+
+        if (Buffer)
+            Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
     }
 
     while (Length > 0)
     {
-        TempLength = min(VACB_MAPPING_GRANULARITY, Length);
-        Status = ReadVacbChain(SharedCacheMap, ReadOffset, TempLength, Buffer);
+        ASSERT(CurrentOffset % VACB_MAPPING_GRANULARITY == 0);
+        PartialLength = min(VACB_MAPPING_GRANULARITY, Length);
+        Status = CcRosRequestVacb(SharedCacheMap,
+                                  CurrentOffset,
+                                  &BaseAddress,
+                                  &Valid,
+                                  &Vacb);
         if (!NT_SUCCESS(Status))
+            ExRaiseStatus(Status);
+        if (!Valid &&
+            (Operation == CcOperationRead ||
+             PartialLength < VACB_MAPPING_GRANULARITY))
         {
-            IoStatus->Information = 0;
-            IoStatus->Status = Status;
-            DPRINT("ReadVacbChain failed, Status %x\n", Status);
-            return FALSE;
+            Status = CcReadVirtualAddress(Vacb);
+            if (!NT_SUCCESS(Status))
+            {
+                CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
+                ExRaiseStatus(Status);
+            }
         }
+        Status = ReadWriteOrZero(BaseAddress, Buffer, PartialLength, Operation);
 
-        ReadLength += TempLength;
-        Length -= TempLength;
-        ReadOffset += TempLength;
+        CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, Operation != CcOperationRead, FALSE);
 
-        Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-    }
+        if (!NT_SUCCESS(Status))
+            ExRaiseStatus(STATUS_INVALID_USER_BUFFER);
+
+        Length -= PartialLength;
+        CurrentOffset += PartialLength;
+        BytesCopied += PartialLength;
 
+        if (Buffer)
+            Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
+    }
     IoStatus->Status = STATUS_SUCCESS;
-    IoStatus->Information = ReadLength;
-    DPRINT("CcCopyRead O.K.\n");
+    IoStatus->Information = BytesCopied;
     return TRUE;
 }
 
+/*
+ * @unimplemented
+ */
+BOOLEAN
+NTAPI
+CcCanIWrite (
+    IN PFILE_OBJECT FileObject,
+    IN ULONG BytesToWrite,
+    IN BOOLEAN Wait,
+    IN BOOLEAN Retrying)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+CcCopyRead (
+    IN PFILE_OBJECT FileObject,
+    IN PLARGE_INTEGER FileOffset,
+    IN ULONG Length,
+    IN BOOLEAN Wait,
+    OUT PVOID Buffer,
+    OUT PIO_STATUS_BLOCK IoStatus)
+{
+    DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
+           "Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
+           FileObject, FileOffset->QuadPart, Length, Wait,
+           Buffer, IoStatus);
+
+    return CcCopyData(FileObject,
+                      FileOffset->QuadPart,
+                      Buffer,
+                      Length,
+                      CcOperationRead,
+                      Wait,
+                      IoStatus);
+}
+
 /*
  * @implemented
  */
@@ -447,109 +382,19 @@ CcCopyWrite (
     IN BOOLEAN Wait,
     IN PVOID Buffer)
 {
-    NTSTATUS Status;
-    ULONG WriteOffset;
-    KIRQL oldirql;
-    PROS_SHARED_CACHE_MAP SharedCacheMap;
-    PLIST_ENTRY current_entry;
-    PROS_VACB Vacb;
-    ULONG TempLength;
-    PVOID BaseAddress;
-    BOOLEAN Valid;
+    IO_STATUS_BLOCK IoStatus;
 
     DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
            "Length %lu, Wait %u, Buffer 0x%p)\n",
            FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
 
-    SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
-    WriteOffset = (ULONG)FileOffset->QuadPart;
-
-    if (!Wait)
-    {
-        /* testing, if the requested datas are available */
-        KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
-        /* FIXME: this loop doesn't take into account areas that don't have
-         * a VACB in the list yet */
-        current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
-        while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
-        {
-            Vacb = CONTAINING_RECORD(current_entry,
-                                     ROS_VACB,
-                                     CacheMapVacbListEntry);
-            if (!Vacb->Valid &&
-                DoRangesIntersect(Vacb->FileOffset.QuadPart,
-                                  VACB_MAPPING_GRANULARITY,
-                                  WriteOffset, Length))
-            {
-                KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
-                /* datas not available */
-                return FALSE;
-            }
-            if (Vacb->FileOffset.QuadPart >= WriteOffset + Length)
-                break;
-            current_entry = current_entry->Flink;
-        }
-        KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
-    }
-
-    TempLength = WriteOffset % VACB_MAPPING_GRANULARITY;
-    if (TempLength != 0)
-    {
-        ULONG ROffset;
-        ROffset = ROUND_DOWN(WriteOffset, VACB_MAPPING_GRANULARITY);
-        TempLength = min(Length, VACB_MAPPING_GRANULARITY - TempLength);
-        Status = CcRosRequestVacb(SharedCacheMap, ROffset,
-                                  &BaseAddress, &Valid, &Vacb);
-        if (!NT_SUCCESS(Status))
-        {
-            return FALSE;
-        }
-        if (!Valid)
-        {
-            if (!NT_SUCCESS(CcReadVirtualAddress(Vacb)))
-            {
-                return FALSE;
-            }
-        }
-        RtlCopyMemory((char*)BaseAddress + WriteOffset % VACB_MAPPING_GRANULARITY,
+    return CcCopyData(FileObject,
+                      FileOffset->QuadPart,
                       Buffer,
-                      TempLength);
-        CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, TRUE, FALSE);
-
-        Length -= TempLength;
-        WriteOffset += TempLength;
-
-        Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-    }
-
-    while (Length > 0)
-    {
-        TempLength = min(VACB_MAPPING_GRANULARITY, Length);
-        Status = CcRosRequestVacb(SharedCacheMap,
-                                  WriteOffset,
-                                  &BaseAddress,
-                                  &Valid,
-                                  &Vacb);
-        if (!NT_SUCCESS(Status))
-        {
-            return FALSE;
-        }
-        if (!Valid && TempLength < VACB_MAPPING_GRANULARITY)
-        {
-            if (!NT_SUCCESS(CcReadVirtualAddress(Vacb)))
-            {
-                CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
-                return FALSE;
-            }
-        }
-        RtlCopyMemory(BaseAddress, Buffer, TempLength);
-        CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, TRUE, FALSE);
-        Length -= TempLength;
-        WriteOffset += TempLength;
-
-        Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-    }
-    return TRUE;
+                      Length,
+                      CcOperationWrite,
+                      Wait,
+                      &IoStatus);
 }
 
 /*
@@ -679,102 +524,15 @@ CcZeroData (
     }
     else
     {
-        /* File is cached */
-        KIRQL oldirql;
-        PROS_SHARED_CACHE_MAP SharedCacheMap;
-        PLIST_ENTRY current_entry;
-        PROS_VACB Vacb, current, previous;
-        ULONG TempLength;
-
-        SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
-        if (!Wait)
-        {
-            /* testing, if the requested datas are available */
-            KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
-            /* FIXME: this loop doesn't take into account areas that don't have
-             * a VACB in the list yet */
-            current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
-            while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
-            {
-                Vacb = CONTAINING_RECORD(current_entry,
-                                         ROS_VACB,
-                                         CacheMapVacbListEntry);
-                if (!Vacb->Valid &&
-                    DoRangesIntersect(Vacb->FileOffset.QuadPart,
-                                      VACB_MAPPING_GRANULARITY,
-                                      WriteOffset.u.LowPart, Length))
-                {
-                    KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
-                    /* datas not available */
-                    return FALSE;
-                }
-                if (Vacb->FileOffset.QuadPart >= WriteOffset.u.LowPart + Length)
-                    break;
-                current_entry = current_entry->Flink;
-            }
-            KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
-        }
-
-        while (Length > 0)
-        {
-            ULONG Offset;
-            Offset = WriteOffset.u.LowPart % VACB_MAPPING_GRANULARITY;
-            if (Length + Offset > MAX_ZERO_LENGTH)
-            {
-                CurrentLength = MAX_ZERO_LENGTH - Offset;
-            }
-            else
-            {
-                CurrentLength = Length;
-            }
-            Status = CcRosGetVacbChain(SharedCacheMap, WriteOffset.u.LowPart - Offset,
-                                       Offset + CurrentLength, &Vacb);
-            if (!NT_SUCCESS(Status))
-            {
-                return FALSE;
-            }
-            current = Vacb;
-
-            while (current != NULL)
-            {
-                Offset = WriteOffset.u.LowPart % VACB_MAPPING_GRANULARITY;
-                if ((Offset != 0) ||
-                    (Offset + CurrentLength < VACB_MAPPING_GRANULARITY))
-                {
-                    if (!current->Valid)
-                    {
-                        /* read the block */
-                        Status = CcReadVirtualAddress(current);
-                        if (!NT_SUCCESS(Status))
-                        {
-                            DPRINT1("CcReadVirtualAddress failed, status %x\n",
-                                    Status);
-                        }
-                    }
-                    TempLength = min(CurrentLength, VACB_MAPPING_GRANULARITY - Offset);
-                }
-                else
-                {
-                    TempLength = VACB_MAPPING_GRANULARITY;
-                }
-                RtlZeroMemory((PUCHAR)current->BaseAddress + Offset,
-                              TempLength);
-
-                WriteOffset.QuadPart += TempLength;
-                CurrentLength -= TempLength;
-                Length -= TempLength;
-
-                current = current->NextInChain;
-            }
-
-            current = Vacb;
-            while (current != NULL)
-            {
-                previous = current;
-                current = current->NextInChain;
-                CcRosReleaseVacb(SharedCacheMap, previous, TRUE, TRUE, FALSE);
-            }
-        }
+        IO_STATUS_BLOCK IoStatus;
+
+        return CcCopyData(FileObject,
+                          WriteOffset.QuadPart,
+                          NULL,
+                          Length,
+                          CcOperationZero,
+                          Wait,
+                          &IoStatus);
     }
 
     return TRUE;