Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfastio.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/fsrtl/fastio.c 00005 * PURPOSE: Provides Fast I/O entrypoints to the Cache Manager 00006 * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* PUBLIC FUNCTIONS **********************************************************/ 00016 00017 /* 00018 * @implemented 00019 */ 00020 VOID 00021 NTAPI 00022 FsRtlIncrementCcFastReadResourceMiss(VOID) 00023 { 00024 CcFastReadResourceMiss++; 00025 } 00026 00027 /* 00028 * @implemented 00029 */ 00030 VOID 00031 NTAPI 00032 FsRtlIncrementCcFastReadNotPossible(VOID) 00033 { 00034 CcFastReadNotPossible++; 00035 } 00036 00037 /* 00038 * @implemented 00039 */ 00040 VOID 00041 NTAPI 00042 FsRtlIncrementCcFastReadWait(VOID) 00043 { 00044 CcFastReadWait++; 00045 } 00046 00047 /* 00048 * @implemented 00049 */ 00050 VOID 00051 NTAPI 00052 FsRtlIncrementCcFastReadNoWait(VOID) 00053 { 00054 CcFastReadNoWait++; 00055 } 00056 00057 /* 00058 * @implemented 00059 */ 00060 BOOLEAN 00061 NTAPI 00062 FsRtlCopyRead(IN PFILE_OBJECT FileObject, 00063 IN PLARGE_INTEGER FileOffset, 00064 IN ULONG Length, 00065 IN BOOLEAN Wait, 00066 IN ULONG LockKey, 00067 OUT PVOID Buffer, 00068 OUT PIO_STATUS_BLOCK IoStatus, 00069 IN PDEVICE_OBJECT DeviceObject) 00070 { 00071 00072 PFSRTL_COMMON_FCB_HEADER FcbHeader; 00073 LARGE_INTEGER Offset; 00074 PFAST_IO_DISPATCH FastIoDispatch; 00075 PDEVICE_OBJECT Device; 00076 BOOLEAN Result = TRUE; 00077 ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset, Length); 00078 00079 PAGED_CODE(); 00080 ASSERT(FileObject); 00081 ASSERT(FileObject->FsContext); 00082 00083 /* No actual read */ 00084 if (!Length) 00085 { 00086 /* Return success */ 00087 IoStatus->Status = STATUS_SUCCESS; 00088 IoStatus->Information = 0; 00089 return TRUE; 00090 } 00091 00092 if (Length > MAXLONGLONG - FileOffset->QuadPart) 00093 { 00094 IoStatus->Status = STATUS_INVALID_PARAMETER; 00095 IoStatus->Information = 0; 00096 return FALSE; 00097 } 00098 00099 /* Get the offset and FCB header */ 00100 Offset.QuadPart = FileOffset->QuadPart + Length; 00101 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext; 00102 00103 if (Wait) 00104 { 00105 /* Use a Resource Acquire */ 00106 FsRtlEnterFileSystem(); 00107 CcFastReadWait++; 00108 ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE); 00109 } 00110 else 00111 { 00112 /* Acquire the resource without blocking. Return false and the I/O manager 00113 * will retry using the standard IRP method. Use a Resource Acquire. 00114 */ 00115 FsRtlEnterFileSystem(); 00116 if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE)) 00117 { 00118 FsRtlExitFileSystem(); 00119 FsRtlIncrementCcFastReadResourceMiss(); 00120 return FALSE; 00121 } 00122 } 00123 00124 /* Check if this is a fast I/O cached file */ 00125 if (!(FileObject->PrivateCacheMap) || 00126 (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) 00127 { 00128 /* It's not, so fail */ 00129 Result = FALSE; 00130 goto Cleanup; 00131 } 00132 00133 /* Check if we need to find out if fast I/O is available */ 00134 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable) 00135 { 00136 /* Sanity check */ 00137 ASSERT(!KeIsExecutingDpc()); 00138 00139 /* Get the Fast I/O table */ 00140 Device = IoGetRelatedDeviceObject(FileObject); 00141 FastIoDispatch = Device->DriverObject->FastIoDispatch; 00142 00143 /* Sanity check */ 00144 ASSERT(FastIoDispatch != NULL); 00145 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 00146 00147 /* Ask the driver if we can do it */ 00148 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 00149 FileOffset, 00150 Length, 00151 TRUE, 00152 LockKey, 00153 TRUE, 00154 IoStatus, 00155 Device)) 00156 { 00157 /* It's not, fail */ 00158 Result = FALSE; 00159 goto Cleanup; 00160 } 00161 } 00162 00163 /* Check if we read too much */ 00164 if (Offset.QuadPart > FcbHeader->FileSize.QuadPart) 00165 { 00166 /* We did, check if the file offset is past the end */ 00167 if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart) 00168 { 00169 /* Set end of file */ 00170 IoStatus->Status = STATUS_END_OF_FILE; 00171 IoStatus->Information = 0; 00172 goto Cleanup; 00173 } 00174 00175 /* Otherwise, just normalize the length */ 00176 Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart); 00177 } 00178 00179 /* Set this as top-level IRP */ 00180 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; 00181 00182 _SEH2_TRY 00183 { 00184 /* Make sure the IO and file size is below 4GB */ 00185 if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart)) 00186 { 00187 00188 /* Call the cache controller */ 00189 CcFastCopyRead(FileObject, 00190 FileOffset->LowPart, 00191 Length, 00192 PageCount, 00193 Buffer, 00194 IoStatus); 00195 00196 /* File was accessed */ 00197 FileObject->Flags |= FO_FILE_FAST_IO_READ; 00198 00199 if (IoStatus->Status != STATUS_END_OF_FILE) 00200 { 00201 ASSERT((ULONGLONG)FcbHeader->FileSize.QuadPart >= 00202 ((ULONGLONG)FileOffset->QuadPart + IoStatus->Information)); 00203 } 00204 } 00205 else 00206 { 00207 00208 /* Call the cache controller */ 00209 Result = CcCopyRead(FileObject, 00210 FileOffset, 00211 Length, 00212 Wait, 00213 Buffer, 00214 IoStatus); 00215 00216 /* File was accessed */ 00217 FileObject->Flags |= FO_FILE_FAST_IO_READ; 00218 00219 if (Result == TRUE) 00220 { 00221 ASSERT((IoStatus->Status == STATUS_END_OF_FILE) || 00222 (((ULONGLONG)FileOffset->QuadPart + IoStatus->Information) <= 00223 (ULONGLONG)FcbHeader->FileSize.QuadPart)); 00224 } 00225 } 00226 00227 /* Update the current file offset */ 00228 if (Result == TRUE) 00229 { 00230 FileObject->CurrentByteOffset.QuadPart += IoStatus->Information; 00231 } 00232 } 00233 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 00234 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 00235 { 00236 Result = FALSE; 00237 } 00238 _SEH2_END; 00239 00240 PsGetCurrentThread()->TopLevelIrp = 0; 00241 00242 /* Return to caller */ 00243 Cleanup: 00244 00245 ExReleaseResourceLite(FcbHeader->Resource); 00246 FsRtlExitFileSystem(); 00247 00248 if (Result == FALSE) 00249 { 00250 CcFastReadNotPossible += 1; 00251 } 00252 00253 return Result; 00254 } 00255 00256 00257 /* 00258 * @implemented 00259 */ 00260 BOOLEAN 00261 NTAPI 00262 FsRtlCopyWrite(IN PFILE_OBJECT FileObject, 00263 IN PLARGE_INTEGER FileOffset, 00264 IN ULONG Length, 00265 IN BOOLEAN Wait, 00266 IN ULONG LockKey, 00267 OUT PVOID Buffer, 00268 OUT PIO_STATUS_BLOCK IoStatus, 00269 IN PDEVICE_OBJECT DeviceObject) 00270 { 00271 BOOLEAN Result = TRUE; 00272 PFAST_IO_DISPATCH FastIoDispatch; 00273 PDEVICE_OBJECT Device; 00274 PFSRTL_COMMON_FCB_HEADER FcbHeader; 00275 PSHARED_CACHE_MAP SharedCacheMap; 00276 00277 /* WDK doc. 00278 * Offset == 0xffffffffffffffff indicates append to the end of file. 00279 */ 00280 BOOLEAN FileOffsetAppend = (FileOffset->HighPart == (LONG)0xffffffff) && 00281 (FileOffset->LowPart == 0xffffffff); 00282 00283 BOOLEAN ResourceAquiredShared = FALSE; 00284 BOOLEAN b_4GB = FALSE; 00285 BOOLEAN FileSizeModified = FALSE; 00286 LARGE_INTEGER OldFileSize; 00287 LARGE_INTEGER OldValidDataLength; 00288 LARGE_INTEGER NewSize; 00289 LARGE_INTEGER Offset; 00290 00291 PAGED_CODE(); 00292 00293 ASSERT(FileObject); 00294 ASSERT(FileObject->FsContext); 00295 00296 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405) 00297 /* Silence incorrect GCC 4.5.x warning */ 00298 OldFileSize.LowPart = 0; 00299 #endif 00300 00301 /* Initialize some of the vars and pointers */ 00302 NewSize.QuadPart = 0; 00303 Offset.QuadPart = FileOffset->QuadPart + Length; 00304 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext; 00305 00306 /* Nagar p.544. 00307 * Check with Cc if we can write and check if the IO > 64kB (WDK macro). 00308 */ 00309 if ((CcCanIWrite(FileObject, Length, Wait, FALSE) == FALSE) || 00310 (CcCopyWriteWontFlush(FileObject, FileOffset, Length) == FALSE) || 00311 ((FileObject->Flags & FO_WRITE_THROUGH))) 00312 { 00313 return FALSE; 00314 } 00315 00316 /* No actual read */ 00317 if (!Length) 00318 { 00319 IoStatus->Status = STATUS_SUCCESS; 00320 IoStatus->Information = Length; 00321 return TRUE; 00322 } 00323 00324 FsRtlEnterFileSystem(); 00325 00326 /* Nagar p.544/545. 00327 * The CcFastCopyWrite doesn't deal with filesize beyond 4GB. 00328 */ 00329 if (Wait && (FcbHeader->AllocationSize.HighPart == 0)) 00330 { 00331 /* If the file offset is not past the file size, 00332 * then we can acquire the lock shared. 00333 */ 00334 if ((FileOffsetAppend == FALSE) && 00335 (Offset.LowPart <= FcbHeader->ValidDataLength.LowPart)) 00336 { 00337 ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE); 00338 ResourceAquiredShared = TRUE; 00339 } 00340 else 00341 { 00342 ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE); 00343 } 00344 00345 /* Nagar p.544/545. 00346 * If we append, use the file size as offset. 00347 * Also, check that we aren't crossing the 4GB boundary. 00348 */ 00349 if (FileOffsetAppend == TRUE) 00350 { 00351 Offset.LowPart = FcbHeader->FileSize.LowPart; 00352 NewSize.LowPart = FcbHeader->FileSize.LowPart + Length; 00353 b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart); 00354 00355 } 00356 else 00357 { 00358 Offset.LowPart = FileOffset->LowPart; 00359 NewSize.LowPart = FileOffset->LowPart + Length; 00360 b_4GB = (NewSize.LowPart < FileOffset->LowPart) || 00361 (FileOffset->HighPart != 0); 00362 } 00363 00364 /* Nagar p.544/545. 00365 * Make sure that caching is initated. 00366 * That fast are allowed for this file stream. 00367 * That we are not extending past the allocated size. 00368 * That we are not creating a hole bigger than 8k. 00369 * That we are not crossing the 4GB boundary. 00370 */ 00371 if ((FileObject->PrivateCacheMap != NULL) && 00372 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) && 00373 (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) && 00374 (Offset.LowPart < FcbHeader->ValidDataLength.LowPart + 0x2000) && 00375 !b_4GB) 00376 { 00377 /* If we are extending past the file size, we need to 00378 * release the lock and acquire it exclusively, because 00379 * we are going to need to update the FcbHeader. 00380 */ 00381 if (ResourceAquiredShared && 00382 (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart + 0x2000)) 00383 { 00384 /* Then we need to acquire the resource exclusive */ 00385 ExReleaseResourceLite(FcbHeader->Resource); 00386 ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE); 00387 if (FileOffsetAppend == TRUE) 00388 { 00389 Offset.LowPart = FcbHeader->FileSize.LowPart; // ?? 00390 NewSize.LowPart = FcbHeader->FileSize.LowPart + Length; 00391 00392 /* Make sure we don't cross the 4GB boundary */ 00393 b_4GB = (NewSize.LowPart < Offset.LowPart); 00394 } 00395 00396 /* Recheck some of the conditions since we let the lock go */ 00397 if ((FileObject->PrivateCacheMap != NULL) && 00398 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) && 00399 (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) && 00400 (FcbHeader->AllocationSize.HighPart == 0) && 00401 !b_4GB) 00402 { 00403 /* Do nothing? */ 00404 } 00405 else 00406 { 00407 goto FailAndCleanup; 00408 } 00409 } 00410 00411 } 00412 else 00413 { 00414 goto FailAndCleanup; 00415 } 00416 00417 /* Check if we need to find out if fast I/O is available */ 00418 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable) 00419 { 00420 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus; 00421 00422 /* Sanity check */ 00423 ASSERT(!KeIsExecutingDpc()); 00424 00425 /* Get the Fast I/O table */ 00426 Device = IoGetRelatedDeviceObject(FileObject); 00427 FastIoDispatch = Device->DriverObject->FastIoDispatch; 00428 00429 /* Sanity check */ 00430 ASSERT(FastIoDispatch != NULL); 00431 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 00432 00433 /* Ask the driver if we can do it */ 00434 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 00435 FileOffsetAppend ? 00436 &FcbHeader->FileSize : 00437 FileOffset, 00438 Length, 00439 TRUE, 00440 LockKey, 00441 FALSE, 00442 &FastIoCheckIfPossibleStatus, 00443 Device)) 00444 { 00445 /* It's not, fail */ 00446 goto FailAndCleanup; 00447 } 00448 } 00449 00450 /* If we are going to extend the file then save 00451 * the old file size in case the operation fails. 00452 */ 00453 if (NewSize.LowPart > FcbHeader->FileSize.LowPart) 00454 { 00455 FileSizeModified = TRUE; 00456 OldFileSize.LowPart = FcbHeader->FileSize.LowPart; 00457 OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart; 00458 FcbHeader->FileSize.LowPart = NewSize.LowPart; 00459 } 00460 00461 /* Set this as top-level IRP */ 00462 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; 00463 00464 _SEH2_TRY 00465 { 00466 if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) 00467 { 00468 LARGE_INTEGER OffsetVar; 00469 OffsetVar.LowPart = Offset.LowPart; 00470 OffsetVar.HighPart = 0; 00471 CcZeroData(FileObject, &FcbHeader->ValidDataLength, &OffsetVar, TRUE); 00472 } 00473 00474 /* Call the cache manager */ 00475 CcFastCopyWrite(FileObject, Offset.LowPart, Length, Buffer); 00476 } 00477 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 00478 EXCEPTION_EXECUTE_HANDLER : 00479 EXCEPTION_CONTINUE_SEARCH) 00480 { 00481 Result = FALSE; 00482 } 00483 _SEH2_END; 00484 00485 /* Remove ourselves at the top level component after the IO is done */ 00486 PsGetCurrentThread()->TopLevelIrp = 0; 00487 00488 /* Did the operation succeed? */ 00489 if (Result == TRUE) 00490 { 00491 /* Update the valid file size if necessary */ 00492 if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart) 00493 { 00494 FcbHeader->ValidDataLength.LowPart = NewSize.LowPart; 00495 } 00496 00497 /* Flag the file as modified */ 00498 FileObject->Flags |= FO_FILE_MODIFIED; 00499 00500 /* Update the strucutres if the file size changed */ 00501 if (FileSizeModified) 00502 { 00503 SharedCacheMap = 00504 (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; 00505 SharedCacheMap->FileSize.LowPart = NewSize.LowPart; 00506 FileObject->Flags |= FO_FILE_SIZE_CHANGED; 00507 } 00508 00509 /* Update the file object current file offset */ 00510 FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart; 00511 00512 } 00513 else 00514 { 00515 /* Result == FALSE if we get here */ 00516 if (FileSizeModified) 00517 { 00518 /* If the file size was modified then restore the old file size */ 00519 if (FcbHeader->PagingIoResource != NULL) 00520 { 00521 /* Nagar P.544. 00522 * Restore the old file size if operation didn't succeed. 00523 */ 00524 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 00525 FcbHeader->FileSize.LowPart = OldFileSize.LowPart; 00526 FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart; 00527 ExReleaseResourceLite(FcbHeader->PagingIoResource); 00528 } 00529 else 00530 { 00531 /* If there is no lock and do it without */ 00532 FcbHeader->FileSize.LowPart = OldFileSize.LowPart; 00533 FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart; 00534 } 00535 } 00536 else 00537 { 00538 /* Do nothing? */ 00539 } 00540 } 00541 00542 goto Cleanup; 00543 } 00544 else 00545 { 00546 LARGE_INTEGER OldFileSize; 00547 00548 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405) 00549 /* Silence incorrect GCC 4.5.x warning */ 00550 OldFileSize.QuadPart = 0; 00551 #endif 00552 00553 /* Sanity check */ 00554 ASSERT(!KeIsExecutingDpc()); 00555 00556 /* Nagar P.544. 00557 * Check if we need to acquire the resource exclusive. 00558 */ 00559 if ((FileOffsetAppend == FALSE) && 00560 (FileOffset->QuadPart + Length <= FcbHeader->ValidDataLength.QuadPart)) 00561 { 00562 /* Acquire the resource shared */ 00563 if (!ExAcquireResourceSharedLite(FcbHeader->Resource, Wait)) 00564 { 00565 goto LeaveCriticalAndFail; 00566 } 00567 ResourceAquiredShared = TRUE; 00568 } 00569 else 00570 { 00571 /* Acquire the resource exclusive */ 00572 if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource, Wait)) 00573 { 00574 goto LeaveCriticalAndFail; 00575 } 00576 } 00577 00578 /* Check if we are appending */ 00579 if (FileOffsetAppend == TRUE) 00580 { 00581 Offset.QuadPart = FcbHeader->FileSize.QuadPart; 00582 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length; 00583 } 00584 else 00585 { 00586 Offset.QuadPart = FileOffset->QuadPart; 00587 NewSize.QuadPart += FileOffset->QuadPart + Length; 00588 } 00589 00590 /* Nagar p.544/545. 00591 * Make sure that caching is initated. 00592 * That fast are allowed for this file stream. 00593 * That we are not extending past the allocated size. 00594 * That we are not creating a hole bigger than 8k. 00595 */ 00596 if ((FileObject->PrivateCacheMap != NULL) && 00597 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) && 00598 (FcbHeader->ValidDataLength.QuadPart + 0x2000 > Offset.QuadPart) && 00599 (Length <= MAXLONGLONG - Offset.QuadPart) && 00600 (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart)) 00601 { 00602 /* Check if we can keep the lock shared */ 00603 if (ResourceAquiredShared && 00604 (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart)) 00605 { 00606 ExReleaseResourceLite(FcbHeader->Resource); 00607 if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource, Wait)) 00608 { 00609 goto LeaveCriticalAndFail; 00610 } 00611 00612 /* Compute the offset and the new filesize */ 00613 if (FileOffsetAppend) 00614 { 00615 Offset.QuadPart = FcbHeader->FileSize.QuadPart; 00616 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length; 00617 } 00618 00619 /* Recheck the above points since we released and reacquire the lock */ 00620 if ((FileObject->PrivateCacheMap != NULL) && 00621 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) && 00622 (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)) 00623 { 00624 /* Do nothing */ 00625 } 00626 else 00627 { 00628 goto FailAndCleanup; 00629 } 00630 } 00631 00632 /* Check if we need to find out if fast I/O is available */ 00633 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable) 00634 { 00635 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus; 00636 00637 /* Sanity check */ 00638 ASSERT(!KeIsExecutingDpc()); 00639 00640 /* Get the Fast I/O table */ 00641 Device = IoGetRelatedDeviceObject(FileObject); 00642 FastIoDispatch = Device->DriverObject->FastIoDispatch; 00643 00644 /* Sanity check */ 00645 ASSERT(FastIoDispatch != NULL); 00646 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 00647 00648 /* Ask the driver if we can do it */ 00649 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 00650 FileOffsetAppend ? 00651 &FcbHeader->FileSize : 00652 FileOffset, 00653 Length, 00654 TRUE, 00655 LockKey, 00656 FALSE, 00657 &FastIoCheckIfPossibleStatus, 00658 Device)) 00659 { 00660 /* It's not, fail */ 00661 goto FailAndCleanup; 00662 } 00663 } 00664 00665 /* If we are going to modify the filesize, 00666 * save the old fs in case the operation fails. 00667 */ 00668 if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) 00669 { 00670 FileSizeModified = TRUE; 00671 OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart; 00672 OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart; 00673 00674 /* If the high part of the filesize is going 00675 * to change, grab the Paging IoResouce. 00676 */ 00677 if (NewSize.HighPart != FcbHeader->FileSize.HighPart && 00678 FcbHeader->PagingIoResource) 00679 { 00680 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 00681 FcbHeader->FileSize.QuadPart = NewSize.QuadPart; 00682 ExReleaseResourceLite(FcbHeader->PagingIoResource); 00683 } 00684 else 00685 { 00686 FcbHeader->FileSize.QuadPart = NewSize.QuadPart; 00687 } 00688 } 00689 00690 /* Nagar p.544. 00691 * Set ourselves as top component. 00692 */ 00693 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; 00694 00695 _SEH2_TRY 00696 { 00697 BOOLEAN CallCc = TRUE; 00698 00699 /* Check if there is a gap between the end of the file 00700 * and the offset. If yes, then we have to zero the data. 00701 */ 00702 if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) 00703 { 00704 if (!(Result = CcZeroData(FileObject, 00705 &FcbHeader->ValidDataLength, 00706 &Offset, 00707 Wait))) 00708 { 00709 /* If this operation fails, then we have to exit. We can jump 00710 * outside the SEH, so I a using a variable to exit normally. 00711 */ 00712 CallCc = FALSE; 00713 } 00714 } 00715 00716 /* Unless the CcZeroData failed, call the cache manager */ 00717 if (CallCc) 00718 { 00719 Result = CcCopyWrite(FileObject, &Offset, Length, Wait, Buffer); 00720 } 00721 } 00722 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 00723 EXCEPTION_EXECUTE_HANDLER : 00724 EXCEPTION_CONTINUE_SEARCH) 00725 { 00726 Result = FALSE; 00727 } 00728 _SEH2_END; 00729 00730 /* Reset the top component */ 00731 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; 00732 00733 /* Did the operation suceeded */ 00734 if (Result) 00735 { 00736 /* Check if we need to update the filesize */ 00737 if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) 00738 { 00739 if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && 00740 FcbHeader->PagingIoResource) 00741 { 00742 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 00743 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart; 00744 ExReleaseResourceLite(FcbHeader->PagingIoResource); 00745 } 00746 else 00747 { 00748 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart; 00749 } 00750 } 00751 00752 /* Flag the file as modified */ 00753 FileObject->Flags |= FO_FILE_MODIFIED; 00754 00755 /* Check if the filesize has changed */ 00756 if (FileSizeModified) 00757 { 00758 /* Update the file sizes */ 00759 SharedCacheMap = 00760 (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; 00761 SharedCacheMap->FileSize.QuadPart = NewSize.QuadPart; 00762 FileObject->Flags |= FO_FILE_SIZE_CHANGED; 00763 } 00764 00765 /* Update the current FO byte offset */ 00766 FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart; 00767 } 00768 else 00769 { 00770 /* The operation did not succeed. 00771 * Reset the file size to what it should be. 00772 */ 00773 if (FileSizeModified) 00774 { 00775 if (FcbHeader->PagingIoResource) 00776 { 00777 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 00778 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart; 00779 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart; 00780 ExReleaseResourceLite(FcbHeader->PagingIoResource); 00781 } 00782 else 00783 { 00784 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart; 00785 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart; 00786 } 00787 } 00788 } 00789 00790 goto Cleanup; 00791 } 00792 else 00793 { 00794 goto FailAndCleanup; 00795 } 00796 } 00797 00798 LeaveCriticalAndFail: 00799 00800 FsRtlExitFileSystem(); 00801 return FALSE; 00802 00803 FailAndCleanup: 00804 00805 ExReleaseResourceLite(FcbHeader->Resource); 00806 FsRtlExitFileSystem(); 00807 return FALSE; 00808 00809 Cleanup: 00810 00811 ExReleaseResourceLite(FcbHeader->Resource); 00812 FsRtlExitFileSystem(); 00813 return Result; 00814 } 00815 00816 /* 00817 * @implemented 00818 */ 00819 NTSTATUS 00820 NTAPI 00821 FsRtlGetFileSize(IN PFILE_OBJECT FileObject, 00822 IN OUT PLARGE_INTEGER FileSize) 00823 { 00824 FILE_STANDARD_INFORMATION Info; 00825 NTSTATUS Status; 00826 IO_STATUS_BLOCK IoStatus; 00827 PDEVICE_OBJECT DeviceObject; 00828 PFAST_IO_DISPATCH FastDispatch; 00829 KEVENT Event; 00830 PIO_STACK_LOCATION IoStackLocation; 00831 PIRP Irp; 00832 BOOLEAN OldHardError; 00833 00834 PAGED_CODE(); 00835 00836 /* Get Device Object and Fast Calls */ 00837 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00838 FastDispatch = DeviceObject->DriverObject->FastIoDispatch; 00839 00840 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo. 00841 * Call the function and see if it succeeds. 00842 */ 00843 if (!FastDispatch || 00844 !FastDispatch->FastIoQueryStandardInfo || 00845 !FastDispatch->FastIoQueryStandardInfo(FileObject, 00846 TRUE, 00847 &Info, 00848 &IoStatus, 00849 DeviceObject)) 00850 { 00851 /* If any of the above failed, then we are going to send an 00852 * IRP to the device object. Initialize the event for the IO. 00853 */ 00854 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00855 00856 /* Allocate the IRP */ 00857 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00858 00859 if (Irp == NULL) 00860 { 00861 return STATUS_INSUFFICIENT_RESOURCES; 00862 } 00863 00864 /* Don't process hard error */ 00865 OldHardError = IoSetThreadHardErrorMode(FALSE); 00866 00867 /* Setup the IRP */ 00868 Irp->UserIosb = &IoStatus; 00869 Irp->UserEvent = &Event; 00870 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00871 Irp->Flags = IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO; 00872 Irp->RequestorMode = KernelMode; 00873 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00874 Irp->AssociatedIrp.SystemBuffer = &Info; 00875 00876 /* Setup out stack location */ 00877 IoStackLocation = Irp->Tail.Overlay.CurrentStackLocation; 00878 IoStackLocation--; 00879 IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION; 00880 IoStackLocation->FileObject = FileObject; 00881 IoStackLocation->DeviceObject = DeviceObject; 00882 IoStackLocation->Parameters.QueryFile.Length = 00883 ALIGN_UP(sizeof(FILE_INFORMATION_CLASS), ULONG); 00884 IoStackLocation->Parameters.QueryFile.FileInformationClass = 00885 FileStandardInformation; 00886 00887 /* Send the IRP to the related device object */ 00888 Status = IoCallDriver(DeviceObject, Irp); 00889 00890 /* Standard DDK IRP result processing */ 00891 if (Status == STATUS_PENDING) 00892 { 00893 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00894 } 00895 00896 /* If there was a synchronous error, signal it */ 00897 if (!NT_SUCCESS(Status)) 00898 { 00899 IoStatus.Status = Status; 00900 } 00901 00902 IoSetThreadHardErrorMode(OldHardError); 00903 } 00904 00905 /* Check the sync/async IO result */ 00906 if (NT_SUCCESS(IoStatus.Status)) 00907 { 00908 /* Was the request for a directory? */ 00909 if (Info.Directory) 00910 { 00911 IoStatus.Status = STATUS_FILE_IS_A_DIRECTORY; 00912 } 00913 else 00914 { 00915 FileSize->QuadPart = Info.EndOfFile.QuadPart; 00916 } 00917 } 00918 00919 return IoStatus.Status; 00920 } 00921 00922 /* 00923 * @implemented 00924 */ 00925 BOOLEAN 00926 NTAPI 00927 FsRtlMdlRead(IN PFILE_OBJECT FileObject, 00928 IN PLARGE_INTEGER FileOffset, 00929 IN ULONG Length, 00930 IN ULONG LockKey, 00931 OUT PMDL *MdlChain, 00932 OUT PIO_STATUS_BLOCK IoStatus) 00933 { 00934 PDEVICE_OBJECT DeviceObject, BaseDeviceObject; 00935 PFAST_IO_DISPATCH FastDispatch; 00936 00937 /* Get Device Object and Fast Calls */ 00938 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00939 FastDispatch = DeviceObject->DriverObject->FastIoDispatch; 00940 00941 /* Check if we support Fast Calls, and check this one */ 00942 if (FastDispatch && FastDispatch->MdlRead) 00943 { 00944 /* Use the fast path */ 00945 return FastDispatch->MdlRead(FileObject, 00946 FileOffset, 00947 Length, 00948 LockKey, 00949 MdlChain, 00950 IoStatus, 00951 DeviceObject); 00952 } 00953 00954 /* Get the Base File System (Volume) and Fast Calls */ 00955 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject); 00956 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch; 00957 00958 /* If the Base Device Object has its own FastDispatch Routine, fail */ 00959 if (FastDispatch && FastDispatch->MdlRead && BaseDeviceObject != DeviceObject) 00960 { 00961 return FALSE; 00962 } 00963 00964 /* No fast path, use slow path */ 00965 return FsRtlMdlReadDev(FileObject, 00966 FileOffset, 00967 Length, 00968 LockKey, 00969 MdlChain, 00970 IoStatus, 00971 DeviceObject); 00972 } 00973 00974 /* 00975 * @implemented 00976 */ 00977 BOOLEAN 00978 NTAPI 00979 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject, 00980 IN OUT PMDL MdlChain) 00981 { 00982 PDEVICE_OBJECT DeviceObject, BaseDeviceObject; 00983 PFAST_IO_DISPATCH FastDispatch; 00984 00985 /* Get Device Object and Fast Calls */ 00986 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00987 FastDispatch = DeviceObject->DriverObject->FastIoDispatch; 00988 00989 /* Check if we support Fast Calls, and check this one */ 00990 if (FastDispatch && FastDispatch->MdlReadComplete) 00991 { 00992 /* Use the fast path */ 00993 return FastDispatch->MdlReadComplete(FileObject, MdlChain, DeviceObject); 00994 } 00995 00996 /* Get the Base File System (Volume) and Fast Calls */ 00997 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject); 00998 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch; 00999 01000 /* If the Base Device Object has its own FastDispatch Routine, fail */ 01001 if ((BaseDeviceObject != DeviceObject) && 01002 FastDispatch && 01003 FastDispatch->MdlReadComplete) 01004 { 01005 return FALSE; 01006 } 01007 01008 /* No fast path, use slow path */ 01009 return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject); 01010 } 01011 01012 /* 01013 * @implemented 01014 */ 01015 BOOLEAN 01016 NTAPI 01017 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject, 01018 IN PMDL MemoryDescriptorList, 01019 IN PDEVICE_OBJECT DeviceObject) 01020 { 01021 /* Call the Cache Manager */ 01022 CcMdlReadComplete2(MemoryDescriptorList, FileObject); 01023 return TRUE; 01024 } 01025 01026 /* 01027 * @implemented 01028 */ 01029 BOOLEAN 01030 NTAPI 01031 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject, 01032 IN PLARGE_INTEGER FileOffset, 01033 IN ULONG Length, 01034 IN ULONG LockKey, 01035 OUT PMDL *MdlChain, 01036 OUT PIO_STATUS_BLOCK IoStatus, 01037 IN PDEVICE_OBJECT DeviceObject) 01038 { 01039 PFSRTL_COMMON_FCB_HEADER FcbHeader; 01040 BOOLEAN Result = TRUE; 01041 LARGE_INTEGER Offset; 01042 PFAST_IO_DISPATCH FastIoDispatch; 01043 PDEVICE_OBJECT Device; 01044 PAGED_CODE(); 01045 01046 /* No actual read */ 01047 if (!Length) 01048 { 01049 /* Return success */ 01050 IoStatus->Status = STATUS_SUCCESS; 01051 IoStatus->Information = 0; 01052 return TRUE; 01053 } 01054 01055 /* Sanity check */ 01056 ASSERT(MAXLONGLONG - FileOffset->QuadPart >= (LONGLONG)Length); 01057 01058 /* Get the offset and FCB header */ 01059 Offset.QuadPart = FileOffset->QuadPart + Length; 01060 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext; 01061 01062 /* Enter the FS */ 01063 FsRtlEnterFileSystem(); 01064 CcFastMdlReadWait++; 01065 01066 /* Lock the FCB */ 01067 ExAcquireResourceShared(FcbHeader->Resource, TRUE); 01068 01069 /* Check if this is a fast I/O cached file */ 01070 if (!(FileObject->PrivateCacheMap) || 01071 (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) 01072 { 01073 /* It's not, so fail */ 01074 CcFastMdlReadNotPossible += 1; 01075 Result = FALSE; 01076 goto Cleanup; 01077 } 01078 01079 /* Check if we need to find out if fast I/O is available */ 01080 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable) 01081 { 01082 /* Get the Fast I/O table */ 01083 Device = IoGetRelatedDeviceObject(FileObject); 01084 FastIoDispatch = Device->DriverObject->FastIoDispatch; 01085 01086 /* Sanity check */ 01087 ASSERT(!KeIsExecutingDpc()); 01088 ASSERT(FastIoDispatch != NULL); 01089 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 01090 01091 /* Ask the driver if we can do it */ 01092 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 01093 FileOffset, 01094 Length, 01095 TRUE, 01096 LockKey, 01097 TRUE, 01098 IoStatus, 01099 Device)) 01100 { 01101 /* It's not, fail */ 01102 CcFastMdlReadNotPossible += 1; 01103 Result = FALSE; 01104 goto Cleanup; 01105 } 01106 } 01107 01108 /* Check if we read too much */ 01109 if (Offset.QuadPart > FcbHeader->FileSize.QuadPart) 01110 { 01111 /* We did, check if the file offset is past the end */ 01112 if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart) 01113 { 01114 /* Set end of file */ 01115 IoStatus->Status = STATUS_END_OF_FILE; 01116 IoStatus->Information = 0; 01117 goto Cleanup; 01118 } 01119 01120 /* Otherwise, just normalize the length */ 01121 Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart); 01122 } 01123 01124 /* Set this as top-level IRP */ 01125 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; 01126 01127 _SEH2_TRY 01128 { 01129 /* Attempt a read */ 01130 CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus); 01131 FileObject->Flags |= FO_FILE_FAST_IO_READ; 01132 } 01133 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 01134 EXCEPTION_EXECUTE_HANDLER : 01135 EXCEPTION_CONTINUE_SEARCH) 01136 { 01137 Result = FALSE; 01138 } 01139 _SEH2_END; 01140 01141 01142 /* Remove the top-level IRP flag */ 01143 PsGetCurrentThread()->TopLevelIrp = 0; 01144 01145 /* Return to caller */ 01146 Cleanup: 01147 01148 ExReleaseResourceLite(FcbHeader->Resource); 01149 FsRtlExitFileSystem(); 01150 01151 return Result; 01152 } 01153 01154 /* 01155 * @implemented 01156 */ 01157 BOOLEAN 01158 NTAPI 01159 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject, 01160 IN PLARGE_INTEGER FileOffset, 01161 IN PMDL MdlChain) 01162 { 01163 PDEVICE_OBJECT DeviceObject, BaseDeviceObject; 01164 PFAST_IO_DISPATCH FastDispatch; 01165 01166 /* Get Device Object and Fast Calls */ 01167 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01168 FastDispatch = DeviceObject->DriverObject->FastIoDispatch; 01169 01170 /* Check if we support Fast Calls, and check this one */ 01171 if (FastDispatch && FastDispatch->MdlWriteComplete) 01172 { 01173 /* Use the fast path */ 01174 return FastDispatch->MdlWriteComplete(FileObject, 01175 FileOffset, 01176 MdlChain, 01177 DeviceObject); 01178 } 01179 01180 /* Get the Base File System (Volume) and Fast Calls */ 01181 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject); 01182 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch; 01183 01184 /* If the Base Device Object has its own FastDispatch Routine, fail */ 01185 if (FastDispatch && 01186 FastDispatch->MdlWriteComplete && 01187 BaseDeviceObject != DeviceObject) 01188 { 01189 return FALSE; 01190 } 01191 01192 /* No fast path, use slow path */ 01193 return FsRtlMdlWriteCompleteDev(FileObject, 01194 FileOffset, 01195 MdlChain, 01196 DeviceObject); 01197 } 01198 01199 /* 01200 * @implemented 01201 */ 01202 BOOLEAN 01203 NTAPI 01204 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject, 01205 IN PLARGE_INTEGER FileOffset, 01206 IN PMDL MdlChain, 01207 IN PDEVICE_OBJECT DeviceObject) 01208 { 01209 if (FileObject->Flags & FO_WRITE_THROUGH) 01210 { 01211 return FALSE; 01212 } 01213 01214 /* Call the Cache Manager */ 01215 CcMdlWriteComplete2(FileObject, FileOffset, MdlChain); 01216 return TRUE; 01217 } 01218 01219 /* 01220 * @implemented 01221 */ 01222 BOOLEAN 01223 NTAPI 01224 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject, 01225 IN PLARGE_INTEGER FileOffset, 01226 IN ULONG Length, 01227 IN ULONG LockKey, 01228 OUT PMDL *MdlChain, 01229 OUT PIO_STATUS_BLOCK IoStatus) 01230 { 01231 PDEVICE_OBJECT DeviceObject, BaseDeviceObject; 01232 PFAST_IO_DISPATCH FastDispatch; 01233 01234 /* Get Device Object and Fast Calls */ 01235 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01236 FastDispatch = DeviceObject->DriverObject->FastIoDispatch; 01237 01238 /* Check if we support Fast Calls, and check this one */ 01239 if (FastDispatch && FastDispatch->PrepareMdlWrite) 01240 { 01241 /* Use the fast path */ 01242 return FastDispatch->PrepareMdlWrite(FileObject, 01243 FileOffset, 01244 Length, 01245 LockKey, 01246 MdlChain, 01247 IoStatus, 01248 DeviceObject); 01249 } 01250 01251 /* Get the Base File System (Volume) and Fast Calls */ 01252 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject); 01253 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch; 01254 01255 /* If the Base Device Object has its own FastDispatch Routine, fail */ 01256 if (FastDispatch && 01257 FastDispatch->PrepareMdlWrite && 01258 BaseDeviceObject != DeviceObject) 01259 { 01260 return FALSE; 01261 } 01262 01263 /* No fast path, use slow path */ 01264 return FsRtlPrepareMdlWriteDev(FileObject, 01265 FileOffset, 01266 Length, 01267 LockKey, 01268 MdlChain, 01269 IoStatus, 01270 DeviceObject); 01271 } 01272 01273 /* 01274 * @implemented 01275 */ 01276 BOOLEAN 01277 NTAPI 01278 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject, 01279 IN PLARGE_INTEGER FileOffset, 01280 IN ULONG Length, 01281 IN ULONG LockKey, 01282 OUT PMDL *MdlChain, 01283 OUT PIO_STATUS_BLOCK IoStatus, 01284 IN PDEVICE_OBJECT DeviceObject) 01285 { 01286 BOOLEAN Result = TRUE; 01287 PFAST_IO_DISPATCH FastIoDispatch; 01288 PDEVICE_OBJECT Device; 01289 PFSRTL_COMMON_FCB_HEADER FcbHeader; 01290 PSHARED_CACHE_MAP SharedCacheMap; 01291 01292 LARGE_INTEGER OldFileSize; 01293 LARGE_INTEGER OldValidDataLength; 01294 LARGE_INTEGER NewSize; 01295 LARGE_INTEGER Offset; 01296 01297 /* WDK doc. 01298 * Offset == 0xffffffffffffffff indicates append to the end of file. 01299 */ 01300 BOOLEAN FileOffsetAppend = (FileOffset->HighPart == (LONG)0xffffffff) && 01301 (FileOffset->LowPart == 0xffffffff); 01302 01303 BOOLEAN FileSizeModified = FALSE; 01304 BOOLEAN ResourceAquiredShared = FALSE; 01305 01306 /* Initialize some of the vars and pointers */ 01307 OldFileSize.QuadPart = 0; 01308 OldValidDataLength.QuadPart = 0; 01309 01310 PAGED_CODE(); 01311 01312 Offset.QuadPart = FileOffset->QuadPart + Length; 01313 01314 /* Nagar p.544. 01315 * Check with Cc if we can write. 01316 */ 01317 if (!CcCanIWrite(FileObject, Length, TRUE, FALSE) || 01318 (FileObject->Flags & FO_WRITE_THROUGH)) 01319 { 01320 return FALSE; 01321 } 01322 01323 IoStatus->Status = STATUS_SUCCESS; 01324 01325 /* No actual read */ 01326 if (!Length) 01327 { 01328 return TRUE; 01329 } 01330 01331 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext; 01332 FsRtlEnterFileSystem(); 01333 01334 /* Check we are going to extend the file */ 01335 if ((FileOffsetAppend == FALSE) && 01336 (FileOffset->QuadPart + Length <= FcbHeader->ValidDataLength.QuadPart)) 01337 { 01338 /* Acquire the resource shared */ 01339 ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE); 01340 ResourceAquiredShared = TRUE; 01341 } 01342 else 01343 { 01344 /* Acquire the resource exclusive */ 01345 ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE); 01346 } 01347 01348 /* Check if we are appending */ 01349 if (FileOffsetAppend == TRUE) 01350 { 01351 Offset.QuadPart = FcbHeader->FileSize.QuadPart; 01352 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length; 01353 } 01354 else 01355 { 01356 Offset.QuadPart = FileOffset->QuadPart; 01357 NewSize.QuadPart = FileOffset->QuadPart + Length; 01358 } 01359 01360 if ((FileObject->PrivateCacheMap) && 01361 (FcbHeader->IsFastIoPossible) && 01362 (Length <= MAXLONGLONG - FileOffset->QuadPart) && 01363 (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart)) 01364 { 01365 /* Check if we can keep the lock shared */ 01366 if (ResourceAquiredShared && 01367 (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart)) 01368 { 01369 ExReleaseResourceLite(FcbHeader->Resource); 01370 ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE); 01371 01372 /* Compute the offset and the new filesize */ 01373 if (FileOffsetAppend) 01374 { 01375 Offset.QuadPart = FcbHeader->FileSize.QuadPart; 01376 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length; 01377 } 01378 01379 /* Recheck the above points since we released and reacquire the lock */ 01380 if ((FileObject->PrivateCacheMap != NULL) && 01381 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) && 01382 (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)) 01383 { 01384 /* Do nothing */ 01385 } 01386 else 01387 { 01388 goto FailAndCleanup; 01389 } 01390 } 01391 01392 /* Check if we need to find out if fast I/O is available */ 01393 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable) 01394 { 01395 /* Sanity check */ 01396 /* ASSERT(!KeIsExecutingDpc()); */ 01397 01398 /* Get the Fast I/O table */ 01399 Device = IoGetRelatedDeviceObject(FileObject); 01400 FastIoDispatch = Device->DriverObject->FastIoDispatch; 01401 01402 /* Sanity check */ 01403 ASSERT(FastIoDispatch != NULL); 01404 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 01405 01406 /* Ask the driver if we can do it */ 01407 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 01408 FileOffset, 01409 Length, 01410 TRUE, 01411 LockKey, 01412 FALSE, 01413 IoStatus, 01414 Device)) 01415 { 01416 /* It's not, fail */ 01417 goto FailAndCleanup; 01418 } 01419 } 01420 01421 /* If we are going to modify the filesize, 01422 * save the old fs in case the operation fails. 01423 */ 01424 if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) 01425 { 01426 FileSizeModified = TRUE; 01427 OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart; 01428 OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart; 01429 01430 /* If the high part of the filesize is going 01431 * to change, grab the Paging IoResouce. 01432 */ 01433 if (NewSize.HighPart != FcbHeader->FileSize.HighPart && 01434 FcbHeader->PagingIoResource) 01435 { 01436 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 01437 FcbHeader->FileSize.QuadPart = NewSize.QuadPart; 01438 ExReleaseResourceLite(FcbHeader->PagingIoResource); 01439 } 01440 else 01441 { 01442 FcbHeader->FileSize.QuadPart = NewSize.QuadPart; 01443 } 01444 } 01445 01446 01447 /* Nagar p.544. 01448 * Set ourselves as top component. 01449 */ 01450 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; 01451 _SEH2_TRY 01452 { 01453 /* Check if there is a gap between the end of the file and the offset. 01454 * If yes, then we have to zero the data. 01455 */ 01456 if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) 01457 { 01458 Result = CcZeroData(FileObject, 01459 &FcbHeader->ValidDataLength, 01460 &Offset, 01461 TRUE); 01462 if (Result) 01463 { 01464 CcPrepareMdlWrite(FileObject, 01465 &Offset, 01466 Length, 01467 MdlChain, 01468 IoStatus); 01469 } 01470 } 01471 else 01472 { 01473 CcPrepareMdlWrite(FileObject, &Offset, Length, MdlChain, IoStatus); 01474 } 01475 01476 } 01477 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 01478 EXCEPTION_EXECUTE_HANDLER : 01479 EXCEPTION_CONTINUE_SEARCH) 01480 { 01481 Result = FALSE; 01482 } 01483 _SEH2_END; 01484 01485 /* Reset the top component */ 01486 PsGetCurrentThread()->TopLevelIrp = 0; 01487 01488 /* Did the operation suceeded */ 01489 if (Result) 01490 { 01491 /* Check if we need to update the filesize */ 01492 if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) 01493 { 01494 if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && 01495 FcbHeader->PagingIoResource) 01496 { 01497 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 01498 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart; 01499 ExReleaseResourceLite(FcbHeader->PagingIoResource); 01500 } 01501 else 01502 { 01503 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart; 01504 } 01505 } 01506 01507 /* Flag the file as modified */ 01508 FileObject->Flags |= FO_FILE_MODIFIED; 01509 01510 /* Check if the filesize has changed */ 01511 if (FileSizeModified) 01512 { 01513 SharedCacheMap = 01514 (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; 01515 SharedCacheMap->FileSize.QuadPart = NewSize.QuadPart; 01516 FileObject->Flags |= FO_FILE_SIZE_CHANGED; 01517 } 01518 } 01519 else 01520 { 01521 /* The operation did not succeed. 01522 * Reset the file size to what it should be. 01523 */ 01524 if (FileSizeModified) 01525 { 01526 if (FcbHeader->PagingIoResource) 01527 { 01528 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE); 01529 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart; 01530 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart; 01531 ExReleaseResourceLite(FcbHeader->PagingIoResource); 01532 } 01533 else 01534 { 01535 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart; 01536 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart; 01537 } 01538 } 01539 } 01540 01541 goto Cleanup; 01542 } 01543 else 01544 { 01545 goto FailAndCleanup; 01546 } 01547 01548 FailAndCleanup: 01549 01550 ExReleaseResourceLite(FcbHeader->Resource); 01551 FsRtlExitFileSystem(); 01552 return FALSE; 01553 01554 Cleanup: 01555 01556 ExReleaseResourceLite(FcbHeader->Resource); 01557 FsRtlExitFileSystem(); 01558 return Result; 01559 } 01560 01561 /* 01562 * @implemented 01563 */ 01564 VOID 01565 NTAPI 01566 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject) 01567 { 01568 /* PAGED_CODE(); */ 01569 /* FsRtlAcquireFileExclusiveCommon(FileObject, 0, 0); */ 01570 KeBugCheck(FILE_SYSTEM); 01571 } 01572 01573 /* 01574 * @implemented 01575 */ 01576 VOID 01577 NTAPI 01578 FsRtlReleaseFile(IN PFILE_OBJECT FileObject) 01579 { 01580 KeBugCheck(FILE_SYSTEM); 01581 } 01582 01583 /*++ 01584 * @name FsRtlRegisterFileSystemFilterCallbacks 01585 * @unimplemented 01586 * 01587 * FILLME 01588 * 01589 * @param FilterDriverObject 01590 * FILLME 01591 * 01592 * @param Callbacks 01593 * FILLME 01594 * 01595 * @return None 01596 * 01597 * @remarks None 01598 * 01599 *--*/ 01600 NTSTATUS 01601 NTAPI 01602 FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject, 01603 IN PFS_FILTER_CALLBACKS Callbacks) 01604 { 01605 UNIMPLEMENTED; 01606 return STATUS_NOT_IMPLEMENTED; 01607 } Generated on Sun May 27 2012 04:27:39 for ReactOS by
1.7.6.1
|