ファイル/フォルダの圧縮属性をセット/リセットするにはCreateFileでファイル/フォルダをオープンし、DeviceIoControlでFSCTL_SET_COMPRESSIONを指定します。
uses
Windows, SysUtils;
type
{ Compress operation }
TCompressOperation = (coCompress, coDecompress);
const
FSCTL_SET_COMPRESSION = $0009C040;
COMPRESSION_FORMAT_NONE = $00000000;
COMPRESSION_FORMAT_DEFAULT = $00000001;
procedure InternalCompressFile(const Filename: String;
Operation: TCompressOperation;
Attr: DWORD); forward;
function NeedChangeCompression(Operation: TCompressOperation;
Attr: DWORD): Boolean; forward;
{$WARN SYMBOL_PLATFORM OFF}
procedure CompressFile(const Filename: String; Operation: TCompressOperation);
var
Attr: DWORD;
begin
if VolumeCanCompress(Filename) = False then
begin
{ This volume is not support compression }
Exit;
end;
{ Get file attributes }
Attr := GetFileAttributes(PChar(Filename));
if Attr = $FFFFFFFF then
begin
RaiseLastOSError;
end;
if NeedChangeCompression(Operation,Attr) = True then
begin
{ Compress or decompress }
InternalCompressFile(Filename,Operation,Attr);
end;
end;
procedure InternalCompressFile(const Filename: String;
Operation: TCompressOperation;
Attr: DWORD);
const
CompressionFormat: array [TCompressOperation] of DWORD =
(COMPRESSION_FORMAT_DEFAULT, // Compress by default format
COMPRESSION_FORMAT_NONE); // Decompress
var
Handle: THandle;
InBuffer: DWORD;
BytesReturned: DWORD;
Access: DWORD;
Flags: DWORD;
begin
{ Flags for CreateFile }
Access := GENERIC_READ or GENERIC_WRITE;
if (Attr and FILE_ATTRIBUTE_DIRECTORY) = 0 then
begin
Flags := FILE_ATTRIBUTE_NORMAL;
end
else
begin
Flags := FILE_FLAG_BACKUP_SEMANTICS;
end;
{ Reset read-only attribute }
if (Attr and FILE_ATTRIBUTE_READONLY) <> 0 then
begin
SetFileAttributes(PChar(Filename),Attr and not FILE_ATTRIBUTE_READONLY);
end;
try
{ Open file or directory }
Handle := CreateFile(PChar(Filename),Access,0,nil,OPEN_EXISTING,Flags,0);
if Handle = INVALID_HANDLE_VALUE then
begin
RaiseLastOSError;
end;
try
{ Compress or decompress }
InBuffer := CompressionFormat[Operation];
Win32Check(DeviceIoControl(Handle,FSCTL_SET_COMPRESSION,
@InBuffer,SizeOf(InBuffer),
nil,0,BytesReturned,nil));
finally
{ Close }
CloseHandle(Handle);
end;
finally
{ Restore read-only attribute }
if (Attr and FILE_ATTRIBUTE_READONLY) <> 0 then
begin
SetFileAttributes(PChar(Filename),
GetFileAttributes(PChar(Filename)) or
FILE_ATTRIBUTE_READONLY);
end;
end;
end;
function NeedChangeCompression(Operation: TCompressOperation;
Attr: DWORD): Boolean;
begin
Result := ((Ord(Operation) xor
Ord((Attr and FILE_ATTRIBUTE_COMPRESSED) <> 0)) = 0);
end;
{$WARN SYMBOL_PLATFORM ON}
ファイル/フォルダをオープンするときはCreateFileでdwDesiredAccessにGENERIC_READ or GENERIC_WRITEを、dwCreationDispositionにOPEN_EXISTINGを、それぞれ指定する必要があります。また対象がフォルダのときはdwFlagsAndAttributesにFILE_FLAG_BACKUP_SEMANTICSを指定します。さらにファイル/フォルダの属性に書込禁止(FILE_ATTRIBUTE_READONLY)が含まれている場合はSetFileAttributesで一時的に解除する必要もあります。元ねたはNTFSの圧縮機能 - HEROPA's HomePageやサンプルプログラム集 ファイルの圧縮属性の変更あたり。
0 件のコメント:
コメントを投稿