[RDBSS]
[reactos.git] / reactos / sdk / lib / drivers / copysup / copysup.c
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 writting 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 = (((LARGE_INTEGER)LastOffset).LowPart <
552 Fcb->FileSize.LowPart);
553 }
554
555 /* Make sure caching is still enabled */
556 if (FileObject->PrivateCacheMap == NULL ||
557 Fcb->IsFastIoPossible == FastIoIsNotPossible)
558 {
559 ExReleaseResourceLite(Fcb->Resource);
560 FsRtlExitFileSystem();
561
562 return FALSE;
563 }
564
565 /* And that we're not writting beyond allocation size
566 * and that we're not going above 4GB
567 */
568 if ((Fcb->AllocationSize.LowPart < LastOffset.LowPart) ||
569 (Fcb->AllocationSize.HighPart != 0) || AboveFour)
570 {
571 ExReleaseResourceLite(Fcb->Resource);
572 FsRtlExitFileSystem();
573
574 return FALSE;
575 }
576 }
577
578 /* If FastIO is questionable, then question */
579 if (Fcb->IsFastIoPossible == FastIoIsQuestionable)
580 {
581 PFAST_IO_DISPATCH FastIoDispatch;
582 PDEVICE_OBJECT RelatedDeviceObject;
583 C_ASSERT(sizeof(LARGE_INTEGER) == sizeof(LONGLONG));
584
585 RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject);
586 FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch;
587 ASSERT(FastIoDispatch != NULL);
588 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
589
590 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
591 &WriteOffset,
592 Length, Wait, LockKey,
593 FALSE, &LocalIoStatus,
594 RelatedDeviceObject))
595 {
596 ExReleaseResourceLite(Fcb->Resource);
597 FsRtlExitFileSystem();
598
599 return FALSE;
600 }
601 }
602
603 /* If we write beyond EOF, then, save previous sizes (in case of failure)
604 * and update file size, to allow writing
605 */
606 if (LastOffset.LowPart > Fcb->FileSize.LowPart)
607 {
608 FileSizeChanged = TRUE;
609 InitialFileSize.LowPart = Fcb->FileSize.LowPart;
610 InitialValidDataLength.LowPart = Fcb->ValidDataLength.LowPart;
611 Fcb->FileSize.LowPart = LastOffset.LowPart;
612 }
613
614 /* Set caller provided context as top level IRP */
615 IoSetTopLevelIrp(TopLevelContext);
616
617 Ret = TRUE;
618
619 /* And perform the writing */
620 _SEH2_TRY
621 {
622 /* Check whether we've to create a hole first -
623 * it cannot fail, we can wait
624 */
625 if (LastOffset.LowPart > Fcb->ValidDataLength.LowPart)
626 {
627 CcZeroData(FileObject, &Fcb->ValidDataLength, &WriteOffset, TRUE);
628 }
629
630 /* Write data */
631 CcFastCopyWrite(FileObject, WriteOffset.LowPart, Length, Buffer);
632 }
633 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
634 EXCEPTION_EXECUTE_HANDLER :
635 EXCEPTION_CONTINUE_SEARCH)
636 {
637 Ret = FALSE;
638 }
639 _SEH2_END;
640
641 /* Restore top level IRP */
642 IoSetTopLevelIrp(NULL);
643
644 /* If writing succeed */
645 if (Ret)
646 {
647 /* If we wrote beyond VDL, update it */
648 if (LastOffset.LowPart > Fcb->ValidDataLength.LowPart)
649 {
650 Fcb->ValidDataLength.LowPart = LastOffset.LowPart;
651 }
652
653 /* File was obviously modified */
654 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
655
656 /* And if we increased it, modify size in Cc and update FO */
657 if (FileSizeChanged)
658 {
659 (*CcGetFileSizePointer(FileObject)).LowPart = LastOffset.LowPart;
660 SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED);
661 }
662
663 /* Update offset - we're still below 4GB, so high part must be 0 */
664 FileObject->CurrentByteOffset.LowPart = WriteOffset.LowPart + Length;
665 FileObject->CurrentByteOffset.HighPart = 0;
666 }
667 else
668 {
669 /* We failed, we need to restore previous sizes */
670 if (FileSizeChanged)
671 {
672 if (Fcb->PagingIoResource != NULL)
673 {
674 ExAcquireResourceExclusiveLite(Fcb->PagingIoResource, TRUE);
675 Fcb->FileSize.LowPart = InitialFileSize.LowPart;
676 Fcb->ValidDataLength.LowPart = InitialValidDataLength.LowPart;
677 ExReleaseResourceLite(Fcb->PagingIoResource);
678 }
679 else
680 {
681 Fcb->FileSize.LowPart = InitialFileSize.LowPart;
682 Fcb->ValidDataLength.LowPart = InitialValidDataLength.LowPart;
683 }
684 }
685 }
686 }
687
688 /* Release our resource and leave */
689 ExReleaseResourceLite(Fcb->Resource);
690
691 FsRtlExitFileSystem();
692
693 return Ret;
694 }