mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
848 lines
32 KiB
C
848 lines
32 KiB
C
#include <ntifs.h>
|
|
#include "ntndk.h"
|
|
#include "fsrtl_glue.h"
|
|
|
|
#include "fastio.h"
|
|
#include "fsrtl.h"
|
|
|
|
/*
|
|
This is the main test function. It is called from DriverEntry.
|
|
|
|
There is a DbgBreakPoint() call at the beginning of DriverEntry.
|
|
In order to run the test again, simply type
|
|
net stop fsrtl
|
|
net start fsrtl
|
|
|
|
Author: Dom Cote
|
|
*/
|
|
|
|
BOOLEAN FsRtlTest_StartTest() {
|
|
HANDLE Fh = NULL;
|
|
PFILE_OBJECT Pfo = NULL;
|
|
|
|
HANDLE DirFh = NULL;
|
|
PFILE_OBJECT DirPfo = NULL;
|
|
|
|
|
|
IO_STATUS_BLOCK IoStatus;
|
|
BOOLEAN Return;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LONGLONG i = 0;
|
|
|
|
PCHAR Buffer;
|
|
PMDL MdlChain = 0;
|
|
|
|
LARGE_INTEGER Offset;
|
|
ULONG Length = 0;
|
|
LARGE_INTEGER OldSize;
|
|
|
|
/* Parameters we are going to use in the test from the FCB */
|
|
PFSRTL_COMMON_FCB_HEADER FcbHeader;
|
|
PLARGE_INTEGER AllocationSize;
|
|
PLARGE_INTEGER ValidDataLength;
|
|
PLARGE_INTEGER FileSize;
|
|
|
|
PDEVICE_OBJECT pRelatedDo = NULL;
|
|
|
|
/* Allocate a 100KB buffer to do IOs */
|
|
Buffer = ExAllocatePool(PagedPool,100*_1KB);
|
|
|
|
/* ------------------------------------------------------------------------
|
|
TESTING:
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
OUT PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
with Wait = TRUE
|
|
|
|
------------------------------------------------------------------------ */
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
FSRTL_TEST("Opening Test File.",((Pfo != NULL) && (Fh != NULL)));
|
|
|
|
/* Extract the test variable from the FCB struct */
|
|
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)Pfo->FsContext;
|
|
AllocationSize = &FcbHeader->AllocationSize;
|
|
ValidDataLength = &FcbHeader->ValidDataLength;
|
|
FileSize = &FcbHeader->FileSize;
|
|
|
|
/* Try to cache without caching having been initialized. This should fail.*/
|
|
Length = 10*_1KB;
|
|
FSRTL_TEST("FsRtlCopyWrite() - No cache map test.",!FsRtlCopyWrite(Pfo,AllocationSize,Length,TRUE,0,Buffer,&IoStatus,NULL));
|
|
|
|
/* We are going to build a 100k file */
|
|
/* This will inititate caching and build some size */
|
|
Offset.QuadPart = 0;
|
|
Length = 100*_1KB;
|
|
Return = FsRltTest_WritefileZw(Fh,&Offset,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlCopyWrite() - Building 100k filesize.",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Extending the file by 1/2 sector, 256 bytes. */
|
|
Offset.QuadPart = 0x7fffffffffff;
|
|
Length = 0x100;
|
|
Return = FsRltTest_WritefileZw(Fh,NULL,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlCopyWrite() - Extending by 1/2 sector.",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Append to the file past the allocation size*/
|
|
Offset.LowPart = 0xFFFFFFFF;
|
|
Offset.HighPart = 0xFFFFFFFF;
|
|
OldSize.QuadPart = FileSize->QuadPart;
|
|
Length = (ULONG) (AllocationSize->QuadPart -ValidDataLength->QuadPart);
|
|
FSRTL_TEST("FsRtlCopyWrite() - Testing extending past allocation size",!FsRtlCopyWrite(Pfo,&Offset,Length+1,TRUE,0,Buffer,&IoStatus,NULL));
|
|
FSRTL_TEST("FsRtlCopyWrite() - Testing extending not past allocation size",FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL));
|
|
FSRTL_TEST("FsRtlCopyWrite() - Check filesize",(FileSize->QuadPart = (OldSize.QuadPart+Length)));
|
|
|
|
/* Try do write a 65kb IO and check that if fails. Maximum IO size for thus function is 64KB */
|
|
Offset.QuadPart = 0;
|
|
Length = 65*_1KB;
|
|
FSRTL_TEST("FsRtlCopyWrite() - 65KB IO Test",!FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL));
|
|
|
|
/* Try do write a 64kb IO. Maximum IO size for thus function is 64KB */
|
|
Length = 64*_1KB;
|
|
FSRTL_TEST("FsRtlCopyWrite() - 64KB IO Test",FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL))
|
|
|
|
/* Test the fast Io questionable flag
|
|
This test fails and should succeed. I am not sure why. When FsRtlCopyWrite() queries the FastIoTable of the related
|
|
device object, it comes back with no.
|
|
FcbHeader->IsFastIoPossible = FastIoIsQuestionable;
|
|
FSRTL_TEST("FastIo is questionable flag",FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL))
|
|
*/
|
|
|
|
/* Test the fast Io not possible flag */
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlCopyWrite() - FastIo is not possible flag",!FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL))
|
|
/* Set the flag back to what it was */
|
|
FcbHeader->IsFastIoPossible = FastIoIsPossible;
|
|
FSRTL_TEST("FsRtlCopyWrite() - FastIo is possbile flag",FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL))
|
|
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
TESTING:
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
OUT PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
with Wait = FALSE
|
|
|
|
------------------------------------------------------------------------ */
|
|
|
|
/* We are going to repeat the same bunch of tests but with Wait = FALSE. So we exercise the second part of the function. */
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
|
|
/* Extract the test variable from the FCB struct */
|
|
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)Pfo->FsContext;
|
|
AllocationSize = &FcbHeader->AllocationSize;
|
|
ValidDataLength = &FcbHeader->ValidDataLength;
|
|
FileSize = &FcbHeader->FileSize;
|
|
|
|
/* Try to cache without caching having been initialized. This should fail.*/
|
|
Length = 10*_1KB;
|
|
FSRTL_TEST("FsRtlCopyWrite() - No cache map test. Wait = FALSE",!FsRtlCopyWrite(Pfo,AllocationSize,Length,FALSE,0,Buffer,&IoStatus,NULL));
|
|
|
|
/* We are going to build a 100k file */
|
|
/* This will inititate caching and build some size */
|
|
Offset.QuadPart = 0;
|
|
Length = 100*_1KB;
|
|
Return = FsRltTest_WritefileZw(Fh,&Offset,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlCopyWrite() - Building 100k filesize. Wait = FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Extending the file by 1/2 sector, 256 bytes. */
|
|
Offset.QuadPart = 0x7fffffffffff;
|
|
Length = 0x100;
|
|
Return = FsRltTest_WritefileZw(Fh,NULL,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlCopyWrite() - Extending by 1/2 sector. Wait = FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Append to the file past the allocation size*/
|
|
Offset.LowPart = 0xFFFFFFFF;
|
|
Offset.HighPart = 0xFFFFFFFF;
|
|
OldSize.QuadPart = FileSize->QuadPart;
|
|
Length = (ULONG) (AllocationSize->QuadPart -ValidDataLength->QuadPart);
|
|
FSRTL_TEST("FsRtlCopyWrite() - Testing extending past allocation size Wait = FALSE",!FsRtlCopyWrite(Pfo,&Offset,Length+1,FALSE,0,Buffer,&IoStatus,NULL));
|
|
FSRTL_TEST("FsRtlCopyWrite() - Testing extending not past allocation size. Wait = FALSE",FsRtlCopyWrite(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL));
|
|
FSRTL_TEST("FsRtlCopyWrite() - Check filesize",(FileSize->QuadPart = (OldSize.QuadPart+Length)));
|
|
|
|
/* Try do write a 65kb IO and check that if fails. Maximum IO size for thus function is 64KB */
|
|
Offset.QuadPart = 0;
|
|
Length = 65*_1KB;
|
|
FSRTL_TEST("FsRtlCopyWrite() - 65KB IO Test. Wait = FALSE",!FsRtlCopyWrite(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL));
|
|
|
|
/* Try do write a 64kb IO. Maximum IO size for thus function is 64KB */
|
|
Length = 64*_1KB;
|
|
FSRTL_TEST("FsRtlCopyWrite() - 64KB IO Test. Wait = FALSE",FsRtlCopyWrite(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL))
|
|
|
|
/* Test the fast Io questionable flag
|
|
This test fails and should succeed. I am not sure why. When FsRtlCopyWrite() queries the FastIoTable of the related
|
|
device object, it comes back with no.
|
|
FcbHeader->IsFastIoPossible = FastIoIsQuestionable;
|
|
FSRTL_TEST("FastIo is questionable flag",FsRtlCopyWrite(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL))
|
|
*/
|
|
|
|
/* Test the fast Io not possible flag */
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlCopyWrite() - FastIo is not possible flag. Wait = FALSE",!FsRtlCopyWrite(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL))
|
|
/* Set the flag back to what it was */
|
|
FcbHeader->IsFastIoPossible = FastIoIsPossible;
|
|
FSRTL_TEST("FsRtlCopyWrite() - FastIo is possbile flag. Wait = FALSE",FsRtlCopyWrite(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL))
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------
|
|
TESTING:
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRtlCopyRead(IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
OUT PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
------------------------------------------------------------------------------------------ */
|
|
|
|
Offset.LowPart = 0x0;
|
|
Offset.HighPart = 0x0;
|
|
Length = 0x10000;
|
|
|
|
/* Testing a 64KB read with Wait = TRUE */
|
|
Return = FsRtlCopyRead(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlCopyRead() - Testing 64k IO Wait=TRUE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Testing a 64KB read with Wait = FALSE */
|
|
Return = FsRtlCopyRead(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlCopyRead() - Testing 64k IO Wait=FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Testing read past the end of the file */
|
|
Offset.QuadPart = FileSize->QuadPart - (5 * _1KB);
|
|
Length = 10 * _1KB;
|
|
Return = FsRtlCopyRead(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlCopyRead() - Testing reading past end of file but starting before EOF",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status) && IoStatus.Information == (FileSize->QuadPart-Offset.QuadPart)));
|
|
|
|
Offset.QuadPart = FileSize->QuadPart + 1;
|
|
Length = 10 * _1KB;
|
|
Return = FsRtlCopyRead(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlCopyRead() - Testing reading past end of file but starting after EOF",(NT_SUCCESS(Return) && (IoStatus.Status == STATUS_END_OF_FILE) && IoStatus.Information == 0));
|
|
|
|
|
|
/* Testing a 64KB read with Wait = TRUE */
|
|
Offset.LowPart = 0x0;
|
|
Offset.HighPart = 0x0;
|
|
Length = 0x10000;
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlCopyRead() - FastIo is not possible flag. Wait = FALSE",!FsRtlCopyRead(Pfo,&Offset,Length,FALSE,0,Buffer,&IoStatus,NULL));
|
|
FSRTL_TEST("FsRtlCopyRead() - FastIo is not possible flag. Wait = TRUE",!FsRtlCopyRead(Pfo,&Offset,Length,TRUE,0,Buffer,&IoStatus,NULL));
|
|
FcbHeader->IsFastIoPossible = FastIoIsPossible;
|
|
Return = TRUE;
|
|
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
TESTING:
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
------------------------------------------------------------------------ */
|
|
|
|
/* We are going to repeat the same bunch of tests but with Wait = FALSE. So we exercise the second part of the function. */
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
|
|
/* Extract the test variable from the FCB struct */
|
|
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)Pfo->FsContext;
|
|
AllocationSize = &FcbHeader->AllocationSize;
|
|
ValidDataLength = &FcbHeader->ValidDataLength;
|
|
FileSize = &FcbHeader->FileSize;
|
|
|
|
/* Try to cache without caching having been initialized. This should fail.*/
|
|
Length = 10*_1KB;
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - No cache map test. Wait = FALSE",
|
|
!FsRtlPrepareMdlWriteDev(Pfo,AllocationSize,Length,0,MdlChain,&IoStatus,NULL));
|
|
|
|
/* We are going to build a 100k file */
|
|
/* This will inititate caching and build some size */
|
|
Offset.QuadPart = 0;
|
|
Length = 100*_1KB;
|
|
Return = FsRltTest_WritefileZw(Fh,&Offset,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Building 100k filesize. Wait = FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Extending the file by 1/2 sector, 256 bytes. */
|
|
Offset.QuadPart = 0x7fffffffffff;
|
|
Length = 0x100;
|
|
Return = FsRltTest_WritefileZw(Fh,NULL,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Extending by 1/2 sector. Wait = FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
|
|
pRelatedDo = IoGetRelatedDeviceObject(Pfo);
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Did we get related DO ?",pRelatedDo);
|
|
|
|
|
|
/* Append to the file past the allocation size*/
|
|
Offset.QuadPart = FileSize->QuadPart;
|
|
OldSize.QuadPart = FileSize->QuadPart;
|
|
Length = (ULONG) (AllocationSize->QuadPart -ValidDataLength->QuadPart);
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Testing extending past allocation size.",
|
|
!FsRtlPrepareMdlWriteDev(Pfo,&Offset,Length+1,0,&MdlChain,&IoStatus,pRelatedDo));
|
|
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Testing extending not past allocation size.",
|
|
FsRtlPrepareMdlWriteDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,pRelatedDo));
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Check filesize",(FileSize->QuadPart = (OldSize.QuadPart+Length)));
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Release the MDL.",FsRtlMdlWriteCompleteDev(Pfo,&Offset,MdlChain,pRelatedDo));
|
|
|
|
|
|
/* Try do write a 65kb IO and check that if fails. Maximum IO size for thus function is 64KB */
|
|
Offset.QuadPart = 0;
|
|
MdlChain = NULL;
|
|
Length = 65*_1KB;
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - 65KB IO Test.",
|
|
FsRtlPrepareMdlWriteDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,pRelatedDo));
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Release the MDL.",FsRtlMdlWriteCompleteDev(Pfo,&Offset,MdlChain,pRelatedDo));
|
|
|
|
/* Try do write a 64kb IO. Maximum IO size for thus function is 64KB */
|
|
Length = 64*_1KB;
|
|
MdlChain = NULL;
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - 64KB IO Test.",
|
|
FsRtlPrepareMdlWriteDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,NULL))
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - Release the MDL.",FsRtlMdlWriteCompleteDev(Pfo,&Offset,MdlChain,NULL));
|
|
|
|
/* Test the fast Io not possible flag */
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlPrepareMdlWriteDev() - FastIo is not possible flag.",
|
|
!FsRtlPrepareMdlWriteDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,NULL))
|
|
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
TESTING:
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRtlPrepareMdlWrite( IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
------------------------------------------------------------------------ */
|
|
|
|
/* We are going to repeat the same bunch of tests but with Wait = FALSE. So we exercise the second part of the function. */
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
|
|
/* Extract the test variable from the FCB struct */
|
|
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)Pfo->FsContext;
|
|
AllocationSize = &FcbHeader->AllocationSize;
|
|
ValidDataLength = &FcbHeader->ValidDataLength;
|
|
FileSize = &FcbHeader->FileSize;
|
|
|
|
/* Try to cache without caching having been initialized. This should fail.*/
|
|
Length = 10*_1KB;
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - No cache map test. Wait = FALSE",
|
|
!FsRtlPrepareMdlWrite(Pfo,AllocationSize,Length,0,MdlChain,&IoStatus));
|
|
|
|
/* We are going to build a 100k file */
|
|
/* This will inititate caching and build some size */
|
|
Offset.QuadPart = 0;
|
|
Length = 100*_1KB;
|
|
Return = FsRltTest_WritefileZw(Fh,&Offset,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Building 100k filesize. Wait = FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
/* Extending the file by 1/2 sector, 256 bytes. */
|
|
Offset.QuadPart = 0x7fffffffffff;
|
|
Length = 0x100;
|
|
Return = FsRltTest_WritefileZw(Fh,NULL,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Extending by 1/2 sector. Wait = FALSE",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
|
|
/* Append to the file past the allocation size*/
|
|
MdlChain = NULL;
|
|
Offset.QuadPart = FileSize->QuadPart;
|
|
OldSize.QuadPart = FileSize->QuadPart;
|
|
Length = (ULONG) (AllocationSize->QuadPart -ValidDataLength->QuadPart);
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Testing extending past allocation size.",
|
|
!FsRtlPrepareMdlWrite(Pfo,&Offset,Length+1,0,&MdlChain,&IoStatus));
|
|
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Testing extending not past allocation size.",
|
|
FsRtlPrepareMdlWrite(Pfo,&Offset,Length,0,&MdlChain,&IoStatus));
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Check filesize",(FileSize->QuadPart = (OldSize.QuadPart+Length)));
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Release the MDL.",FsRtlMdlWriteComplete(Pfo,&Offset,MdlChain));
|
|
|
|
|
|
/* Try do write a 65kb IO and check that if fails. Maximum IO size for thus function is 64KB */
|
|
Offset.QuadPart = 0;
|
|
MdlChain = NULL;
|
|
Length = 65*_1KB;
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - 65KB IO Test.",
|
|
!FsRtlPrepareMdlWrite(Pfo,&Offset,Length,0,&MdlChain,&IoStatus));
|
|
//FSRTL_TEST("FsRtlPrepareMdlWrite() - Release the MDL.",FsRtlMdlWriteComplete(Pfo,&Offset,MdlChain));
|
|
|
|
/* Try do write a 64kb IO. Maximum IO size for thus function is 64KB */
|
|
Length = 64*_1KB;
|
|
MdlChain = NULL;
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - 64KB IO Test.",
|
|
FsRtlPrepareMdlWrite(Pfo,&Offset,Length,0,&MdlChain,&IoStatus))
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - Release the MDL.",FsRtlMdlWriteComplete(Pfo,&Offset,MdlChain));
|
|
|
|
/* Test the fast Io not possible flag */
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlPrepareMdlWrite() - FastIo is not possible flag.",
|
|
!FsRtlPrepareMdlWrite(Pfo,&Offset,Length,0,&MdlChain,&IoStatus))
|
|
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------
|
|
TESTING:
|
|
|
|
FsRtlMdlReadDev(IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,
|
|
IN PMDL MemoryDescriptorList,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
|
|
/* Extract the test variable from the FCB struct */
|
|
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)Pfo->FsContext;
|
|
AllocationSize = &FcbHeader->AllocationSize;
|
|
ValidDataLength = &FcbHeader->ValidDataLength;
|
|
FileSize = &FcbHeader->FileSize;
|
|
|
|
|
|
/* We are going to build a 100k file */
|
|
/* This will inititate caching and build some size */
|
|
Offset.QuadPart = 0;
|
|
Length = 100*_1KB;
|
|
Return = FsRltTest_WritefileZw(Fh,&Offset,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlMdlReadDev() - Building 100k filesize.",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
|
|
Offset.LowPart = 0x0;
|
|
Offset.HighPart = 0x0;
|
|
Length = 0x10000;
|
|
|
|
/* Testing a 64KB read */
|
|
MdlChain = NULL;
|
|
Return = FsRtlMdlReadDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlMdlReadDev() - Testing 64k IO",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
FSRTL_TEST("FsRtlMdlReadDev() - Releasing the MDL",FsRtlMdlReadCompleteDev(Pfo,MdlChain,NULL));
|
|
|
|
|
|
/* Testing read past the end of the file */
|
|
Offset.QuadPart = FileSize->QuadPart - (5 * _1KB);
|
|
Length = 10 * _1KB;
|
|
MdlChain = NULL;
|
|
Return = FsRtlMdlReadDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlMdlReadDev() - Testing reading past end of file but starting before EOF",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status) && IoStatus.Information == (FileSize->QuadPart-Offset.QuadPart)));
|
|
FSRTL_TEST("FsRtlMdlReadDev() - Releasing the MDL",FsRtlMdlReadCompleteDev(Pfo,MdlChain,NULL));
|
|
|
|
Offset.QuadPart = FileSize->QuadPart + 1;
|
|
Length = 10 * _1KB;
|
|
MdlChain = NULL;
|
|
Return = FsRtlMdlReadDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,NULL);
|
|
FSRTL_TEST("FsRtlMdlReadDev() - Testing reading past end of file but starting after EOF",(NT_SUCCESS(Return) && (IoStatus.Status == STATUS_END_OF_FILE) && IoStatus.Information == 0));
|
|
|
|
/* Testing FastIoIsNotPossible */
|
|
Offset.LowPart = 0x0;
|
|
Offset.HighPart = 0x0;
|
|
MdlChain = NULL;
|
|
Length = 0x10000;
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlMdlReadDev() - FastIo is not possible flag. Wait = TRUE",!FsRtlMdlReadDev(Pfo,&Offset,Length,0,&MdlChain,&IoStatus,NULL));
|
|
|
|
Return = TRUE;
|
|
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------
|
|
TESTING:
|
|
|
|
FsRtlMdlRead(IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus)
|
|
|
|
FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,
|
|
IN PMDL MemoryDescriptorList)
|
|
|
|
------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
|
|
/* Extract the test variable from the FCB struct */
|
|
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)Pfo->FsContext;
|
|
AllocationSize = &FcbHeader->AllocationSize;
|
|
ValidDataLength = &FcbHeader->ValidDataLength;
|
|
FileSize = &FcbHeader->FileSize;
|
|
|
|
|
|
/* We are going to build a 100k file */
|
|
/* This will inititate caching and build some size */
|
|
Offset.QuadPart = 0;
|
|
Length = 100*_1KB;
|
|
Return = FsRltTest_WritefileZw(Fh,&Offset,Length, Buffer, &IoStatus);
|
|
FSRTL_TEST("FsRtlMdlRead() - Building 100k filesize.",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
Return = TRUE;
|
|
|
|
|
|
Offset.LowPart = 0x0;
|
|
Offset.HighPart = 0x0;
|
|
Length = 0x10000;
|
|
|
|
/* Testing a 64KB read */
|
|
MdlChain = NULL;
|
|
Return = FsRtlMdlRead(Pfo,&Offset,Length,0,&MdlChain,&IoStatus);
|
|
FSRTL_TEST("FsRtlMdlRead() - Testing 64k IO",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status ) && IoStatus.Information == Length));
|
|
FSRTL_TEST("FsRtlMdlRead() - Releasing the MDL",FsRtlMdlReadComplete(Pfo,MdlChain));
|
|
|
|
|
|
/* Testing read past the end of the file */
|
|
Offset.QuadPart = FileSize->QuadPart - (5 * _1KB);
|
|
Length = 10 * _1KB;
|
|
MdlChain = NULL;
|
|
Return = FsRtlMdlRead(Pfo,&Offset,Length,0,&MdlChain,&IoStatus);
|
|
FSRTL_TEST("FsRtlMdlRead() - Testing reading past end of file but starting before EOF",(NT_SUCCESS(Return) && NT_SUCCESS(IoStatus.Status) && IoStatus.Information == (FileSize->QuadPart-Offset.QuadPart)));
|
|
FSRTL_TEST("FsRtlMdlRead() - Releasing the MDL",FsRtlMdlReadComplete(Pfo,MdlChain));
|
|
|
|
Offset.QuadPart = FileSize->QuadPart + 1;
|
|
Length = 10 * _1KB;
|
|
MdlChain = NULL;
|
|
Return = FsRtlMdlRead(Pfo,&Offset,Length,0,&MdlChain,&IoStatus);
|
|
FSRTL_TEST("FsRtlMdlRead() - Testing reading past end of file but starting after EOF",(NT_SUCCESS(Return) && (IoStatus.Status == STATUS_END_OF_FILE) && IoStatus.Information == 0));
|
|
|
|
/* Testing FastIoIsNotPossible */
|
|
Offset.LowPart = 0x0;
|
|
Offset.HighPart = 0x0;
|
|
MdlChain = NULL;
|
|
Length = 0x10000;
|
|
FcbHeader->IsFastIoPossible = FastIoIsNotPossible;
|
|
FSRTL_TEST("FsRtlMdlRead() - FastIo is not possible flag. Wait = TRUE",!FsRtlMdlRead(Pfo,&Offset,Length,0,&MdlChain,&IoStatus));
|
|
|
|
Return = TRUE;
|
|
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------
|
|
TESTING:
|
|
|
|
FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
|
|
IN OUT PLARGE_INTEGER FileSize)
|
|
|
|
------------------------------------------------------------------------------------------
|
|
*/
|
|
FsRtlTest_OpenTestFile(&Fh, &Pfo);
|
|
FSRTL_TEST("FsRtlGetFileSize() - Opening Test File.",((Pfo != NULL) && (Fh != NULL)));
|
|
|
|
FsRtlTest_OpenTestDirectory(&DirFh, &DirPfo);
|
|
FSRTL_TEST("FsRtlGetFileSize() - Opening Test Directory.",((DirPfo != NULL) && (DirFh != NULL)));
|
|
|
|
Status = FsRtlGetFileSize(Pfo,&OldSize);
|
|
FSRTL_TEST("FsRtlGetFileSize() - Get the size of a real file",NT_SUCCESS(Status));
|
|
|
|
Status = FsRtlGetFileSize(DirPfo,&OldSize);
|
|
FSRTL_TEST("FsRtlGetFileSize() - Get the size of a directory file",(Status == STATUS_FILE_IS_A_DIRECTORY));
|
|
|
|
|
|
/* The test if over. Do clean up */
|
|
|
|
Cleanup:
|
|
|
|
if (DirPfo)
|
|
{
|
|
ObDereferenceObject(DirPfo);
|
|
DirPfo = NULL;
|
|
}
|
|
|
|
if (DirFh)
|
|
{
|
|
ZwClose(DirFh);
|
|
DirFh = NULL;
|
|
}
|
|
if (Pfo)
|
|
{
|
|
ObDereferenceObject(Pfo);
|
|
Pfo = NULL;
|
|
}
|
|
|
|
if (Fh)
|
|
{
|
|
ZwClose(Fh);
|
|
Fh = NULL;
|
|
}
|
|
|
|
if (Buffer != NULL) {
|
|
ExFreePool(Buffer);
|
|
Buffer = NULL;
|
|
}
|
|
|
|
return Return;
|
|
|
|
}
|
|
|
|
/* This function is just a wrapper around ZwWriteFile */
|
|
NTSTATUS FsRltTest_WritefileZw(HANDLE fh, PLARGE_INTEGER Offset, ULONG Length, PVOID Buffer, PIO_STATUS_BLOCK pIoStatus){
|
|
NTSTATUS Return;
|
|
|
|
Return = ZwWriteFile(
|
|
fh,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
pIoStatus,
|
|
Buffer,
|
|
Length,
|
|
Offset,
|
|
NULL
|
|
);
|
|
|
|
return Return;
|
|
}
|
|
|
|
/* This function fills the buffer with a test pattern */
|
|
void FsRtlTest_FillBuffer(LARGE_INTEGER Start, ULONG Length, PVOID Buffer) {
|
|
ULONG i = 0;
|
|
PULONGLONG Index = (PULONGLONG) Buffer;
|
|
|
|
for (i=0; i<Length/sizeof(ULONGLONG); i++) {
|
|
Index[i] = Start.QuadPart + i;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* This function opens a test file with the FILE_DELETE_ON_CLOSE flag
|
|
and reference the file object
|
|
*/
|
|
NTSTATUS FsRtlTest_OpenTestFile(PHANDLE Pfh, PFILE_OBJECT *Ppfo) {
|
|
UNICODE_STRING FileName;
|
|
OBJECT_ATTRIBUTES oa;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS Return;
|
|
|
|
RtlInitUnicodeString(&FileName,L"\\??\\C:\\fsrtl.bin");
|
|
|
|
InitializeObjectAttributes(
|
|
&oa,
|
|
&FileName,
|
|
OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL;
|
|
);
|
|
|
|
Return = IoCreateFile(Pfh,
|
|
GENERIC_WRITE,
|
|
&oa,
|
|
&IoStatus,
|
|
0,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0,
|
|
FILE_OVERWRITE_IF ,
|
|
FILE_SYNCHRONOUS_IO_ALERT | FILE_DELETE_ON_CLOSE,
|
|
NULL,
|
|
0,
|
|
CreateFileTypeNone,
|
|
NULL,
|
|
0);
|
|
|
|
Return = ObReferenceObjectByHandle(
|
|
*Pfh,
|
|
GENERIC_WRITE,
|
|
NULL,
|
|
KernelMode,
|
|
Ppfo,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
NTSTATUS FsRtlTest_OpenTestDirectory(PHANDLE Pfh, PFILE_OBJECT *Ppfo) {
|
|
UNICODE_STRING FileName;
|
|
OBJECT_ATTRIBUTES oa;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS Return;
|
|
|
|
RtlInitUnicodeString(&FileName,L"\\??\\C:\\testdir01");
|
|
|
|
InitializeObjectAttributes(
|
|
&oa,
|
|
&FileName,
|
|
OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL;
|
|
);
|
|
|
|
Return = IoCreateFile(Pfh,
|
|
GENERIC_WRITE,
|
|
&oa,
|
|
&IoStatus,
|
|
0,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0,
|
|
FILE_OPEN_IF,
|
|
FILE_DIRECTORY_FILE,FILE_SYNCHRONOUS_IO_ALERT | FILE_DELETE_ON_CLOSE,
|
|
NULL,
|
|
0,
|
|
CreateFileTypeNone,
|
|
NULL,
|
|
0);
|
|
|
|
Return = ObReferenceObjectByHandle(
|
|
*Pfh,
|
|
GENERIC_WRITE,
|
|
NULL,
|
|
KernelMode,
|
|
Ppfo,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
/* All the testing is done from driver entry */
|
|
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
|
|
{
|
|
PDEVICE_OBJECT DeviceObject;
|
|
NTSTATUS mStatus;
|
|
UNICODE_STRING uniName, uniDOSName;
|
|
PDEVOBJ_EXTENSION x;
|
|
|
|
DbgPrint("Loading the FSRTL test driver.\n");
|
|
DbgBreakPoint();
|
|
|
|
/* register device functions */
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRtlTest_DispatchCreateClose;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRtlTest_DispatchCreateClose;
|
|
DriverObject->DriverUnload = FsRtlTest_Unload;
|
|
|
|
if (!FsRtlTest_StartTest()) {
|
|
DbgPrint("FsRtl test failed.\n");
|
|
} else {
|
|
DbgPrint("FsRtl test OK.\n");
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS FsRtlTest_DispatchCreateClose( IN PDEVICE_OBJECT devObj, IN PIRP Irp )
|
|
{
|
|
DbgPrint(("FsRtl: Open / Close\n"));
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID FsRtlTest_Unload( IN PDRIVER_OBJECT DriverObject )
|
|
{
|
|
DbgPrint(("FsRtl: Unloading.\n"));
|
|
}
|
|
|
|
|