unit Archive;
// LZH/ZIP形式の圧縮ファイルを解凍 (要:UnLha32.dll, UnZip32.dll)
interface
uses
Windows, SysUtils, Classes, Dialogs;
procedure Init_Archive;
procedure Term_Archive;
function lzh_extract( srcFile, desFile: string ): boolean;
function zip_extract( srcFile, desFile: string ): boolean;
var
CanUnLha, CanUnZip: boolean;
implementation
type
TDllPrnt = function(Buffer: PChar; Size: ULONG): integer; stdcall;
TDllPassword = function(P: PChar; N: Integer; M, Name: PChar): integer; stdcall;
TDllService = function (CurFile: PChar; Size: ULONG): integer; stdcall;
TDllSnd = procedure; stdcall;
TDllReplace = function(FileName: PChar): integer; stdcall;
TDllMessage = procedure (UnCompSize: ULONG; CompSize: ULONG; Factor: UINT;
Month: UINT; Day: UINT; Year: UINT; Hour: UINT; Minute: UINT;
C: Char; FileName: PChar; MethBuf: PChar; CRC: ULONG; Crypt: Char); stdcall;
PUserFunctions = ^TUserFunctions;
USERFUNCTIONS = record
Print : TDllPrnt;
Sound : TDllSnd;
Replace : TDllReplace;
Password : TDllPassword;
SendApplicationMessage : TDllMessage;
ServCallBk : TDllService;
TotalSizeComp : ULONG;
TotalSize : ULONG;
CompFactor : Integer;
NumMembers : UINT;
cchComment : UINT;
end;
TUserFunctions = USERFUNCTIONS;
PDCL = ^TDCL;
DCL = record
ExtractOnlyNewer : Integer; { true if you are to extract only newer }
SpaceToUnderscore : Integer; { true if convert space to underscore }
PromptToOverwrite : Integer; { true if prompt to overwrite is wanted }
fQuiet : Integer; { quiet flag. 1 = few messages, 2 = no messages, 0 = all messages }
nCFlag : Integer; { write to stdout if true }
nTFlag : Integer; { test zip file }
nVFlag : Integer; { verbose listing }
nUFlag : Integer; { "update" (extract only newer/new files) }
nZFlag : Integer; { display zip file comment }
nDFlag : Integer; { all args are files/dir to be extracted }
nOFlag : Integer; { true if you are to always over-write files, false if not }
nAFlag : Integer; { do end-of-line translation }
nZIFlag : Integer; { get zip info if true }
C_flag : Integer; { be case insensitive if TRUE }
fPrivilege : Integer; { 1 => restore Acl's, 2 => Use privileges }
lpszZipFN : PChar; { zip file name }
lpszExtractDir : PChar; { Directory to extract to. NULL for the current directory }
end ;
TDCL = DCL;
var
UnLha32Dll, UnZip32Dll: THandle;
_Unlha: function(_hwnd:HWND; szCmdLine,szOutput:PChar; wSize:dword):
integer stdcall;
_Wiz_SingleEntryUnzip: function(_hwnd:HWND; ifnv:PPChar; xfnc:Integer;
xfnv:PPChar; var Options:TDCL; var UserFunc:TUserFunctions):
integer; stdcall;
//======================================================================
// 機能:解凍の初期処理
//======================================================================
procedure Init_Archive;
begin
// UNLHA32.DLLのライブラリロード
UnLha32Dll := LoadLibrary( 'UNLHA32.DLL' );
@_Unlha := Nil;
if UnLha32Dll<>0 then begin {UNLHA32.DLLが存在する}
@_Unlha := GetProcAddress( UnLha32Dll,'Unlha' );
end;
CanUnLha := @_Unlha<>Nil;
// UNZIP32.DLLのライブラリロード
UnZip32Dll := LoadLibrary( 'UNZIP32.DLL' );
@_Wiz_SingleEntryUnzip := Nil;
if UnZip32Dll<>0 then begin {UNZIP32.DLLが存在する}
@_Wiz_SingleEntryUnzip :=
GetProcAddress( UnZip32Dll,'Wiz_SingleEntryUnzip' );
end;
CanUnZip := @_Wiz_SingleEntryUnzip<>Nil;
end;
//======================================================================
// 機能:解凍の終了処理
//======================================================================
procedure Term_Archive;
begin
if UnLha32Dll<>0 then FreeLibrary(UnLha32Dll);
if UnZip32Dll<>0 then FreeLibrary(UnZip32Dll);
end;
//======================================================================
// 機能:LZH形式の圧縮ファイルを解凍
//======================================================================
function lzh_extract( srcFile, desFile: string ): boolean;
var
CmdLine, Output: string;
iRet: Integer;
begin
if CanUnLha=FALSE then
iret := -1
else begin
SetLength( Output,255 ); {解凍結果を返す為のバッファ}
{(未使用なのでサイズは適当)}
// CmdLine := format( 'e "%s" "%s"',[srcFile,desFile] ); {Path無効}
CmdLine := format( 'x -jf0 "%s" "%s"',[srcFile,desFile] ); {Path有効}
iRet := _Unlha( 0, PChar(Cmdline), PChar(Output), Length(Output) );
end;
Result := (iRet=0);
end;
//----------------------------------------------------------------------
// 機能:UnZip32.dllの為の関数群
//----------------------------------------------------------------------
function DummyPrint(Buffer: PChar; Size: LongWord): Integer; stdcall;
begin
if Buffer<>nil then begin
if StrPos(Buffer, 'error')<>Nil then
ShowMessage('UnZip32.dllでエラーが発生');
end;
Result := Size;
end;
//----------------------------------------------------------------------
function DllReplace(FileName: PChar): integer; stdcall;
begin
Result := 1;
end;
//----------------------------------------------------------------------
function DummyPassword(P: PChar; N: Integer; M, Name: PChar): Integer; stdcall;
begin
Result := 1;
end;
//----------------------------------------------------------------------
function DllPassword(P: PChar; N: Integer; M, Name: PChar): integer; stdcall;
begin
Result := 1;
end;
//----------------------------------------------------------------------
procedure DllMessage( UnCompSize: ULONG; CompSize: ULONG; Factor: UINT;
Month: UINT; Day: UINT; Year: UINT; Hour: UINT; Minute: UINT;
C: Char; FileName: PChar; MethBuf: PChar; CRC: ULONG; Crypt: Char); stdcall;
begin
Exit;
end;
//----------------------------------------------------------------------
function DllService(CurFile: PChar; Size: ULONG): integer; stdcall;
begin
Result := 0;
end;
//----------------------------------------------------------------------
procedure Set_UserFunctions(var Z:TUserFunctions);
begin
{ prepare TUserFunctions structure }
with Z do begin
@Print := @DummyPrint;
@Sound := nil;
@Replace := @DllReplace;
@Password := @DllPassword;
@SendApplicationMessage := @DllMessage;
@ServCallBk := @DllService;
end;
end;
//======================================================================
// 機能:ZIP形式の圧縮ファイルを解凍
//======================================================================
function zip_extract(srcFile, desFile: string): boolean;
var
UF: TUserFunctions;
Opt: TDCL;
rc: integer;
begin
if CanUnZip=FALSE then
rc := -1
else begin
Set_UserFunctions(UF);
{ set unzip operation options }
ZeroMemory( @Opt, Sizeof(Opt) );
// Opt.nDFlag := 0; // path無しで展開
Opt.nDFlag := 1; // path付きで展開
Opt.fPrivilege := 1;
Opt.lpszZipFN := PChar(srcFile);
Opt.lpszExtractDir := PChar(desFile);
Opt.nTFlag := 0;
{ extract }
rc := _Wiz_SingleEntryUnzip(
0, { number of file names being passed }
nil, { file names to be unarchived }
0, { number of "file names to be excluded from processing" being passed }
nil, { file names to be excluded from the unarchiving process }
Opt, { pointer to a structure with the flags for setting the various options }
UF { pointer to a structure that contains pointers to user functions }
);
end;
Result := (rc=1);
end;
end.
(上記コードをArchive.pasとして保存する)
<< 使用例 >>
uses Archive;
procedure TForm1.Button1Click(Sender: TObject);
var
kakucho: string;
result: boolean;
begin
Init_Archive();
result := FALSE;
kakucho := LowerCase( ExtractFileExt(ファイル名) );
if CanUnLha and (kakucho='.lzh') then begin
result := lzh_extract( ファイル名,展開先フォルダー );
end;
if CanUnZip and (kakucho='.zip') then begin
result := zip_extract( ファイル名,展開先フォルダー );
end;
if result=FALSE then
ShowMessage( '指定ファイルを解凍出来ません。' );
Term_Archive();
end;
<< バグ情報 >>
・セキュリティ情報を含むZIP形式をNTFS形式のドライブに解凍すると、セキュリティ
情報のユーザー名が正しく作成されません。
<< 修正履歴 >>
・LZH形式を解凍時、解凍先パス名に空白が含まれていると処理が失敗するので
修正 (2009/12/02)
|
|
・インターネット上の情報や書籍の内容を一部参考に作成してます。 ・コーディング内容は著作権フリーですが、使用する場合は自己責任にてお願いします。 ・記述内容に問題点や改善点がありましたらこちらまでお願いします。 |