mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00

The main motivation to switch to that newer driver is, that our old one simply can not read all isos. Especially complex ones made trouble and were only shown as empty in explorer. It is still possible to build and use the old driver when needed, only thing that needs to be done for that is to revert 0.4.8-dev-164-gec6b3ecbe4
Porting back the state up to 0.4.8-release-100-g8f947b5 implies: Fixing the following JIRA-IDs (or avoid introducing them): CORE-18029 "Mute noisy DPRINT 'SectionObject has ImageSection'" CORE-17405 "Fix a macro-copy-paste and shrink the binary size" CORE-15659 "Unable to build the gcc Release version in Windows using RosBE 2.1.6 (module cdfs fails)" CORE-14315 "CDFS_NEW assertion during first stage setup due to new CcPerformReadAhead" CORE-14128 "Avast! Free Antivirus 7.0 hangs the system when trying to detect a newly created virus" CORE-14067 "CDFS_NEW assertions and exceptions" CORE-14003 "Shutting down LiveCD asserts since introduction of MS PL CDFS_NEW" CORE-13184 "Restore ability to install from disk-image" by picking the following commits: 0.4.8-release-100-g8f947b5322
[NTOSKRNL] Mute noisy DPRINT 'SectionObject has ImageSection' CORE-18029 0.4.8-release-80-geb1ea19588
[CDFS_NEW] == 0.4.15-dev-1456-g889eab7
CORE-17405 0.4.8-release-62-g8c07aad4a8
[CDFS_NEW/XDK] == 0.4.11-dev-39-ga2f9762
+ 0.4.11-dev-40-g6d7ec8c
CORE-14067 0.4.8-release-3-g5d976d04e8
[CDFS_NEW] == 0.4.12-dev-431-gbccad87f3c
+ 0.4.12-dev-432-g3463b2db9f
CORE-15659 0.4.8-RC-3-g51f9494d48
[CDFS_NEW] superseded later by the proper fix 0.4.8-release-62-g8c07aad4a8
CORE-14067 0.4.8-dev-1069-ga5e89014dc
[CDFS_NEW] CORE-14315 0.4.8-dev-475-ga59d4674de
[NTOSKRNL] io/iomgr/device.c (forgotten assert) CORE-14128 0.4.8-dev-221-g9d67a24799
[CDFS_NEW] 0.4.8-dev-220-g67a7e45e35
[CDFS_NEW/DOC] 0.4.8-dev-219-g6a3bbf24e0
[CDFS_NEW] 0.4.8-dev-218-gec26cde4a1
[CDFS_NEW] 0.4.8-dev-217-gbc2378a356
[CDFS_NEW] 0.4.8-dev-216-g5429771b99
[CDFS_NEW] 0.4.8-dev-215-gfd34548263
[CDFS_NEW] Sync with MS-PL driver 0.4.8-dev-164-gec6b3ecbe4
[FILESYSTEMS] switch from CDFS to CDFS_NEW in CMakeLists.txt 0.4.8-dev-160-g2b217e4ecf
[NTOSKRNL] Mute spam CcSetReadAheadGranularity() 0.4.8-dev-159-g64cb138a67
[NTOSKRNL] Mute spam CcPurgeCacheSection() 0.4.8-dev-150-gf723d230a0
[CDFS_NEW] 0.4.8-dev-133-gfaee3753ea
[CDFS_NEW] CORE-14003 0.4.8-dev-132-g1d777ffab5
[NTOSKRNL] iofunc.c CORE-14003 0.4.8-dev-131-gc3d5a3f2bd
[NTOSKRNL] iofunc.c CORE-14003 0.4.8-dev-130-g3b64f7f8fb
[NTOSKRNL] ob/obref.c & co CORE-14003 0.4.8-dev-129-g7eefe70294
[NTOSKRNL] io/iomgr.c & co CORE-14003 0.4.8-dev-127-g5f255827d3
[CDFS_NEW] 0.4.8-dev-126-g1bef48796e
[NTOSKRNL] just a comment, superseded later 0.4.8-dev-125-gcbf0430b56
[CDFS_NEW] 0.4.8-dev-123-gf88fe43abd
[NTOSKRNL] io/iomgr/device.c (forbidden DPRINT) 0.4.8-dev-122-g6c73385625
[CDFS_NEW] CORE-13184 0.4.8-dev-97-g94298313c0
[CDFS_NEW] 0.4.8-dev-95-ge88eeb21af
[CDFS_NEW/NTOSKRNL] CcWaitForCurrentLazyWriterActivity() stub return Success 0.4.8-dev-94-g03d5be6437
[CDFS_NEW] 0.4.8-dev-93-gfa1c60db50
[CDFS_NEW] 0.4.8-dev-92-g8b2fd60829
[CDFS_NEW] 0.4.8-dev-91-ge4da7ecc50
[CDFS_NEW] 0.4.8-dev-90-g7b19676e2b
[CDFS_NEW] 0.4.8-dev-89-g3d4b8783fd
[CDFS_NEW] 0.4.8-dev-88-g818025ecc8
[CDFS_NEW] 0.4.8-dev-87-g2639dd6736
[CDFS_NEW] 0.4.8-dev-86-g755bdb5d0b
[CDFS_NEW] 0.4.8-dev-85-g3cbcb1bade
[CDFS_NEW] and mute spam in opcode INSTEAD of picking: 0.4.8-dev-165-g2284a457a3
[NTOSKRNL] oplock.c Fixup 0.4.8-dev-163-gd3d5853956
[NTOSKRNL] oplock.c Implement oplock-support 0.4.12-dev-232-gf488102c86
[CDFS] was also left out for now I am aware, that the backport introduces white-space-glitches within CDFS_NEW. I decided to live with them in favor of better sync to master and newer releases.
614 lines
16 KiB
C
614 lines
16 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: ntoskrnl/cc/copy.c
|
|
* PURPOSE: Implements cache managers copy interface
|
|
*
|
|
* PROGRAMMERS:
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
static PFN_NUMBER CcZeroPage = 0;
|
|
|
|
#define MAX_ZERO_LENGTH (256 * 1024)
|
|
|
|
typedef enum _CC_COPY_OPERATION
|
|
{
|
|
CcOperationRead,
|
|
CcOperationWrite,
|
|
CcOperationZero
|
|
} CC_COPY_OPERATION;
|
|
|
|
ULONG CcRosTraceLevel = 0;
|
|
ULONG CcFastMdlReadWait;
|
|
ULONG CcFastMdlReadNotPossible;
|
|
ULONG CcFastReadNotPossible;
|
|
ULONG CcFastReadWait;
|
|
ULONG CcFastReadNoWait;
|
|
ULONG CcFastReadResourceMiss;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
VOID
|
|
NTAPI
|
|
MiZeroPhysicalPage (
|
|
IN PFN_NUMBER PageFrameIndex
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcInitCacheZeroPage (
|
|
VOID)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
MI_SET_USAGE(MI_USAGE_CACHE);
|
|
//MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
|
|
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, TRUE, &CcZeroPage);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DbgPrint("Can't allocate CcZeroPage.\n");
|
|
KeBugCheck(CACHE_MANAGER);
|
|
}
|
|
MiZeroPhysicalPage(CcZeroPage);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcReadVirtualAddress (
|
|
PROS_VACB Vacb)
|
|
{
|
|
ULONG Size, Pages;
|
|
PMDL Mdl;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
KEVENT Event;
|
|
|
|
Size = (ULONG)(Vacb->SharedCacheMap->SectionSize.QuadPart - Vacb->FileOffset.QuadPart);
|
|
if (Size > VACB_MAPPING_GRANULARITY)
|
|
{
|
|
Size = VACB_MAPPING_GRANULARITY;
|
|
}
|
|
|
|
Pages = BYTES_TO_PAGES(Size);
|
|
ASSERT(Pages * PAGE_SIZE <= VACB_MAPPING_GRANULARITY);
|
|
|
|
Mdl = IoAllocateMdl(Vacb->BaseAddress, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
|
|
if (!Mdl)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_TRY
|
|
{
|
|
MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
|
|
}
|
|
_SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
KeBugCheck(CACHE_MANAGER);
|
|
} _SEH2_END;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Mdl->MdlFlags |= MDL_IO_PAGE_READ;
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
Status = IoPageRead(Vacb->SharedCacheMap->FileObject, Mdl, &Vacb->FileOffset, &Event, &IoStatus);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
MmUnlockPages(Mdl);
|
|
}
|
|
|
|
IoFreeMdl(Mdl);
|
|
|
|
if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
|
|
{
|
|
DPRINT1("IoPageRead failed, Status %x\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
if (Size < VACB_MAPPING_GRANULARITY)
|
|
{
|
|
RtlZeroMemory((char*)Vacb->BaseAddress + Size,
|
|
VACB_MAPPING_GRANULARITY - Size);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcWriteVirtualAddress (
|
|
PROS_VACB Vacb)
|
|
{
|
|
ULONG Size;
|
|
PMDL Mdl;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
KEVENT Event;
|
|
|
|
Vacb->Dirty = FALSE;
|
|
Size = (ULONG)(Vacb->SharedCacheMap->SectionSize.QuadPart - Vacb->FileOffset.QuadPart);
|
|
if (Size > VACB_MAPPING_GRANULARITY)
|
|
{
|
|
Size = VACB_MAPPING_GRANULARITY;
|
|
}
|
|
//
|
|
// Nonpaged pool PDEs in ReactOS must actually be synchronized between the
|
|
// MmGlobalPageDirectory and the real system PDE directory. What a mess...
|
|
//
|
|
{
|
|
ULONG i = 0;
|
|
do
|
|
{
|
|
MmGetPfnForProcess(NULL, (PVOID)((ULONG_PTR)Vacb->BaseAddress + (i << PAGE_SHIFT)));
|
|
} while (++i < (Size >> PAGE_SHIFT));
|
|
}
|
|
|
|
Mdl = IoAllocateMdl(Vacb->BaseAddress, Size, FALSE, FALSE, NULL);
|
|
if (!Mdl)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_TRY
|
|
{
|
|
MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess);
|
|
}
|
|
_SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
KeBugCheck(CACHE_MANAGER);
|
|
} _SEH2_END;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
Status = IoSynchronousPageWrite(Vacb->SharedCacheMap->FileObject, Mdl, &Vacb->FileOffset, &Event, &IoStatus);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
MmUnlockPages(Mdl);
|
|
}
|
|
IoFreeMdl(Mdl);
|
|
if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
|
|
{
|
|
DPRINT1("IoPageWrite failed, Status %x\n", Status);
|
|
Vacb->Dirty = TRUE;
|
|
return Status;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
ReadWriteOrZero(
|
|
_Inout_ PVOID BaseAddress,
|
|
_Inout_opt_ PVOID Buffer,
|
|
_In_ ULONG Length,
|
|
_In_ CC_COPY_OPERATION Operation)
|
|
{
|
|
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;
|
|
}
|
|
|
|
BOOLEAN
|
|
CcCopyData (
|
|
_In_ PFILE_OBJECT FileObject,
|
|
_In_ LONGLONG FileOffset,
|
|
_Inout_ PVOID Buffer,
|
|
_In_ LONGLONG Length,
|
|
_In_ CC_COPY_OPERATION Operation,
|
|
_In_ BOOLEAN Wait,
|
|
_Out_ PIO_STATUS_BLOCK IoStatus)
|
|
{
|
|
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;
|
|
|
|
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
|
CurrentOffset = FileOffset;
|
|
BytesCopied = 0;
|
|
|
|
if (!Wait)
|
|
{
|
|
/* 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 */
|
|
ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
|
|
while (ListEntry != &SharedCacheMap->CacheMapVacbListHead)
|
|
{
|
|
Vacb = CONTAINING_RECORD(ListEntry,
|
|
ROS_VACB,
|
|
CacheMapVacbListEntry);
|
|
ListEntry = ListEntry->Flink;
|
|
if (!Vacb->Valid &&
|
|
DoRangesIntersect(Vacb->FileOffset.QuadPart,
|
|
VACB_MAPPING_GRANULARITY,
|
|
CurrentOffset, Length))
|
|
{
|
|
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
|
|
/* data not available */
|
|
return FALSE;
|
|
}
|
|
if (Vacb->FileOffset.QuadPart >= CurrentOffset + Length)
|
|
break;
|
|
}
|
|
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
|
|
}
|
|
|
|
PartialLength = CurrentOffset % VACB_MAPPING_GRANULARITY;
|
|
if (PartialLength != 0)
|
|
{
|
|
PartialLength = min(Length, VACB_MAPPING_GRANULARITY - PartialLength);
|
|
Status = CcRosRequestVacb(SharedCacheMap,
|
|
ROUND_DOWN(CurrentOffset,
|
|
VACB_MAPPING_GRANULARITY),
|
|
&BaseAddress,
|
|
&Valid,
|
|
&Vacb);
|
|
if (!NT_SUCCESS(Status))
|
|
ExRaiseStatus(Status);
|
|
if (!Valid)
|
|
{
|
|
Status = CcReadVirtualAddress(Vacb);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
|
|
ExRaiseStatus(Status);
|
|
}
|
|
}
|
|
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 (Operation != CcOperationZero)
|
|
Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
|
|
}
|
|
|
|
while (Length > 0)
|
|
{
|
|
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))
|
|
{
|
|
Status = CcReadVirtualAddress(Vacb);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
|
|
ExRaiseStatus(Status);
|
|
}
|
|
}
|
|
Status = ReadWriteOrZero(BaseAddress, 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 (Operation != CcOperationZero)
|
|
Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
|
|
}
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
IoStatus->Information = BytesCopied;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcCanIWrite (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ULONG BytesToWrite,
|
|
IN BOOLEAN Wait,
|
|
IN BOOLEAN Retrying)
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p BytesToWrite=%lu Wait=%d Retrying=%d\n",
|
|
FileObject, BytesToWrite, Wait, Retrying);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @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)
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d\n",
|
|
FileObject, FileOffset->QuadPart, Length, Wait);
|
|
|
|
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
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcCopyWrite (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN PVOID Buffer)
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d Buffer=%p\n",
|
|
FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
|
|
|
|
DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
|
|
"Length %lu, Wait %u, Buffer 0x%p)\n",
|
|
FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
|
|
|
|
return CcCopyData(FileObject,
|
|
FileOffset->QuadPart,
|
|
Buffer,
|
|
Length,
|
|
CcOperationWrite,
|
|
Wait,
|
|
&IoStatus);
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
CcDeferWrite (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PCC_POST_DEFERRED_WRITE PostRoutine,
|
|
IN PVOID Context1,
|
|
IN PVOID Context2,
|
|
IN ULONG BytesToWrite,
|
|
IN BOOLEAN Retrying)
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p PostRoutine=%p Context1=%p Context2=%p BytesToWrite=%lu Retrying=%d\n",
|
|
FileObject, PostRoutine, Context1, Context2, BytesToWrite, Retrying);
|
|
|
|
PostRoutine(Context1, Context2);
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
CcFastCopyRead (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ULONG FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG PageCount,
|
|
OUT PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus)
|
|
{
|
|
LARGE_INTEGER LargeFileOffset;
|
|
BOOLEAN Success;
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu PageCount=%lu Buffer=%p\n",
|
|
FileObject, FileOffset, Length, PageCount, Buffer);
|
|
|
|
DBG_UNREFERENCED_PARAMETER(PageCount);
|
|
|
|
LargeFileOffset.QuadPart = FileOffset;
|
|
Success = CcCopyRead(FileObject,
|
|
&LargeFileOffset,
|
|
Length,
|
|
TRUE,
|
|
Buffer,
|
|
IoStatus);
|
|
ASSERT(Success == TRUE);
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
CcFastCopyWrite (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ULONG FileOffset,
|
|
IN ULONG Length,
|
|
IN PVOID Buffer)
|
|
{
|
|
LARGE_INTEGER LargeFileOffset;
|
|
BOOLEAN Success;
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu Buffer=%p\n",
|
|
FileObject, FileOffset, Length, Buffer);
|
|
|
|
LargeFileOffset.QuadPart = FileOffset;
|
|
Success = CcCopyWrite(FileObject,
|
|
&LargeFileOffset,
|
|
Length,
|
|
TRUE,
|
|
Buffer);
|
|
ASSERT(Success == TRUE);
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
CcWaitForCurrentLazyWriterActivity (
|
|
VOID)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcZeroData (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER StartOffset,
|
|
IN PLARGE_INTEGER EndOffset,
|
|
IN BOOLEAN Wait)
|
|
{
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER WriteOffset;
|
|
LONGLONG Length;
|
|
ULONG CurrentLength;
|
|
PMDL Mdl;
|
|
ULONG i;
|
|
IO_STATUS_BLOCK Iosb;
|
|
KEVENT Event;
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p StartOffset=%I64u EndOffset=%I64u Wait=%d\n",
|
|
FileObject, StartOffset->QuadPart, EndOffset->QuadPart, Wait);
|
|
|
|
DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
|
|
"Wait %u)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
|
|
Wait);
|
|
|
|
Length = EndOffset->QuadPart - StartOffset->QuadPart;
|
|
WriteOffset.QuadPart = StartOffset->QuadPart;
|
|
|
|
if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
|
|
{
|
|
/* File is not cached */
|
|
|
|
Mdl = _alloca(MmSizeOfMdl(NULL, MAX_ZERO_LENGTH));
|
|
|
|
while (Length > 0)
|
|
{
|
|
if (Length + WriteOffset.QuadPart % PAGE_SIZE > MAX_ZERO_LENGTH)
|
|
{
|
|
CurrentLength = MAX_ZERO_LENGTH - WriteOffset.QuadPart % PAGE_SIZE;
|
|
}
|
|
else
|
|
{
|
|
CurrentLength = Length;
|
|
}
|
|
MmInitializeMdl(Mdl, (PVOID)(ULONG_PTR)WriteOffset.QuadPart, CurrentLength);
|
|
Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
|
|
for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++)
|
|
{
|
|
((PPFN_NUMBER)(Mdl + 1))[i] = CcZeroPage;
|
|
}
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
Status = IoSynchronousPageWrite(FileObject, Mdl, &WriteOffset, &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))
|
|
{
|
|
return FALSE;
|
|
}
|
|
WriteOffset.QuadPart += CurrentLength;
|
|
Length -= CurrentLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
return CcCopyData(FileObject,
|
|
WriteOffset.QuadPart,
|
|
NULL,
|
|
Length,
|
|
CcOperationZero,
|
|
Wait,
|
|
&IoStatus);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|