2.1.5.10.30 FSCTL_SET_COMPRESSION
The server provides:
Open: An Open of a DataFile or DirectoryFile.
InputBuffer: An array of bytes containing a USHORT value indicating the requested compression state of the stream, as specified in [MS-FSCC] section 2.3.67.
InputBufferSize: The number of bytes in InputBuffer.
On completion, the object store MUST return:
Status: An NTSTATUS code that specifies the result.
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.<129><130>
The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
InputBufferSize is less than sizeof(USHORT) (2 bytes).
InputBuffer.CompressionState is not one of the predefined values in [MS-FSCC] section 2.3.69.
Pseudocode for the operation is as follows:
If InputBuffer.CompressionState != COMPRESSION_FORMAT_NONE:
If compression support is disabled in the object store,<131> the operation MUST be failed with STATUS_COMPRESSION_DISABLED.
If Open.File.Volume.ClusterSize is greater than 4,096, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST, because compression is not supported on volumes with a cluster size greater than 4 KB.
EndIf
If Open.File.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.
If Open.Stream.IsEncrypted is TRUE, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST.
If (InputBuffer.CompressionState == COMPRESSION_FORMAT_NONE and Open.Stream.IsCompressed is FALSE) or (InputBuffer.CompressionState != COMPRESSION_FORMAT_NONE and Open.Stream.IsCompressed is TRUE), the operation MUST return STATUS_SUCCESS at this point.
The object store MUST initialize ChangedAllocation to FALSE.
The object store MUST post a USN change as specified in section 2.1.4.11 with File equal to File, Reason equal to USN_REASON_COMPRESSION_CHANGE, and FileName equal to Open.Link.Name.
If InputBuffer.CompressionState != COMPRESSION_FORMAT_NONE:
If Open.Stream.AllocationSize is less than BlockAlign(Open.Stream.AllocationSize, Open.File.Volume.CompressionUnitSize), the object store MUST increase Open.Stream.AllocationSize to BlockAlign(Open.Stream.AllocationSize, Open.File.Volume.CompressionUnitSize). If there is not enough disk space, the operation MUST be failed with STATUS_DISK_FULL; otherwise the object store MUST set ChangedAllocation to TRUE.
EndIf
If InputBuffer.CompressionState == COMPRESSION_FORMAT_NONE, the object store MUST set Open.Stream.IsCompressed to FALSE; otherwise it MUST be set to TRUE.
If Open.Stream.StreamType is DirectoryStream or Open.Stream.Name is empty, the object store MUST propagate the compression state to Open.File:
If Open.Stream.IsCompressed is TRUE, the object store MUST set Open.File.FileAttributes.FILE_ATTRIBUTE_COMPRESSED to TRUE; otherwise it MUST be set to FALSE.
EndIf
Send directory change notification as specified in section 2.1.4.1, with Volume equal to Open.File.Volume, Action equal to FILE_ACTION_MODIFIED, FilterMatch equal to FILE_NOTIFY_CHANGE_ATTRIBUTES, and FileName equal to Open.FileName.
If Open.Stream.StreamType is DirectoryStream, the operation MUST return STATUS_SUCCESS at this point.
If Open.Stream.IsCompressed is FALSE and Open.Stream.AllocationSize is greater than BlockAlign(Open.Stream.Size, Open.File.Volume.ClusterSize), the object store SHOULD free excess allocation by setting Open.Stream.AllocationSize to BlockAlign(Open.Stream.Size, Open.File.Volume.ClusterSize). If any allocation is freed in this way, the object store MUST set ChangedAllocation to TRUE.
If Open.Stream.IsSparse is TRUE, the object store SHOULD free any allocated compression unit-aligned extents beyond Open.Stream.ValidDataLength. If any allocation is freed in this way, the object store MUST set ChangedAllocation to TRUE.
If ChangedAllocation is TRUE and Open.Stream.Name is empty, the object store MUST set Open.File.PendingNotifications.FILE_NOTIFY_CHANGE_SIZE to TRUE.
Upon successful completion of the operation, the object store MUST return:
Status set to STATUS_SUCCESS.