// UnRDLL - simple example of UnRAR.dll usage // Translated from UnRDLL.c // Use Delphi 2.0 or higher to compile this module // // Ported to Delphi by Eugene Kotlyarov, fidonet: 2:5058/26.9 ek@oris.ru // Fixed version by Alexey Torgashin , 2:5020/604.24@fidonet program UnRDLL; {$APPTYPE CONSOLE} {$H+} uses AnsiStrings, Windows, UnRAR, SysUtils; const EXTRACT = 0; TEST = 1; PRINT = 2; procedure ShowComment(CmtBuf: PAnsiChar); forward; procedure OutHelp; forward; procedure OutOpenArchiveError(Error: Integer; ArcName: PAnsiChar); forward; procedure OutProcessFileError(Error: Integer); forward; procedure ShowArcInfo(Flags: UINT; ArcName: PAnsiChar); forward; const CR = #13#10; function SFmt(const S: AnsiString; Width: Byte): AnsiString; begin if Length(S) < Width then Result := S + StringOfChar(AnsiChar(' '), Width - Length(S)) else Result := Copy(S, 1, Width); end; function CallbackProc(msg: UINT; UserData, P1, P2: integer) :integer; stdcall; var Ch: AnsiChar; I: Integer; C: PAnsiChar; S: AnsiString; begin Result := 0; case msg of UCM_CHANGEVOLUME: if (P2 = RAR_VOL_ASK) then begin Write(CR, 'Insert disk with ', PAnsiChar(P1), ' and press ''Enter'' or enter ''Q'' to exit '); Readln(Ch); if (UpCase (Ch) = 'Q') then Result := -1; end; UCM_NEEDPASSWORD: begin Write(CR, 'Please enter the password for this archive: '); Readln(S); C := PAnsiChar(S); Move(pointer(C)^, pointer(p1)^, AnsiStrings.StrLen(C) + 1); //+1 to copy the zero end; UCM_PROCESSDATA: begin if (UserData <> 0) and (PINT (UserData)^ = PRINT) then begin Flush (Output); // Windows.WriteFile fails on big data for I := 0 to P2 - 1 do Write(PAnsiChar(P1 + I)^); Flush (Output); end; end; end; end; procedure ExtractArchive(ArcName: PAnsiChar; Mode: Integer); var hArcData: THandle; RHCode, PFCode: Integer; CmtBuf: array[0..Pred(16384)] of AnsiChar; HeaderData: RARHeaderData; OpenArchiveData: RAROpenArchiveDataEx; Operation: Integer; begin OpenArchiveData.ArcName := ArcName; OpenArchiveData.CmtBuf := @CmtBuf; OpenArchiveData.CmtBufSize := SizeOf(CmtBuf); OpenArchiveData.OpenMode := RAR_OM_EXTRACT; hArcData := RAROpenArchiveEx(OpenArchiveData); if (OpenArchiveData.OpenResult <> 0) then begin OutOpenArchiveError(OpenArchiveData.OpenResult, ArcName); Exit; end; ShowArcInfo(OpenArchiveData.Flags, ArcName); if (OpenArchiveData.CmtState = 1) then ShowComment(CmtBuf); RARSetCallback (hArcData, CallbackProc, Integer (@Mode)); HeaderData.CmtBuf := nil; repeat RHCode := RARReadHeader(hArcData, HeaderData); if RHCode <> 0 then Break; case Mode of EXTRACT: Write(CR, 'Extracting ', SFmt(HeaderData.FileName, 45)); TEST: Write(CR, 'Testing ', SFmt(HeaderData.FileName, 45)); PRINT: Write(CR, 'Printing ', SFmt(HeaderData.FileName, 45), CR); end; if Mode = EXTRACT then Operation := RAR_EXTRACT else Operation := RAR_TEST; PFCode := RARProcessFile(hArcData, Operation, nil, nil); if (PFCode = 0) then Write(' Ok') else begin OutProcessFileError(PFCode); Break; end; until False; if (RHCode = ERAR_BAD_DATA) then Write(CR, 'File header broken'); RARCloseArchive(hArcData); end; procedure ListArchive(ArcName: PAnsiChar); var hArcData: THandle; RHCode, PFCode: Integer; CmtBuf: array[0..Pred(16384)] of AnsiChar; HeaderData: RARHeaderDataEx; OpenArchiveData: RAROpenArchiveDataEx; begin OpenArchiveData.ArcName := ArcName; OpenArchiveData.CmtBuf := @CmtBuf; OpenArchiveData.CmtBufSize := SizeOf(CmtBuf); OpenArchiveData.OpenMode := RAR_OM_LIST; hArcData := RAROpenArchiveEx(OpenArchiveData); if (OpenArchiveData.OpenResult <> 0) then begin OutOpenArchiveError(OpenArchiveData.OpenResult, ArcName); Exit; end; ShowArcInfo(OpenArchiveData.Flags, ArcName); if (OpenArchiveData.CmtState = 1) then ShowComment(CmtBuf); RARSetCallback (hArcData, CallbackProc, 0); HeaderData.CmtBuf := @CmtBuf; HeaderData.CmtBufSize := SizeOf(CmtBuf); Write(CR, 'File', StringOfChar(' ',42),'Size'); Write(CR, StringOfChar('-', 50)); repeat RHCode := RARReadHeaderEx(hArcData, HeaderData); if RHCode <> 0 then Break; Write(CR, SFmt(HeaderData.FileName, 39), ' ', (HeaderData.UnpSize + HeaderData.UnpSizeHigh * 4294967296.0):10:0); if (HeaderData.CmtState = 1) then ShowComment(CmtBuf); PFCode:= RARProcessFile(hArcData, RAR_SKIP, nil, nil); if (PFCode <> 0) then begin OutProcessFileError(PFCode); Break; end; until False; if (RHCode = ERAR_BAD_DATA) then Write(CR, 'File header broken'); RARCloseArchive(hArcData); end; procedure ShowComment(CmtBuf: PAnsiChar); begin Write(CR, 'Comment:', CR, CmtBuf, CR); end; procedure ShowArcInfo(Flags: UINT; ArcName: PAnsiChar); function CheckFlag(S: AnsiString; FlagBit: UINT): AnsiString; begin if (Flags and FlagBit) > 0 then result := 'yes' else result := 'no'; Write(CR, Format('%-16s %s',[S, Result])); end; begin Writeln(CR, 'Archive ', ArcName); CheckFlag('Volume:', 1); CheckFlag('Comment:', 2); CheckFlag('Locked:', 4); CheckFlag('Solid:', 8); CheckFlag('New naming:', 16); CheckFlag('Authenticity:', 32); CheckFlag('Recovery:', 64); CheckFlag('Encr.headers:', 128); CheckFlag('First volume:', 256); Writeln(CR, '---------------------------'); end; procedure OutHelp; begin Write(CR, 'UNRDLL. This is a simple example of UNRAR.DLL usage', CR); Write(CR, 'Syntax:', CR); Write(CR, 'UNRDLL X extract archive contents'); Write(CR, 'UNRDLL T test archive contents'); Write(CR, 'UNRDLL P print archive contents to stdout'); Write(CR, 'UNRDLL L view archive contents', CR); end; procedure OutOpenArchiveError(Error: Integer; ArcName: PAnsiChar); begin case Error of ERAR_NO_MEMORY: Write(CR, 'Not enough memory'); ERAR_EOPEN: Write(CR, 'Cannot open ', ArcName); ERAR_BAD_ARCHIVE: Write(CR, ArcName, ' is not RAR archive'); ERAR_BAD_DATA: Write(CR, ArcName, ': archive header broken'); ERAR_UNKNOWN: Write(CR, 'Unknown error'); end; end; procedure OutProcessFileError(Error: Integer); begin case Error of ERAR_UNKNOWN_FORMAT: Write('Unknown archive format'); ERAR_BAD_ARCHIVE: Write('Bad volume'); ERAR_ECREATE: Write('File create error'); ERAR_EOPEN: Write('Volume open error'); ERAR_ECLOSE: Write('File close error'); ERAR_EREAD: Write('Read error'); ERAR_EWRITE: Write('Write error'); ERAR_BAD_DATA: Write('CRC error'); ERAR_UNKNOWN: Write('Unknown error'); end; end; begin if ParamCount <> 2 then begin OutHelp; Halt(0); end; case UpCase(ParamStr(1)[1]) of 'X': ExtractArchive(PAnsiChar(AnsiString(ParamStr(2))), EXTRACT); 'T': ExtractArchive(PAnsiChar(AnsiString(ParamStr(2))), TEST); 'P': ExtractArchive(PAnsiChar(AnsiString(ParamStr(2))), PRINT); 'L': ListArchive(PAnsiChar(AnsiString(ParamStr(2)))); else OutHelp; end; Halt(0); end.