- COMPUTE_PAGES_SPANNED is deprecated, use ADDRESS_AND_SIZE_TO_SPAN_PAGES instead
[reactos.git] / reactos / ntoskrnl / fsrtl / fastio.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/fastio.c
5 * PURPOSE: Provides Fast I/O entrypoints to the Cache Manager
6 * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PUBLIC FUNCTIONS **********************************************************/
16
17 /*
18 * @implemented
19 */
20 VOID
21 NTAPI
22 FsRtlIncrementCcFastReadResourceMiss(VOID)
23 {
24 CcFastReadResourceMiss++;
25 }
26
27 /*
28 * @implemented
29 */
30 VOID
31 NTAPI
32 FsRtlIncrementCcFastReadNotPossible(VOID)
33 {
34 CcFastReadNotPossible++;
35 }
36
37 /*
38 * @implemented
39 */
40 VOID
41 NTAPI
42 FsRtlIncrementCcFastReadWait(VOID)
43 {
44 CcFastReadWait++;
45 }
46
47 /*
48 * @implemented
49 */
50 VOID
51 NTAPI
52 FsRtlIncrementCcFastReadNoWait(VOID)
53 {
54 CcFastReadNoWait++;
55 }
56
57 /*
58 * @implemented
59 */
60 BOOLEAN
61 NTAPI
62 FsRtlCopyRead(IN PFILE_OBJECT FileObject,
63 IN PLARGE_INTEGER FileOffset,
64 IN ULONG Length,
65 IN BOOLEAN Wait,
66 IN ULONG LockKey,
67 OUT PVOID Buffer,
68 OUT PIO_STATUS_BLOCK IoStatus,
69 IN PDEVICE_OBJECT DeviceObject)
70 {
71
72 PFSRTL_COMMON_FCB_HEADER FcbHeader;
73 LARGE_INTEGER Offset;
74 PFAST_IO_DISPATCH FastIoDispatch;
75 PDEVICE_OBJECT Device;
76 BOOLEAN Result = TRUE;
77 ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset,Length);
78
79 PAGED_CODE();
80 ASSERT(FileObject);
81 ASSERT(FileObject->FsContext);
82
83 /* No actual read */
84 if (!Length)
85 {
86 /* Return success */
87 IoStatus->Status = STATUS_SUCCESS;
88 IoStatus->Information = 0;
89 return TRUE;
90 }
91
92 if (MAXLONGLONG < (LONGLONG) FileOffset->QuadPart + Length) {
93 IoStatus->Status = STATUS_INVALID_PARAMETER;
94 IoStatus->Information = 0;
95 return FALSE;
96 }
97
98 /* Get the offset and FCB header */
99 Offset.QuadPart = FileOffset->QuadPart + Length;
100 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
101
102
103 if (Wait) {
104 /* Use a Resource Acquire */
105 FsRtlEnterFileSystem();
106 CcFastReadWait++;
107 ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
108 } else {
109 /* Acquire the resource without blocking */
110 /* Return false and the I/O manager will retry using the standard IRP method. */
111 /* Use a Resource Acquire */
112 FsRtlEnterFileSystem();
113 if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE)) {
114 FsRtlExitFileSystem();
115 FsRtlIncrementCcFastReadResourceMiss();
116 return FALSE;
117 }
118 }
119
120
121 /* Check if this is a fast I/O cached file */
122 if (!(FileObject->PrivateCacheMap) ||
123 (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) {
124 /* It's not, so fail */
125 Result = FALSE;
126 goto Cleanup;
127 }
128
129 /* Check if we need to find out if fast I/O is available */
130 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
131 {
132 /* Sanity check */
133 ASSERT(!KeIsExecutingDpc());
134
135 /* Get the Fast I/O table */
136 Device = IoGetRelatedDeviceObject(FileObject);
137 FastIoDispatch = Device->DriverObject->FastIoDispatch;
138
139 /* Sanity check */
140 ASSERT(FastIoDispatch != NULL);
141 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
142
143 /* Ask the driver if we can do it */
144 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
145 FileOffset,
146 Length,
147 TRUE,
148 LockKey,
149 TRUE,
150 IoStatus,
151 Device))
152 {
153 /* It's not, fail */
154 Result = FALSE;
155 goto Cleanup;
156 }
157 }
158
159 /* Check if we read too much */
160 if (Offset.QuadPart > FcbHeader->FileSize.QuadPart){
161 /* We did, check if the file offset is past the end */
162 if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart){
163 /* Set end of file */
164 IoStatus->Status = STATUS_END_OF_FILE;
165 IoStatus->Information = 0;
166 goto Cleanup;
167 }
168
169 /* Otherwise, just normalize the length */
170 Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
171 }
172
173 /* Set this as top-level IRP */
174 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
175
176 _SEH2_TRY
177 {
178 /* Make sure the IO and file size is below 4GB */
179 if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) {
180
181 /* Call the cache controller */
182 CcFastCopyRead (FileObject,FileOffset->LowPart,Length,PageCount,Buffer,IoStatus);
183 /* File was accessed */
184 FileObject->Flags |= FO_FILE_FAST_IO_READ;
185 if (IoStatus->Status != STATUS_END_OF_FILE) {
186 ASSERT(( FcbHeader->FileSize.QuadPart) >= (FileOffset->QuadPart + IoStatus->Information));
187 }
188
189 } else {
190
191 /* Call the cache controller */
192 Result = CcCopyRead(FileObject, FileOffset, Length, Wait,Buffer, IoStatus);
193 /* File was accessed */
194 FileObject->Flags |= FO_FILE_FAST_IO_READ;
195 if (Result == TRUE) {
196 ASSERT( (IoStatus->Status == STATUS_END_OF_FILE) ||
197 ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <= FcbHeader->FileSize.QuadPart)
198 );
199 }
200 }
201
202 /* Update the current file offset */
203 if (Result == TRUE) {
204 FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
205 }
206 }
207 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
208 {
209 Result = FALSE;
210 } _SEH2_END;
211
212 PsGetCurrentThread()->TopLevelIrp = 0;
213
214 /* Return to caller */
215 Cleanup:
216
217 ExReleaseResourceLite(FcbHeader->Resource);
218 FsRtlExitFileSystem();
219
220 if (Result == FALSE) {
221 CcFastReadNotPossible += 1;
222 }
223
224 return Result;
225
226 }
227
228
229 /*
230 * @implemented
231 */
232 BOOLEAN
233 NTAPI
234 FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
235 IN PLARGE_INTEGER FileOffset,
236 IN ULONG Length,
237 IN BOOLEAN Wait,
238 IN ULONG LockKey,
239 OUT PVOID Buffer,
240 OUT PIO_STATUS_BLOCK IoStatus,
241 IN PDEVICE_OBJECT DeviceObject)
242 {
243
244 BOOLEAN Result = TRUE;
245 PFAST_IO_DISPATCH FastIoDispatch;
246 PDEVICE_OBJECT Device;
247 PFSRTL_COMMON_FCB_HEADER FcbHeader;
248
249 /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
250 BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) && (FileOffset->LowPart == 0xffffffff));
251 BOOLEAN ResourceAquiredShared = FALSE;
252
253 BOOLEAN b_4GB = FALSE;
254
255 BOOLEAN FileSizeModified = FALSE;
256 LARGE_INTEGER OldFileSize;
257 LARGE_INTEGER OldValidDataLength;
258
259 LARGE_INTEGER NewSize;
260 LARGE_INTEGER Offset;
261
262 PAGED_CODE();
263
264 ASSERT(FileObject);
265 ASSERT(FileObject->FsContext);
266
267 /* Initialize some of the vars and pointers */
268 NewSize.QuadPart = 0;
269 Offset.QuadPart = FileOffset->QuadPart + Length;
270 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
271
272 /* Nagar p.544 -- Check with Cc if we can write and check if the IO > 64kB (WDK macro) */
273 if ( (CcCanIWrite(FileObject, Length,Wait, FALSE) == FALSE) ||
274 (CcCopyWriteWontFlush(FileObject,FileOffset,Length) == FALSE) ||
275 ((FileObject->Flags & FO_WRITE_THROUGH )== TRUE)
276 )
277 {
278 return FALSE;
279 }
280
281 /* No actual read */
282 if (!Length)
283 {
284 IoStatus->Status = STATUS_SUCCESS;
285 IoStatus->Information = Length;
286 return TRUE;
287 }
288
289 FsRtlEnterFileSystem();
290
291 /* Nagar p.544/545 -- The CcFastCopyWrite doesn't deal with filesize beyond 4GB*/
292 if (Wait && (FcbHeader->AllocationSize.HighPart == 0))
293 {
294 /* If the file offset is not past the file size, then we can acquire the lock shared */
295 if ((FileOffsetAppend == FALSE) && (Offset.LowPart <= FcbHeader->ValidDataLength.LowPart)){
296 ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
297 ResourceAquiredShared = TRUE;
298 } else {
299 ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
300 }
301
302 /* Nagar p.544/545 -- If we append, use the file size as offset. Also, check that we aren't crossing the 4GB boundary */
303 if ((FileOffsetAppend == TRUE)) {
304 Offset.LowPart = FcbHeader->FileSize.LowPart;
305 NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
306 b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart);
307
308 } else {
309 Offset.LowPart = FileOffset->LowPart;
310 NewSize.LowPart = FileOffset->LowPart + Length;
311 b_4GB = ((NewSize.LowPart < FileOffset->LowPart) || (FileOffset->HighPart != 0));
312 }
313
314 /* Nagar p.544/545
315 Make sure that caching is initated.
316 That fast are allowed for this file stream.
317 That we are not extending past the allocated size
318 That we are not creating a hole bigger than 8k
319 That we are not crossing the 4GB boundary
320 */
321 if ( (FileObject->PrivateCacheMap != NULL) &&
322 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
323 (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
324 (Offset.LowPart < (FcbHeader->ValidDataLength.LowPart + 0x2000) ) &&
325 !b_4GB
326 )
327 {
328 /* If we are extending past the file size, we need to release the lock and acquire it
329 exclusively, because we are going to need to update the FcbHeader */
330 if (ResourceAquiredShared && (NewSize.LowPart > (FcbHeader->ValidDataLength.LowPart + 0x2000))) {
331 /* Then we need to acquire the resource exclusive */
332 ExReleaseResourceLite(FcbHeader->Resource);
333 ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
334 if (FileOffsetAppend == TRUE) {
335 Offset.LowPart = FcbHeader->FileSize.LowPart; // ??
336 NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
337 /* Make sure we don't cross the 4GB boundary */
338 b_4GB = (NewSize.LowPart < Offset.LowPart);
339 }
340
341 /* Recheck some of the conditions since we let the lock go */
342 if ( (FileObject->PrivateCacheMap != NULL) &&
343 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
344 (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
345 (FcbHeader->AllocationSize.HighPart == 0) &&
346 !b_4GB
347 )
348 {
349 } else
350 {
351 goto FailAndCleanup;
352 }
353 }
354
355 }else
356 {
357 goto FailAndCleanup;
358 }
359
360 /* Check if we need to find out if fast I/O is available */
361 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
362 {
363 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
364
365 /* Sanity check */
366 ASSERT(!KeIsExecutingDpc());
367
368 /* Get the Fast I/O table */
369 Device = IoGetRelatedDeviceObject(FileObject);
370 FastIoDispatch = Device->DriverObject->FastIoDispatch;
371
372 /* Sanity check */
373 ASSERT(FastIoDispatch != NULL);
374 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
375
376 /* Ask the driver if we can do it */
377 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
378 FileOffsetAppend? &FcbHeader->FileSize:FileOffset,
379 Length,
380 TRUE,
381 LockKey,
382 FALSE,
383 &FastIoCheckIfPossibleStatus,
384 Device))
385 {
386 /* It's not, fail */
387 goto FailAndCleanup;
388 }
389 }
390
391 /* If we are going to extend the file then save the old file size
392 in case the operation fails
393 */
394 if (NewSize.LowPart > FcbHeader->FileSize.LowPart) {
395 FileSizeModified = TRUE;
396 OldFileSize.LowPart = FcbHeader->FileSize.LowPart;
397 OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart;
398 FcbHeader->FileSize.LowPart = NewSize.LowPart;
399 }
400
401 /* Set this as top-level IRP */
402 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
403
404 _SEH2_TRY
405 {
406 if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) {
407 LARGE_INTEGER OffsetVar;
408 OffsetVar.LowPart = Offset.LowPart;
409 OffsetVar.HighPart = 0;
410 CcZeroData(FileObject,&FcbHeader->ValidDataLength,&OffsetVar,TRUE);
411 }
412
413 /* Call the cache manager */
414 CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer);
415 }
416 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
417 {
418 Result = FALSE;
419 } _SEH2_END;
420
421 /* Remove ourselves at the top level component after the IO is done */
422 PsGetCurrentThread()->TopLevelIrp = 0;
423
424 /* Did the operation succeed ? */
425 if (Result == TRUE) {
426 /* Update the valid file size if necessary */
427 if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart){
428 FcbHeader->ValidDataLength.LowPart = NewSize.LowPart ;
429 }
430
431 /* Flag the file as modified */
432 FileObject->Flags |= FO_FILE_MODIFIED;
433
434 /* Update the strucutres if the file size changed */
435 if (FileSizeModified) {
436 ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.LowPart = NewSize.LowPart;
437 FileObject->Flags |= FO_FILE_SIZE_CHANGED;
438 }
439
440 /* Update the file object current file offset */
441 FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart;
442
443 } else {
444
445 /* Result == FALSE if we get here. */
446 if (FileSizeModified) {
447 /* If the file size was modified then restore the old file size */
448 if(FcbHeader->PagingIoResource != NULL) {
449 // Nagar P.544 Restore the old file size if operation didn't succeed.
450 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource,TRUE);
451 FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
452 FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
453 ExReleaseResourceLite(FcbHeader->PagingIoResource);
454 } else {
455 /* If there is no lock and do it without */
456 FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
457 FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
458 }
459 } else {
460 }
461 }
462
463 goto Cleanup;
464
465 } else {
466
467 LARGE_INTEGER OldFileSize;
468
469 /* Sanity check */
470 ASSERT(!KeIsExecutingDpc());
471
472 // Nagar P.544
473 /* Check if we need to acquire the resource exclusive */
474 if ( (FileOffsetAppend == FALSE) &&
475 ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
476 )
477 {
478 /* Acquire the resource shared */
479 if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) {
480 goto LeaveCriticalAndFail;
481 }
482 ResourceAquiredShared =TRUE;
483 } else {
484 /* Acquire the resource exclusive */
485 if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) {
486 goto LeaveCriticalAndFail;
487 }
488 }
489
490 /* Check if we are appending */
491 if (FileOffsetAppend == TRUE) {
492 Offset.QuadPart = FcbHeader->FileSize.QuadPart;
493 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
494 } else {
495 Offset.QuadPart = FileOffset->QuadPart;
496 NewSize.QuadPart += FileOffset->QuadPart + Length;
497 }
498
499 /* Nagar p.544/545
500 Make sure that caching is initated.
501 That fast are allowed for this file stream.
502 That we are not extending past the allocated size
503 That we are not creating a hole bigger than 8k
504 */
505 if ( (FileObject->PrivateCacheMap != NULL) &&
506 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
507 ((FcbHeader->ValidDataLength.QuadPart + 0x2000) > Offset.QuadPart) &&
508 (MAXLONGLONG > (Offset.QuadPart + Length)) &&
509 (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart)
510 )
511 {
512 /* Check if we can keep the lock shared */
513 if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {
514 ExReleaseResourceLite(FcbHeader->Resource);
515 if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait))
516 {
517 goto LeaveCriticalAndFail;
518 }
519
520 /* Compute the offset and the new filesize */
521 if (FileOffsetAppend) {
522 Offset.QuadPart = FcbHeader->FileSize.QuadPart;
523 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
524 }
525
526 /* Recheck the above points since we released and reacquire the lock */
527 if ( (FileObject->PrivateCacheMap != NULL) &&
528 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
529 (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
530 )
531 {
532 /* Do nothing */
533 } else {
534 goto FailAndCleanup;
535 }
536 }
537
538 /* Check if we need to find out if fast I/O is available */
539 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
540 {
541 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
542
543 /* Sanity check */
544 ASSERT(!KeIsExecutingDpc());
545
546 /* Get the Fast I/O table */
547 Device = IoGetRelatedDeviceObject(FileObject);
548 FastIoDispatch = Device->DriverObject->FastIoDispatch;
549
550 /* Sanity check */
551 ASSERT(FastIoDispatch != NULL);
552 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
553
554 /* Ask the driver if we can do it */
555 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
556 FileOffsetAppend? &FcbHeader->FileSize:FileOffset,
557 Length,
558 TRUE,
559 LockKey,
560 FALSE,
561 &FastIoCheckIfPossibleStatus,
562 Device))
563 {
564 /* It's not, fail */
565 goto FailAndCleanup;
566 }
567 }
568
569
570 /* If we are going to modify the filesize, save the old fs in case the operation fails */
571 if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) {
572 FileSizeModified = TRUE;
573 OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
574 OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
575
576 /* If the high part of the filesize is going to change, grab the Paging IoResouce */
577 if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource) {
578 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
579 FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
580 ExReleaseResourceLite(FcbHeader->PagingIoResource);
581 } else {
582 FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
583 }
584 }
585
586 /* Nagar p.544 */
587 /* Set ourselves as top component */
588 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
589 _SEH2_TRY
590 {
591 BOOLEAN CallCc = TRUE;
592 /* Check if there is a gap between the end of the file and the offset
593 If yes, then we have to zero the data
594 */
595 if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
596 if (!(Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,Wait))) {
597 /* If this operation fails, then we have to exit
598 We can jump outside the SEH, so I a using a variable to exit
599 normally
600 */
601 CallCc = FALSE;
602 }
603 }
604
605 /* Unless the CcZeroData failed, call the cache manager */
606 if (CallCc) {
607 Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer);
608 }
609 }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
610 {
611 Result = FALSE;
612 } _SEH2_END;
613
614 /* Reset the top component */
615 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
616
617 /* Did the operation suceeded */
618 if (Result) {
619 /* Check if we need to update the filesize */
620 if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
621 if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {
622 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
623 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
624 ExReleaseResourceLite(FcbHeader->PagingIoResource);
625 } else {
626 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
627 }
628 }
629
630 /* Flag the file as modified */
631 FileObject->Flags |= FO_FILE_MODIFIED;
632 /* Check if the filesize has changed */
633 if (FileSizeModified) {
634 /* Update the file sizes */
635 ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;
636 FileObject->Flags |= FO_FILE_SIZE_CHANGED;
637 }
638 /* Update the current FO byte offset */
639 FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;
640 }
641 else
642 {
643 /* The operation did not succeed
644 Reset the file size to what it should be
645 */
646 if (FileSizeModified) {
647 if (FcbHeader->PagingIoResource) {
648 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
649 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
650 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
651 ExReleaseResourceLite(FcbHeader->PagingIoResource);
652 }else{
653 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
654 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
655 }
656 }
657 }
658 goto Cleanup;
659 } else {
660 goto FailAndCleanup;
661 }
662
663 ASSERT(0);
664 }
665
666 LeaveCriticalAndFail:
667 FsRtlExitFileSystem();
668 return FALSE;
669
670
671 FailAndCleanup:
672
673 ExReleaseResourceLite(FcbHeader->Resource);
674 FsRtlExitFileSystem();
675 return FALSE;
676
677 Cleanup:
678
679 ExReleaseResourceLite(FcbHeader->Resource);
680 FsRtlExitFileSystem();
681 return Result;
682 }
683
684 /*
685 * @implemented
686 */
687 NTSTATUS
688 NTAPI
689 FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
690 IN OUT PLARGE_INTEGER FileSize)
691 {
692 FILE_STANDARD_INFORMATION Info;
693 NTSTATUS Status;
694 IO_STATUS_BLOCK IoStatus;
695 PDEVICE_OBJECT DeviceObject;
696 PFAST_IO_DISPATCH FastDispatch;
697 KEVENT Event;
698 PIO_STACK_LOCATION IoStackLocation;
699 PIRP Irp;
700 BOOLEAN OldHardError;
701
702
703 PAGED_CODE();
704
705 /* Get Device Object and Fast Calls */
706 DeviceObject = IoGetRelatedDeviceObject(FileObject);
707 FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
708
709 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo */
710 /* Call the function and see if it succeeds */
711 if ( !FastDispatch ||
712 !FastDispatch->FastIoQueryStandardInfo ||
713 !FastDispatch->FastIoQueryStandardInfo(FileObject,TRUE,
714 &Info,&IoStatus,DeviceObject))
715 {
716 /* If any of the above failed, then we are going to send an IRP to the device object */
717 /* Initialize the even for the IO */
718 KeInitializeEvent(&Event,NotificationEvent,FALSE);
719 /* Allocate the IRP */
720 Irp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
721 if (Irp == NULL)
722 {
723 return STATUS_INSUFFICIENT_RESOURCES;
724 }
725
726
727 /* Don't process hard error */
728 OldHardError = IoSetThreadHardErrorMode(FALSE);
729
730 /* Setup the IRP */
731 Irp->UserIosb = &IoStatus;
732 Irp->UserEvent = &Event;
733 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
734 Irp->Flags = IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO;
735 Irp->RequestorMode = KernelMode;
736 Irp->Tail.Overlay.OriginalFileObject = FileObject;
737 Irp->AssociatedIrp.SystemBuffer = &Info;
738
739 /* Setup out stack location */
740 IoStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
741 IoStackLocation--;
742 IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;
743 IoStackLocation->FileObject = FileObject;
744 IoStackLocation->DeviceObject = DeviceObject;
745 IoStackLocation->Parameters.QueryFile.Length = ALIGN_UP(sizeof(FILE_INFORMATION_CLASS),ULONG);
746 IoStackLocation->Parameters.QueryFile.FileInformationClass = FileStandardInformation;
747
748 /* Send the IRP to the related device object */
749 Status = IofCallDriver(DeviceObject,Irp);
750
751 /* Standard DDK IRP result processing */
752 if (Status == STATUS_PENDING)
753 {
754 KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
755 }
756
757 /* If there was a synchronous error, signal it */
758 if (!NT_SUCCESS(Status))
759 {
760 IoStatus.Status = Status;
761 }
762
763 IoSetThreadHardErrorMode(OldHardError);
764 }
765
766 /* Check the sync/async IO result */
767 if (NT_SUCCESS(IoStatus.Status))
768 {
769 /* Was the request for a directory ? */
770 if (Info.Directory)
771 {
772 IoStatus.Status = STATUS_FILE_IS_A_DIRECTORY;
773 }
774 else
775 {
776 FileSize->QuadPart = Info.EndOfFile.QuadPart;
777 }
778 }
779
780 return IoStatus.Status;
781 }
782
783
784 /*
785 * @implemented
786 */
787 BOOLEAN
788 NTAPI
789 FsRtlMdlRead(IN PFILE_OBJECT FileObject,
790 IN PLARGE_INTEGER FileOffset,
791 IN ULONG Length,
792 IN ULONG LockKey,
793 OUT PMDL *MdlChain,
794 OUT PIO_STATUS_BLOCK IoStatus)
795 {
796 PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
797 PFAST_IO_DISPATCH FastDispatch;
798
799 /* Get Device Object and Fast Calls */
800 DeviceObject = IoGetRelatedDeviceObject(FileObject);
801 FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
802
803 /* Check if we support Fast Calls, and check this one */
804 if (FastDispatch && FastDispatch->MdlRead)
805 {
806 /* Use the fast path */
807 return FastDispatch->MdlRead(FileObject,
808 FileOffset,
809 Length,
810 LockKey,
811 MdlChain,
812 IoStatus,
813 DeviceObject);
814 }
815
816 /* Get the Base File System (Volume) and Fast Calls */
817 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
818 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
819
820 /* If the Base Device Object has its own FastDispatch Routine, fail */
821 if (FastDispatch && FastDispatch->MdlRead &&
822 BaseDeviceObject != DeviceObject)
823 {
824 return FALSE;
825 }
826
827 /* No fast path, use slow path */
828 return FsRtlMdlReadDev(FileObject,
829 FileOffset,
830 Length,
831 LockKey,
832 MdlChain,
833 IoStatus,
834 DeviceObject);
835 }
836
837 /*
838 * @implemented
839 */
840 BOOLEAN
841 NTAPI
842 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,
843 IN OUT PMDL MdlChain)
844 {
845 PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
846 PFAST_IO_DISPATCH FastDispatch;
847
848 /* Get Device Object and Fast Calls */
849 DeviceObject = IoGetRelatedDeviceObject(FileObject);
850 FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
851
852 /* Check if we support Fast Calls, and check this one */
853 if (FastDispatch && FastDispatch->MdlReadComplete)
854 {
855 /* Use the fast path */
856 return FastDispatch->MdlReadComplete(FileObject,
857 MdlChain,
858 DeviceObject);
859 }
860
861 /* Get the Base File System (Volume) and Fast Calls */
862 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
863 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
864
865 /* If the Base Device Object has its own FastDispatch Routine, fail */
866 if ((BaseDeviceObject != DeviceObject) && FastDispatch
867 && FastDispatch->MdlReadComplete)
868 {
869 return FALSE;
870 }
871
872 /* No fast path, use slow path */
873 return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject);
874 }
875
876 /*
877 * @implemented
878 */
879 BOOLEAN
880 NTAPI
881 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,
882 IN PMDL MemoryDescriptorList,
883 IN PDEVICE_OBJECT DeviceObject)
884 {
885 /* Call the Cache Manager */
886 CcMdlReadComplete2(MemoryDescriptorList, FileObject);
887 return TRUE;
888 }
889
890
891 /*
892 * @implemented
893 */
894 BOOLEAN
895 NTAPI
896 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject,
897 IN PLARGE_INTEGER FileOffset,
898 IN ULONG Length,
899 IN ULONG LockKey,
900 OUT PMDL *MdlChain,
901 OUT PIO_STATUS_BLOCK IoStatus,
902 IN PDEVICE_OBJECT DeviceObject)
903 {
904 PFSRTL_COMMON_FCB_HEADER FcbHeader;
905 BOOLEAN Result = TRUE;
906 LARGE_INTEGER Offset;
907 PFAST_IO_DISPATCH FastIoDispatch;
908 PDEVICE_OBJECT Device;
909 PAGED_CODE();
910
911 /* No actual read */
912 if (!Length)
913 {
914 /* Return success */
915 IoStatus->Status = STATUS_SUCCESS;
916 IoStatus->Information = 0;
917 return TRUE;
918 }
919
920 /* Sanity check */
921 ASSERT(MAXLONGLONG - FileOffset->QuadPart >= (LONGLONG)Length);
922
923 /* Get the offset and FCB header */
924 Offset.QuadPart = FileOffset->QuadPart + Length;
925 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
926
927 /* Enter the FS */
928 FsRtlEnterFileSystem();
929 CcFastMdlReadWait++;
930
931 /* Lock the FCB */
932 ExAcquireResourceShared(FcbHeader->Resource, TRUE);
933
934 /* Check if this is a fast I/O cached file */
935 if (!(FileObject->PrivateCacheMap) ||
936 (FcbHeader->IsFastIoPossible == FastIoIsNotPossible))
937 {
938 /* It's not, so fail */
939 CcFastMdlReadNotPossible += 1;
940 Result = FALSE;
941 goto Cleanup;
942 }
943
944 /* Check if we need to find out if fast I/O is available */
945 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
946 {
947 /* Get the Fast I/O table */
948 Device = IoGetRelatedDeviceObject(FileObject);
949 FastIoDispatch = Device->DriverObject->FastIoDispatch;
950
951 /* Sanity check */
952 ASSERT(!KeIsExecutingDpc());
953 ASSERT(FastIoDispatch != NULL);
954 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
955
956 /* Ask the driver if we can do it */
957 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
958 FileOffset,
959 Length,
960 TRUE,
961 LockKey,
962 TRUE,
963 IoStatus,
964 Device))
965 {
966 /* It's not, fail */
967 CcFastMdlReadNotPossible += 1;
968 Result = FALSE;
969 goto Cleanup;
970 }
971 }
972
973 /* Check if we read too much */
974 if (Offset.QuadPart > FcbHeader->FileSize.QuadPart)
975 {
976 /* We did, check if the file offset is past the end */
977 if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart)
978 {
979 /* Set end of file */
980 IoStatus->Status = STATUS_END_OF_FILE;
981 IoStatus->Information = 0;
982 goto Cleanup;
983 }
984
985 /* Otherwise, just normalize the length */
986 Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
987 }
988
989 /* Set this as top-level IRP */
990 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
991
992 _SEH2_TRY
993 {
994 /* Attempt a read */
995 CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus);
996 FileObject->Flags |= FO_FILE_FAST_IO_READ;
997 }
998 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
999 {
1000 Result = FALSE;
1001 } _SEH2_END;
1002
1003
1004 /* Remove the top-level IRP flag */
1005 PsGetCurrentThread()->TopLevelIrp = 0;
1006
1007 /* Return to caller */
1008 Cleanup:
1009 ExReleaseResourceLite(FcbHeader->Resource);
1010 FsRtlExitFileSystem();
1011 return Result;
1012 }
1013
1014 /*
1015 * @implemented
1016 */
1017 BOOLEAN
1018 NTAPI
1019 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject,
1020 IN PLARGE_INTEGER FileOffset,
1021 IN PMDL MdlChain)
1022 {
1023 PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
1024 PFAST_IO_DISPATCH FastDispatch;
1025
1026 /* Get Device Object and Fast Calls */
1027 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1028 FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
1029
1030 /* Check if we support Fast Calls, and check this one */
1031 if (FastDispatch && FastDispatch->MdlWriteComplete)
1032 {
1033 /* Use the fast path */
1034 return FastDispatch->MdlWriteComplete(FileObject,
1035 FileOffset,
1036 MdlChain,
1037 DeviceObject);
1038 }
1039
1040 /* Get the Base File System (Volume) and Fast Calls */
1041 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
1042 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
1043
1044 /* If the Base Device Object has its own FastDispatch Routine, fail */
1045 if (FastDispatch && FastDispatch->MdlWriteComplete &&
1046 BaseDeviceObject != DeviceObject)
1047 {
1048 return FALSE;
1049 }
1050
1051 /* No fast path, use slow path */
1052 return FsRtlMdlWriteCompleteDev(FileObject,
1053 FileOffset,
1054 MdlChain,
1055 DeviceObject);
1056 }
1057
1058 /*
1059 * @implemented
1060 */
1061 BOOLEAN
1062 NTAPI
1063 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject,
1064 IN PLARGE_INTEGER FileOffset,
1065 IN PMDL MdlChain,
1066 IN PDEVICE_OBJECT DeviceObject)
1067 {
1068 if (FileObject->Flags & FO_WRITE_THROUGH)
1069 {
1070 return FALSE;
1071 }
1072
1073
1074 /* Call the Cache Manager */
1075 CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);
1076 return TRUE;
1077 }
1078
1079 /*
1080 * @implemented
1081 */
1082 BOOLEAN
1083 NTAPI
1084 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
1085 IN PLARGE_INTEGER FileOffset,
1086 IN ULONG Length,
1087 IN ULONG LockKey,
1088 OUT PMDL *MdlChain,
1089 OUT PIO_STATUS_BLOCK IoStatus)
1090 {
1091 PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
1092 PFAST_IO_DISPATCH FastDispatch;
1093
1094 /* Get Device Object and Fast Calls */
1095 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1096 FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
1097
1098 /* Check if we support Fast Calls, and check this one */
1099 if (FastDispatch && FastDispatch->PrepareMdlWrite)
1100 {
1101 /* Use the fast path */
1102 return FastDispatch->PrepareMdlWrite(FileObject,
1103 FileOffset,
1104 Length,
1105 LockKey,
1106 MdlChain,
1107 IoStatus,
1108 DeviceObject);
1109 }
1110
1111 /* Get the Base File System (Volume) and Fast Calls */
1112 BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
1113 FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
1114
1115 /* If the Base Device Object has its own FastDispatch Routine, fail */
1116 if (FastDispatch && FastDispatch->PrepareMdlWrite &&
1117 BaseDeviceObject != DeviceObject)
1118 {
1119 return FALSE;
1120 }
1121
1122 /* No fast path, use slow path */
1123 return FsRtlPrepareMdlWriteDev(FileObject,
1124 FileOffset,
1125 Length,
1126 LockKey,
1127 MdlChain,
1128 IoStatus,
1129 DeviceObject);
1130 }
1131
1132 /*
1133 * @implemented
1134 */
1135 BOOLEAN
1136 NTAPI
1137 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
1138 IN PLARGE_INTEGER FileOffset,
1139 IN ULONG Length,
1140 IN ULONG LockKey,
1141 OUT PMDL *MdlChain,
1142 OUT PIO_STATUS_BLOCK IoStatus,
1143 IN PDEVICE_OBJECT DeviceObject)
1144 {
1145 BOOLEAN Result = TRUE;
1146 PFAST_IO_DISPATCH FastIoDispatch;
1147 PDEVICE_OBJECT Device;
1148 PFSRTL_COMMON_FCB_HEADER FcbHeader;
1149
1150 LARGE_INTEGER OldFileSize;
1151 LARGE_INTEGER OldValidDataLength;
1152 LARGE_INTEGER NewSize;
1153 LARGE_INTEGER Offset;
1154
1155 /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
1156 BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == (LONG)0xffffffff) && (FileOffset->LowPart == 0xffffffff));
1157 BOOLEAN FileSizeModified = FALSE;
1158 BOOLEAN ResourceAquiredShared = FALSE;
1159
1160 /* Initialize some of the vars and pointers */
1161 OldFileSize.QuadPart = 0;
1162 OldValidDataLength.QuadPart = 0;
1163
1164 PAGED_CODE();
1165
1166 Offset.QuadPart = FileOffset->QuadPart + Length;
1167
1168 /* Nagar p.544 -- Check with Cc if we can write */
1169 if ( (!CcCanIWrite(FileObject, Length,TRUE,FALSE))||
1170 (FileObject->Flags & FO_WRITE_THROUGH))
1171 {
1172 return FALSE;
1173 }
1174
1175 IoStatus->Status = STATUS_SUCCESS;
1176
1177 /* No actual read */
1178 if (!Length)
1179 {
1180 return TRUE;
1181 }
1182
1183 FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
1184 FsRtlEnterFileSystem();
1185
1186 /* Check we are going to extend the file */
1187 if ( (FileOffsetAppend == FALSE) &&
1188 ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
1189 )
1190 {
1191 /* Acquire the resource shared */
1192 ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
1193 ResourceAquiredShared =TRUE;
1194 } else
1195 {
1196 /* Acquire the resource exclusive */
1197 ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
1198 }
1199
1200 /* Check if we are appending */
1201 if (FileOffsetAppend == TRUE) {
1202 Offset.QuadPart = FcbHeader->FileSize.QuadPart;
1203 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
1204 } else
1205 {
1206 Offset.QuadPart = FileOffset->QuadPart;
1207 NewSize.QuadPart = FileOffset->QuadPart + Length;
1208 }
1209
1210 if ( (FileObject->PrivateCacheMap) &&
1211 (FcbHeader->IsFastIoPossible) &&
1212 (MAXLONGLONG >= (LONGLONG) FileOffset->QuadPart + Length) &&
1213 (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart) )
1214 {
1215 /* Check if we can keep the lock shared */
1216 if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {
1217 ExReleaseResourceLite(FcbHeader->Resource);
1218 ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
1219
1220 /* Compute the offset and the new filesize */
1221 if (FileOffsetAppend) {
1222 Offset.QuadPart = FcbHeader->FileSize.QuadPart;
1223 NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
1224 }
1225
1226 /* Recheck the above points since we released and reacquire the lock */
1227 if ( (FileObject->PrivateCacheMap != NULL) &&
1228 (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
1229 (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
1230 )
1231 {
1232 /* Do nothing */
1233 } else {
1234 goto FailAndCleanup;
1235 }
1236 }
1237
1238 /* Check if we need to find out if fast I/O is available */
1239 if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
1240 {
1241 /* Sanity check */
1242 /* ASSERT(!KeIsExecutingDpc()); */
1243
1244 /* Get the Fast I/O table */
1245 Device = IoGetRelatedDeviceObject(FileObject);
1246 FastIoDispatch = Device->DriverObject->FastIoDispatch;
1247
1248 /* Sanity check */
1249 ASSERT(FastIoDispatch != NULL);
1250 ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
1251
1252 /* Ask the driver if we can do it */
1253 if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
1254 FileOffset,
1255 Length,
1256 TRUE,
1257 LockKey,
1258 FALSE,
1259 IoStatus,
1260 Device))
1261 {
1262 /* It's not, fail */
1263 goto FailAndCleanup;
1264 }
1265 }
1266
1267 /* If we are going to modify the filesize, save the old fs in case the operation fails */
1268 if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
1269 {
1270 FileSizeModified = TRUE;
1271 OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
1272 OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
1273
1274 /* If the high part of the filesize is going to change, grab the Paging IoResouce */
1275 if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource)
1276 {
1277 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
1278 FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
1279 ExReleaseResourceLite(FcbHeader->PagingIoResource);
1280 } else {
1281 FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
1282 }
1283 }
1284
1285
1286 /* Nagar p.544 */
1287 /* Set ourselves as top component */
1288 PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
1289 _SEH2_TRY
1290 {
1291 /* Check if there is a gap between the end of the file and the offset
1292 If yes, then we have to zero the data
1293 */
1294 if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
1295 Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,TRUE);
1296 if (Result)
1297 {
1298 CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
1299 }
1300 } else {
1301 CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
1302 }
1303
1304 }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
1305 {
1306 Result = FALSE;
1307 } _SEH2_END;
1308
1309 /* Reset the top component */
1310 PsGetCurrentThread()->TopLevelIrp = 0;
1311
1312 /* Did the operation suceeded */
1313 if (Result) {
1314 /* Check if we need to update the filesize */
1315 if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
1316 if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {
1317 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
1318 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
1319 ExReleaseResourceLite(FcbHeader->PagingIoResource);
1320 } else {
1321 FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
1322 }
1323 }
1324
1325 /* Flag the file as modified */
1326 FileObject->Flags |= FO_FILE_MODIFIED;
1327 /* Check if the filesize has changed */
1328 if (FileSizeModified) {
1329 /* Update the file sizes */
1330 ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;
1331 FileObject->Flags |= FO_FILE_SIZE_CHANGED;
1332 }
1333
1334 }
1335 else
1336 {
1337 /* The operation did not succeed
1338 Reset the file size to what it should be
1339 */
1340 if (FileSizeModified) {
1341 if (FcbHeader->PagingIoResource) {
1342 ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
1343 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
1344 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
1345 ExReleaseResourceLite(FcbHeader->PagingIoResource);
1346 }else{
1347 FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
1348 FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
1349 }
1350 }
1351 }
1352
1353 goto Cleanup;
1354
1355 }
1356 else
1357 {
1358 goto FailAndCleanup;
1359 }
1360
1361
1362 FailAndCleanup:
1363
1364 ExReleaseResourceLite(FcbHeader->Resource);
1365 FsRtlExitFileSystem();
1366 return FALSE;
1367
1368 Cleanup:
1369
1370 ExReleaseResourceLite(FcbHeader->Resource);
1371 FsRtlExitFileSystem();
1372 return Result;
1373
1374 }
1375
1376 /*
1377 * @implemented
1378 */
1379 VOID
1380 NTAPI
1381 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
1382 {
1383 /*
1384 PAGED_CODE();
1385 FsRtlAcquireFileExclusiveCommon(FileObject,0,0);
1386 */
1387 KeBugCheck(FILE_SYSTEM);
1388 }
1389
1390 /*
1391 * @implemented
1392 */
1393 VOID
1394 NTAPI
1395 FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
1396 {
1397
1398 KeBugCheck(FILE_SYSTEM);
1399 }
1400
1401 /*++
1402 * @name FsRtlRegisterFileSystemFilterCallbacks
1403 * @unimplemented
1404 *
1405 * FILLME
1406 *
1407 * @param FilterDriverObject
1408 * FILLME
1409 *
1410 * @param Callbacks
1411 * FILLME
1412 *
1413 * @return None
1414 *
1415 * @remarks None
1416 *
1417 *--*/
1418 NTSTATUS
1419 NTAPI
1420 FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject,
1421 IN PFS_FILTER_CALLBACKS Callbacks)
1422 {
1423 UNIMPLEMENTED;
1424 return STATUS_NOT_IMPLEMENTED;
1425 }
1426