1 /* 2 * ReactOS kernel 3 * Copyright (C) 2017 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS kernel 22 * FILE: sdk/lib/drivers/copysup/copysup.c 23 * PURPOSE: CopySup library 24 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org) 25 */ 26 27 /* INCLUDES *****************************************************************/ 28 29 #include "copysup.h" 30 #include <pseh/pseh2.h> 31 #define NDEBUG 32 #include <debug.h> 33 34 /* FUNCTIONS ****************************************************************/ 35 36 /* 37 * @implemented 38 */ 39 BOOLEAN 40 FsRtlCopyRead2( 41 IN PFILE_OBJECT FileObject, 42 IN PLARGE_INTEGER FileOffset, 43 IN ULONG Length, 44 IN BOOLEAN Wait, 45 IN ULONG LockKey, 46 OUT PVOID Buffer, 47 OUT PIO_STATUS_BLOCK IoStatus, 48 IN PDEVICE_OBJECT DeviceObject, 49 IN PVOID TopLevelContext) 50 { 51 BOOLEAN Ret; 52 ULONG PageCount; 53 LARGE_INTEGER FinalOffset; 54 PFSRTL_COMMON_FCB_HEADER Fcb; 55 PFAST_IO_DISPATCH FastIoDispatch; 56 PDEVICE_OBJECT RelatedDeviceObject; 57 58 PAGED_CODE(); 59 60 Ret = TRUE; 61 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset, Length); 62 63 /* Null-length read is always OK */ 64 if (Length == 0) 65 { 66 IoStatus->Information = 0; 67 IoStatus->Status = STATUS_SUCCESS; 68 69 return TRUE; 70 } 71 72 /* Check we don't overflow */ 73 FinalOffset.QuadPart = FileOffset->QuadPart + Length; 74 if (FinalOffset.QuadPart <= 0) 75 { 76 return FALSE; 77 } 78 79 /* Get the FCB (at least, its header) */ 80 Fcb = FileObject->FsContext; 81 82 FsRtlEnterFileSystem(); 83 84 /* Acquire its resource (shared) */ 85 if (Wait) 86 { 87 ExAcquireResourceSharedLite(Fcb->Resource, TRUE); 88 } 89 else 90 { 91 if (!ExAcquireResourceSharedLite(Fcb->Resource, FALSE)) 92 { 93 Ret = FALSE; 94 goto CriticalSection; 95 } 96 } 97 98 /* If cache wasn't initialized, or FastIO isn't possible, fail */ 99 if (FileObject->PrivateCacheMap == NULL || Fcb->IsFastIoPossible == FastIoIsNotPossible) 100 { 101 Ret = FALSE; 102 goto Resource; 103 } 104 105 /* If FastIO is questionable, then, question! */ 106 if (Fcb->IsFastIoPossible == FastIoIsQuestionable) 107 { 108 RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject); 109 FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch; 110 ASSERT(FastIoDispatch != NULL); 111 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 112 113 /* If it's not possible, then fail */ 114 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, FileOffset, Length, 115 Wait, LockKey, TRUE, IoStatus, RelatedDeviceObject)) 116 { 117 Ret = FALSE; 118 goto Resource; 119 } 120 } 121 122 /* If we get beyond file end... */ 123 if (FinalOffset.QuadPart > Fcb->FileSize.QuadPart) 124 { 125 /* Fail if the offset was already beyond file end */ 126 if (FileOffset->QuadPart >= Fcb->FileSize.QuadPart) 127 { 128 IoStatus->Information = 0; 129 IoStatus->Status = STATUS_END_OF_FILE; 130 goto Resource; 131 } 132 133 /* Otherwise, just fix read length */ 134 Length = (ULONG)(Fcb->FileSize.QuadPart - FileOffset->QuadPart); 135 } 136 137 /* Set caller provided context as TLI */ 138 IoSetTopLevelIrp(TopLevelContext); 139 140 _SEH2_TRY 141 { 142 /* If we cannot wait, or if file is bigger than 4GB */ 143 if (!Wait || (FinalOffset.HighPart | Fcb->FileSize.HighPart) != 0) 144 { 145 /* Forward to Cc */ 146 Ret = CcCopyRead(FileObject, FileOffset, Length, Wait, Buffer, IoStatus); 147 SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ); 148 149 /* Validate output */ 150 ASSERT(!Ret || (IoStatus->Status == STATUS_END_OF_FILE) || (((ULONGLONG)FileOffset->QuadPart + IoStatus->Information) <= (ULONGLONG)Fcb->FileSize.QuadPart)); 151 } 152 else 153 { 154 /* Forward to Cc */ 155 CcFastCopyRead(FileObject, FileOffset->LowPart, Length, PageCount, Buffer, IoStatus); 156 SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ); 157 158 /* Validate output */ 159 ASSERT((IoStatus->Status == STATUS_END_OF_FILE) || ((FileOffset->LowPart + IoStatus->Information) <= Fcb->FileSize.LowPart)); 160 } 161 162 /* If read was successful, update the byte offset in the FO */ 163 if (Ret) 164 { 165 FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information; 166 } 167 } 168 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 169 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 170 { 171 Ret = FALSE; 172 } 173 _SEH2_END; 174 175 /* Reset TLI */ 176 IoSetTopLevelIrp(NULL); 177 178 Resource: 179 ExReleaseResourceLite(Fcb->Resource); 180 CriticalSection: 181 FsRtlExitFileSystem(); 182 183 return Ret; 184 } 185 186 /* 187 * @implemented 188 */ 189 BOOLEAN 190 FsRtlCopyWrite2( 191 IN PFILE_OBJECT FileObject, 192 IN PLARGE_INTEGER FileOffset, 193 IN ULONG Length, 194 IN BOOLEAN Wait, 195 IN ULONG LockKey, 196 IN PVOID Buffer, 197 OUT PIO_STATUS_BLOCK IoStatus, 198 IN PDEVICE_OBJECT DeviceObject, 199 IN PVOID TopLevelContext) 200 { 201 IO_STATUS_BLOCK LocalIoStatus; 202 PFSRTL_ADVANCED_FCB_HEADER Fcb; 203 BOOLEAN WriteToEof, AcquiredShared, FileSizeChanged, Ret; 204 LARGE_INTEGER WriteOffset, LastOffset, InitialFileSize, InitialValidDataLength; 205 206 PAGED_CODE(); 207 208 /* First, check whether we're writing to EOF */ 209 WriteToEof = ((FileOffset->LowPart == FILE_WRITE_TO_END_OF_FILE) && 210 (FileOffset->HighPart == -1)); 211 212 /* If Cc says we cannot write, fail now */ 213 if (!CcCanIWrite(FileObject, Length, Wait, FALSE)) 214 { 215 return FALSE; 216 } 217 218 /* Write through means no cache */ 219 if (BooleanFlagOn(FileObject->Flags, FO_WRITE_THROUGH)) 220 { 221 return FALSE; 222 } 223 224 /* If write is > 64Kb, don't use FastIO */ 225 if (!CcCopyWriteWontFlush(FileObject, FileOffset, Length)) 226 { 227 return FALSE; 228 } 229 230 /* Initialize the IO_STATUS_BLOCK */ 231 IoStatus->Status = STATUS_SUCCESS; 232 IoStatus->Information = Length; 233 234 /* No length, it's already written! */ 235 if (Length == 0) 236 { 237 return TRUE; 238 } 239 240 AcquiredShared = FALSE; 241 FileSizeChanged = FALSE; 242 Fcb = FileObject->FsContext; 243 244 FsRtlEnterFileSystem(); 245 246 /* If we cannot wait, or deal with files bigger then 4GB */ 247 if (!Wait || (Fcb->AllocationSize.HighPart != 0)) 248 { 249 /* If we're to extend the file, then, acquire exclusively */ 250 if (WriteToEof || FileOffset->QuadPart + Length > Fcb->ValidDataLength.QuadPart) 251 { 252 if (!ExAcquireResourceExclusiveLite(Fcb->Resource, Wait)) 253 { 254 FsRtlExitFileSystem(); 255 return FALSE; 256 } 257 } 258 /* Otherwise, a shared lock is enough */ 259 else 260 { 261 if (!ExAcquireResourceSharedLite(Fcb->Resource, Wait)) 262 { 263 FsRtlExitFileSystem(); 264 return FALSE; 265 } 266 267 AcquiredShared = TRUE; 268 } 269 270 /* Get first write offset, and last */ 271 if (WriteToEof) 272 { 273 WriteOffset.QuadPart = Fcb->FileSize.QuadPart; 274 LastOffset.QuadPart = WriteOffset.QuadPart + Length; 275 } 276 else 277 { 278 WriteOffset.QuadPart = FileOffset->QuadPart; 279 LastOffset.QuadPart = WriteOffset.QuadPart + Length; 280 } 281 282 /* If cache wasn't initialized, fail */ 283 if (FileObject->PrivateCacheMap == NULL || 284 Fcb->IsFastIoPossible == FastIoIsNotPossible) 285 { 286 ExReleaseResourceLite(Fcb->Resource); 287 FsRtlExitFileSystem(); 288 289 return FALSE; 290 } 291 292 /* If we're to write beyond allocation size, it's no go, 293 * same is we create a hole bigger than 8kb 294 */ 295 if ((Fcb->ValidDataLength.QuadPart + 0x2000 <= WriteOffset.QuadPart) || 296 (Length > MAXLONGLONG - WriteOffset.QuadPart) || 297 (Fcb->AllocationSize.QuadPart < LastOffset.QuadPart)) 298 { 299 ExReleaseResourceLite(Fcb->Resource); 300 FsRtlExitFileSystem(); 301 302 return FALSE; 303 } 304 305 /* If we have to extend the VDL, shared lock isn't enough */ 306 if (AcquiredShared && LastOffset.QuadPart > Fcb->ValidDataLength.QuadPart) 307 { 308 /* So release, and attempt to acquire exclusively */ 309 ExReleaseResourceLite(Fcb->Resource); 310 if (!ExAcquireResourceExclusiveLite(Fcb->Resource, Wait)) 311 { 312 FsRtlExitFileSystem(); 313 return FALSE; 314 } 315 316 /* Get again EOF, in case file size changed in between */ 317 if (WriteToEof) 318 { 319 WriteOffset.QuadPart = Fcb->FileSize.QuadPart; 320 LastOffset.QuadPart = WriteOffset.QuadPart + Length; 321 } 322 323 /* Make sure caching is still enabled */ 324 if (FileObject->PrivateCacheMap == NULL || 325 Fcb->IsFastIoPossible == FastIoIsNotPossible) 326 { 327 ExReleaseResourceLite(Fcb->Resource); 328 FsRtlExitFileSystem(); 329 330 return FALSE; 331 } 332 333 /* And that we're not writing beyond allocation size */ 334 if (Fcb->AllocationSize.QuadPart < LastOffset.QuadPart) 335 { 336 ExReleaseResourceLite(Fcb->Resource); 337 FsRtlExitFileSystem(); 338 339 return FALSE; 340 } 341 } 342 343 /* If FastIO is questionable, then question */ 344 if (Fcb->IsFastIoPossible == FastIoIsQuestionable) 345 { 346 PFAST_IO_DISPATCH FastIoDispatch; 347 PDEVICE_OBJECT RelatedDeviceObject; 348 349 RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject); 350 FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch; 351 ASSERT(FastIoDispatch != NULL); 352 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 353 354 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 355 &WriteOffset, 356 Length, Wait, LockKey, 357 FALSE, &LocalIoStatus, 358 RelatedDeviceObject)) 359 { 360 ExReleaseResourceLite(Fcb->Resource); 361 FsRtlExitFileSystem(); 362 363 return FALSE; 364 } 365 } 366 367 /* If we write beyond EOF, then, save previous sizes (in case of failure) 368 * and update file size, to allow writing 369 */ 370 if (LastOffset.QuadPart > Fcb->FileSize.QuadPart) 371 { 372 FileSizeChanged = TRUE; 373 InitialFileSize.QuadPart = Fcb->FileSize.QuadPart; 374 InitialValidDataLength.QuadPart = Fcb->ValidDataLength.QuadPart; 375 376 if (LastOffset.HighPart != Fcb->FileSize.HighPart && 377 Fcb->PagingIoResource != NULL) 378 { 379 ExAcquireResourceExclusiveLite(Fcb->PagingIoResource, TRUE); 380 Fcb->FileSize.QuadPart = LastOffset.QuadPart; 381 ExReleaseResourceLite(Fcb->PagingIoResource); 382 } 383 else 384 { 385 Fcb->FileSize.QuadPart = LastOffset.QuadPart; 386 } 387 } 388 389 /* Set caller provided context as top level IRP */ 390 IoSetTopLevelIrp(TopLevelContext); 391 392 Ret = TRUE; 393 394 /* And perform the writing */ 395 _SEH2_TRY 396 { 397 /* Check whether we've to create a hole first */ 398 if (LastOffset.QuadPart > Fcb->ValidDataLength.QuadPart) 399 { 400 Ret = CcZeroData(FileObject, &Fcb->ValidDataLength, 401 &WriteOffset, Wait); 402 } 403 404 /* If not needed, or if it worked, write data */ 405 if (Ret) 406 { 407 Ret = CcCopyWrite(FileObject, &WriteOffset, 408 Length, Wait, Buffer); 409 } 410 } 411 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 412 EXCEPTION_EXECUTE_HANDLER : 413 EXCEPTION_CONTINUE_SEARCH) 414 { 415 Ret = FALSE; 416 } 417 _SEH2_END; 418 419 /* Restore top level IRP */ 420 IoSetTopLevelIrp(NULL); 421 422 /* If writing succeed */ 423 if (Ret) 424 { 425 /* If we wrote beyond VDL, update it */ 426 if (LastOffset.QuadPart > Fcb->ValidDataLength.QuadPart) 427 { 428 if (LastOffset.HighPart != Fcb->ValidDataLength.HighPart && 429 Fcb->PagingIoResource != NULL) 430 { 431 ExAcquireResourceExclusiveLite(Fcb->PagingIoResource, TRUE); 432 Fcb->ValidDataLength.QuadPart = LastOffset.QuadPart; 433 ExReleaseResourceLite(Fcb->PagingIoResource); 434 } 435 else 436 { 437 Fcb->ValidDataLength.QuadPart = LastOffset.QuadPart; 438 } 439 } 440 441 /* File was obviously modified */ 442 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 443 444 /* And if we increased it, modify size in Cc and update FO */ 445 if (FileSizeChanged) 446 { 447 (*CcGetFileSizePointer(FileObject)).QuadPart = LastOffset.QuadPart; 448 SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED); 449 } 450 451 /* Update offset */ 452 FileObject->CurrentByteOffset.QuadPart = WriteOffset.QuadPart + Length; 453 } 454 else 455 { 456 /* We failed, we need to restore previous sizes */ 457 if (FileSizeChanged) 458 { 459 if (Fcb->PagingIoResource != NULL) 460 { 461 ExAcquireResourceExclusiveLite(Fcb->PagingIoResource, TRUE); 462 Fcb->FileSize.QuadPart = InitialFileSize.QuadPart; 463 Fcb->ValidDataLength.QuadPart = InitialValidDataLength.QuadPart; 464 ExReleaseResourceLite(Fcb->PagingIoResource); 465 } 466 else 467 { 468 Fcb->FileSize.QuadPart = InitialFileSize.QuadPart; 469 Fcb->ValidDataLength.QuadPart = InitialValidDataLength.QuadPart; 470 } 471 } 472 } 473 } 474 else 475 { 476 BOOLEAN AboveFour; 477 478 WriteOffset.HighPart = 0; 479 LastOffset.HighPart = 0; 480 481 /* If we're to extend the file, then, acquire exclusively 482 * Here, easy stuff, we know we can wait, no return to check! 483 */ 484 if (WriteToEof || FileOffset->QuadPart + Length > Fcb->ValidDataLength.QuadPart) 485 { 486 ExAcquireResourceExclusiveLite(Fcb->Resource, TRUE); 487 } 488 /* Otherwise, a shared lock is enough */ 489 else 490 { 491 ExAcquireResourceSharedLite(Fcb->Resource, TRUE); 492 AcquiredShared = TRUE; 493 } 494 495 /* Get first write offset, and last 496 * Also check whether our writing will bring us 497 * beyond the 4GB 498 */ 499 if (WriteToEof) 500 { 501 WriteOffset.LowPart = Fcb->FileSize.LowPart; 502 LastOffset.LowPart = WriteOffset.LowPart + Length; 503 AboveFour = (LastOffset.LowPart < Fcb->FileSize.LowPart); 504 } 505 else 506 { 507 WriteOffset.LowPart = FileOffset->LowPart; 508 LastOffset.LowPart = WriteOffset.LowPart + Length; 509 AboveFour = (LastOffset.LowPart < FileOffset->LowPart) || 510 (FileOffset->HighPart != 0); 511 } 512 513 /* If cache wasn't initialized, fail */ 514 if (FileObject->PrivateCacheMap == NULL || 515 Fcb->IsFastIoPossible == FastIoIsNotPossible) 516 { 517 ExReleaseResourceLite(Fcb->Resource); 518 FsRtlExitFileSystem(); 519 520 return FALSE; 521 } 522 523 /* If we're to write beyond allocation size, it's no go, 524 * same is we create a hole bigger than 8kb 525 * same if we end writing beyond 4GB 526 */ 527 if ((Fcb->AllocationSize.LowPart < LastOffset.LowPart) || 528 (WriteOffset.LowPart >= Fcb->ValidDataLength.LowPart + 0x2000) || 529 AboveFour) 530 { 531 ExReleaseResourceLite(Fcb->Resource); 532 FsRtlExitFileSystem(); 533 534 return FALSE; 535 } 536 537 /* If we have to extend the VDL, shared lock isn't enough */ 538 if (AcquiredShared && LastOffset.LowPart > Fcb->ValidDataLength.LowPart) 539 { 540 /* So release, and acquire exclusively */ 541 ExReleaseResourceLite(Fcb->Resource); 542 ExAcquireResourceExclusiveLite(Fcb->Resource, TRUE); 543 544 /* Get again EOF, in case file size changed in between and 545 * recheck we won't go beyond 4GB 546 */ 547 if (WriteToEof) 548 { 549 WriteOffset.LowPart = Fcb->FileSize.LowPart; 550 LastOffset.LowPart = WriteOffset.LowPart + Length; 551 AboveFour = (LastOffset.LowPart < Fcb->FileSize.LowPart); 552 } 553 554 /* Make sure caching is still enabled */ 555 if (FileObject->PrivateCacheMap == NULL || 556 Fcb->IsFastIoPossible == FastIoIsNotPossible) 557 { 558 ExReleaseResourceLite(Fcb->Resource); 559 FsRtlExitFileSystem(); 560 561 return FALSE; 562 } 563 564 /* And that we're not writing beyond allocation size 565 * and that we're not going above 4GB 566 */ 567 if ((Fcb->AllocationSize.LowPart < LastOffset.LowPart) || 568 (Fcb->AllocationSize.HighPart != 0) || AboveFour) 569 { 570 ExReleaseResourceLite(Fcb->Resource); 571 FsRtlExitFileSystem(); 572 573 return FALSE; 574 } 575 } 576 577 /* If FastIO is questionable, then question */ 578 if (Fcb->IsFastIoPossible == FastIoIsQuestionable) 579 { 580 PFAST_IO_DISPATCH FastIoDispatch; 581 PDEVICE_OBJECT RelatedDeviceObject; 582 583 RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject); 584 FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch; 585 ASSERT(FastIoDispatch != NULL); 586 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL); 587 588 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, 589 &WriteOffset, 590 Length, Wait, LockKey, 591 FALSE, &LocalIoStatus, 592 RelatedDeviceObject)) 593 { 594 ExReleaseResourceLite(Fcb->Resource); 595 FsRtlExitFileSystem(); 596 597 return FALSE; 598 } 599 } 600 601 /* If we write beyond EOF, then, save previous sizes (in case of failure) 602 * and update file size, to allow writing 603 */ 604 if (LastOffset.LowPart > Fcb->FileSize.LowPart) 605 { 606 FileSizeChanged = TRUE; 607 InitialFileSize.LowPart = Fcb->FileSize.LowPart; 608 InitialValidDataLength.LowPart = Fcb->ValidDataLength.LowPart; 609 Fcb->FileSize.LowPart = LastOffset.LowPart; 610 } 611 612 /* Set caller provided context as top level IRP */ 613 IoSetTopLevelIrp(TopLevelContext); 614 615 Ret = TRUE; 616 617 /* And perform the writing */ 618 _SEH2_TRY 619 { 620 /* Check whether we've to create a hole first - 621 * it cannot fail, we can wait 622 */ 623 if (LastOffset.LowPart > Fcb->ValidDataLength.LowPart) 624 { 625 CcZeroData(FileObject, &Fcb->ValidDataLength, &WriteOffset, TRUE); 626 } 627 628 /* Write data */ 629 CcFastCopyWrite(FileObject, WriteOffset.LowPart, Length, Buffer); 630 } 631 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? 632 EXCEPTION_EXECUTE_HANDLER : 633 EXCEPTION_CONTINUE_SEARCH) 634 { 635 Ret = FALSE; 636 } 637 _SEH2_END; 638 639 /* Restore top level IRP */ 640 IoSetTopLevelIrp(NULL); 641 642 /* If writing succeed */ 643 if (Ret) 644 { 645 /* If we wrote beyond VDL, update it */ 646 if (LastOffset.LowPart > Fcb->ValidDataLength.LowPart) 647 { 648 Fcb->ValidDataLength.LowPart = LastOffset.LowPart; 649 } 650 651 /* File was obviously modified */ 652 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 653 654 /* And if we increased it, modify size in Cc and update FO */ 655 if (FileSizeChanged) 656 { 657 (*CcGetFileSizePointer(FileObject)).LowPart = LastOffset.LowPart; 658 SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED); 659 } 660 661 /* Update offset - we're still below 4GB, so high part must be 0 */ 662 FileObject->CurrentByteOffset.LowPart = WriteOffset.LowPart + Length; 663 FileObject->CurrentByteOffset.HighPart = 0; 664 } 665 else 666 { 667 /* We failed, we need to restore previous sizes */ 668 if (FileSizeChanged) 669 { 670 if (Fcb->PagingIoResource != NULL) 671 { 672 ExAcquireResourceExclusiveLite(Fcb->PagingIoResource, TRUE); 673 Fcb->FileSize.LowPart = InitialFileSize.LowPart; 674 Fcb->ValidDataLength.LowPart = InitialValidDataLength.LowPart; 675 ExReleaseResourceLite(Fcb->PagingIoResource); 676 } 677 else 678 { 679 Fcb->FileSize.LowPart = InitialFileSize.LowPart; 680 Fcb->ValidDataLength.LowPart = InitialValidDataLength.LowPart; 681 } 682 } 683 } 684 } 685 686 /* Release our resource and leave */ 687 ExReleaseResourceLite(Fcb->Resource); 688 689 FsRtlExitFileSystem(); 690 691 return Ret; 692 } 693