mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 08:53:01 -05:00
sys: IRP_MJ_WRITE: implementation
This commit is contained in:
parent
a7f1316ffe
commit
d46d1e169a
@ -181,6 +181,22 @@ typedef struct
|
|||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
} Close;
|
} Close;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext;
|
||||||
|
UINT64 UserContext2;
|
||||||
|
} Read;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext;
|
||||||
|
UINT64 UserContext2;
|
||||||
|
UINT64 Address;
|
||||||
|
UINT64 Offset;
|
||||||
|
UINT32 Length;
|
||||||
|
UINT32 Key;
|
||||||
|
UINT32 Append:1; /* append to end of file */
|
||||||
|
UINT32 PagingIo:1; /* write's beyond EOF are NOP's (file size remains same) */
|
||||||
|
} Write;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
@ -281,6 +297,10 @@ typedef struct
|
|||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
} Overwrite;
|
} Overwrite;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
} Write;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
} QueryInformation;
|
} QueryInformation;
|
||||||
|
@ -61,6 +61,10 @@ VOID FspAcquireFileForNtCreateSection(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_VOID(PAGED_CODE());
|
FSP_ENTER_VOID(PAGED_CODE());
|
||||||
|
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE_VOID("FileObject=%p", FileObject);
|
FSP_LEAVE_VOID("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +73,10 @@ VOID FspReleaseFileForNtCreateSection(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_VOID(PAGED_CODE());
|
FSP_ENTER_VOID(PAGED_CODE());
|
||||||
|
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE_VOID("FileObject=%p", FileObject);
|
FSP_LEAVE_VOID("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +88,10 @@ NTSTATUS FspAcquireForModWrite(
|
|||||||
{
|
{
|
||||||
FSP_ENTER(PAGED_CODE());
|
FSP_ENTER(PAGED_CODE());
|
||||||
|
|
||||||
Result = STATUS_NOT_IMPLEMENTED;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
*ResourceToRelease = 0;
|
||||||
|
|
||||||
FSP_LEAVE("FileObject=%p", FileObject);
|
FSP_LEAVE("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
@ -92,7 +103,9 @@ NTSTATUS FspReleaseForModWrite(
|
|||||||
{
|
{
|
||||||
FSP_ENTER(PAGED_CODE());
|
FSP_ENTER(PAGED_CODE());
|
||||||
|
|
||||||
Result = STATUS_NOT_IMPLEMENTED;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE("FileObject=%p", FileObject);
|
FSP_LEAVE("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
@ -103,7 +116,9 @@ NTSTATUS FspAcquireForCcFlush(
|
|||||||
{
|
{
|
||||||
FSP_ENTER(PAGED_CODE());
|
FSP_ENTER(PAGED_CODE());
|
||||||
|
|
||||||
Result = STATUS_NOT_IMPLEMENTED;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE("FileObject=%p", FileObject);
|
FSP_LEAVE("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
@ -114,7 +129,9 @@ NTSTATUS FspReleaseForCcFlush(
|
|||||||
{
|
{
|
||||||
FSP_ENTER(PAGED_CODE());
|
FSP_ENTER(PAGED_CODE());
|
||||||
|
|
||||||
Result = STATUS_NOT_IMPLEMENTED;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE("FileObject=%p", FileObject);
|
FSP_LEAVE("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
@ -125,7 +142,9 @@ BOOLEAN FspAcquireForLazyWrite(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_BOOL(PAGED_CODE());
|
FSP_ENTER_BOOL(PAGED_CODE());
|
||||||
|
|
||||||
Result = FALSE;
|
FSP_FILE_NODE *FileNode = Context;
|
||||||
|
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
|
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
|
||||||
}
|
}
|
||||||
@ -135,6 +154,10 @@ VOID FspReleaseFromLazyWrite(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_VOID(PAGED_CODE());
|
FSP_ENTER_VOID(PAGED_CODE());
|
||||||
|
|
||||||
|
FSP_FILE_NODE *FileNode = Context;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE_VOID("Context=%p", Context);
|
FSP_LEAVE_VOID("Context=%p", Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +167,9 @@ BOOLEAN FspAcquireForReadAhead(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_BOOL(PAGED_CODE());
|
FSP_ENTER_BOOL(PAGED_CODE());
|
||||||
|
|
||||||
Result = FALSE;
|
FSP_FILE_NODE *FileNode = Context;
|
||||||
|
|
||||||
|
FspFileNodeAcquireShared(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
|
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
|
||||||
}
|
}
|
||||||
@ -154,5 +179,9 @@ VOID FspReleaseFromReadAhead(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_VOID(PAGED_CODE());
|
FSP_ENTER_VOID(PAGED_CODE());
|
||||||
|
|
||||||
|
FSP_FILE_NODE *FileNode = Context;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
|
||||||
FSP_LEAVE_VOID("Context=%p", Context);
|
FSP_LEAVE_VOID("Context=%p", Context);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,9 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
|
/* !!!: REVISIT! */
|
||||||
FspFileNodeClose(FileNode, FileObject, &DeletePending);
|
FspFileNodeClose(FileNode, FileObject, &DeletePending);
|
||||||
|
CcUninitializeCacheMap(FileObject, 0, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If DeletePending is TRUE, the FileNode is no longer in the Context table,
|
* If DeletePending is TRUE, the FileNode is no longer in the Context table,
|
||||||
|
@ -583,6 +583,10 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
FileObject->PrivateCacheMap = 0;
|
FileObject->PrivateCacheMap = 0;
|
||||||
FileObject->FsContext = FileNode;
|
FileObject->FsContext = FileNode;
|
||||||
FileObject->FsContext2 = FileDesc;
|
FileObject->FsContext2 = FileDesc;
|
||||||
|
if (FspTimeoutInfinity32 == FsvolDeviceExtension->VolumeParams.FileInfoTimeout &&
|
||||||
|
!FlagOn(IrpSp->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING))
|
||||||
|
/* enable caching! */
|
||||||
|
SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
|
||||||
|
|
||||||
if (FILE_SUPERSEDED != Response->IoStatus.Information &&
|
if (FILE_SUPERSEDED != Response->IoStatus.Information &&
|
||||||
FILE_OVERWRITTEN != Response->IoStatus.Information)
|
FILE_OVERWRITTEN != Response->IoStatus.Information)
|
||||||
|
@ -93,8 +93,8 @@ NTSTATUS DriverEntry(
|
|||||||
/* setup fast I/O and resource acquisition */
|
/* setup fast I/O and resource acquisition */
|
||||||
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
||||||
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
||||||
FspFastIoDispatch.FastIoRead = FsRtlCopyRead;
|
//FspFastIoDispatch.FastIoRead = 0;
|
||||||
FspFastIoDispatch.FastIoWrite = FsRtlCopyWrite;
|
//FspFastIoDispatch.FastIoWrite = 0;
|
||||||
//FspFastIoDispatch.FastIoQueryBasicInfo = 0;
|
//FspFastIoDispatch.FastIoQueryBasicInfo = 0;
|
||||||
//FspFastIoDispatch.FastIoQueryStandardInfo = 0;
|
//FspFastIoDispatch.FastIoQueryStandardInfo = 0;
|
||||||
//FspFastIoDispatch.FastIoLock = 0;
|
//FspFastIoDispatch.FastIoLock = 0;
|
||||||
@ -107,10 +107,10 @@ NTSTATUS DriverEntry(
|
|||||||
//FspFastIoDispatch.FastIoDetachDevice = 0;
|
//FspFastIoDispatch.FastIoDetachDevice = 0;
|
||||||
//FspFastIoDispatch.FastIoQueryNetworkOpenInfo = 0;
|
//FspFastIoDispatch.FastIoQueryNetworkOpenInfo = 0;
|
||||||
FspFastIoDispatch.AcquireForModWrite = FspAcquireForModWrite;
|
FspFastIoDispatch.AcquireForModWrite = FspAcquireForModWrite;
|
||||||
FspFastIoDispatch.MdlRead = FsRtlMdlReadDev;
|
//FspFastIoDispatch.MdlRead = 0;
|
||||||
FspFastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
|
//FspFastIoDispatch.MdlReadComplete = 0;
|
||||||
FspFastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
|
//FspFastIoDispatch.PrepareMdlWrite = 0;
|
||||||
FspFastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
|
//FspFastIoDispatch.MdlWriteComplete = 0;
|
||||||
//FspFastIoDispatch.FastIoReadCompressed = 0;
|
//FspFastIoDispatch.FastIoReadCompressed = 0;
|
||||||
//FspFastIoDispatch.FastIoWriteCompressed = 0;
|
//FspFastIoDispatch.FastIoWriteCompressed = 0;
|
||||||
//FspFastIoDispatch.MdlReadCompleteCompressed = 0;
|
//FspFastIoDispatch.MdlReadCompleteCompressed = 0;
|
||||||
|
@ -273,6 +273,7 @@ FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare;
|
|||||||
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||||
|
FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||||
|
|
||||||
/* fast I/O and resource acquisition callbacks */
|
/* fast I/O and resource acquisition callbacks */
|
||||||
@ -378,13 +379,18 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE
|
|||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
NTSTATUS FspLockUserBuffer(PVOID UserBuffer, ULONG Length,
|
NTSTATUS FspLockUserBuffer(PVOID UserBuffer, ULONG Length,
|
||||||
KPROCESSOR_MODE RequestorMode, LOCK_OPERATION Operation, PMDL *PMdl);
|
KPROCESSOR_MODE RequestorMode, LOCK_OPERATION Operation, PMDL *PMdl);
|
||||||
|
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress);
|
||||||
|
NTSTATUS FspCcInitializeCacheMap(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes,
|
||||||
|
BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS Callbacks, PVOID CallbackContext);
|
||||||
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes);
|
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes);
|
||||||
|
NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length,
|
||||||
|
BOOLEAN Wait, PVOID Buffer);
|
||||||
|
NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length,
|
||||||
|
PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus);
|
||||||
NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain);
|
NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain);
|
||||||
NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation,
|
NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength,
|
PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength,
|
||||||
PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor);
|
PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor);
|
||||||
#define FspSetTopLevelIrp(Irp) (IoGetTopLevelIrp() ? FALSE : (IoSetTopLevelIrp(Irp), TRUE))
|
|
||||||
#define FspResetTopLevelIrp(TopLevel) ((TopLevel) ? IoSetTopLevelIrp(0) : (void)0)
|
|
||||||
|
|
||||||
/* utility: synchronous work queue */
|
/* utility: synchronous work queue */
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -409,6 +415,19 @@ VOID FspInitializeDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem,
|
|||||||
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
|
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
|
||||||
VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEGER Delay);
|
VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEGER Delay);
|
||||||
|
|
||||||
|
/* utility: safe MDL */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PMDL Mdl;
|
||||||
|
PVOID Buffer;
|
||||||
|
PMDL UserMdl;
|
||||||
|
LOCK_OPERATION Operation;
|
||||||
|
} FSP_SAFE_MDL;
|
||||||
|
BOOLEAN FspSafeMdlCheck(PMDL Mdl);
|
||||||
|
NTSTATUS FspSafeMdlCreate(PMDL UserMdl, LOCK_OPERATION Operation, FSP_SAFE_MDL **PSafeMdl);
|
||||||
|
VOID FspSafeMdlCopyBack(FSP_SAFE_MDL *SafeMdl);
|
||||||
|
VOID FspSafeMdlDelete(FSP_SAFE_MDL *SafeMdl);
|
||||||
|
|
||||||
/* IRP context */
|
/* IRP context */
|
||||||
#define FspIrpTimestampInfinity ((ULONG)-1L)
|
#define FspIrpTimestampInfinity ((ULONG)-1L)
|
||||||
#define FspIrpTimestamp(Irp) \
|
#define FspIrpTimestamp(Irp) \
|
||||||
|
316
src/sys/util.c
316
src/sys/util.c
@ -11,7 +11,14 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE
|
|||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
NTSTATUS FspLockUserBuffer(PVOID UserBuffer, ULONG Length,
|
NTSTATUS FspLockUserBuffer(PVOID UserBuffer, ULONG Length,
|
||||||
KPROCESSOR_MODE RequestorMode, LOCK_OPERATION Operation, PMDL *PMdl);
|
KPROCESSOR_MODE RequestorMode, LOCK_OPERATION Operation, PMDL *PMdl);
|
||||||
|
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress);
|
||||||
|
NTSTATUS FspCcInitializeCacheMap(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes,
|
||||||
|
BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS Callbacks, PVOID CallbackContext);
|
||||||
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes);
|
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes);
|
||||||
|
NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length,
|
||||||
|
BOOLEAN Wait, PVOID Buffer);
|
||||||
|
NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length,
|
||||||
|
PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus);
|
||||||
NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain);
|
NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain);
|
||||||
NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation,
|
NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength,
|
PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength,
|
||||||
@ -24,13 +31,21 @@ VOID FspInitializeDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem,
|
|||||||
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
|
PWORKER_THREAD_ROUTINE Routine, PVOID Context);
|
||||||
VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEGER Delay);
|
VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEGER Delay);
|
||||||
static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC;
|
static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC;
|
||||||
|
BOOLEAN FspSafeMdlCheck(PMDL Mdl);
|
||||||
|
NTSTATUS FspSafeMdlCreate(PMDL UserMdl, LOCK_OPERATION Operation, FSP_SAFE_MDL **PSafeMdl);
|
||||||
|
VOID FspSafeMdlCopyBack(FSP_SAFE_MDL *SafeMdl);
|
||||||
|
VOID FspSafeMdlDelete(FSP_SAFE_MDL *SafeMdl);
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspUnicodePathIsValid)
|
#pragma alloc_text(PAGE, FspUnicodePathIsValid)
|
||||||
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
||||||
#pragma alloc_text(PAGE, FspCreateGuid)
|
#pragma alloc_text(PAGE, FspCreateGuid)
|
||||||
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
||||||
|
#pragma alloc_text(PAGE, FspMapLockedPagesInUserMode)
|
||||||
|
#pragma alloc_text(PAGE, FspCcInitializeCacheMap)
|
||||||
#pragma alloc_text(PAGE, FspCcSetFileSizes)
|
#pragma alloc_text(PAGE, FspCcSetFileSizes)
|
||||||
|
#pragma alloc_text(PAGE, FspCcCopyWrite)
|
||||||
|
#pragma alloc_text(PAGE, FspCcPrepareMdlWrite)
|
||||||
#pragma alloc_text(PAGE, FspCcMdlWriteComplete)
|
#pragma alloc_text(PAGE, FspCcMdlWriteComplete)
|
||||||
#pragma alloc_text(PAGE, FspQuerySecurityDescriptorInfo)
|
#pragma alloc_text(PAGE, FspQuerySecurityDescriptorInfo)
|
||||||
#pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem)
|
#pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem)
|
||||||
@ -38,6 +53,10 @@ static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC;
|
|||||||
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine)
|
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine)
|
||||||
#pragma alloc_text(PAGE, FspInitializeDelayedWorkItem)
|
#pragma alloc_text(PAGE, FspInitializeDelayedWorkItem)
|
||||||
#pragma alloc_text(PAGE, FspQueueDelayedWorkItem)
|
#pragma alloc_text(PAGE, FspQueueDelayedWorkItem)
|
||||||
|
#pragma alloc_text(PAGE, FspSafeMdlCheck)
|
||||||
|
#pragma alloc_text(PAGE, FspSafeMdlCreate)
|
||||||
|
#pragma alloc_text(PAGE, FspSafeMdlCopyBack)
|
||||||
|
#pragma alloc_text(PAGE, FspSafeMdlDelete)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const LONG Delays[] =
|
static const LONG Delays[] =
|
||||||
@ -183,6 +202,38 @@ NTSTATUS FspLockUserBuffer(PVOID UserBuffer, ULONG Length,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
*PAddress = MmMapLockedPagesSpecifyCache(Mdl, UserMode, MmCached, 0, FALSE, NormalPagePriority);
|
||||||
|
return 0 != *PAddress ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
*PAddress = 0;
|
||||||
|
return GetExceptionCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspCcInitializeCacheMap(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes,
|
||||||
|
BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS Callbacks, PVOID CallbackContext)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CcInitializeCacheMap(FileObject, FileSizes, PinAccess, Callbacks, CallbackContext);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
return GetExceptionCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes)
|
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -198,6 +249,56 @@ NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length,
|
||||||
|
BOOLEAN Wait, PVOID Buffer)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BOOLEAN Success = CcCopyWrite(FileObject, FileOffset, Length, Wait, Buffer);
|
||||||
|
return Success ? STATUS_SUCCESS : STATUS_PENDING;
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
return GetExceptionCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length,
|
||||||
|
PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PMdlChain = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CcPrepareMdlWrite(FileObject, FileOffset, Length, PMdlChain, IoStatus);
|
||||||
|
Result = IoStatus->Status;
|
||||||
|
}
|
||||||
|
except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Result = GetExceptionCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (0 != *PMdlChain)
|
||||||
|
{
|
||||||
|
CcMdlWriteAbort(FileObject, *PMdlChain);
|
||||||
|
*PMdlChain = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
IoStatus->Status = Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain)
|
NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -293,3 +394,218 @@ static VOID FspQueueDelayedWorkItemDPC(PKDPC Dpc,
|
|||||||
|
|
||||||
ExQueueWorkItem(&DelayedWorkItem->WorkQueueItem, DelayedWorkQueue);
|
ExQueueWorkItem(&DelayedWorkItem->WorkQueueItem, DelayedWorkQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspSafeMdlCheck(PMDL Mdl)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PVOID VirtualAddress = MmGetMdlVirtualAddress(Mdl);
|
||||||
|
ULONG ByteCount = MmGetMdlByteCount(Mdl);
|
||||||
|
|
||||||
|
return 0 == BYTE_OFFSET(VirtualAddress) && 0 == BYTE_OFFSET(ByteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspSafeMdlCreate(PMDL UserMdl, LOCK_OPERATION Operation, FSP_SAFE_MDL **PSafeMdl)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PVOID VirtualAddress = MmGetMdlVirtualAddress(UserMdl);
|
||||||
|
ULONG ByteCount = MmGetMdlByteCount(UserMdl);
|
||||||
|
ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, ByteCount);
|
||||||
|
FSP_SAFE_MDL *SafeMdl;
|
||||||
|
PMDL TempMdl;
|
||||||
|
PPFN_NUMBER UserPfnArray, SafePfnArray, TempPfnArray;
|
||||||
|
ULONG ByteOffsetBgn0, ByteOffsetEnd0, ByteOffsetEnd1;
|
||||||
|
BOOLEAN Buffer0, Buffer1;
|
||||||
|
ULONG BufferPageCount;
|
||||||
|
|
||||||
|
ASSERT(0 != PageCount);
|
||||||
|
|
||||||
|
*PSafeMdl = 0;
|
||||||
|
|
||||||
|
SafeMdl = FspAllocNonPaged(sizeof *SafeMdl);
|
||||||
|
if (0 == SafeMdl)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
RtlZeroMemory(SafeMdl, sizeof *SafeMdl);
|
||||||
|
|
||||||
|
SafeMdl->Mdl = IoAllocateMdl(VirtualAddress, ByteCount, FALSE, FALSE, 0);
|
||||||
|
if (0 == SafeMdl->Mdl)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
UserPfnArray = MmGetMdlPfnArray(UserMdl);
|
||||||
|
SafePfnArray = MmGetMdlPfnArray(SafeMdl->Mdl);
|
||||||
|
RtlCopyMemory(SafePfnArray, UserPfnArray, PageCount * sizeof(PFN_NUMBER));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible cases:
|
||||||
|
*
|
||||||
|
* ----+---------+---------+----
|
||||||
|
*
|
||||||
|
* *---------* +
|
||||||
|
* + *----* +
|
||||||
|
* *----* + +
|
||||||
|
* + *---* + +
|
||||||
|
* *--------...--------*
|
||||||
|
* + *---...--------*
|
||||||
|
* *--------...---* +
|
||||||
|
* + *---...---* +
|
||||||
|
*/
|
||||||
|
if (1 == PageCount)
|
||||||
|
{
|
||||||
|
ByteOffsetBgn0 = BYTE_OFFSET(VirtualAddress);
|
||||||
|
ByteOffsetEnd0 = BYTE_OFFSET(ByteCount + (PAGE_SIZE - 1));
|
||||||
|
ByteOffsetEnd1 = 0;
|
||||||
|
Buffer0 = 0 != ByteOffsetBgn0 || PAGE_SIZE != ByteOffsetEnd0;
|
||||||
|
Buffer1 = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteOffsetBgn0 = BYTE_OFFSET(VirtualAddress);
|
||||||
|
ByteOffsetEnd0 = PAGE_SIZE;
|
||||||
|
ByteOffsetEnd1 = BYTE_OFFSET((PUINT8)VirtualAddress + ByteCount + (PAGE_SIZE - 1));
|
||||||
|
Buffer0 = 0 != ByteOffsetBgn0;
|
||||||
|
Buffer1 = PAGE_SIZE != ByteOffsetEnd1;
|
||||||
|
}
|
||||||
|
BufferPageCount = Buffer0 + Buffer1;
|
||||||
|
|
||||||
|
if (0 < BufferPageCount)
|
||||||
|
{
|
||||||
|
SafeMdl->Buffer = FspAllocNonPaged(PAGE_SIZE * BufferPageCount);
|
||||||
|
if (0 == SafeMdl->Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempMdl = IoAllocateMdl(SafeMdl->Buffer, PAGE_SIZE * BufferPageCount, FALSE, FALSE, 0);
|
||||||
|
if (0 == TempMdl)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MmBuildMdlForNonPagedPool(TempMdl);
|
||||||
|
|
||||||
|
TempPfnArray = MmGetMdlPfnArray(SafeMdl);
|
||||||
|
if (IoReadAccess == Operation)
|
||||||
|
{
|
||||||
|
if (Buffer0)
|
||||||
|
{
|
||||||
|
RtlZeroMemory((PUINT8)SafeMdl->Buffer, ByteOffsetBgn0);
|
||||||
|
RtlCopyMemory((PUINT8)SafeMdl->Buffer + ByteOffsetBgn0,
|
||||||
|
(PUINT8)VirtualAddress + ByteOffsetBgn0, ByteOffsetEnd0 - ByteOffsetBgn0);
|
||||||
|
RtlZeroMemory((PUINT8)SafeMdl->Buffer + ByteOffsetEnd0, PAGE_SIZE - ByteOffsetEnd0);
|
||||||
|
UserPfnArray[0] = TempPfnArray[0];
|
||||||
|
}
|
||||||
|
if (Buffer1)
|
||||||
|
{
|
||||||
|
RtlCopyMemory((PUINT8)SafeMdl->Buffer + (BufferPageCount - 1) * PAGE_SIZE,
|
||||||
|
(PUINT8)VirtualAddress + (PageCount - 1) * PAGE_SIZE, ByteOffsetEnd1);
|
||||||
|
RtlZeroMemory((PUINT8)SafeMdl->Buffer + (BufferPageCount - 1) * PAGE_SIZE + ByteOffsetEnd1,
|
||||||
|
PAGE_SIZE - ByteOffsetEnd1);
|
||||||
|
UserPfnArray[PageCount - 1] = TempPfnArray[BufferPageCount - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlZeroMemory((PUINT8)SafeMdl->Buffer, PAGE_SIZE * BufferPageCount);
|
||||||
|
if (Buffer0)
|
||||||
|
UserPfnArray[0] = TempPfnArray[0];
|
||||||
|
if (Buffer1)
|
||||||
|
UserPfnArray[PageCount - 1] = TempPfnArray[BufferPageCount - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
IoFreeMdl(TempMdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeMdl->UserMdl = UserMdl;
|
||||||
|
*PSafeMdl = SafeMdl;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result) && 0 != SafeMdl)
|
||||||
|
{
|
||||||
|
if (0 != SafeMdl->Buffer)
|
||||||
|
FspFree(SafeMdl->Buffer);
|
||||||
|
if (0 != SafeMdl->Mdl)
|
||||||
|
IoFreeMdl(SafeMdl->Mdl);
|
||||||
|
FspFree(SafeMdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspSafeMdlCopyBack(FSP_SAFE_MDL *SafeMdl)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (IoReadAccess == SafeMdl->Operation)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PVOID VirtualAddress = MmGetMdlVirtualAddress(SafeMdl->UserMdl);
|
||||||
|
ULONG ByteCount = MmGetMdlByteCount(SafeMdl->UserMdl);
|
||||||
|
ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, ByteCount);
|
||||||
|
ULONG ByteOffsetBgn0, ByteOffsetEnd0, ByteOffsetEnd1;
|
||||||
|
BOOLEAN Buffer0, Buffer1;
|
||||||
|
ULONG BufferPageCount;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible cases:
|
||||||
|
*
|
||||||
|
* ----+---------+---------+----
|
||||||
|
*
|
||||||
|
* *---------* +
|
||||||
|
* + *----* +
|
||||||
|
* *----* + +
|
||||||
|
* + *---* + +
|
||||||
|
* *--------...--------*
|
||||||
|
* + *---...--------*
|
||||||
|
* *--------...---* +
|
||||||
|
* + *---...---* +
|
||||||
|
*/
|
||||||
|
if (1 == PageCount)
|
||||||
|
{
|
||||||
|
ByteOffsetBgn0 = BYTE_OFFSET(VirtualAddress);
|
||||||
|
ByteOffsetEnd0 = BYTE_OFFSET(ByteCount + (PAGE_SIZE - 1));
|
||||||
|
ByteOffsetEnd1 = 0;
|
||||||
|
Buffer0 = 0 != ByteOffsetBgn0 || PAGE_SIZE != ByteOffsetEnd0;
|
||||||
|
Buffer1 = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteOffsetBgn0 = BYTE_OFFSET(VirtualAddress);
|
||||||
|
ByteOffsetEnd0 = PAGE_SIZE;
|
||||||
|
ByteOffsetEnd1 = BYTE_OFFSET((PUINT8)VirtualAddress + ByteCount + (PAGE_SIZE - 1));
|
||||||
|
Buffer0 = 0 != ByteOffsetBgn0;
|
||||||
|
Buffer1 = PAGE_SIZE != ByteOffsetEnd1;
|
||||||
|
}
|
||||||
|
BufferPageCount = Buffer0 + Buffer1;
|
||||||
|
|
||||||
|
if (0 < BufferPageCount)
|
||||||
|
{
|
||||||
|
if (Buffer0)
|
||||||
|
RtlCopyMemory((PUINT8)VirtualAddress + ByteOffsetBgn0,
|
||||||
|
(PUINT8)SafeMdl->Buffer + ByteOffsetBgn0, ByteOffsetEnd0 - ByteOffsetBgn0);
|
||||||
|
if (Buffer1)
|
||||||
|
RtlCopyMemory((PUINT8)VirtualAddress + (PageCount - 1) * PAGE_SIZE,
|
||||||
|
(PUINT8)SafeMdl->Buffer + (BufferPageCount - 1) * PAGE_SIZE, ByteOffsetEnd1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspSafeMdlDelete(FSP_SAFE_MDL *SafeMdl)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != SafeMdl->Buffer)
|
||||||
|
FspFree(SafeMdl->Buffer);
|
||||||
|
if (0 != SafeMdl->Mdl)
|
||||||
|
IoFreeMdl(SafeMdl->Mdl);
|
||||||
|
FspFree(SafeMdl);
|
||||||
|
}
|
||||||
|
391
src/sys/write.c
391
src/sys/write.c
@ -14,7 +14,9 @@ static NTSTATUS FspFsvolWriteCached(
|
|||||||
static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2);
|
static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2);
|
||||||
static NTSTATUS FspFsvolWriteNonCached(
|
static NTSTATUS FspFsvolWriteNonCached(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||||
|
static FSP_IOP_REQUEST_FINI FspFsvolWriteNonCachedRequestFini;
|
||||||
FSP_DRIVER_DISPATCH FspWrite;
|
FSP_DRIVER_DISPATCH FspWrite;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
@ -22,10 +24,21 @@ FSP_DRIVER_DISPATCH FspWrite;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolWriteCached)
|
#pragma alloc_text(PAGE, FspFsvolWriteCached)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteCachedDeferred)
|
#pragma alloc_text(PAGE, FspFsvolWriteCachedDeferred)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteNonCached)
|
#pragma alloc_text(PAGE, FspFsvolWriteNonCached)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolWritePrepare)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteComplete)
|
#pragma alloc_text(PAGE, FspFsvolWriteComplete)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolWriteNonCachedRequestFini)
|
||||||
#pragma alloc_text(PAGE, FspWrite)
|
#pragma alloc_text(PAGE, FspWrite)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* WriteNonCached */
|
||||||
|
RequestIrp = 0,
|
||||||
|
RequestSafeMdl = 1,
|
||||||
|
RequestAddress = 2,
|
||||||
|
RequestProcess = 3,
|
||||||
|
};
|
||||||
|
|
||||||
static NTSTATUS FspFsvolWrite(
|
static NTSTATUS FspFsvolWrite(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -36,49 +49,36 @@ static NTSTATUS FspFsvolWrite(
|
|||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN TopLevel = FspSetTopLevelIrp(Irp);
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
/* is this an MDL complete request? */
|
/* is this an MDL complete request? */
|
||||||
if (FlagOn(IrpSp->MinorFunction, IRP_MN_COMPLETE))
|
if (FlagOn(IrpSp->MinorFunction, IRP_MN_COMPLETE))
|
||||||
{
|
{
|
||||||
Result = FspCcMdlWriteComplete(IrpSp->FileObject,
|
Result = FspCcMdlWriteComplete(FileObject,
|
||||||
&IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
|
&IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
|
||||||
Irp->MdlAddress = 0;
|
Irp->MdlAddress = 0;
|
||||||
goto exit;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only regular files can be written */
|
/* only regular files can be written */
|
||||||
if (((FSP_FILE_NODE *)IrpSp->FileObject->FsContext)->IsDirectory)
|
if (FileNode->IsDirectory)
|
||||||
{
|
return STATUS_INVALID_PARAMETER;
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do we have anything to write? */
|
/* do we have anything to write? */
|
||||||
if (0 == IrpSp->Parameters.Write.Length)
|
if (0 == IrpSp->Parameters.Write.Length)
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Result = STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* probe and lock the user buffer */
|
/* are we doing cached or non-cached I/O? */
|
||||||
if (0 == Irp->MdlAddress)
|
if (FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
|
||||||
{
|
!FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE))
|
||||||
Result = FspLockUserBuffer(Irp->UserBuffer, IrpSp->Parameters.Write.Length,
|
|
||||||
Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE))
|
|
||||||
Result = FspFsvolWriteCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp));
|
Result = FspFsvolWriteCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp));
|
||||||
else
|
else
|
||||||
Result = FspFsvolWriteNonCached(FsvolDeviceObject, Irp, IrpSp);
|
Result = FspFsvolWriteNonCached(FsvolDeviceObject, Irp, IrpSp);
|
||||||
|
|
||||||
exit:
|
|
||||||
FspResetTopLevelIrp(TopLevel);
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,32 +89,36 @@ static NTSTATUS FspFsvolWriteCached(
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
FSP_FSCTL_TRANSACT_REQ *RequestWorkItem = FspIrpRequest(Irp);
|
BOOLEAN Retrying = 0 != FspIrpRequest(Irp);
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
#if 0
|
|
||||||
ULONG WriteKey = IrpSp->Parameters.Write.Key;
|
|
||||||
LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset;
|
LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset;
|
||||||
#endif
|
|
||||||
ULONG WriteLength = IrpSp->Parameters.Write.Length;
|
ULONG WriteLength = IrpSp->Parameters.Write.Length;
|
||||||
#if 0
|
#if 0
|
||||||
BOOLEAN WriteToEof =
|
/* !!!: lock support! */
|
||||||
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
ULONG WriteKey = IrpSp->Parameters.Write.Key;
|
||||||
#endif
|
#endif
|
||||||
|
BOOLEAN WriteToEndOfFile =
|
||||||
|
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||||
|
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
CC_FILE_SIZES FileSizes;
|
||||||
|
UINT64 WriteEndOffset;
|
||||||
|
BOOLEAN Success;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
/* should we defer the write? */
|
/* should we defer the write? */
|
||||||
if (DEBUGRANDTEST(10, TRUE) ||
|
Success = DEBUGRANDTEST(90, TRUE) && CcCanIWrite(FileObject, WriteLength, CanWait, Retrying);
|
||||||
!CcCanIWrite(FileObject, WriteLength, CanWait, 0 != RequestWorkItem))
|
if (!Success)
|
||||||
{
|
{
|
||||||
Result = FspWqCreateIrpWorkItem(Irp, FspFsvolWriteCached, 0);
|
Result = FspWqCreateIrpWorkItem(Irp, FspFsvolWriteCached, 0);
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
IoMarkIrpPending(Irp);
|
IoMarkIrpPending(Irp);
|
||||||
CcDeferWrite(FileObject, FspFsvolWriteCachedDeferred, Irp, 0, WriteLength,
|
CcDeferWrite(FileObject, FspFsvolWriteCachedDeferred, Irp, 0, WriteLength, Retrying);
|
||||||
0 != RequestWorkItem);
|
|
||||||
|
|
||||||
return STATUS_PENDING;
|
return STATUS_PENDING;
|
||||||
}
|
}
|
||||||
@ -122,7 +126,97 @@ static NTSTATUS FspFsvolWriteCached(
|
|||||||
/* if we are unable to defer we will go ahead and (try to) service the IRP now! */
|
/* if we are unable to defer we will go ahead and (try to) service the IRP now! */
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
/* try to acquire the FileNode Main exclusive */
|
||||||
|
Success = DEBUGRANDTEST(90, TRUE) &&
|
||||||
|
FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
|
if (!Success)
|
||||||
|
return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteCached, 0);
|
||||||
|
|
||||||
|
/* compute new file size and allocation size */
|
||||||
|
ASSERT(FspTimeoutInfinity32 == FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||||
|
FspFileNodeGetFileInfo(FileNode, &FileInfo);
|
||||||
|
FileSizes.AllocationSize.QuadPart = FileInfo.AllocationSize;
|
||||||
|
FileSizes.FileSize.QuadPart = FileInfo.FileSize;
|
||||||
|
FileSizes.ValidDataLength.QuadPart = MAXLONGLONG;
|
||||||
|
WriteEndOffset = WriteToEndOfFile ?
|
||||||
|
FileInfo.FileSize + WriteLength : WriteOffset.QuadPart + WriteLength;
|
||||||
|
if (FileInfo.FileSize < WriteEndOffset)
|
||||||
|
{
|
||||||
|
/* file is being extended */
|
||||||
|
FileSizes.FileSize.QuadPart = WriteEndOffset;
|
||||||
|
if (FileSizes.FileSize.QuadPart > FileSizes.AllocationSize.QuadPart)
|
||||||
|
{
|
||||||
|
UINT64 AllocationUnit = FsvolDeviceExtension->VolumeParams.SectorSize *
|
||||||
|
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
|
||||||
|
FileSizes.AllocationSize.QuadPart = (FileSizes.FileSize.QuadPart + AllocationUnit - 1)
|
||||||
|
/ AllocationUnit * AllocationUnit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize cache if not already initialized! */
|
||||||
|
if (0 == FileObject->PrivateCacheMap)
|
||||||
|
{
|
||||||
|
Result = FspCcInitializeCacheMap(FileObject, &FileSizes, FALSE,
|
||||||
|
&FspCacheManagerCallbacks, FileNode);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FileInfo.FileSize < WriteEndOffset)
|
||||||
|
{
|
||||||
|
/* file is being extended */
|
||||||
|
Result = FspCcSetFileSizes(FileObject, &FileSizes);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* are we using the copy or MDL interface? */
|
||||||
|
if (!FlagOn(IrpSp->MinorFunction, IRP_MN_MDL))
|
||||||
|
{
|
||||||
|
PVOID Buffer;
|
||||||
|
|
||||||
|
Buffer = 0 == Irp->MdlAddress ?
|
||||||
|
Irp->UserBuffer : MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
||||||
|
if (0 == Buffer)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait || Retrying, Buffer);
|
||||||
|
if (STATUS_PENDING == Result)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteCached, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = WriteLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(0 == Irp->MdlAddress);
|
||||||
|
|
||||||
|
Result = FspCcPrepareMdlWrite(FileObject, &WriteOffset, WriteLength,
|
||||||
|
&Irp->MdlAddress, &Irp->IoStatus);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the current file offset if synchronous I/O */
|
||||||
|
if (SynchronousIo)
|
||||||
|
FileObject->CurrentByteOffset.QuadPart = WriteEndOffset;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2)
|
static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2)
|
||||||
@ -135,7 +229,166 @@ static NTSTATUS FspFsvolWriteNonCached(
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
NTSTATUS Result;
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset;
|
||||||
|
ULONG WriteLength = IrpSp->Parameters.Write.Length;
|
||||||
|
ULONG WriteKey = IrpSp->Parameters.Write.Key;
|
||||||
|
BOOLEAN WriteToEndOfFile =
|
||||||
|
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||||
|
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
|
||||||
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
|
/* no MDL requests on the non-cached path */
|
||||||
|
if (FlagOn(IrpSp->MinorFunction, IRP_MN_MDL))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/* paging I/O cannot change the file size */
|
||||||
|
if (PagingIo && WriteToEndOfFile)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/* if non-cached I/O check the offset/length alignment */
|
||||||
|
/*
|
||||||
|
* We are going to avoid doing this test, because we don't really need to restrict
|
||||||
|
* ourselves for non-cached I/O, but also because we do not always know the correct
|
||||||
|
* file size for our alignment test. The file size is needed, because the alignment
|
||||||
|
* test is:
|
||||||
|
*
|
||||||
|
* if WriteOffset is sector aligned
|
||||||
|
* and (WriteLength is sector aligned or WriteOffset + WriteLength >= FileSize)
|
||||||
|
*
|
||||||
|
* This means that the user-mode file system must be able to deal with variable size
|
||||||
|
* I/O, but this was the case anyway because of the following part of the test:
|
||||||
|
*
|
||||||
|
* WriteOffset + WriteLength >= FileSize
|
||||||
|
*
|
||||||
|
* In any case the user-mode file system can enforce this rule if it wants!
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
if (!PagingIo)
|
||||||
|
{
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
if (0 != WriteOffset.QuadPart % FsvolDeviceExtension->VolumeParams.SectorSize ||
|
||||||
|
0 != WriteLength % FsvolDeviceExtension->VolumeParams.SectorSize)
|
||||||
|
return STATUS_NOT_IMPLEMENTED; /* FastFat does this! */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* probe and lock the user buffer */
|
||||||
|
if (0 == Irp->MdlAddress)
|
||||||
|
{
|
||||||
|
Result = FspLockUserBuffer(Irp->UserBuffer, IrpSp->Parameters.Write.Length,
|
||||||
|
Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create request */
|
||||||
|
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolWriteNonCachedRequestFini, &Request);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
Request->Kind = FspFsctlTransactWriteKind;
|
||||||
|
Request->Req.Write.UserContext = FileNode->UserContext;
|
||||||
|
Request->Req.Write.UserContext2 = FileDesc->UserContext2;
|
||||||
|
Request->Req.Write.Offset = WriteOffset.QuadPart;
|
||||||
|
Request->Req.Write.Length = WriteLength;
|
||||||
|
Request->Req.Write.Key = WriteKey;
|
||||||
|
Request->Req.Write.Append = WriteToEndOfFile;
|
||||||
|
Request->Req.Write.PagingIo = PagingIo;
|
||||||
|
|
||||||
|
return FSP_STATUS_IOQ_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFsvolWritePrepare(
|
||||||
|
PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||||
|
FSP_SAFE_MDL *SafeMdl = 0;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
BOOLEAN Success;
|
||||||
|
|
||||||
|
Success = DEBUGRANDTEST(90, TRUE) && FspFileNodeTryAcquireExclusive(FileNode, Full);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
FspIopRetryPrepareIrp(Irp, &Result);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if this is a non-cached transfer on a cached file then flush and purge the file */
|
||||||
|
if (!PagingIo && 0 != FileObject->SectionObjectPointer->DataSectionObject)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER FlushOffset = IrpSp->Parameters.Write.ByteOffset;
|
||||||
|
PLARGE_INTEGER PFlushOffset = &FlushOffset;
|
||||||
|
ULONG FlushLength = IrpSp->Parameters.Write.Length;
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
IO_STATUS_BLOCK IoStatus = { 0 };
|
||||||
|
|
||||||
|
if (FILE_WRITE_TO_END_OF_FILE == FlushOffset.LowPart && -1L == FlushOffset.HighPart)
|
||||||
|
{
|
||||||
|
if (FspFileNodeTryGetFileInfo(FileNode, &FileInfo))
|
||||||
|
FlushOffset.QuadPart = FileInfo.FileSize;
|
||||||
|
else
|
||||||
|
PFlushOffset = 0; /* we don't know how big the file is, so flush it all! */
|
||||||
|
}
|
||||||
|
|
||||||
|
CcFlushCache(FileObject->SectionObjectPointer, PFlushOffset, FlushLength, &IoStatus);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcPurgeCacheSection(FileObject->SectionObjectPointer, PFlushOffset, FlushLength, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a "safe" MDL if necessary */
|
||||||
|
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||||
|
{
|
||||||
|
Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map the MDL into user-mode */
|
||||||
|
Result = FspMapLockedPagesInUserMode(0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlDelete(SafeMdl);
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a pointer to the current process so that we can unmap the address later */
|
||||||
|
Process = PsGetCurrentProcess();
|
||||||
|
ObReferenceObject(Process);
|
||||||
|
|
||||||
|
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspFileNodeSetOwner(FileNode, Pgio, Request);
|
||||||
|
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||||
|
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolWriteComplete(
|
NTSTATUS FspFsvolWriteComplete(
|
||||||
@ -143,6 +396,36 @@ NTSTATUS FspFsvolWriteComplete(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_IOC(PAGED_CODE());
|
FSP_ENTER_IOC(PAGED_CODE());
|
||||||
|
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset;
|
||||||
|
BOOLEAN WriteToEndOfFile =
|
||||||
|
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||||
|
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||||
|
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = Response->IoStatus.Status;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PagingIo)
|
||||||
|
{
|
||||||
|
/* update file info */
|
||||||
|
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Write.FileInfo);
|
||||||
|
|
||||||
|
/* update the current file offset if synchronous I/O (and not paging I/O) */
|
||||||
|
if (SynchronousIo)
|
||||||
|
FileObject->CurrentByteOffset.QuadPart = WriteToEndOfFile ?
|
||||||
|
Response->Rsp.Write.FileInfo.FileSize :
|
||||||
|
WriteOffset.QuadPart + Response->IoStatus.Information;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = Response->IoStatus.Information;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
FSP_LEAVE_IOC(
|
FSP_LEAVE_IOC(
|
||||||
"FileObject=%p, UserBuffer=%p, MdlAddress=%p, "
|
"FileObject=%p, UserBuffer=%p, MdlAddress=%p, "
|
||||||
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
|
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
|
||||||
@ -152,6 +435,44 @@ NTSTATUS FspFsvolWriteComplete(
|
|||||||
IrpSp->Parameters.Write.Length);
|
IrpSp->Parameters.Write.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvolWriteNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PIRP Irp = Context[RequestIrp];
|
||||||
|
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||||
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
|
if (0 != Address)
|
||||||
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
|
ASSERT(0 != Process);
|
||||||
|
Attach = Process != PsGetCurrentProcess();
|
||||||
|
|
||||||
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlDelete(SafeMdl);
|
||||||
|
|
||||||
|
if (0 != Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
FSP_FILE_NODE *FileNode = IrpSp->FileObject->FsContext;
|
||||||
|
|
||||||
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspWrite(
|
NTSTATUS FspWrite(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user