Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
The server provides:
Open: An Open of a DataFile.
InputBuffer: An array of bytes containing a single FILE_ALLOCATED_RANGE_BUFFER structure indicating the range to query for allocation, as specified in [MS-FSCC] section 2.3.52.
InputBufferSize: The number of bytes in InputBuffer.
OutputBufferSize: The maximum number of bytes to return in OutputBuffer.
On completion, the object store MUST return:
Status: An NTSTATUS code that specifies the result.
OutputBuffer: An array of bytes that will return an array of zero or more FILE_ALLOCATED_RANGE_BUFFER structures as specified in [MS-FSCC] section 2.3.52.
BytesReturned: The number of bytes returned in OutputBuffer.
This operation uses the following local variables:
32-bit unsigned integer indicating the index of the next FILE_ALLOCATED_RANGE_BUFFER to fill in OutputBuffer (initialized to 0): OutputBufferIndex.
64-bit unsigned integer QueryStart: Is initialized to ClustersFromBytesTruncate(Open.File.Volume, InputBuffer.FileOffset). This is the cluster containing the first byte of the queried range.
64-bit unsigned integer QueryNext: Is initialized to ClustersFromBytesTruncate(Open.File.Volume, (InputBuffer.FileOffset + InputBuffer.Length - 1) ) + 1. This is the cluster following the last cluster of the range.
64-bit unsigned integers (initialized to 0): ExtentFirstVcn, ExtentNextVcn, RangeFirstVcn, RangeNextVcn
Boolean values (initialized to FALSE): FoundRangeStart, FoundRangeEnd
Pointer to an EXTENTS element (initialized to NULL): Extent
FILE_ALLOCATED_RANGE_BUFFER (initialized to zeros): Range
Support for this operation is optional. If the object store does not implement this functionality, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST.<114>
Pseudocode for the operation is as follows:
If Open.Stream.StreamType is DirectoryStream, the operation MUST be failed with STATUS_INVALID_PARAMETER.
If InputBufferSize is less than sizeof(FILE_ALLOCATED_RANGE_BUFFER), the operation MUST be failed with STATUS_INVALID_PARAMETER.
If (InputBuffer.FileOffset < 0) or (InputBuffer.Length < 0) or (InputBuffer.Length > MAXLONGLONG - InputBuffer.FileOffset), the operation MUST be failed with STATUS_INVALID_PARAMETER. If InputBuffer.Length is 0:
Set BytesReturned to 0.
Return STATUS_SUCCESS.
EndIf
If OutputBufferSize < sizeof(FILE_ALLOCATED_RANGE_BUFFER), the operation MUST be failed with STATUS_BUFFER_TOO_SMALL.
If Open.Stream.IsSparse is FALSE:
Set OutputBuffer.FileOffset to InputBuffer.FileOffset.
Set OutputBuffer.Length to InputBuffer.Length.
Set BytesReturned to sizeof(FILE_ALLOCATED_RANGE_BUFFER).
Return STATUS_SUCCESS.
Else:
For sparse files, return a list of contiguous allocated ranges within the requested range. Contiguous allocated ranges in a sparse file might be fragmented on disk, therefore it is necessary to loop through the EXTENTS on this stream, coalescing the adjacent allocated EXTENTS into a single FILE_ALLOCATED_RANGE_BUFFER entry.
Set Status to STATUS_SUCCESS.
Set BytesReturned to 0.
For each Extent in Open.Stream.ExtentList:
Set ExtentFirstVcn to ExtentNextVcn.
Set ExtentNextVcn to Extent.NextVcn.
If Extent.Lcn != 0xffffffffffffffff, meaning Extent is allocated (not a sparse hole):
If FoundRangeStart is FALSE:
If QueryStart < ExtentFirstVcn:
Set FoundRangeStart to TRUE.
Set RangeFirstVcn to ExtentFirstVcn.
Else If ExtentFirstVcn <= QueryStart and QueryStart < ExtentNextVcn:
Set FoundRangeStart to TRUE.
Set RangeFirstVcn to QueryStart.
EndIf
EndIf
If FoundRangeStart is TRUE:
If QueryNext <= ExtentFirstVcn:
Break out of the For loop.
Else If ExtentFirstVcn < QueryNext and QueryNext <= ExtentNextVcn:
Set FoundRangeEnd to TRUE.
Set RangeNextVcn to QueryNext.
Else (ExtentNextVcn < QueryNext):
Set FoundRangeEnd to FALSE.
Set RangeNextVcn to ExtentNextVcn.
EndIf
EndIf
Else If FoundRangeStart is TRUE:
Set FoundRangeEnd to TRUE.
EndIf
If FoundRangeEnd is TRUE:
Set FoundRangeStart to FALSE and FoundRangeEnd to FALSE.
Add Range to OutputBuffer as follows:
Set Range.FileOffset to RangeFirstVcn * Open.File.Volume.ClusterSize.
Set Range.Length to (RangeNextVcn - RangeFirstVcn) * Open.File.Volume.ClusterSize.
If OutputBufferSize < ((OutputBufferIndex + 1) * sizeof(FILE_ALLOCATED_RANGE_BUFFER) ) then:
Set RangeFirstVcn to 0 and RangeNextVcn to 0.
Set Status to STATUS_BUFFER_OVERFLOW.
Break out of the For loop.
EndIf
Copy Range to OutputBuffer[OutputBufferIndex].
Increment OutputBufferIndex by 1.
Set RangeFirstVcn to 0 and RangeNextVcn to 0.
EndIf
EndFor
If RangeNextVcn is not 0:
If OutputBufferSize < ((OutputBufferIndex + 1) * sizeof(FILE_ALLOCATED_RANGE_BUFFER)) then:
Set Status to STATUS_BUFFER_OVERFLOW.
Else add Range to OutputBuffer as follows:
Set Range.FileOffset to RangeFirstVcn * Open.File.Volume.ClusterSize.
Set Range.Length to (RangeNextVcn - RangeFirstVcn) * Open.File.Volume.ClusterSize.
Copy Range to OutputBuffer[OutputBufferIndex].
Increment OutputBufferIndex by 1.
EndIf
EndIf
Bias the first and the last returned ranges so that they match the offset/length passed in, using the following algorithm:
If OutputBufferIndex > 0:
If OutputBuffer[0].FileOffset < InputBuffer.FileOffset:
Set OutputBuffer[0].Length to OutputBuffer[0].Length - (InputBuffer.FileOffset -OutputBuffer[0].FileOffset).
Set OutputBuffer[0].FileOffset to InputBuffer.FileOffset.
EndIf
If (OutputBuffer[OutputBufferIndex - 1].FileOffset + OutputBuffer[OutputBufferIndex - 1].Length) > (InputBuffer.FileOffset + InputBuffer.Length):
Set OutputBuffer[OutputBufferIndex - 1].Length to InputBuffer.FileOffset + InputBuffer.Length - OutputBuffer[OutputBufferIndex - 1].FileOffset.
EndIf
EndIf
Endif
Upon successful completion of the operation, the object store MUST return:
BytesReturned set to OutputBufferIndex * sizeof(FILE_ALLOCATED_RANGE_BUFFER).
Status set to STATUS_SUCCESS.