{*******************************************************} { } { ProcessAlzip } { } { Copyright (C) 2023 kku } { } {*******************************************************} unit ProcessAlzip; (******************************************************************************************************************** Egg.pas - Egg.pas는 이스트소프트사에서 공개한 EGG/ALZ의 해제 모듈의 헤더파일인 unegg.h를 델파이 언어로 번역한 것 입니다. - 이스트소프트사는 EGG/ALZ 해제 모듈을 상용프로그램에 이용할 때에는 허가를 받을 것을 요구하고 있으므로 주의하십시오. - EGG/ALZ 해제 모듈은 32비트와 64비트가 따로 있습니다.(UnEGG32.dll, UnEGG64.dll) - Egg.pas는 32비트인 UnEGG32.dll만을 사용합니다. - unegg.h를 번역하여 이 유닛을 만든 양병규에게 저작인접권이 있지만 양병규는 저작인접권을 모두 포기합니다. - 그러나 원본이 이스트소프트에 권리가 있으므로 이스트소프트가 제시한 라이센스를 그대로 따라야합니다. - 즉, Egg.pas와 UnEGG32.dll, UnEGG64.dll를 이용하는 경우에는 이스트소프트사의 라이센스를 따라야합니다. - 이스트소프트사가 공개한 자료와 라이센스는 http://www.altools.co.kr/Product/ALZip_Egg.aspx 에 있습니다. - 양병규 delmadang@hanmail.net *********************************************************************************************************************) interface uses Windows, System.Classes, System.SysUtils; const GG_TYPE_INVALID = 0; // 지원하지 않는 파일 EGG_TYPE_ALZ = 1; // ALZ파일을 의미합니다. EGG_TYPE_EGG = 2; // EGG파일을 의미합니다. EGG_ERROR_SUCCESS = 1; // 성공 EGG_ERROR_FAIL = 0; // 실패 EGG_ERROR_SKIP = 2; // 건너뛰기 EGG_ERROR_CANCEL = 3; // 취소 EGG_ERROR_IO = 4; // I/O 오류 EGG_ERROR_TYPEMISMATCH = 5; // 형식이 일치하지 않음 EGG_ERROR_FILE = 6; // File관련 작업 오류 EGG_ERROR_FORMAT = 7; // Format관련 오류 EGG_ERROR_ALGORITHM = 8; // Algorithm 오류 EGG_ERROR_WRONGPASSWORD = 9; // Password 오류 EGG_WORKCODE_NONE = 0; // 기본값 EGG_WORKCODE_SCAN = 1; // 현재 헤더를 추출하는 중입니다. EGG_WORKCODE_EXTRACT = 2; // 현재 압축해제 작업 중입니다. EGG_WORKCODE_TEST = 3; // 현재 테스트 작업 중입니다. CODE_Extract = 1; CODE_Progress = 2; CODE_Start = 3; CODE_Finish = 4; CODE_ActivityStart = 5; CODE_ActivityFinish = 6; CODE_QueryPassword = 7; CODE_Error = 8; CODE_Test = 9; {$IFDEF WIN64} // DLL_EGG = 'UnEGG64.dll'; DLL_EGG = 'Bs1Ugcp.dll'; {$ELSE} DLL_EGG = 'UnEGG32.dll'; {$ENDIF} type size_t = NativeUInt; // DWORD; time_t = LONGLONG; egg_handle = THandle; // size_t; egg_type = Integer; Psize_t = ^size_t; Pegg_type = ^egg_type; Pegg_handle = ^egg_handle; PExtract = ^Extract; Extract = packed record index: size_t; nameInArchive: PWideChar; fileName: array[0..MAX_PATH-1] of WideChar; end; PProgress = ^Progress; Progress = packed record total: SHORT; current: SHORT; end; PStart = ^Start; Start = packed record code: UINT; end; PFinish = ^Finish; Finish = packed record code: UINT; result: UINT; end; PActivityStart = ^ActivityStart; ActivityStart = packed record index: size_t; code: UINT; end; PActivityFinish = ^ActivityFinish; ActivityFinish = packed record index: size_t; code: UINT; result: UINT; end; PQueryPassword = ^QueryPassword; QueryPassword = packed record index: size_t; queryCount: size_t; password: array[0..1023] of WideChar; end; PError = ^Error; Error = packed record index: size_t; code: UINT; end; PTest = ^Test; Test = packed record index: size_t; nameInArchive: PWideChar; skipThisFile: BOOL; end; TFileSize = packed record SizeHigh: Cardinal; SizeLow: Cardinal; end; PEGGFileHeader = ^TEGGFileHeader; TEGGFileHeader = packed record size: size_t; fileName: PWideChar; comment: PWideChar; llPackedSize, llUnpackedSize: ULONGLONG; nAttr: DWORD; crc: DWORD; dwMethod: DWORD; lastModified: time_t; bEnc: Boolean; end; PEggExtractUserData = ^TEggExtractUserData; TEggExtractUserData = record bExistsFail: Boolean; sExportDir: String; arrFiles: array of String; ExtrFileList: TStrings; end; TProcAlzipWork = function(pUserData: PEggExtractUserData; code: UINT; extractData: PExtract): UINT; cdecl; // TProcAlzipWork = function(pUserData: Pointer; code: UINT; extractData: Pointer): UINT; cdecl; TEGG_CreateEgg = function(handle: Pegg_handle; eventProc: TProcAlzipWork; user: Pointer): UINT; cdecl; TEGG_DestroyEgg = function(handle: Pegg_handle): UINT; cdecl; TEGG_IsValidArchive = function(fileName: PWideChar; result: Pegg_type): UINT; cdecl; TEGG_OpenArchive = function(handle: egg_handle; fileName: PWideChar): UINT; cdecl; TEGG_CloseArchive = function(handle: egg_handle): UINT; cdecl; TEGG_Extract = function(handle: egg_handle): UINT; cdecl; TEGG_Test = function(handle: egg_handle): UINT; cdecl; TEGG_GetFileCount = function(handle: egg_handle; count: Psize_t): UINT; cdecl; TEGG_GetFileHeader = function(handle: egg_handle; index: size_t; header: PEGGFileHeader): UINT; cdecl; function EGG_CreateEgg(handle: Pegg_handle; eventProc: TProcAlzipWork; user: Pointer): UINT; function EGG_DestroyEgg(handle: Pegg_handle): UINT; function EGG_IsValidArchive(fileName: PWideChar; eggType: Pegg_type): UINT; function EGG_OpenArchive(handle: egg_handle; fileName: PWideChar): UINT; //function EGG_OpenArchive(handle: egg_handle; fileName: PUTF8Char): UINT; function EGG_CloseArchive(handle: egg_handle): UINT; function EGG_Extract(handle: egg_handle): UINT; function EGG_Test(handle: egg_handle): UINT; function EGG_GetFileCount(handle: egg_handle; count: Psize_t): UINT; function EGG_GetFileHeader(handle: egg_handle; index: size_t; header: PEGGFileHeader): UINT; function ExtractAlzipData(sPath, sExportDir: String; ExtrFileList: TStrings; bExistsFail: Boolean = false): Boolean; implementation var hEggLib: THandle = 0; _fnEGG_CreateEgg: TEGG_CreateEgg = nil; _fnEGG_DestroyEgg: TEGG_DestroyEgg = nil; _fnEGG_IsValidArchive: TEGG_IsValidArchive = nil; _fnEGG_OpenArchive: TEGG_OpenArchive = nil; _fnEGG_CloseArchive: TEGG_CloseArchive = nil; _fnEGG_Extract: TEGG_Extract = nil; _fnEGG_Test: TEGG_Test = nil; _fnEGG_GetFileCount: TEGG_GetFileCount = nil; _fnEGG_GetFileHeader: TEGG_GetFileHeader = nil; function InitEggLib: Boolean; begin if hEggLib = 0 then begin hEggLib := LoadLibrary(DLL_EGG); if hEggLib <> 0 then begin @_fnEGG_CreateEgg := GetProcAddress(hEggLib, 'EGG_CreateEgg'); @_fnEGG_DestroyEgg := GetProcAddress(hEggLib, 'EGG_DestroyEgg'); @_fnEGG_IsValidArchive := GetProcAddress(hEggLib, 'EGG_IsValidArchive'); @_fnEGG_OpenArchive := GetProcAddress(hEggLib, 'EGG_OpenArchive'); @_fnEGG_CloseArchive := GetProcAddress(hEggLib, 'EGG_CloseArchive'); @_fnEGG_Extract := GetProcAddress(hEggLib, 'EGG_Extract'); @_fnEGG_Test := GetProcAddress(hEggLib, 'EGG_Test'); @_fnEGG_GetFileCount := GetProcAddress(hEggLib, 'EGG_GetFileCount'); @_fnEGG_GetFileHeader := GetProcAddress(hEggLib, 'EGG_GetFileHeader'); end; end; Result := hEggLib <> 0; end; function EGG_CreateEgg(handle: Pegg_handle; eventProc: TProcAlzipWork; user: Pointer): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_CreateEgg) then Result := _fnEGG_CreateEgg(handle, eventProc, user); end; function EGG_DestroyEgg(handle: Pegg_handle): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_DestroyEgg) then Result := _fnEGG_DestroyEgg(handle); end; function EGG_IsValidArchive(fileName: PWideChar; eggType: Pegg_type): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_IsValidArchive) then Result := _fnEGG_IsValidArchive(fileName, eggType); end; function EGG_OpenArchive(handle: egg_handle; fileName: PWideChar): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_OpenArchive) then Result := _fnEGG_OpenArchive(handle, fileName); end; function EGG_CloseArchive(handle: egg_handle): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_CloseArchive) then Result := _fnEGG_CloseArchive(handle); end; function EGG_Extract(handle: egg_handle): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_Extract) then Result := _fnEGG_Extract(handle); end; function EGG_Test(handle: egg_handle): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_Test) then Result := _fnEGG_Test(handle); end; function EGG_GetFileCount(handle: egg_handle; count: Psize_t): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_GetFileCount) then Result := _fnEGG_GetFileCount(handle, count); end; function EGG_GetFileHeader(handle: egg_handle; index: size_t; header: PEGGFileHeader): UINT; begin Result := EGG_ERROR_FAIL; if InitEggLib and Assigned(_fnEGG_GetFileHeader) then Result := _fnEGG_GetFileHeader(handle, index, header); end; function ProcessAlzipWork(pUserData: PEggExtractUserData; code: UINT; extractData: PExtract): UINT; cdecl; var sExtractPath: String; begin Result := EGG_ERROR_SUCCESS; case code of CODE_Extract : begin sExtractPath := pUserData.sExportDir + pUserData.arrFiles[extractData.index]; if ForceDirectories(ExtractFilePath(sExtractPath)) then begin if not pUserData.bExistsFail and FileExists(sExtractPath) then DeleteFile(PChar(sExtractPath)); StrCopy(@extractData.fileName, PWideChar(sExtractPath)); pUserData.ExtrFileList.Add(sExtractPath); end; end; CODE_QueryPassword : ; CODE_Error : Result := EGG_ERROR_CANCEL; end; end; function ExtractAlzipData(sPath, sExportDir: String; ExtrFileList: TStrings; bExistsFail: Boolean = false): Boolean; var EggType: egg_type; hEgg: egg_handle; EggUserData: TEggExtractUserData; nFileCnt: size_t; i: Integer; EggFileHeader: TEGGFileHeader; bExtract: Boolean; begin Result := false; if EGG_IsValidArchive(PChar(sPath), @EggType) = EGG_ERROR_SUCCESS then begin hEgg := 0; ExtrFileList.Clear; ZeroMemory(@EggUserData, SizeOf(EggUserData)); EggUserData.bExistsFail := bExistsFail; EggUserData.ExtrFileList := ExtrFileList; if EGG_CreateEgg(@hEgg, ProcessAlzipWork, @EggUserData) = EGG_ERROR_SUCCESS then begin if EGG_OpenArchive(hEgg, PChar(sPath)) = EGG_ERROR_SUCCESS then begin if EGG_GetFileCount(hEgg, @nFileCnt) = EGG_ERROR_SUCCESS then if nFileCnt > 0 then begin bExtract := true; EggUserData.sExportDir := IncludeTrailingPathDelimiter(sExportDir); SetLength(EggUserData.arrFiles, nFileCnt); for i := 0 to nFileCnt - 1 do if EGG_GetFileHeader(hEgg, i, @EggFileHeader) = EGG_ERROR_SUCCESS then begin EggUserData.arrFiles[i] := StringReplace(EggFileHeader.fileName, '/', '\', [rfReplaceAll]); end else begin bExtract := false; break; end; if bExtract then Result := EGG_Extract(hEgg) = EGG_ERROR_SUCCESS; end; EGG_CloseArchive(hEgg); end; EGG_DestroyEgg(@hEgg); end; end; end; end.