LHA with ActivePerl

by Hippo2000(Aug 30th, 2000)


Contents

1. Call from UNLHA32.DLL from Perl
1.1 Required Packages
1.2 Usage
1.3 Examples

See Also


1.Call From UNLHA32.DLL from Perl

The Win32::API module allows you to call DLLs from Perl.
So, I will introduce how to use UNLHA32.DLL with that module.

1.1 Required Package

To call DLL, you can use Win32::API module. It may be included in standard distribution.

Packages Description
Win32::API Implementation of arbitrary Win32 APIs.

1.2 Usage

Before you can call DLL, you should do 2 steps.

(1)Creating a Win32::API object(Function Declaration)
(2)Calling that function

(1) Create a Win32::API Object:
 $oNewAPI = new Win32::API($library, $functionname, \@argumenttypes, $returntype);
(2)Calling that function:
 	$return = $oNewAPI->Call(@arguments);

\@argumenttypes and $returntype are specified with these characters:

Type Char Type
N Numeric?iLONG?
I Numeric?iInteger?
P Other?iStrins?AStruct and so on?

ex. Declarations for UnlhaGetVersion, UnLha functions of UNLHA32.DLL in VB

Declare Function UnlhaGetVersion Lib "unlha32" () As Integer
Declare Function Unlha Lib "unlha32"_
               (ByVal hwnd As Long, ByVal szCmdLine As String, _ 
                ByVal szOutput As String, ByVal dwSize As Long) As Long

same declarations in Perl :

$GetVer = new Win32::API("unlha32",  "UnlhaGetVersion", [], I);
$nRes = $GetVer->Call();
$nRes &= 0xFFFF;	        #only last 2bytes (for Integer)
$Lha = new Win32::API("unlha32", "Unlha", [N, P, P, N], N);
$sBuff = "\x00" x 2000;	#Buffer allocatioin (2000 has no special meanings)
$nRes = $Lha->Call(0, 'a -rx c:\\kabaya.lzh "c:\\My Documents\\" *.htm', $sBuff, 2000);    
$sBuff =~ s/\x00+$//;	#Truncate 

And you can use pack and unpack to set or get datas from/to Structures.

1.2 Usage

Sample programming for compressing, uncompressing, file listing with UNLHA32.DLL

use File::Path;        #Only for remove files (not required for UNLHA)
use Win32::API;

#1. Get Version information
# Function Declaration
my $GetVer = new Win32::API("unlha32",  "UnlhaGetVersion", [], I);
$nRes = $GetVer->Call();
$nRes &= 0xFFFF;		#get last 2 bytes (for int)
			#
print "Ver: $nRes\n";

#2.Get file count
# Function Declaration
my $GetF = new Win32::API("unlha32",  "UnlhaGetFileCount", [P], N);
my $nCnt = $GetF->Call('c:\\tt1.lzh');
print "Count: $nCnt\n";

#3.LHA Commands
# Function Declaration
$Lha = new Win32::API("unlha32", "Unlha", [N, P, P, N], N);
#(1)Compress
#Compress htm files, searching under "c:\My Documents" recursively
unlink('c:\\kabaya.lzh');
$sBuff = "\x00" x 2000;	#Buffer allocation
$nRes = $Lha->Call(0, 'a -rx c:\\kabaya.lzh "c:\\My Documents\\" *.htm', $sBuff, 2000);
$sBuff =~ s/\x00+$//;	#truncate 0x00s
print $sBuff, "\n";

#(2)Uncompress
rmtree('c:\\lhaext\\');		#remove files under "c:\lhaext" recursively
mkdir('c:\\lhaext', 0777);
$sBuff = "\x00" x 2000;	#Buffer allocation
$nRes = $Lha->Call(0, 'x c:\\kabaya.lzh c:\\lhaext\\', $sBuff, 2000);
$sBuff =~ s/\x00+$//;	#truncate 0x00s
print $sBuff, "\n";

#4.Process wit OpenArc
my $lhaOpenArc   = new Win32::API("unlha32",  "UnlhaOpenArchive", [N, P, N], N);
my $lhaFindFirst = new Win32::API("unlha32",  "UnlhaFindFirst", [N, P, P], N);
my $lhaFindNext  = new Win32::API("unlha32",  "UnlhaFindNext",  [N, P], N);
my $lhaCloseArc  = new Win32::API("unlha32",  "UnlhaCloseArchive",  [N], N);

#4.1 Open
my $nArc = $lhaOpenArc->Call(0, "c:\\kabaya.lzh", 0);

#4.2 FindFirst
$oPack= "\x00" x 558;
my $nRes = $lhaFindFirst->Call($nArc, "*", $oPack);

while($nRes ==0) {
    #unpack structure
    ($nSize, $nCmpSize, $nCrc, $nUFlag, $nOStype, $iRatio, $iDate, $iTime, 
       $sFileName, $sDummy, $sAttr, $sMode)
       = unpack("LLLLLSSSa513a3a8a8", $oPack);

    $sFileName =~ s/\x00+$//;  #truncate 0x00s
    print "File:$sFileName SIZE:$nSize -> $nCmpSize (", $iRatio / 10, ")\n";
    #Formating (date, time)
    $iNen  = (($iDate>>9) & 127) + 1980; # Top  7 Bits : Years from 1980
    $iTuki = ($iDate>>5) & 15;	        # Next 4 Bits : Months
    $iHi   = $iDate & 31;	                # Last 5 Bits : Days
    $iHour = ($iTime>>11) & 31;          # Top  5 Bits : Hours
    $iMin  = ($iTime>>5)  & 63;          # Next 6 Bits: Minutes
    $iSec  = ($iTime & 31) * 2;          # Last 5 Bits: Seconds / 2
#    printf "  Date:%4d/%2d/%2d %2d:%02d:%02d\n", 
#                    $iNen, $iTuki, $iHi, $iHour, $iMin, $iSec;

    #    print "CRC :$nCrc FLAG:$nUFlag OS  :$nOStype\n";
    #    print "Attr:$sAttr Mode:$sMode\n";

    #4.3 Get Next Information?iFindNext?j
    $nRes = $lhaFindNext->Call($nArc, $oPack);
}
#4.4 Close
$lhaCloseArc->Call($nArc);

Results:

C:\User>perl lha.pl
Ver: 126
Count: 15

Creating archive : c:/kabaya.lzh

Frozen   ==>  43% index.htm
Frozen   ==>  47% prm.htm
Frozen   ==>  14% unlharef.htm
Frozen   ==>  59% texp.htm
Frozen   ==>  29% perlmail.htm
Frozen   ==>  44% index.htm
Frozen   ==>  24% ppm.htm
Frozen   ==>  28% perlora.htm
Frozen   ==>  33% rcvmail.htm


Extracting from archive : c:/kabaya.lzh

mkdir  c:/lhaext/Nifty
Melted   index.htm                  
Melted   prm.htm                    
mkdir  c:/lhaext/Nifty/v150
Melted   unlharef.htm               
Melted   texp.htm                   
mkdir  c:/lhaext/Nifty/PerlTips
Melted   perlmail.htm               
Melted   index.htm                  
Melted   ppm.htm                    
Melted   perlora.htm                
Melted   rcvmail.htm                


File:Nifty/index.htm SIZE:3029 -> 1314 (43.4)
File:Nifty/prm.htm SIZE:3259 -> 1551 (47.6)
File:Nifty/v150/unlharef.htm SIZE:61353 -> 8904 (14.5)
File:Nifty/texp.htm SIZE:1538 -> 920 (59.8)
File:Nifty/PerlTips/perlmail.htm SIZE:18760 -> 5574 (29.7)
File:Nifty/PerlTips/index.htm SIZE:2331 -> 1040 (44.6)
File:Nifty/PerlTips/ppm.htm SIZE:14902 -> 3589 (24.1)
File:Nifty/PerlTips/perlora.htm SIZE:29187 -> 8168 (28)
File:Nifty/PerlTips/rcvmail.htm SIZE:15563 -> 5151 (33.1)                   

C:\User>

 


See Also