unRAR wrapper/include

Share your advanced PureBasic knowledge/code with the community.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

unRAR wrapper/include

Post by ts-soft »

New Version of my unRAR-wrapper/include.
Support ASCII/Unicode/x86/x64 Windows Only

please download the unrar DLL here: http://www.rarlab.com/rar/UnRARDLL.exe
Unpack or Execute the exe und put the libs and dlls in the same directory as this inlclude.

Code: Select all

;      The unrar.dll library is freeware. This means:
;
;   1. All copyrights To RAR And the unrar.dll are exclusively
;      owned by the author - Alexander Roshal.
;
;   2. The unrar.dll library may be used in any software To handle
;      RAR archives without limitations free of charge.
;
;   3. THE RAR ARCHIVER And THE UNRAR.DLL LIBRARY ARE DISTRIBUTED "AS IS".
;      NO WARRANTY OF ANY KIND IS EXPRESSED Or IMPLIED.  YOU USE AT 
;      YOUR OWN RISK. THE AUTHOR WILL Not BE LIABLE For Data LOSS, 
;      DAMAGES, LOSS OF PROFITS Or ANY OTHER KIND OF LOSS While USING
;      Or MISUSING THIS SOFTWARE.
;
;      Thank you For your interest in RAR And unrar.dll.
;
;
;                                            Alexander L. Roshal

; you can download the required lib and dll at:
; http://www.rarlab.com/rar/UnRARDLL.exe

; the wrapper/include for purebasic is written by Thomas 'ts-soft' Schulz, Berlin Germany

EnableExplicit

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
#unRARlib$ = "unrar.lib"
CompilerElse
#unRARlib$ = "unrar64.lib"
CompilerEndIf

#ERAR_END_ARCHIVE        = 10
#ERAR_NO_MEMORY          = 11
#ERAR_BAD_DATA           = 12
#ERAR_BAD_ARCHIVE        = 13
#ERAR_UNKNOWN_FORMAT     = 14
#ERAR_EOPEN              = 15
#ERAR_ECREATE            = 16
#ERAR_ECLOSE             = 17
#ERAR_EREAD              = 18
#ERAR_EWRITE             = 19
#ERAR_SMALL_BUF          = 20
#ERAR_UNKNOWN            = 21
#ERAR_MISSING_PASSWORD   = 22

#RAR_HEADERFLAG_ENCRYPTED  = %00000100
#RAR_OM_LIST             = 0
#RAR_OM_EXTRACT          = 1
#RAR_OM_LIST_INCSPLIT    = 2

#RAR_SKIP                = 0
#RAR_TEST                = 1
#RAR_EXTRACT             = 2

#RAR_VOL_ASK             = 0
#RAR_VOL_NOTIFY          = 1

#RAR_DLL_VERSION         = 4

Enumeration ; UNRARCALLBACK_MESSAGES
  #UCM_CHANGEVOLUME
  #UCM_PROCESSDATA
  #UCM_NEEDPASSWORD
EndEnumeration

Prototype UNRARCALLBACK(msg, UserData, P1, P2)
Prototype CHANGEVOLPROC(ArcName.s, Mode)
Prototype PROCESSDATAPROC(*Addr, Size)

Structure RARHeaderDataEx
  ArcName.b[1024]
  ArcNameW.w[1024]
  FileName.b[1024]
  FileNameW.w[1024]
  Flags.l
  PackSize.l
  PackSizeHigh.l
  UnpSize.l
  UnpSizeHigh.l
  HostOS.l
  FileCRC.l
  FileTime.l
  UnpVer.l
  Method.l
  FileAttr.l
  *CmtBuf
  CmtBufSize.l
  CmtSize.l
  CmtState.l
  Reserved.l[1024]
EndStructure

Structure RAROpenArchiveDataEx
  *ArcName
  *ArcNameW
  OpenMode.l
  OpenResult.l
  *CmtBuf
  CmtBufSize.l
  CmtSize.l
  CmtState.l
  Flags.l
  *Callback.UNRARCALLBACK
  *UserData
  Reserved.l[28]
EndStructure

Import #unRARlib$
  RAROpenArchiveEx(*ArchiveData.RAROpenArchiveDataEx)
  RARCloseArchive(hArcData)
  RARReadHeaderEx(hArcData, *HeaderData.RARHeaderDataEx)
  RARProcessFile(hArcData, Operation, DestPath.s, DestName.s)
  RARProcessFileW(hArcData, Operation, DestPath.s, DestName.s)
  RARSetCallback(hArcData, *Callback.UNRARCALLBACK, UserData)
  RARSetChangeVolProc(hArcData, *ChangeVolProc.CHANGEVOLPROC)
  RARSetProcessDataProc(hArcData, *ProcessDataProc.PROCESSDATAPROC)
  RARSetPassword(hArcData, Password.p-ascii)
  RARGetDllVersion()
EndImport

Structure RarInfos
  filename.s
  PackSize.l
  UnpSize.l
EndStructure

Procedure RAR_GetInfo(File.s, List rarfiles.RarInfos())
  Protected hRAR, fFile.s
  Protected rarheader.RARHeaderDataEx
  Protected raropen.RAROpenArchiveDataEx
  
  ClearList(rarfiles())
  
  CompilerIf #PB_Compiler_Unicode
  raropen\ArcNameW = @File
  CompilerElse
  raropen\ArcName= @File
  CompilerEndIf
  
  raropen\OpenMode = #RAR_OM_LIST
  
  hRAR = RAROpenArchiveEx(@raropen)
  If hRAR
    While Not RARReadHeaderEx(hRAR, @rarheader)
      CompilerIf #PB_Compiler_Unicode
      fFile = PeekS(@rarheader\FileNameW)
      CompilerElse
      fFile  =PeekS(@rarheader\FileName)
      CompilerEndIf
      AddElement(rarfiles())
      rarfiles()\filename = fFile
      rarfiles()\PackSize = rarheader\PackSize
      rarfiles()\UnpSize = rarheader\UnpSize
      RARProcessFile(hRAR, #RAR_OM_LIST, "", File)
    Wend
    RARCloseArchive(hRAR)
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure RAR_Unpack(rarfile.s, destpath.s = "", password.s = "", *callback = 0, *userdata = 0)
  Protected hRAR
  Protected rarheader.RARHeaderDataEx
  Protected raropen.RAROpenArchiveDataEx
  
  CompilerIf #PB_Compiler_Unicode
  raropen\ArcNameW = @rarfile
  CompilerElse
  raropen\ArcName= @rarfile
  If destpath
    CharToOem_(destpath, destpath)
  EndIf
  CompilerEndIf
  
  raropen\OpenMode = #RAR_OM_EXTRACT
  raropen\Callback = *callback
  raropen\UserData = *userdata

  hRAR = RAROpenArchiveEx(@raropen)
  If hRAR
    RARSetPassword(hRAR, password)
    While Not RARReadHeaderEx(hRAR, @rarheader)
      CompilerIf #PB_Compiler_Unicode
      RARProcessFileW(hRAR, #RAR_EXTRACT, destpath, #NULL$)
      CompilerElse
      RARProcessFile(hRAR, #RAR_EXTRACT, destpath, #NULL$)
      CompilerEndIf
    Wend
    RARCloseArchive(hRAR)
    ProcedureReturn #True
  EndIf
  
  
  ProcedureReturn #False   
EndProcedure

; test
CompilerIf #PB_Compiler_Debugger
NewList rar.RarInfos()
Define File.s = OpenFileRequester("", "", "RAR-Archiv (*.rar)|*.rar", 0)
If File
  If RAR_GetInfo(File, rar())
    ForEach rar()
      Debug rar()\filename
      Debug rar()\PackSize
      Debug rar()\UnpSize
      Debug "-----------------"
    Next
  EndIf
EndIf
CompilerEndIf
// edit
added callback support to RAR_Unpack()
Last edited by ts-soft on Sat Jan 28, 2012 1:57 pm, edited 1 time in total.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: unRAR wrapper/include

Post by Kwai chang caine »

Works great here, thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: unRAR wrapper/include

Post by ts-soft »

added callback-support to RAR_Unpack(), see first posting.

Small Example:

Code: Select all

XIncludeFile "unRAR_Include.pbi"

Procedure RAR_Callback(msg, UserData, P1, P2)

  Select msg
    Case #UCM_NEEDPASSWORD
      Debug "Password needed"
      Debug "--------------"
      ProcedureReturn -1
  EndSelect
  Debug P1
  Debug P2
  Debug "--------------"
EndProcedure

Define File.s = OpenFileRequester("", "", "RAR-Archiv (*.rar)|*.rar", 0)
Define Path.s = PathRequester("Select Destinationpath", "")

If File
  RAR_Unpack(File, Path, "", @RAR_Callback())
EndIf
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: unRAR wrapper/include

Post by Kwai chang caine »

Thanks THOMAS 8)
But i have a little problem
#UCM_NEEDPASSWORD :(
ImageThe happiness is a road...
Not a destination
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: unRAR wrapper/include

Post by ts-soft »

This constant is defined in the updated source in the first post.
For using read the documentation included in the download of unrar.dll!

Greetings - Thomas

// edit
better example:

Code: Select all

XIncludeFile "unRAR_Include.pbi"

Procedure RAR_Callback(msg, UserData, P1, P2)

  Select msg
    Case #UCM_NEEDPASSWORD
      Protected PWD.s = InputRequester("", "Password needed", "")
      If PWD
        PokeS(P1, PWD, -1, #PB_Ascii)
      Else
        ProcedureReturn -1
      EndIf
    
    Case #UCM_CHANGEVOLUME
      Select P2
        Case #RAR_VOL_ASK
          MessageRequester("", PeekS(P1, -1, #PB_Ascii) + #LF$ + "is missing", #MB_ICONERROR)
          ProcedureReturn -1
        Case #RAR_VOL_NOTIFY
          ProcedureReturn 0
      EndSelect
    Case #UCM_PROCESSDATA
      ; Process unpacked data
      ; for more information read the documentation "RARCallback.htm"
  EndSelect

EndProcedure

Define File.s = OpenFileRequester("", "", "RAR-Archiv (*.rar)|*.rar", 0)
Define Path.s = PathRequester("Select Destinationpath", "")

If File
  RAR_Unpack(File, Path, "", @RAR_Callback())
EndIf
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: unRAR wrapper/include

Post by Kwai chang caine »

Works like a charm, thanks again for all your greats works 8)
ImageThe happiness is a road...
Not a destination
User avatar
graph100
Enthusiast
Enthusiast
Posts: 115
Joined: Tue Aug 10, 2010 3:17 pm

Re: unRAR wrapper/include

Post by graph100 »

ts-soft !! this is just great !

but (I always have some but, I'm sorry :mrgreen: ), I have a problem with the use :?
here it is :

I'm developing a software (free of charge) to view image which are contained in *.zip or in *.cbr or *.cbz
These last two are in reality *.rar

Actually with the help of your MiniZip include I managed to add the zip support in my software (many many thanks for that ^^. And now I think of it, I will immediately add the credit of zip support ! (I forgot -_- ))

So now I've focus on the rar support. But the problem is : with the Zip lib, reading one file in the zip, extracting it in the memory, and using it with CatchImage() for exemple, was possible.
For now, with the unrar code, it's not possible :?
Or maybe I didn't understand something in the help ?

Do you think it's possible to use these lib with a function like that :
*memory_pointer = RAR_CatchFile(file.s, file_name.s)
_________________________________________________
My Website : CeriseCode (Warning : perpetual changes & not completed ;))
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: unRAR wrapper/include

Post by ts-soft »

I don't know, the documentation is not the best and my english is bad.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
graph100
Enthusiast
Enthusiast
Posts: 115
Joined: Tue Aug 10, 2010 3:17 pm

Re: unRAR wrapper/include

Post by graph100 »

well ^^

I've done a little self ass-kicking, and here is my little contribution :

Code: Select all

Procedure __Callback_RAR(msg, UserData, P1, P2)
	
	Select msg
    Case #UCM_NEEDPASSWORD
      Protected PWD.s = InputRequester("", "Password needed", "")
      If PWD
        PokeS(P1, PWD, -1, #PB_Ascii)
      Else
        ProcedureReturn -1
      EndIf
   
    Case #UCM_CHANGEVOLUME
      Select P2
        Case #RAR_VOL_ASK
          MessageRequester("", PeekS(P1, -1, #PB_Ascii) + #LF$ + "is missing", #MB_ICONERROR)
          ProcedureReturn -1
        Case #RAR_VOL_NOTIFY
          ProcedureReturn 0
      EndSelect
      
    Case #UCM_PROCESSDATA
      ; Process unpacked data
      ; for more information read the documentation "RARCallback.htm"
      
      CopyMemory(P1, PeekI(UserData), P2)
      PokeI(UserData, PeekI(UserData) + P2)
      
      
  EndSelect

EndProcedure

Procedure.i RAR_CatchFile(rarfile.s, FileNumber.l, password.s = "")
	Protected hRAR, *mem.i, *mem_1.i, res, a
	Protected rarheader.RARHeaderDataEx
	Protected raropen.RAROpenArchiveDataEx
	
	CompilerIf #PB_Compiler_Unicode
		raropen\ArcNameW = @rarfile
	CompilerElse
		raropen\ArcName = @rarfile
	CompilerEndIf
	
	raropen\OpenMode = #RAR_OM_EXTRACT
	raropen\Callback = @__Callback_RAR()
	raropen\UserData = @*mem_1
	
	
	hRAR = RAROpenArchiveEx(@raropen)
	
	If hRAR = 0 : ProcedureReturn 0 : EndIf
	
	RARSetPassword(hRAR, password)
	
	For a = 1 To FileNumber - 1
		If RARReadHeaderEx(hRAR, @rarheader) = #ERAR_END_ARCHIVE : ProcedureReturn 0 : EndIf
		
		CompilerIf #PB_Compiler_Unicode
			RARProcessFileW(hRAR, #RAR_SKIP, #NULL$, #NULL$)
		CompilerElse
			RARProcessFile(hRAR, #RAR_SKIP, #NULL$, #NULL$)
		CompilerEndIf
	Next
	
	If RARReadHeaderEx(hRAR, @rarheader) : ProcedureReturn 0 : EndIf
	If rarheader\FileAttr & #FILE_ATTRIBUTE_DIRECTORY : ProcedureReturn 0 : EndIf ; on ne peux extraire en mémoire un répertoire
	
	*mem = AllocateMemory(rarheader\UnpSize)
	
	If *mem = 0 : ProcedureReturn 0 : EndIf
	
	*mem_1 = *mem
	
	CompilerIf #PB_Compiler_Unicode
		res = RARProcessFileW(hRAR, #RAR_TEST, #NULL$, #NULL$)
	CompilerElse
		res = RARProcessFile(hRAR, #RAR_TEST, #NULL$, #NULL$)
	CompilerEndIf
	
	If res
		FreeMemory(*mem)
		
		ProcedureReturn 0
	EndIf
	
	RARCloseArchive(hRAR)
	
	ProcedureReturn *mem
EndProcedure

Add the procedure to your code to work, I have made an exemple, but it need an include of my own to work nicely (it quickly display the image in a rar file, without unpacking them on the disk !)

Thanks to that I'm able to finish a long awaited feature in my project :D

Thanks again Ts !
_________________________________________________
My Website : CeriseCode (Warning : perpetual changes & not completed ;))
Post Reply