* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/fsrtl/fastio.c
* PURPOSE: Provides Fast I/O entrypoints to the Cache Manager
- * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org
+ * PROGRAMMERS: Dominique Cote (buzdelabuz2@gmail.com)
+ * Alex Ionescu (alex.ionescu@reactos.org)
+ * Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES ******************************************************************/
if (IoStatus->Status != STATUS_END_OF_FILE)
{
- ASSERT(FcbHeader->FileSize.QuadPart >=
- FileOffset->QuadPart + IoStatus->Information);
+ ASSERT((ULONGLONG)FcbHeader->FileSize.QuadPart >=
+ ((ULONGLONG)FileOffset->QuadPart + IoStatus->Information));
}
}
else
if (Result == TRUE)
{
ASSERT((IoStatus->Status == STATUS_END_OF_FILE) ||
- ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <=
- FcbHeader->FileSize.QuadPart));
+ (((ULONGLONG)FileOffset->QuadPart + IoStatus->Information) <=
+ (ULONGLONG)FcbHeader->FileSize.QuadPart));
}
}
/* Update the current file offset */
if (Result == TRUE)
{
- FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
+ FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information;
}
}
_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
BOOLEAN FileOffsetAppend = (FileOffset->HighPart == (LONG)0xffffffff) &&
(FileOffset->LowPart == 0xffffffff);
- BOOLEAN ResourceAquiredShared = FALSE;
+ BOOLEAN ResourceAcquiredShared = FALSE;
BOOLEAN b_4GB = FALSE;
BOOLEAN FileSizeModified = FALSE;
LARGE_INTEGER OldFileSize;
ASSERT(FileObject);
ASSERT(FileObject->FsContext);
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
- /* Silence incorrect GCC 4.5.x warning */
- OldFileSize.LowPart = 0;
-#endif
-
/* Initialize some of the vars and pointers */
NewSize.QuadPart = 0;
Offset.QuadPart = FileOffset->QuadPart + Length;
*/
if ((CcCanIWrite(FileObject, Length, Wait, FALSE) == FALSE) ||
(CcCopyWriteWontFlush(FileObject, FileOffset, Length) == FALSE) ||
- ((FileObject->Flags & FO_WRITE_THROUGH) == TRUE))
+ ((FileObject->Flags & FO_WRITE_THROUGH)))
{
return FALSE;
}
(Offset.LowPart <= FcbHeader->ValidDataLength.LowPart))
{
ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- ResourceAquiredShared = TRUE;
+ ResourceAcquiredShared = TRUE;
}
else
{
* release the lock and acquire it exclusively, because
* we are going to need to update the FcbHeader.
*/
- if (ResourceAquiredShared &&
+ if (ResourceAcquiredShared &&
(NewSize.LowPart > FcbHeader->ValidDataLength.LowPart + 0x2000))
{
/* Then we need to acquire the resource exclusive */
{
LARGE_INTEGER OldFileSize;
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
- /* Silence incorrect GCC 4.5.x warning */
- OldFileSize.QuadPart = 0;
-#endif
-
/* Sanity check */
ASSERT(!KeIsExecutingDpc());
{
goto LeaveCriticalAndFail;
}
- ResourceAquiredShared = TRUE;
+ ResourceAcquiredShared = TRUE;
}
else
{
(FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart))
{
/* Check if we can keep the lock shared */
- if (ResourceAquiredShared &&
+ if (ResourceAcquiredShared &&
(NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart))
{
ExReleaseResourceLite(FcbHeader->Resource);
&FcbHeader->FileSize :
FileOffset,
Length,
- TRUE,
+ Wait,
LockKey,
FALSE,
&FastIoCheckIfPossibleStatus,
&Offset,
Wait)))
{
- /* If this operation fails, then we have to exit. We can jump
- * outside the SEH, so I a using a variable to exit normally.
+ /* If this operation fails, then we have to exit. We can't jump
+ * outside the SEH, so I am using a variable to exit normally.
*/
CallCc = FALSE;
}
IoStackLocation->FileObject = FileObject;
IoStackLocation->DeviceObject = DeviceObject;
IoStackLocation->Parameters.QueryFile.Length =
- ALIGN_UP(sizeof(FILE_INFORMATION_CLASS), ULONG);
+ sizeof(FILE_STANDARD_INFORMATION);
IoStackLocation->Parameters.QueryFile.FileInformationClass =
FileStandardInformation;
IN PDEVICE_OBJECT DeviceObject)
{
/* Call the Cache Manager */
- CcMdlReadComplete2(MemoryDescriptorList, FileObject);
+ CcMdlReadComplete2(FileObject, MemoryDescriptorList);
return TRUE;
}
(FileOffset->LowPart == 0xffffffff);
BOOLEAN FileSizeModified = FALSE;
- BOOLEAN ResourceAquiredShared = FALSE;
+ BOOLEAN ResourceAcquiredShared = FALSE;
/* Initialize some of the vars and pointers */
OldFileSize.QuadPart = 0;
{
/* Acquire the resource shared */
ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- ResourceAquiredShared = TRUE;
+ ResourceAcquiredShared = TRUE;
}
else
{
(NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart))
{
/* Check if we can keep the lock shared */
- if (ResourceAquiredShared &&
+ if (ResourceAcquiredShared &&
(NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart))
{
ExReleaseResourceLite(FcbHeader->Resource);
return Result;
}
+NTSTATUS
+NTAPI
+FsRtlAcquireFileExclusiveCommon(IN PFILE_OBJECT FileObject,
+ IN FS_FILTER_SECTION_SYNC_TYPE SyncType,
+ IN ULONG Reserved)
+{
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ PDEVICE_OBJECT DeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+
+ /* Get Device Object and Fast Calls */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Get master FsRtl lock */
+ FsRtlEnterFileSystem();
+
+ /* Check if Fast Calls are supported, and check AcquireFileForNtCreateSection */
+ if (FastDispatch &&
+ FastDispatch->AcquireFileForNtCreateSection)
+ {
+ /* Call the AcquireFileForNtCreateSection FastIo handler */
+ FastDispatch->AcquireFileForNtCreateSection(FileObject);
+ }
+ else
+ {
+ /* No FastIo handler, acquire file's resource exclusively */
+ if (FcbHeader && FcbHeader->Resource) ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
+ }
+
+ return STATUS_SUCCESS;
+}
+
/*
* @implemented
*/
NTAPI
FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
{
- /* PAGED_CODE(); */
- /* FsRtlAcquireFileExclusiveCommon(FileObject, 0, 0); */
- KeBugCheck(FILE_SYSTEM);
+ PAGED_CODE();
+
+ /* Call the common routine. Don't care about the result */
+ (VOID)FsRtlAcquireFileExclusiveCommon(FileObject, SyncTypeOther, 0);
}
/*
NTAPI
FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
{
- KeBugCheck(FILE_SYSTEM);
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ PDEVICE_OBJECT DeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+
+ /* Get Device Object and Fast Calls */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
+ if (FastDispatch &&
+ FastDispatch->ReleaseFileForNtCreateSection)
+ {
+ /* Call the ReleaseFileForNtCreateSection FastIo handler */
+ FastDispatch->ReleaseFileForNtCreateSection(FileObject);
+ }
+ else
+ {
+ /* No FastIo handler, release file's resource */
+ if (FcbHeader && FcbHeader->Resource) ExReleaseResourceLite(FcbHeader->Resource);
+ }
+
+ /* Release master FsRtl lock */
+ FsRtlExitFileSystem();
+}
+
+/*
+* @implemented
+*/
+NTSTATUS
+NTAPI
+FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject)
+{
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ NTSTATUS Status;
+
+ /* Get the Base File System (Volume) and Fast Calls */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Get master FsRtl lock */
+ FsRtlEnterFileSystem();
+
+ /* Check if Fast Calls are supported, and check AcquireForCcFlush */
+ if (FastDispatch &&
+ FastDispatch->AcquireForCcFlush)
+ {
+ /* Call the AcquireForCcFlush FastIo handler */
+ Status = FastDispatch->AcquireForCcFlush(FileObject, BaseDeviceObject);
+
+ /* Return either success or inability to wait.
+ In case of other failure - fall through */
+ if (Status == STATUS_SUCCESS ||
+ Status == STATUS_CANT_WAIT)
+ {
+ return Status;
+ }
+ }
+
+ /* No FastIo handler (or it failed). Acquire Main resource */
+ if (FcbHeader->Resource)
+ {
+ /* Acquire it - either shared if it's already acquired
+ or exclusively if we are the first */
+ if (ExIsResourceAcquiredSharedLite(FcbHeader->Resource))
+ ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
+ else
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
+ }
+
+ /* Also acquire its PagingIO resource */
+ if (FcbHeader->PagingIoResource)
+ ExAcquireResourceSharedLite(FcbHeader->PagingIoResource, TRUE);
+
+ return STATUS_SUCCESS;
+}
+
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlAcquireFileForCcFlush(IN PFILE_OBJECT FileObject)
+{
+ PAGED_CODE();
+
+ /* Call the common routine. Don't care about the result */
+ (VOID)FsRtlAcquireFileForCcFlushEx(FileObject);
+}
+
+
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject)
+{
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+
+ /* Get Device Object and Fast Calls */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if Fast Calls are supported, and check ReleaseForCcFlush */
+ if (FastDispatch &&
+ FastDispatch->ReleaseForCcFlush)
+ {
+ /* Call the ReleaseForCcFlush FastIo handler */
+ Status = FastDispatch->ReleaseForCcFlush(FileObject, BaseDeviceObject);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* No FastIo handler (or it failed). Release PagingIO resource and
+ then Main resource */
+ if (FcbHeader->PagingIoResource) ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ if (FcbHeader->Resource) ExReleaseResourceLite(FcbHeader->Resource);
+ }
+
+ /* Release master FsRtl lock */
+ FsRtlExitFileSystem();
+}
+
+/*
+* @implemented
+*/
+NTSTATUS
+NTAPI
+FsRtlAcquireFileForModWriteEx(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER EndingOffset,
+ IN PERESOURCE *ResourceToRelease)
+{
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ PERESOURCE ResourceToAcquire = NULL;
+ BOOLEAN Exclusive = FALSE;
+ BOOLEAN Result;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Get Device Object and Fast Calls */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if Fast Calls are supported, and check AcquireForModWrite */
+ if (FastDispatch &&
+ FastDispatch->AcquireForModWrite)
+ {
+ /* Call the AcquireForModWrite FastIo handler */
+ Status = FastDispatch->AcquireForModWrite(FileObject,
+ EndingOffset,
+ ResourceToRelease,
+ BaseDeviceObject);
+
+ /* Return either success or inability to wait.
+ In case of other failure - fall through */
+ if (Status == STATUS_SUCCESS ||
+ Status == STATUS_CANT_WAIT)
+ {
+ return Status;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+
+ /* No FastIo handler, use algorithm from Nagar p.550. */
+ if (!FcbHeader->Resource)
+ {
+ *ResourceToRelease = NULL;
+ return STATUS_SUCCESS;
+ }
+
+ /* Default condition - shared acquiring of Paging IO Resource */
+ ResourceToAcquire = FcbHeader->PagingIoResource;
+
+ /* Decide on type of locking and type of resource based on historical magic
+ well explain by Nagar in p. 550-551 */
+ if ((EndingOffset->QuadPart > FcbHeader->ValidDataLength.QuadPart &&
+ FcbHeader->FileSize.QuadPart != FcbHeader->ValidDataLength.QuadPart) ||
+ (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX))
+ {
+ /* Either exclusive flag is set or write operation is extending
+ the valid data length. Prefer exclusive acquire then */
+ Exclusive = TRUE;
+ ResourceToAcquire = FcbHeader->Resource;
+ }
+ else if (!FcbHeader->PagingIoResource ||
+ (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH))
+ {
+ /* Acquire main resource shared if flag is specified or
+ if PagingIo resource is missing */
+ Exclusive = FALSE;
+ ResourceToAcquire = FcbHeader->Resource;
+ }
+
+ /* Acquire the resource in the loop, since the above code is unsafe */
+ while (TRUE)
+ {
+ Result = FALSE;
+
+ if (Exclusive)
+ Result = ExAcquireResourceExclusiveLite(ResourceToAcquire, FALSE);
+ else
+ Result = ExAcquireSharedWaitForExclusive(ResourceToAcquire, FALSE);
+
+ if (!Result) {
+ Status = STATUS_CANT_WAIT;
+ break;
+ }
+
+ /* Do the magic ifs again */
+ if ((EndingOffset->QuadPart > FcbHeader->ValidDataLength.QuadPart) ||
+ (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX))
+ {
+ /* Check what we have */
+ if (Exclusive)
+ {
+ /* Asked for exclusive, got exclusive! */
+ break;
+ }
+ else
+ {
+ /* Asked for exclusive, got shared. Release it and retry. */
+ ExReleaseResourceLite(ResourceToAcquire);
+ Exclusive = TRUE;
+ ResourceToAcquire = FcbHeader->Resource;
+ }
+ }
+ else if (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH)
+ {
+ if (Exclusive)
+ {
+ /* Asked for shared, got exclusive - convert */
+ ExConvertExclusiveToSharedLite(ResourceToAcquire);
+ break;
+ }
+ else if (ResourceToAcquire != FcbHeader->Resource)
+ {
+ /* Asked for main resource, got something else */
+ ExReleaseResourceLite(ResourceToAcquire);
+ ResourceToAcquire = FcbHeader->Resource;
+ Exclusive = TRUE;
+ }
+ }
+ else if (FcbHeader->PagingIoResource &&
+ ResourceToAcquire != FcbHeader->PagingIoResource)
+ {
+ /* There is PagingIo resource, but other resource was acquired */
+ ResourceToAcquire = FcbHeader->PagingIoResource;
+ if (!ExAcquireSharedWaitForExclusive(ResourceToAcquire, FALSE))
+ {
+ Status = STATUS_CANT_WAIT;
+ ExReleaseResourceLite(FcbHeader->Resource);
+ }
+
+ break;
+ }
+ else if (Exclusive)
+ {
+ /* Asked for shared got exclusive - convert */
+ ExConvertExclusiveToSharedLite(ResourceToAcquire);
+ break;
+ }
+ }
+
+ /* If the resource was acquired successfully - pass it to the caller */
+ if (NT_SUCCESS(Status))
+ *ResourceToRelease = ResourceToAcquire;
+
+ return Status;
}
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlReleaseFileForModWrite(IN PFILE_OBJECT FileObject,
+ IN PERESOURCE ResourceToRelease)
+{
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
+ if (FastDispatch &&
+ FastDispatch->ReleaseForModWrite)
+ {
+ /* Call the ReleaseForModWrite FastIo handler */
+ Status = FastDispatch->ReleaseForModWrite(FileObject,
+ ResourceToRelease,
+ BaseDeviceObject);
+ }
+
+ /* Just release the resource if previous op failed */
+ if (!NT_SUCCESS(Status))
+ {
+ ExReleaseResourceLite(ResourceToRelease);
+ }
+}
+
+
/*++
* @name FsRtlRegisterFileSystemFilterCallbacks
* @unimplemented
*--*/
NTSTATUS
NTAPI
-FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject,
- IN PFS_FILTER_CALLBACKS Callbacks)
+FsRtlRegisterFileSystemFilterCallbacks(
+ PDRIVER_OBJECT FilterDriverObject,
+ PFS_FILTER_CALLBACKS Callbacks)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PFS_FILTER_CALLBACKS NewCallbacks;
+ PEXTENDED_DRIVER_EXTENSION DriverExtension;
+ PAGED_CODE();
+
+ /* Verify parameters */
+ if ((FilterDriverObject == NULL) || (Callbacks == NULL))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Allocate a buffer for a copy of the callbacks */
+ NewCallbacks = ExAllocatePoolWithTag(NonPagedPool,
+ Callbacks->SizeOfFsFilterCallbacks,
+ 'gmSF');
+ if (NewCallbacks == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Copy the callbacks */
+ RtlCopyMemory(NewCallbacks, Callbacks, Callbacks->SizeOfFsFilterCallbacks);
+
+ /* Set the callbacks in the driver extension */
+ DriverExtension = (PEXTENDED_DRIVER_EXTENSION)FilterDriverObject->DriverExtension;
+ DriverExtension->FsFilterCallbacks = NewCallbacks;
+
+ return STATUS_SUCCESS;
}