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