* LICENSE: GPL - See COPYING in the top level directory\r
* FILE: ntoskrnl/fsrtl/fastio.c\r
* PURPOSE: Provides Fast I/O entrypoints to the Cache Manager\r
- * PROGRAMMERS: None.\r
+ * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org\r
*/\r
\r
/* INCLUDES ******************************************************************/\r
}\r
\r
/*\r
- * @unimplemented\r
+ * @implemented\r
*/\r
BOOLEAN\r
NTAPI\r
OUT PIO_STATUS_BLOCK IoStatus,\r
IN PDEVICE_OBJECT DeviceObject)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+\r
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;\r
+ LARGE_INTEGER Offset;\r
+ PFAST_IO_DISPATCH FastIoDispatch;\r
+ PDEVICE_OBJECT Device;\r
+ BOOLEAN Result = TRUE;\r
+ ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset,Length);\r
+\r
+ PAGED_CODE();\r
+ ASSERT(FileObject);\r
+ ASSERT(FileObject->FsContext);\r
+\r
+ /* No actual read */\r
+ if (!Length)\r
+ {\r
+ /* Return success */\r
+ IoStatus->Status = STATUS_SUCCESS;\r
+ IoStatus->Information = 0;\r
+ return TRUE;\r
+ }\r
+\r
+ if (MAXLONGLONG < (LONGLONG) FileOffset->QuadPart + Length) {\r
+ IoStatus->Status = STATUS_INVALID_PARAMETER;\r
+ IoStatus->Information = 0;\r
+ return FALSE;\r
+ }\r
+\r
+ /* Get the offset and FCB header */\r
+ Offset.QuadPart = FileOffset->QuadPart + Length;\r
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;\r
+\r
+\r
+ if (Wait) {\r
+ /* Use a Resource Acquire */\r
+ FsRtlEnterFileSystem();\r
+ CcFastReadWait++;\r
+ ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);\r
+ } else {\r
+ /* Acquire the resource without blocking */\r
+ /* Return false and the I/O manager will retry using the standard IRP method. */\r
+ /* Use a Resource Acquire */\r
+ FsRtlEnterFileSystem();\r
+ if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE)) {\r
+ FsRtlExitFileSystem();\r
+ FsRtlIncrementCcFastReadResourceMiss();\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+\r
+ /* Check if this is a fast I/O cached file */\r
+ if (!(FileObject->PrivateCacheMap) ||\r
+ (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) {\r
+ /* It's not, so fail */\r
+ Result = FALSE;\r
+ goto Cleanup;\r
+ }\r
+\r
+ /* Check if we need to find out if fast I/O is available */\r
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)\r
+ {\r
+ /* Sanity check */\r
+ ASSERT(!KeIsExecutingDpc());\r
+\r
+ /* Get the Fast I/O table */\r
+ Device = IoGetRelatedDeviceObject(FileObject);\r
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;\r
+\r
+ /* Sanity check */\r
+ ASSERT(FastIoDispatch != NULL);\r
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);\r
+\r
+ /* Ask the driver if we can do it */\r
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ TRUE,\r
+ LockKey,\r
+ TRUE,\r
+ IoStatus,\r
+ Device))\r
+ {\r
+ /* It's not, fail */\r
+ Result = FALSE;\r
+ goto Cleanup;\r
+ }\r
+ }\r
+\r
+ /* Check if we read too much */\r
+ if (Offset.QuadPart > FcbHeader->FileSize.QuadPart){\r
+ /* We did, check if the file offset is past the end */\r
+ if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart){\r
+ /* Set end of file */\r
+ IoStatus->Status = STATUS_END_OF_FILE;\r
+ IoStatus->Information = 0;\r
+ goto Cleanup;\r
+ }\r
+\r
+ /* Otherwise, just normalize the length */\r
+ Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);\r
+ }\r
+\r
+ /* Set this as top-level IRP */\r
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;\r
+\r
+ _SEH2_TRY\r
+ {\r
+ /* Make sure the IO and file size is below 4GB */\r
+ if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) {\r
+\r
+ /* Call the cache controller */\r
+ CcFastCopyRead (FileObject,FileOffset->LowPart,Length,PageCount,Buffer,IoStatus);\r
+ /* File was accessed */\r
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;\r
+ if (IoStatus->Status != STATUS_END_OF_FILE) {\r
+ ASSERT(( FcbHeader->FileSize.QuadPart) >= (FileOffset->QuadPart + IoStatus->Information));\r
+ }\r
+\r
+ } else {\r
+\r
+ /* Call the cache controller */\r
+ Result = CcCopyRead(FileObject, FileOffset, Length, Wait,Buffer, IoStatus);\r
+ /* File was accessed */\r
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;\r
+ if (Result == TRUE) {\r
+ ASSERT( (IoStatus->Status == STATUS_END_OF_FILE) ||\r
+ ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <= FcbHeader->FileSize.QuadPart)\r
+ );\r
+ }\r
+ }\r
+\r
+ /* Update the current file offset */\r
+ if (Result == TRUE) {\r
+ FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;\r
+ }\r
+ }\r
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)\r
+ {\r
+ Result = FALSE;\r
+ } _SEH2_END;\r
+\r
+ PsGetCurrentThread()->TopLevelIrp = 0;\r
+\r
+ /* Return to caller */\r
+Cleanup:\r
+\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ FsRtlExitFileSystem();\r
+\r
+ if (Result == FALSE) {\r
+ CcFastReadNotPossible += 1;\r
+ }\r
+\r
+ return Result;\r
+\r
}\r
\r
+\r
/*\r
- * @unimplemented\r
+ * @implemented\r
*/\r
BOOLEAN\r
NTAPI\r
OUT PIO_STATUS_BLOCK IoStatus,\r
IN PDEVICE_OBJECT DeviceObject)\r
{\r
- KEBUGCHECK(0);\r
+\r
+ BOOLEAN Result = TRUE;\r
+ PFAST_IO_DISPATCH FastIoDispatch;\r
+ PDEVICE_OBJECT Device;\r
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;\r
+\r
+ /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */\r
+ BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) && (FileOffset->LowPart == 0xffffffff));\r
+ BOOLEAN ResourceAquiredShared = FALSE;\r
+\r
+ BOOLEAN b_4GB = FALSE;\r
+\r
+ BOOLEAN FileSizeModified = FALSE;\r
+ LARGE_INTEGER OldFileSize;\r
+ LARGE_INTEGER OldValidDataLength;\r
+\r
+ LARGE_INTEGER NewSize;\r
+ LARGE_INTEGER Offset;\r
+\r
+ PAGED_CODE();\r
+\r
+ ASSERT(FileObject);\r
+ ASSERT(FileObject->FsContext);\r
+\r
+ /* Initialize some of the vars and pointers */\r
+ NewSize.QuadPart = 0;\r
+ Offset.QuadPart = FileOffset->QuadPart + Length;\r
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;\r
+\r
+ /* Nagar p.544 -- Check with Cc if we can write and check if the IO > 64kB (WDK macro) */\r
+ if ( (CcCanIWrite(FileObject, Length,Wait, FALSE) == FALSE) ||\r
+ (CcCopyWriteWontFlush(FileObject,FileOffset,Length) == FALSE) ||\r
+ ((FileObject->Flags & FO_WRITE_THROUGH )== TRUE)\r
+ )\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ /* No actual read */\r
+ if (!Length)\r
+ {\r
+ IoStatus->Status = STATUS_SUCCESS;\r
+ IoStatus->Information = Length;\r
+ return TRUE;\r
+ }\r
+\r
+ FsRtlEnterFileSystem();\r
+\r
+ /* Nagar p.544/545 -- The CcFastCopyWrite doesn't deal with filesize beyond 4GB*/\r
+ if (Wait && (FcbHeader->AllocationSize.HighPart == 0))\r
+ {\r
+ /* If the file offset is not past the file size, then we can acquire the lock shared */\r
+ if ((FileOffsetAppend == FALSE) && (Offset.LowPart <= FcbHeader->ValidDataLength.LowPart)){\r
+ ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);\r
+ ResourceAquiredShared = TRUE;\r
+ } else {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);\r
+ }\r
+\r
+ /* Nagar p.544/545 -- If we append, use the file size as offset. Also, check that we aren't crossing the 4GB boundary */\r
+ if ((FileOffsetAppend == TRUE)) {\r
+ Offset.LowPart = FcbHeader->FileSize.LowPart;\r
+ NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;\r
+ b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart);\r
+\r
+ } else {\r
+ Offset.LowPart = FileOffset->LowPart;\r
+ NewSize.LowPart = FileOffset->LowPart + Length;\r
+ b_4GB = ((NewSize.LowPart < FileOffset->LowPart) || (FileOffset->HighPart != 0));\r
+ }\r
+\r
+ /* Nagar p.544/545\r
+ Make sure that caching is initated.\r
+ That fast are allowed for this file stream.\r
+ That we are not extending past the allocated size\r
+ That we are not creating a hole bigger than 8k\r
+ That we are not crossing the 4GB boundary\r
+ */\r
+ if ( (FileObject->PrivateCacheMap != NULL) &&\r
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&\r
+ (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&\r
+ (Offset.LowPart < (FcbHeader->ValidDataLength.LowPart + 0x2000) ) &&\r
+ !b_4GB\r
+ )\r
+ {\r
+ /* If we are extending past the file size, we need to release the lock and acquire it\r
+ exclusively, because we are going to need to update the FcbHeader */\r
+ if (ResourceAquiredShared && (NewSize.LowPart > (FcbHeader->ValidDataLength.LowPart + 0x2000))) {\r
+ /* Then we need to acquire the resource exclusive */\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);\r
+ if (FileOffsetAppend == TRUE) {\r
+ Offset.LowPart = FcbHeader->FileSize.LowPart; // ??\r
+ NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;\r
+ /* Make sure we don't cross the 4GB boundary */\r
+ b_4GB = (NewSize.LowPart < Offset.LowPart);\r
+ }\r
+\r
+ /* Recheck some of the conditions since we let the lock go */\r
+ if ( (FileObject->PrivateCacheMap != NULL) &&\r
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&\r
+ (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&\r
+ (FcbHeader->AllocationSize.HighPart == 0) &&\r
+ !b_4GB\r
+ )\r
+ {\r
+ } else\r
+ {\r
+ goto FailAndCleanup;\r
+ }\r
+ }\r
+\r
+ }else\r
+ {\r
+ goto FailAndCleanup;\r
+ }\r
+\r
+ /* Check if we need to find out if fast I/O is available */\r
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)\r
+ {\r
+ IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;\r
+\r
+ /* Sanity check */\r
+ ASSERT(!KeIsExecutingDpc());\r
+\r
+ /* Get the Fast I/O table */\r
+ Device = IoGetRelatedDeviceObject(FileObject);\r
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;\r
+\r
+ /* Sanity check */\r
+ ASSERT(FastIoDispatch != NULL);\r
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);\r
+\r
+ /* Ask the driver if we can do it */\r
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,\r
+ FileOffsetAppend? &FcbHeader->FileSize:FileOffset,\r
+ Length,\r
+ TRUE,\r
+ LockKey,\r
+ FALSE,\r
+ &FastIoCheckIfPossibleStatus,\r
+ Device))\r
+ {\r
+ /* It's not, fail */\r
+ goto FailAndCleanup;\r
+ }\r
+ }\r
+\r
+ /* If we are going to extend the file then save the old file size\r
+ in case the operation fails\r
+ */\r
+ if (NewSize.LowPart > FcbHeader->FileSize.LowPart) {\r
+ FileSizeModified = TRUE;\r
+ OldFileSize.LowPart = FcbHeader->FileSize.LowPart;\r
+ OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart;\r
+ FcbHeader->FileSize.LowPart = NewSize.LowPart;\r
+ }\r
+\r
+ /* Set this as top-level IRP */\r
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;\r
+\r
+ _SEH2_TRY\r
+ {\r
+ if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) {\r
+ LARGE_INTEGER OffsetVar;\r
+ OffsetVar.LowPart = Offset.LowPart;\r
+ OffsetVar.HighPart = 0;\r
+ CcZeroData(FileObject,&FcbHeader->ValidDataLength,&OffsetVar,TRUE);\r
+ }\r
+\r
+ /* Call the cache manager */\r
+ CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer);\r
+ }\r
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)\r
+ {\r
+ Result = FALSE;\r
+ } _SEH2_END;\r
+\r
+ /* Remove ourselves at the top level component after the IO is done */\r
+ PsGetCurrentThread()->TopLevelIrp = 0;\r
+\r
+ /* Did the operation succeed ? */\r
+ if (Result == TRUE) {\r
+ /* Update the valid file size if necessary */\r
+ if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart){\r
+ FcbHeader->ValidDataLength.LowPart = NewSize.LowPart ;\r
+ }\r
+\r
+ /* Flag the file as modified */\r
+ FileObject->Flags |= FO_FILE_MODIFIED;\r
+\r
+ /* Update the strucutres if the file size changed */\r
+ if (FileSizeModified) {\r
+ ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.LowPart = NewSize.LowPart;\r
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;\r
+ }\r
+\r
+ /* Update the file object current file offset */\r
+ FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart;\r
+\r
+ } else {\r
+\r
+ /* Result == FALSE if we get here. */\r
+ if (FileSizeModified) {\r
+ /* If the file size was modified then restore the old file size */\r
+ if(FcbHeader->PagingIoResource != NULL) {\r
+ // Nagar P.544 Restore the old file size if operation didn't succeed.\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource,TRUE);\r
+ FcbHeader->FileSize.LowPart = OldFileSize.LowPart;\r
+ FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ } else {\r
+ /* If there is no lock and do it without */\r
+ FcbHeader->FileSize.LowPart = OldFileSize.LowPart;\r
+ FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;\r
+ }\r
+ } else {\r
+ }\r
+ }\r
+\r
+ goto Cleanup;\r
+\r
+ } else {\r
+\r
+ LARGE_INTEGER OldFileSize;\r
+\r
+ /* Sanity check */\r
+ ASSERT(!KeIsExecutingDpc());\r
+\r
+ // Nagar P.544\r
+ /* Check if we need to acquire the resource exclusive */\r
+ if ( (FileOffsetAppend == FALSE) &&\r
+ ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )\r
+ )\r
+ {\r
+ /* Acquire the resource shared */\r
+ if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) {\r
+ goto LeaveCriticalAndFail;\r
+ }\r
+ ResourceAquiredShared =TRUE;\r
+ } else {\r
+ /* Acquire the resource exclusive */\r
+ if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) {\r
+ goto LeaveCriticalAndFail;\r
+ }\r
+ }\r
+\r
+ /* Check if we are appending */\r
+ if (FileOffsetAppend == TRUE) {\r
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;\r
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;\r
+ } else {\r
+ Offset.QuadPart = FileOffset->QuadPart;\r
+ NewSize.QuadPart += FileOffset->QuadPart + Length;\r
+ }\r
+\r
+ /* Nagar p.544/545\r
+ Make sure that caching is initated.\r
+ That fast are allowed for this file stream.\r
+ That we are not extending past the allocated size\r
+ That we are not creating a hole bigger than 8k\r
+ */\r
+ if ( (FileObject->PrivateCacheMap != NULL) &&\r
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&\r
+ ((FcbHeader->ValidDataLength.QuadPart + 0x2000) > Offset.QuadPart) &&\r
+ (MAXLONGLONG > (Offset.QuadPart + Length)) &&\r
+ (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart)\r
+ )\r
+ {\r
+ /* Check if we can keep the lock shared */\r
+ if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait))\r
+ {\r
+ goto LeaveCriticalAndFail;\r
+ }\r
+\r
+ /* Compute the offset and the new filesize */\r
+ if (FileOffsetAppend) {\r
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;\r
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;\r
+ }\r
+\r
+ /* Recheck the above points since we released and reacquire the lock */\r
+ if ( (FileObject->PrivateCacheMap != NULL) &&\r
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&\r
+ (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)\r
+ )\r
+ {\r
+ /* Do nothing */\r
+ } else {\r
+ goto FailAndCleanup;\r
+ }\r
+ }\r
+\r
+ /* Check if we need to find out if fast I/O is available */\r
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)\r
+ {\r
+ IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;\r
+\r
+ /* Sanity check */\r
+ ASSERT(!KeIsExecutingDpc());\r
+\r
+ /* Get the Fast I/O table */\r
+ Device = IoGetRelatedDeviceObject(FileObject);\r
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;\r
+\r
+ /* Sanity check */\r
+ ASSERT(FastIoDispatch != NULL);\r
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);\r
+\r
+ /* Ask the driver if we can do it */\r
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,\r
+ FileOffsetAppend? &FcbHeader->FileSize:FileOffset,\r
+ Length,\r
+ TRUE,\r
+ LockKey,\r
+ FALSE,\r
+ &FastIoCheckIfPossibleStatus,\r
+ Device))\r
+ {\r
+ /* It's not, fail */\r
+ goto FailAndCleanup;\r
+ }\r
+ }\r
+\r
+\r
+ /* If we are going to modify the filesize, save the old fs in case the operation fails */\r
+ if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) {\r
+ FileSizeModified = TRUE;\r
+ OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;\r
+ OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;\r
+\r
+ /* If the high part of the filesize is going to change, grab the Paging IoResouce */\r
+ if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource) {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);\r
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ } else {\r
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;\r
+ }\r
+ }\r
+\r
+ /* Nagar p.544 */\r
+ /* Set ourselves as top component */\r
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;\r
+ _SEH2_TRY\r
+ {\r
+ BOOLEAN CallCc = TRUE;\r
+ /* Check if there is a gap between the end of the file and the offset\r
+ If yes, then we have to zero the data\r
+ */\r
+ if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {\r
+ if (!(Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,Wait))) {\r
+ /* If this operation fails, then we have to exit\r
+ We can jump outside the SEH, so I a using a variable to exit\r
+ normally\r
+ */\r
+ CallCc = FALSE;\r
+ }\r
+ }\r
+\r
+ /* Unless the CcZeroData failed, call the cache manager */\r
+ if (CallCc) {\r
+ Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer);\r
+ }\r
+ }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)\r
+ {\r
+ Result = FALSE;\r
+ } _SEH2_END;\r
+\r
+ /* Reset the top component */\r
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;\r
+\r
+ /* Did the operation suceeded */\r
+ if (Result) {\r
+ /* Check if we need to update the filesize */\r
+ if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {\r
+ if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);\r
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ } else {\r
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;\r
+ }\r
+ }\r
+\r
+ /* Flag the file as modified */\r
+ FileObject->Flags |= FO_FILE_MODIFIED;\r
+ /* Check if the filesize has changed */\r
+ if (FileSizeModified) {\r
+ /* Update the file sizes */\r
+ ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;\r
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;\r
+ }\r
+ /* Update the current FO byte offset */\r
+ FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;\r
+ }\r
+ else\r
+ {\r
+ /* The operation did not succeed\r
+ Reset the file size to what it should be\r
+ */\r
+ if (FileSizeModified) {\r
+ if (FcbHeader->PagingIoResource) {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);\r
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;\r
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ }else{\r
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;\r
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;\r
+ }\r
+ }\r
+ }\r
+ goto Cleanup;\r
+ } else {\r
+ goto FailAndCleanup;\r
+ }\r
+\r
+ ASSERT(0);\r
+ }\r
+\r
+LeaveCriticalAndFail:\r
+ FsRtlExitFileSystem();\r
+ return FALSE;\r
+\r
+\r
+FailAndCleanup:\r
+\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ FsRtlExitFileSystem();\r
return FALSE;\r
+\r
+Cleanup:\r
+\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ FsRtlExitFileSystem();\r
+ return Result;\r
}\r
\r
/*\r
FsRtlGetFileSize(IN PFILE_OBJECT FileObject,\r
IN OUT PLARGE_INTEGER FileSize)\r
{\r
- KEBUGCHECK(0);\r
- return STATUS_UNSUCCESSFUL;\r
+ FILE_STANDARD_INFORMATION Info;\r
+ NTSTATUS Status;\r
+ IO_STATUS_BLOCK IoStatus;\r
+ PDEVICE_OBJECT DeviceObject;\r
+ PFAST_IO_DISPATCH FastDispatch;\r
+ KEVENT Event;\r
+ PIO_STACK_LOCATION IoStackLocation;\r
+ PIRP Irp;\r
+ BOOLEAN OldHardError;\r
+\r
+\r
+ PAGED_CODE();\r
+\r
+ /* Get Device Object and Fast Calls */\r
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* Check if we support Fast Calls, and check FastIoQueryStandardInfo */\r
+ /* Call the function and see if it succeeds */\r
+ if ( !FastDispatch ||\r
+ !FastDispatch->FastIoQueryStandardInfo ||\r
+ !FastDispatch->FastIoQueryStandardInfo(FileObject,TRUE,\r
+ &Info,&IoStatus,DeviceObject))\r
+ {\r
+ /* If any of the above failed, then we are going to send an IRP to the device object */\r
+ /* Initialize the even for the IO */\r
+ KeInitializeEvent(&Event,NotificationEvent,FALSE);\r
+ /* Allocate the IRP */\r
+ Irp = IoAllocateIrp(DeviceObject->StackSize,FALSE);\r
+ if (Irp == NULL)\r
+ {\r
+ return STATUS_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+\r
+ /* Don't process hard error */\r
+ OldHardError = IoSetThreadHardErrorMode(FALSE);\r
+\r
+ /* Setup the IRP */\r
+ Irp->UserIosb = &IoStatus;\r
+ Irp->UserEvent = &Event;\r
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();\r
+ Irp->Flags = IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO;\r
+ Irp->RequestorMode = KernelMode;\r
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;\r
+ Irp->AssociatedIrp.SystemBuffer = &Info;\r
+\r
+ /* Setup out stack location */\r
+ IoStackLocation = Irp->Tail.Overlay.CurrentStackLocation;\r
+ IoStackLocation--;\r
+ IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;\r
+ IoStackLocation->FileObject = FileObject;\r
+ IoStackLocation->DeviceObject = DeviceObject;\r
+ IoStackLocation->Parameters.QueryFile.Length = ALIGN_UP(sizeof(FILE_INFORMATION_CLASS),ULONG);\r
+ IoStackLocation->Parameters.QueryFile.FileInformationClass = FileStandardInformation;\r
+\r
+ /* Send the IRP to the related device object */\r
+ Status = IofCallDriver(DeviceObject,Irp);\r
+\r
+ /* Standard DDK IRP result processing */\r
+ if (Status == STATUS_PENDING)\r
+ {\r
+ KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);\r
+ }\r
+\r
+ /* If there was a synchronous error, signal it */\r
+ if (!NT_SUCCESS(Status))\r
+ {\r
+ IoStatus.Status = Status;\r
+ }\r
+\r
+ IoSetThreadHardErrorMode(OldHardError);\r
+ }\r
+\r
+ /* Check the sync/async IO result */\r
+ if (NT_SUCCESS(IoStatus.Status))\r
+ {\r
+ /* Was the request for a directory ? */\r
+ if (Info.Directory)\r
+ {\r
+ IoStatus.Status = STATUS_FILE_IS_A_DIRECTORY;\r
+ }\r
+ else\r
+ {\r
+ FileSize->QuadPart = Info.EndOfFile.QuadPart;\r
+ }\r
+ }\r
+\r
+ return IoStatus.Status;\r
}\r
\r
+\r
/*\r
* @implemented\r
*/\r
OUT PMDL *MdlChain,\r
OUT PIO_STATUS_BLOCK IoStatus)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;\r
+ PFAST_IO_DISPATCH FastDispatch;\r
+\r
+ /* Get Device Object and Fast Calls */\r
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* Check if we support Fast Calls, and check this one */\r
+ if (FastDispatch && FastDispatch->MdlRead)\r
+ {\r
+ /* Use the fast path */\r
+ return FastDispatch->MdlRead(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ LockKey,\r
+ MdlChain,\r
+ IoStatus,\r
+ DeviceObject);\r
+ }\r
+\r
+ /* Get the Base File System (Volume) and Fast Calls */\r
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);\r
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* If the Base Device Object has its own FastDispatch Routine, fail */\r
+ if (FastDispatch && FastDispatch->MdlRead &&\r
+ BaseDeviceObject != DeviceObject)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ /* No fast path, use slow path */\r
+ return FsRtlMdlReadDev(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ LockKey,\r
+ MdlChain,\r
+ IoStatus,\r
+ DeviceObject);\r
}\r
\r
/*\r
FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,\r
IN OUT PMDL MdlChain)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;\r
+ PFAST_IO_DISPATCH FastDispatch;\r
+\r
+ /* Get Device Object and Fast Calls */\r
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* Check if we support Fast Calls, and check this one */\r
+ if (FastDispatch && FastDispatch->MdlReadComplete)\r
+ {\r
+ /* Use the fast path */\r
+ return FastDispatch->MdlReadComplete(FileObject,\r
+ MdlChain,\r
+ DeviceObject);\r
+ }\r
+\r
+ /* Get the Base File System (Volume) and Fast Calls */\r
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);\r
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* If the Base Device Object has its own FastDispatch Routine, fail */\r
+ if ((BaseDeviceObject != DeviceObject) && FastDispatch\r
+ && FastDispatch->MdlReadComplete)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ /* No fast path, use slow path */\r
+ return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject);\r
}\r
\r
/*\r
* @implemented\r
*/\r
-BOOLEAN\r
-NTAPI\r
+ BOOLEAN\r
+ NTAPI\r
FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,\r
- IN PMDL MdlChain,\r
+ IN PMDL MemoryDescriptorList,\r
IN PDEVICE_OBJECT DeviceObject)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ /* Call the Cache Manager */\r
+ CcMdlReadComplete2(MemoryDescriptorList, FileObject);\r
+ return TRUE;\r
}\r
\r
+\r
/*\r
* @implemented\r
*/\r
OUT PIO_STATUS_BLOCK IoStatus,\r
IN PDEVICE_OBJECT DeviceObject)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;\r
+ BOOLEAN Result = TRUE;\r
+ LARGE_INTEGER Offset;\r
+ PFAST_IO_DISPATCH FastIoDispatch;\r
+ PDEVICE_OBJECT Device;\r
+ PAGED_CODE();\r
+\r
+ /* No actual read */\r
+ if (!Length)\r
+ {\r
+ /* Return success */\r
+ IoStatus->Status = STATUS_SUCCESS;\r
+ IoStatus->Information = 0;\r
+ return TRUE;\r
+ }\r
+\r
+ /* Sanity check */\r
+ ASSERT(MAXLONGLONG - FileOffset->QuadPart >= (LONGLONG)Length);\r
+\r
+ /* Get the offset and FCB header */\r
+ Offset.QuadPart = FileOffset->QuadPart + Length;\r
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;\r
+\r
+ /* Enter the FS */\r
+ FsRtlEnterFileSystem();\r
+ CcFastMdlReadWait++;\r
+\r
+ /* Lock the FCB */\r
+ ExAcquireResourceShared(FcbHeader->Resource, TRUE);\r
+\r
+ /* Check if this is a fast I/O cached file */\r
+ if (!(FileObject->PrivateCacheMap) ||\r
+ (FcbHeader->IsFastIoPossible == FastIoIsNotPossible))\r
+ {\r
+ /* It's not, so fail */\r
+ CcFastMdlReadNotPossible += 1;\r
+ Result = FALSE;\r
+ goto Cleanup;\r
+ }\r
+\r
+ /* Check if we need to find out if fast I/O is available */\r
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)\r
+ {\r
+ /* Get the Fast I/O table */\r
+ Device = IoGetRelatedDeviceObject(FileObject);\r
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;\r
+\r
+ /* Sanity check */\r
+ ASSERT(!KeIsExecutingDpc());\r
+ ASSERT(FastIoDispatch != NULL);\r
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);\r
+\r
+ /* Ask the driver if we can do it */\r
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ TRUE,\r
+ LockKey,\r
+ TRUE,\r
+ IoStatus,\r
+ Device))\r
+ {\r
+ /* It's not, fail */\r
+ CcFastMdlReadNotPossible += 1;\r
+ Result = FALSE;\r
+ goto Cleanup;\r
+ }\r
+ }\r
+\r
+ /* Check if we read too much */\r
+ if (Offset.QuadPart > FcbHeader->FileSize.QuadPart)\r
+ {\r
+ /* We did, check if the file offset is past the end */\r
+ if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart)\r
+ {\r
+ /* Set end of file */\r
+ IoStatus->Status = STATUS_END_OF_FILE;\r
+ IoStatus->Information = 0;\r
+ goto Cleanup;\r
+ }\r
+\r
+ /* Otherwise, just normalize the length */\r
+ Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);\r
+ }\r
+\r
+ /* Set this as top-level IRP */\r
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;\r
+\r
+ _SEH2_TRY\r
+ {\r
+ /* Attempt a read */\r
+ CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus);\r
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;\r
+ }\r
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)\r
+ {\r
+ Result = FALSE;\r
+ } _SEH2_END;\r
+\r
+\r
+ /* Remove the top-level IRP flag */\r
+ PsGetCurrentThread()->TopLevelIrp = 0;\r
+\r
+ /* Return to caller */\r
+Cleanup:\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ FsRtlExitFileSystem();\r
+ return Result;\r
}\r
\r
/*\r
IN PLARGE_INTEGER FileOffset,\r
IN PMDL MdlChain)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;\r
+ PFAST_IO_DISPATCH FastDispatch;\r
+\r
+ /* Get Device Object and Fast Calls */\r
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* Check if we support Fast Calls, and check this one */\r
+ if (FastDispatch && FastDispatch->MdlWriteComplete)\r
+ {\r
+ /* Use the fast path */\r
+ return FastDispatch->MdlWriteComplete(FileObject,\r
+ FileOffset,\r
+ MdlChain,\r
+ DeviceObject);\r
+ }\r
+\r
+ /* Get the Base File System (Volume) and Fast Calls */\r
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);\r
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* If the Base Device Object has its own FastDispatch Routine, fail */\r
+ if (FastDispatch && FastDispatch->MdlWriteComplete &&\r
+ BaseDeviceObject != DeviceObject)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ /* No fast path, use slow path */\r
+ return FsRtlMdlWriteCompleteDev(FileObject,\r
+ FileOffset,\r
+ MdlChain,\r
+ DeviceObject);\r
}\r
\r
/*\r
IN PMDL MdlChain,\r
IN PDEVICE_OBJECT DeviceObject)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ if (FileObject->Flags & FO_WRITE_THROUGH)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+\r
+ /* Call the Cache Manager */\r
+ CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);\r
+ return TRUE;\r
}\r
\r
/*\r
OUT PMDL *MdlChain,\r
OUT PIO_STATUS_BLOCK IoStatus)\r
{\r
- KEBUGCHECK(0);\r
- return FALSE;\r
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;\r
+ PFAST_IO_DISPATCH FastDispatch;\r
+\r
+ /* Get Device Object and Fast Calls */\r
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* Check if we support Fast Calls, and check this one */\r
+ if (FastDispatch && FastDispatch->PrepareMdlWrite)\r
+ {\r
+ /* Use the fast path */\r
+ return FastDispatch->PrepareMdlWrite(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ LockKey,\r
+ MdlChain,\r
+ IoStatus,\r
+ DeviceObject);\r
+ }\r
+\r
+ /* Get the Base File System (Volume) and Fast Calls */\r
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);\r
+ FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;\r
+\r
+ /* If the Base Device Object has its own FastDispatch Routine, fail */\r
+ if (FastDispatch && FastDispatch->PrepareMdlWrite &&\r
+ BaseDeviceObject != DeviceObject)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ /* No fast path, use slow path */\r
+ return FsRtlPrepareMdlWriteDev(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ LockKey,\r
+ MdlChain,\r
+ IoStatus,\r
+ DeviceObject);\r
}\r
\r
/*\r
- * @unimplemented\r
+ * @implemented\r
*/\r
BOOLEAN\r
NTAPI\r
OUT PIO_STATUS_BLOCK IoStatus,\r
IN PDEVICE_OBJECT DeviceObject)\r
{\r
- KEBUGCHECK(0);\r
+ BOOLEAN Result = TRUE;\r
+ PFAST_IO_DISPATCH FastIoDispatch;\r
+ PDEVICE_OBJECT Device;\r
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;\r
+\r
+ LARGE_INTEGER OldFileSize;\r
+ LARGE_INTEGER OldValidDataLength;\r
+ LARGE_INTEGER NewSize;\r
+ LARGE_INTEGER Offset;\r
+\r
+ /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */\r
+ BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) && (FileOffset->LowPart == 0xffffffff));\r
+ BOOLEAN FileSizeModified = FALSE;\r
+ BOOLEAN ResourceAquiredShared = FALSE;\r
+\r
+ /* Initialize some of the vars and pointers */\r
+ OldFileSize.QuadPart = 0;\r
+ OldValidDataLength.QuadPart = 0;\r
+\r
+ PAGED_CODE();\r
+\r
+ Offset.QuadPart = FileOffset->QuadPart + Length;\r
+\r
+ /* Nagar p.544 -- Check with Cc if we can write */\r
+ if ( (!CcCanIWrite(FileObject, Length,TRUE,FALSE))||\r
+ (FileObject->Flags & FO_WRITE_THROUGH))\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ IoStatus->Status = STATUS_SUCCESS;\r
+\r
+ /* No actual read */\r
+ if (!Length)\r
+ {\r
+ return TRUE;\r
+ }\r
+\r
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;\r
+ FsRtlEnterFileSystem();\r
+\r
+ /* Check we are going to extend the file */\r
+ if ( (FileOffsetAppend == FALSE) &&\r
+ ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )\r
+ )\r
+ {\r
+ /* Acquire the resource shared */\r
+ ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);\r
+ ResourceAquiredShared =TRUE;\r
+ } else\r
+ {\r
+ /* Acquire the resource exclusive */\r
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);\r
+ }\r
+\r
+ /* Check if we are appending */\r
+ if (FileOffsetAppend == TRUE) {\r
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;\r
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;\r
+ } else\r
+ {\r
+ Offset.QuadPart = FileOffset->QuadPart;\r
+ NewSize.QuadPart = FileOffset->QuadPart + Length;\r
+ }\r
+\r
+ if ( (FileObject->PrivateCacheMap) &&\r
+ (FcbHeader->IsFastIoPossible) &&\r
+ (MAXLONGLONG >= (LONGLONG) FileOffset->QuadPart + Length) &&\r
+ (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart) )\r
+ {\r
+ /* Check if we can keep the lock shared */\r
+ if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);\r
+\r
+ /* Compute the offset and the new filesize */\r
+ if (FileOffsetAppend) {\r
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;\r
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;\r
+ }\r
+\r
+ /* Recheck the above points since we released and reacquire the lock */\r
+ if ( (FileObject->PrivateCacheMap != NULL) &&\r
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&\r
+ (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)\r
+ )\r
+ {\r
+ /* Do nothing */\r
+ } else {\r
+ goto FailAndCleanup;\r
+ }\r
+ }\r
+\r
+ /* Check if we need to find out if fast I/O is available */\r
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)\r
+ {\r
+ /* Sanity check */\r
+ /* ASSERT(!KeIsExecutingDpc()); */\r
+\r
+ /* Get the Fast I/O table */\r
+ Device = IoGetRelatedDeviceObject(FileObject);\r
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;\r
+\r
+ /* Sanity check */\r
+ ASSERT(FastIoDispatch != NULL);\r
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);\r
+\r
+ /* Ask the driver if we can do it */\r
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,\r
+ FileOffset,\r
+ Length,\r
+ TRUE,\r
+ LockKey,\r
+ FALSE,\r
+ IoStatus,\r
+ Device))\r
+ {\r
+ /* It's not, fail */\r
+ goto FailAndCleanup;\r
+ }\r
+ }\r
+\r
+ /* If we are going to modify the filesize, save the old fs in case the operation fails */\r
+ if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)\r
+ {\r
+ FileSizeModified = TRUE;\r
+ OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;\r
+ OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;\r
+\r
+ /* If the high part of the filesize is going to change, grab the Paging IoResouce */\r
+ if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource)\r
+ {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);\r
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ } else {\r
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;\r
+ }\r
+ }\r
+\r
+\r
+ /* Nagar p.544 */\r
+ /* Set ourselves as top component */\r
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;\r
+ _SEH2_TRY\r
+ {\r
+ /* Check if there is a gap between the end of the file and the offset\r
+ If yes, then we have to zero the data\r
+ */\r
+ if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {\r
+ Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,TRUE);\r
+ if (Result)\r
+ {\r
+ CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);\r
+ }\r
+ } else {\r
+ CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);\r
+ }\r
+\r
+ }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)\r
+ {\r
+ Result = FALSE;\r
+ } _SEH2_END;\r
+\r
+ /* Reset the top component */\r
+ PsGetCurrentThread()->TopLevelIrp = 0;\r
+\r
+ /* Did the operation suceeded */\r
+ if (Result) {\r
+ /* Check if we need to update the filesize */\r
+ if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {\r
+ if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);\r
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ } else {\r
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;\r
+ }\r
+ }\r
+\r
+ /* Flag the file as modified */\r
+ FileObject->Flags |= FO_FILE_MODIFIED;\r
+ /* Check if the filesize has changed */\r
+ if (FileSizeModified) {\r
+ /* Update the file sizes */\r
+ ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;\r
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;\r
+ }\r
+\r
+ }\r
+ else\r
+ {\r
+ /* The operation did not succeed\r
+ Reset the file size to what it should be\r
+ */\r
+ if (FileSizeModified) {\r
+ if (FcbHeader->PagingIoResource) {\r
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);\r
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;\r
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;\r
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);\r
+ }else{\r
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;\r
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;\r
+ }\r
+ }\r
+ }\r
+\r
+ goto Cleanup;\r
+\r
+ }\r
+ else\r
+ {\r
+ goto FailAndCleanup;\r
+ }\r
+\r
+\r
+FailAndCleanup:\r
+\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ FsRtlExitFileSystem();\r
return FALSE;\r
+\r
+Cleanup:\r
+\r
+ ExReleaseResourceLite(FcbHeader->Resource);\r
+ FsRtlExitFileSystem();\r
+ return Result;\r
+\r
}\r
\r
/*\r
NTAPI\r
FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)\r
{\r
- KEBUGCHECK(0);\r
+ /*\r
+ PAGED_CODE();\r
+ FsRtlAcquireFileExclusiveCommon(FileObject,0,0);\r
+ */\r
+ KeBugCheck(FILE_SYSTEM);\r
}\r
\r
/*\r
NTAPI\r
FsRtlReleaseFile(IN PFILE_OBJECT FileObject)\r
{\r
- KEBUGCHECK(0);\r
+\r
+ KeBugCheck(FILE_SYSTEM);\r
}\r
\r
/*++\r