ReactOS  0.4.13-dev-242-g611e6d7
allocsup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1990-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  AllocSup.c
8 
9 Abstract:
10 
11  This module implements the Allocation support routines for Cdfs.
12 
13  The data structure used here is the CD_MCB. There is an entry in
14  the Mcb for each dirent for a file. The entry will map the offset
15  within some file to a starting disk offset and number of bytes.
16  The Mcb also contains the interleave information for an extent.
17  An interleave consists of a number of blocks with data and a
18  (possibly different) number of blocks to skip. Any number of
19  data/skip pairs may exist in an extent but the data and skip sizes
20  are the same throughout the extent.
21 
22  We store the following information into an Mcb entry for an extent.
23 
24  FileOffset Offset in file for start of extent
25  DiskOffset Offset on disk for start of extent
26  ByteCount Number of file bytes in extent, no skip bytes
27  DataBlockByteCount Number of bytes in each data block
28  TotalBlockByteCount Number of bytes is data block and skip block
29 
30  The disk offset in the Mcb has already been biased by the size of
31  the Xar block if present. All of the byte count fields are aligned
32  on logical block boundaries. If this is a directory or path table
33  then the file offset has been biased to round the initial disk
34  offset down to a sector boundary. The biasing is done when loading
35  the values into an Mcb entry.
36 
37  An XA file has a header prepended to the file and each sector is 2352
38  bytes. The allocation information ignores the header and only deals
39  with 2048 byte sectors. Callers into the allocation package have
40  adjusted the starting offset value to reflect 2048 sectors. On return
41  from this package the caller will have to convert from 2048 sector values
42  into raw XA sector values.
43 
44 
45 --*/
46 
47 #include "cdprocs.h"
48 
49 //
50 // The Bug check file id for this module
51 //
52 
53 #define BugCheckFileId (CDFS_BUG_CHECK_ALLOCSUP)
54 
55 //
56 // Local support routines
57 //
58 
59 ULONG
61  _In_ PIRP_CONTEXT IrpContext,
62  _In_ PFCB Fcb,
64  );
65 
66 VOID
68  _In_ PIRP_CONTEXT IrpContext,
69  _In_ PCD_MCB_ENTRY McbEntry,
73  );
74 
75 #ifdef ALLOC_PRAGMA
76 #pragma alloc_text(PAGE, CdAddInitialAllocation)
77 #pragma alloc_text(PAGE, CdAddAllocationFromDirent)
78 #pragma alloc_text(PAGE, CdDiskOffsetFromMcbEntry)
79 #pragma alloc_text(PAGE, CdFindMcbEntry)
80 #pragma alloc_text(PAGE, CdInitializeMcb)
81 #pragma alloc_text(PAGE, CdLookupAllocation)
82 #pragma alloc_text(PAGE, CdTruncateAllocation)
83 #pragma alloc_text(PAGE, CdUninitializeMcb)
84 #endif
85 
86 
87 _Requires_lock_held_(_Global_critical_region_)
88 VOID
89 #ifdef _MSC_VER
90 // PREFast currently has no way to express the Fcb==Fcb->Vcb->VolumeDasdFcb early return
91 #pragma warning(suppress: 6001 6101)
92 #endif
93 CdLookupAllocation (
94  _In_ PIRP_CONTEXT IrpContext,
95  _In_ PFCB Fcb,
99  )
100 
101 /*++
102 
103 Routine Description:
104 
105  This routine looks through the mapping information for the file
106  to find the logical diskoffset and number of bytes at that offset.
107  We only deal with logical 2048 byte sectors here.
108 
109  If the mapping isn't present we will look it up on disk now.
110  This routine assumes we are looking up a valid range in the file. This
111  routine raises if it can't find mapping for the file offset.
112 
113  The Fcb may not be locked prior to calling this routine. We will always
114  acquire it here.
115 
116 Arguments:
117 
118  Fcb - Fcb representing this stream.
119 
120  FileOffset - Lookup the allocation beginning at this point.
121 
122  DiskOffset - Address to store the logical disk offset.
123 
124  ByteCount - Address to store the number of contiguous bytes beginning
125  at DiskOffset above.
126 
127 Return Value:
128 
129  None.
130 
131 --*/
132 
133 {
134  BOOLEAN FirstPass = TRUE;
135  ULONG McbEntryOffset;
136  PFCB ParentFcb = NULL;
137  BOOLEAN CleanupParent = FALSE;
138 
139  BOOLEAN UnlockFcb = FALSE;
140 
141  LONGLONG CurrentFileOffset;
142  ULONG CurrentMcbOffset;
143  PCD_MCB_ENTRY CurrentMcbEntry;
144 
146  DIRENT Dirent = {0};
147 
148  PAGED_CODE();
149 
150  ASSERT_IRP_CONTEXT( IrpContext );
151  ASSERT_FCB( Fcb );
152 
153  //
154  // For DASD IO we already have clamped the read to the volume limits.
155  // We'll allow reading beyond those limits for extended DASD IO, so
156  // no MCB lookup here.
157  //
158 
159  if (Fcb == Fcb->Vcb->VolumeDasdFcb) {
160 
162  return;
163  }
164 
165  //
166  // Use a try finally to facilitate cleanup.
167  //
168 
169  _SEH2_TRY {
170 
171  //
172  // We use a loop to perform the lookup. If we don't find the mapping in the
173  // first pass then we look up all of the allocation and then look again.
174 
175  while (TRUE) {
176 
177  //
178  //
179  // Lookup the entry containing this file offset.
180  //
181 
182  CdLockFcb( IrpContext, Fcb );
183  UnlockFcb = TRUE;
184 
185  McbEntryOffset = CdFindMcbEntry( IrpContext, Fcb, FileOffset );
186 
187  //
188  // If within the Mcb then we use the data out of this entry and are
189  // done.
190  //
191 
192  if (McbEntryOffset < Fcb->Mcb.CurrentEntryCount) {
193 
194  CdDiskOffsetFromMcbEntry( IrpContext,
195  Fcb->Mcb.McbArray + McbEntryOffset,
196  FileOffset,
197  DiskOffset,
198  ByteCount );
199 
200  break;
201 
202  //
203  // If this is not the first pass then the disk is corrupt.
204  //
205 
206  } else if (!FirstPass) {
207 
209  }
210 
211  CdUnlockFcb( IrpContext, Fcb );
212  UnlockFcb = FALSE;
213 
214  //
215  // Initialize the search dirent structures.
216  //
217 
218  CdInitializeDirContext( IrpContext, &DirContext );
219  CdInitializeDirent( IrpContext, &Dirent );
220 
221  //
222  // Otherwise we need to walk the dirents for this file until we find
223  // the one containing this entry. The parent Fcb should always be
224  // present.
225  //
226 
228  CdAcquireFileShared( IrpContext, ParentFcb );
229  CleanupParent = TRUE;
230 
231  //
232  // Do an unsafe test to see if we need to create a file object.
233  //
234 
236 
237  //
238  // Initialize the local variables to indicate the first dirent
239  // and lookup the first dirent.
240  //
241 
242  CurrentFileOffset = 0;
243  CurrentMcbOffset = 0;
244 
245  CdLookupDirent( IrpContext,
246  ParentFcb,
248  &DirContext );
249 
250  //
251  // If we are adding allocation to the Mcb then add all of it.
252  //
253 
254  while (TRUE ) {
255 
256  //
257  // Update the dirent from the on-disk dirent.
258  //
259 
260  CdUpdateDirentFromRawDirent( IrpContext, ParentFcb, &DirContext, &Dirent );
261 
262  //
263  // Add this dirent to the Mcb if not already present.
264  //
265 
266  CdLockFcb( IrpContext, Fcb );
267  UnlockFcb = TRUE;
268 
269  if (CurrentMcbOffset >= Fcb->Mcb.CurrentEntryCount) {
270 
271  CdAddAllocationFromDirent( IrpContext, Fcb, CurrentMcbOffset, CurrentFileOffset, &Dirent );
272  }
273 
274  CdUnlockFcb( IrpContext, Fcb );
275  UnlockFcb = FALSE;
276 
277  //
278  // If this is the last dirent for the file then exit.
279  //
280 
281  if (!FlagOn( Dirent.DirentFlags, CD_ATTRIBUTE_MULTI )) {
282 
283  break;
284  }
285 
286  //
287  // If we couldn't find another entry then the directory is corrupt because
288  // the last dirent for a file doesn't exist.
289  //
290 
291  if (!CdLookupNextDirent( IrpContext, ParentFcb, &DirContext, &DirContext )) {
292 
294  }
295 
296  //
297  // Update our loop variables.
298  //
299 
300  CurrentMcbEntry = Fcb->Mcb.McbArray + CurrentMcbOffset;
301  CurrentFileOffset += CurrentMcbEntry->ByteCount;
302  CurrentMcbOffset += 1;
303  }
304 
305  //
306  // All of the allocation is loaded. Go back and look up the mapping again.
307  // It better be there this time.
308  //
309 
310  FirstPass = FALSE;
311  }
312 
313  } _SEH2_FINALLY {
314 
315  if (CleanupParent) {
316 
317  //
318  // Release the parent and cleanup the dirent structures.
319  //
320 
321  CdReleaseFile( IrpContext, ParentFcb );
322 
323  CdCleanupDirContext( IrpContext, &DirContext );
324  CdCleanupDirent( IrpContext, &Dirent );
325  }
326 
327  if (UnlockFcb) { CdUnlockFcb( IrpContext, Fcb ); }
328  } _SEH2_END;
329 
330  return;
331 }
332 
333 
334 VOID
336  _In_ PIRP_CONTEXT IrpContext,
337  _Inout_ PFCB Fcb,
338  _In_ ULONG McbEntryOffset,
339  _In_ LONGLONG StartingFileOffset,
341  )
342 
343 /*++
344 
345 Routine Description:
346 
347  This routine is called to add an entry into the Cd Mcb. We grow the Mcb
348  as necessary and update the new entry.
349 
350  NOTE - The Fcb has already been locked prior to makeing this call.
351 
352 Arguments:
353 
354  Fcb - Fcb containing the Mcb to update.
355 
356  McbEntryOffset - Offset into the Mcb array to add this data.
357 
358  StartingFileOffset - Offset in bytes from the start of the file.
359 
360  Dirent - Dirent containing the on-disk data for this entry.
361 
362 Return Value:
363 
364  None
365 
366 --*/
367 
368 {
369  ULONG NewArraySize;
370  PVOID NewMcbArray;
371  PCD_MCB_ENTRY McbEntry;
372 
373  PAGED_CODE();
374 
375  UNREFERENCED_PARAMETER( IrpContext );
376 
377  ASSERT_IRP_CONTEXT( IrpContext );
378  ASSERT_FCB( Fcb );
380 
381  //
382  // If we need to grow the Mcb then do it now.
383  //
384 
385  if (McbEntryOffset >= Fcb->Mcb.MaximumEntryCount) {
386 
387  //
388  // Allocate a new buffer and copy the old data over.
389  //
390 
391  NewArraySize = Fcb->Mcb.MaximumEntryCount * 2 * sizeof( CD_MCB_ENTRY );
392 
393  NewMcbArray = FsRtlAllocatePoolWithTag( CdPagedPool,
394  NewArraySize,
395  TAG_MCB_ARRAY );
396 
397  RtlZeroMemory( NewMcbArray, NewArraySize );
398  RtlCopyMemory( NewMcbArray,
399  Fcb->Mcb.McbArray,
400  Fcb->Mcb.MaximumEntryCount * sizeof( CD_MCB_ENTRY ));
401 
402  //
403  // Deallocate the current array unless it is embedded in the Fcb.
404  //
405 
406  if (Fcb->Mcb.MaximumEntryCount != 1) {
407 
408  CdFreePool( &Fcb->Mcb.McbArray );
409  }
410 
411  //
412  // Now update the Mcb with the new array.
413  //
414 
415  Fcb->Mcb.MaximumEntryCount *= 2;
416  Fcb->Mcb.McbArray = NewMcbArray;
417  }
418 
419  //
420  // Update the new entry with the input data.
421  //
422 
423  McbEntry = Fcb->Mcb.McbArray + McbEntryOffset;
424 
425  //
426  // Start with the location and length on disk.
427  //
428 
429  McbEntry->DiskOffset = LlBytesFromBlocks( Fcb->Vcb, Dirent->StartingOffset );
430  McbEntry->ByteCount = Dirent->DataLength;
431 
432  //
433  // Round the byte count up to a logical block boundary if this is
434  // the last extent.
435  //
436 
437  if (!FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_MULTI )) {
438 
439  McbEntry->ByteCount = BlockAlign( Fcb->Vcb, McbEntry->ByteCount );
440  }
441 
442  //
443  // The file offset is the logical position within this file.
444  // We know this is correct regardless of whether we bias the
445  // file size or disk offset.
446  //
447 
448  McbEntry->FileOffset = StartingFileOffset;
449 
450  //
451  // Convert the interleave information from logical blocks to
452  // bytes.
453  //
454 
455  if (Dirent->FileUnitSize != 0) {
456 
457  McbEntry->DataBlockByteCount = LlBytesFromBlocks( Fcb->Vcb, Dirent->FileUnitSize );
458  McbEntry->TotalBlockByteCount = McbEntry->DataBlockByteCount +
459  LlBytesFromBlocks( Fcb->Vcb, Dirent->InterleaveGapSize );
460 
461  //
462  // If the file is not interleaved then the size of the data block
463  // and total block are the same as the byte count.
464  //
465 
466  } else {
467 
468  McbEntry->DataBlockByteCount =
469  McbEntry->TotalBlockByteCount = McbEntry->ByteCount;
470  }
471 
472  //
473  // Update the number of entries in the Mcb. The Mcb is never sparse
474  // so whenever we add an entry it becomes the last entry in the Mcb.
475  //
476 
477  Fcb->Mcb.CurrentEntryCount = McbEntryOffset + 1;
478 
479  return;
480 }
481 
482 
483 VOID
485  _In_ PIRP_CONTEXT IrpContext,
486  _Inout_ PFCB Fcb,
487  _In_ ULONG StartingBlock,
489  )
490 
491 /*++
492 
493 Routine Description:
494 
495  This routine is called to set up the initial entry in an Mcb.
496 
497  This routine handles the single initial entry for a directory file. We will
498  round the start block down to a sector boundary. Our caller has already
499  biased the DataLength with any adjustments. This is used for the case
500  where there is a single entry and we want to align the data on a sector
501  boundary.
502 
503 Arguments:
504 
505  Fcb - Fcb containing the Mcb to update.
506 
507  StartingBlock - Starting logical block for this directory. This is
508  the start of the actual data. We will bias this by the sector
509  offset of the data.
510 
511  DataLength - Length of the data.
512 
513 Return Value:
514 
515  None
516 
517 --*/
518 
519 {
520  PCD_MCB_ENTRY McbEntry;
521 
522  PAGED_CODE();
523 
524  UNREFERENCED_PARAMETER( IrpContext );
525 
526  ASSERT_IRP_CONTEXT( IrpContext );
527  ASSERT_FCB( Fcb );
530  NT_ASSERT( CDFS_NTC_FCB_DATA != Fcb->NodeTypeCode);
531 
532  //
533  // Update the new entry with the input data.
534  //
535 
536  McbEntry = Fcb->Mcb.McbArray;
537 
538  //
539  // Start with the location and length on disk.
540  //
541 
542  McbEntry->DiskOffset = LlBytesFromBlocks( Fcb->Vcb, StartingBlock );
543  McbEntry->DiskOffset -= Fcb->StreamOffset;
544 
545  McbEntry->ByteCount = DataLength;
546 
547  //
548  // The file offset is the logical position within this file.
549  // We know this is correct regardless of whether we bias the
550  // file size or disk offset.
551  //
552 
553  McbEntry->FileOffset = 0;
554 
555  //
556  // If the file is not interleaved then the size of the data block
557  // and total block are the same as the byte count.
558  //
559 
560  McbEntry->DataBlockByteCount =
561  McbEntry->TotalBlockByteCount = McbEntry->ByteCount;
562 
563  //
564  // Update the number of entries in the Mcb. The Mcb is never sparse
565  // so whenever we add an entry it becomes the last entry in the Mcb.
566  //
567 
569 
570  return;
571 }
572 
573 
574 VOID
576  _In_ PIRP_CONTEXT IrpContext,
577  _Inout_ PFCB Fcb,
578  _In_ LONGLONG StartingFileOffset
579  )
580 
581 /*++
582 
583 Routine Description:
584 
585  This routine truncates the Mcb for a file by eliminating all of the Mcb
586  entries from the entry which contains the given offset.
587 
588  The Fcb should be locked when this routine is called.
589 
590 Arguments:
591 
592  Fcb - Fcb containing the Mcb to truncate.
593 
594  StartingFileOffset - Offset in the file to truncate the Mcb from.
595 
596 Return Value:
597 
598  None
599 
600 --*/
601 
602 {
603  ULONG McbEntryOffset;
604 
605  PAGED_CODE();
606 
607  ASSERT_IRP_CONTEXT( IrpContext );
608  ASSERT_FCB( Fcb );
610 
611  //
612  // Find the entry containg this starting offset.
613  //
614 
615  McbEntryOffset = CdFindMcbEntry( IrpContext, Fcb, StartingFileOffset );
616 
617  //
618  // Now set the current size of the mcb to this point.
619  //
620 
621  Fcb->Mcb.CurrentEntryCount = McbEntryOffset;
622 
623  return;
624 }
625 
626 
627 _At_(Fcb->NodeByteSize, _In_range_(>=, FIELD_OFFSET( FCB, FcbType )))
628 VOID
629 CdInitializeMcb (
630  _In_ PIRP_CONTEXT IrpContext,
632  )
633 
634 /*++
635 
636 Routine Description:
637 
638  This routine is called to initialize the Mcb in an Fcb. We initialize
639  this with an entry count of one and point to the entry in the Fcb
640  itself.
641 
642  Fcb should be acquired exclusively when this is called.
643 
644 Arguments:
645 
646  Fcb - Fcb containing the Mcb to initialize.
647 
648 Return Value:
649 
650  None
651 
652 --*/
653 
654 {
655  PAGED_CODE();
656 
657  UNREFERENCED_PARAMETER( IrpContext );
658 
659  ASSERT_IRP_CONTEXT( IrpContext );
660  ASSERT_FCB( Fcb );
661 
662  //
663  // Set the entry counts to show there is one entry in the array and
664  // it is unused.
665  //
666 
669 
670  Fcb->Mcb.McbArray = &Fcb->McbEntry;
671 
672  return;
673 }
674 
675 
676 _At_(Fcb->NodeByteSize, _In_range_(>=, FIELD_OFFSET( FCB, FcbType )))
677 _When_(Fcb->NodeTypeCode == CDFS_NTC_FCB_PATH_TABLE, _At_(Fcb->NodeByteSize, _In_range_(==, SIZEOF_FCB_INDEX)))
678 _When_(Fcb->NodeTypeCode == CDFS_NTC_FCB_INDEX, _At_(Fcb->NodeByteSize, _In_range_(==, SIZEOF_FCB_INDEX)))
679 _When_(Fcb->NodeTypeCode == CDFS_NTC_FCB_DATA, _At_(Fcb->NodeByteSize, _In_range_(==, SIZEOF_FCB_DATA)))
680 VOID
681 CdUninitializeMcb (
682  _In_ PIRP_CONTEXT IrpContext,
683  _Inout_updates_bytes_(Fcb->NodeByteSize) PFCB Fcb
684  )
685 
686 /*++
687 
688 Routine Description:
689 
690  This routine is called to cleanup an Mcb in an Fcb. We look at the
691  maximum run count in the Fcb and if greater than one we will deallocate
692  the buffer.
693 
694  Fcb should be acquired exclusively when this is called.
695 
696 Arguments:
697 
698  Fcb - Fcb containing the Mcb to uninitialize.
699 
700 Return Value:
701 
702  None
703 
704 --*/
705 
706 {
707  PAGED_CODE();
708 
709  UNREFERENCED_PARAMETER( IrpContext );
710 
711  ASSERT_IRP_CONTEXT( IrpContext );
712  ASSERT_FCB( Fcb );
713 
714  //
715  // If the count is greater than one then this is an allocated buffer.
716  //
717 
718  if (Fcb->Mcb.MaximumEntryCount > 1) {
719 
720  CdFreePool( &Fcb->Mcb.McbArray );
721  }
722 
723  return;
724 }
725 
726 
727 //
728 // Local suupport routine
729 //
730 
731 ULONG
733  _In_ PIRP_CONTEXT IrpContext,
734  _In_ PFCB Fcb,
736  )
737 
738 /*++
739 
740 Routine Description:
741 
742  This routine is called to find the Mcb entry which contains the file
743  offset at the given point. If the file offset is not currently in the
744  Mcb then we return the offset of the entry to add.
745 
746  Fcb should be locked when this is called.
747 
748 Arguments:
749 
750  Fcb - Fcb containing the Mcb to uninitialize.
751 
752  FileOffset - Return the Mcb entry which contains this file offset.
753 
754 Return Value:
755 
756  ULONG - Offset in the Mcb of the entry for this offset.
757 
758 --*/
759 
760 {
761  ULONG CurrentMcbOffset;
762  PCD_MCB_ENTRY CurrentMcbEntry;
763 
764  PAGED_CODE();
765 
766  UNREFERENCED_PARAMETER( IrpContext );
767 
768  ASSERT_IRP_CONTEXT( IrpContext );
769  ASSERT_FCB( Fcb );
771 
772  //
773  // We expect a linear search will be sufficient here.
774  //
775 
776  CurrentMcbOffset = 0;
777  CurrentMcbEntry = Fcb->Mcb.McbArray;
778 
779  while (CurrentMcbOffset < Fcb->Mcb.CurrentEntryCount) {
780 
781  //
782  // Check if the offset lies within the current Mcb position.
783  //
784 
785  if (FileOffset < CurrentMcbEntry->FileOffset + CurrentMcbEntry->ByteCount) {
786 
787  break;
788  }
789 
790  //
791  // Move to the next entry.
792  //
793 
794  CurrentMcbOffset += 1;
795  CurrentMcbEntry += 1;
796  }
797 
798  //
799  // This is the offset containing this file offset (or the point
800  // where an entry should be added).
801  //
802 
803  return CurrentMcbOffset;
804 }
805 
806 
807 //
808 // Local support routine
809 //
810 
811 VOID
813  _In_ PIRP_CONTEXT IrpContext,
814  _In_ PCD_MCB_ENTRY McbEntry,
818  )
819 
820 /*++
821 
822 Routine Description:
823 
824  This routine is called to return the diskoffset and length of the file
825  data which begins at offset 'FileOffset'. We have the Mcb entry which
826  contains the mapping and interleave information.
827 
828  NOTE - This routine deals with data in 2048 byte logical sectors. If
829  this is an XA file then our caller has already converted from
830  'raw' file bytes to 'cooked' file bytes.
831 
832 Arguments:
833 
834  McbEntry - Entry in the Mcb containing the allocation information.
835 
836  FileOffset - Starting Offset in the file to find the matching disk
837  offsets.
838 
839  DiskOffset - Address to store the starting disk offset for this operation.
840 
841  ByteCount - Address to store number of contiguous bytes starting at this
842  disk offset.
843 
844 Return Value:
845 
846  None
847 
848 --*/
849 
850 {
851  LONGLONG ExtentOffset;
852 
853  LONGLONG CurrentDiskOffset;
854  LONGLONG CurrentExtentOffset;
855 
856  LONGLONG LocalByteCount;
857 
858  PAGED_CODE();
859 
860  UNREFERENCED_PARAMETER( IrpContext );
861 
862  ASSERT_IRP_CONTEXT( IrpContext );
863 
864  //
865  // Extent offset is the difference between the file offset and the start
866  // of the extent.
867  //
868 
869  ExtentOffset = FileOffset - McbEntry->FileOffset;
870 
871  //
872  // Optimize the non-interleave case.
873  //
874 
875  if (McbEntry->ByteCount == McbEntry->DataBlockByteCount) {
876 
877  *DiskOffset = McbEntry->DiskOffset + ExtentOffset;
878 
879  LocalByteCount = McbEntry->ByteCount - ExtentOffset;
880 
881  } else {
882 
883  //
884  // Walk though any interleave until we reach the current offset in
885  // this extent.
886  //
887 
888  CurrentExtentOffset = McbEntry->DataBlockByteCount;
889  CurrentDiskOffset = McbEntry->DiskOffset;
890 
891  while (CurrentExtentOffset <= ExtentOffset) {
892 
893  CurrentDiskOffset += McbEntry->TotalBlockByteCount;
894  CurrentExtentOffset += McbEntry->DataBlockByteCount;
895  }
896 
897  //
898  // We are now positioned at the data block containing the starting
899  // file offset we were given. The disk offset is the offset of
900  // the start of this block plus the extent offset into this block.
901  // The byte count is the data block byte count minus our offset into
902  // this block.
903  //
904 
905  *DiskOffset = CurrentDiskOffset + (ExtentOffset + McbEntry->DataBlockByteCount - CurrentExtentOffset);
906 
907  //
908  // Make sure we aren't past the end of the data length. This is possible
909  // if we only use part of the last data block on an interleaved file.
910  //
911 
912  if (CurrentExtentOffset > McbEntry->ByteCount) {
913 
914  CurrentExtentOffset = McbEntry->ByteCount;
915  }
916 
917  LocalByteCount = CurrentExtentOffset - ExtentOffset;
918  }
919 
920  //
921  // If the byte count exceeds our limit then cut it to fit in 32 bits.
922  //
923 
924  if (LocalByteCount > MAXULONG) {
925 
926  *ByteCount = MAXULONG;
927 
928  } else {
929 
930  *ByteCount = (ULONG) LocalByteCount;
931  }
932 
933  return;
934 }
935 
#define SIZEOF_FCB_INDEX
Definition: cdstruc.h:1065
#define SIZEOF_FCB_DATA
Definition: cdstruc.h:1062
_In_ PFCB _In_ LONGLONG _Out_ PLONGLONG DiskOffset
Definition: cdprocs.h:151
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
ULONG CdFindMcbEntry(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ LONGLONG FileOffset)
Definition: allocsup.c:732
#define CdReleaseFile(IC, F)
Definition: cdprocs.h:1008
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
#define CdCleanupDirContext(IC, DC)
Definition: cdprocs.h:553
CD_MCB_ENTRY McbEntry
Definition: cdstruc.h:1021
ULONG MaximumEntryCount
Definition: cdstruc.h:194
_Inout_updates_bytes_(Fcb->NodeByteSize) PFCB Fcb)
Definition: allocsup.c:631
#define CDFS_NTC_FCB_PATH_TABLE
Definition: nodetype.h:29
#define CdAcquireFileShared(IC, F)
Definition: cdprocs.h:1002
_At_(Fcb->NodeByteSize, _In_range_(>=, FIELD_OFFSET(FCB, FcbType))) VOID CdInitializeMcb(_In_ PIRP_CONTEXT IrpContext
Definition: allocsup.c:676
#define ASSERT_FCB(F)
Definition: cddata.h:243
#define CDFS_NTC_FCB_INDEX
Definition: nodetype.h:30
#define PAGED_CODE()
Definition: video.h:57
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1065
_SEH2_TRY
Definition: create.c:4250
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:389
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:249
VOID CdAddAllocationFromDirent(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ ULONG McbEntryOffset, _In_ LONGLONG StartingFileOffset, _In_ PDIRENT Dirent)
Definition: allocsup.c:335
#define CDFS_NTC_FCB_DATA
Definition: nodetype.h:31
#define LlBytesFromBlocks(V, B)
Definition: cdprocs.h:1644
LONGLONG TotalBlockByteCount
Definition: cdstruc.h:230
struct _FCB * VolumeDasdFcb
Definition: cdstruc.h:565
unsigned char BOOLEAN
LONGLONG DataBlockByteCount
Definition: cdstruc.h:229
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN CdLookupNextDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PDIRENT_ENUM_CONTEXT CurrentDirContext, _Inout_ PDIRENT_ENUM_CONTEXT NextDirContext)
Definition: dirsup.c:208
#define _Out_
Definition: no_sal2.h:323
#define BlockAlign(V, L)
Definition: cdprocs.h:1648
#define CdQueryFidDirentOffset(I)
Definition: cdstruc.h:1837
struct _CD_MCB_ENTRY CD_MCB_ENTRY
VOID CdTruncateAllocation(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ LONGLONG StartingFileOffset)
Definition: allocsup.c:575
VOID CdDiskOffsetFromMcbEntry(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_MCB_ENTRY McbEntry, _In_ LONGLONG FileOffset, _Out_ PLONGLONG DiskOffset, _Out_ PULONG ByteCount)
Definition: allocsup.c:812
int64_t LONGLONG
Definition: typedefs.h:66
CdVerifyOrCreateDirStreamFile(IrpContext, Fcb)
#define CdInitializeDirContext(IC, DC)
Definition: cdprocs.h:544
#define CD_ATTRIBUTE_MULTI
Definition: cd.h:356
_Requires_lock_held_(_Global_critical_region_)
Definition: allocsup.c:87
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:429
#define CdInitializeDirent(IC, D)
Definition: cdprocs.h:541
#define CdPagedPool
Definition: cdprocs.h:1385
#define _Inout_
Definition: no_sal2.h:244
_In_ PFCB ParentFcb
Definition: cdprocs.h:741
#define ASSERT_LOCKED_FCB(F)
Definition: cddata.h:267
CD_MCB Mcb
Definition: cdstruc.h:1022
LONGLONG ByteCount
Definition: cdstruc.h:215
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1060
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1049
#define MAXULONG
Definition: typedefs.h:250
#define _In_
Definition: no_sal2.h:204
_SEH2_END
Definition: create.c:4424
#define CdFreePool(x)
Definition: cdprocs.h:2200
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:151
FILE_ID FileId
Definition: cdstruc.h:958
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
_SEH2_FINALLY
Definition: create.c:4395
unsigned int * PULONG
Definition: retypes.h:1
#define _When_(expr, annos)
Definition: no_sal2.h:639
ULONG CurrentEntryCount
Definition: cdstruc.h:195
VOID CdAddInitialAllocation(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ ULONG StartingBlock, _In_ LONGLONG DataLength)
Definition: allocsup.c:484
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
Definition: cdstruc.h:206
unsigned int ULONG
Definition: retypes.h:1
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:429
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define TAG_MCB_ARRAY
Definition: cdprocs.h:91
PVCB Vcb
Definition: cdstruc.h:939
struct _FCB * ParentFcb
Definition: cdstruc.h:946
LONGLONG DiskOffset
Definition: cdstruc.h:214
#define _In_range_(lb, ub)
Definition: no_sal2.h:227
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
_In_ PFCB Fcb
Definition: cdprocs.h:151
#define CdCleanupDirent(IC, D)
Definition: cdprocs.h:547
VOID CdLookupDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ ULONG DirentOffset, _Out_ PDIRENT_ENUM_CONTEXT DirContext)
Definition: dirsup.c:125
struct _CD_MCB_ENTRY * McbArray
Definition: cdstruc.h:201
#define NT_ASSERT
Definition: rtlfuncs.h:3312
LONGLONG FileOffset
Definition: cdstruc.h:221