ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fastio.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.