Page 1 of 1

unRAR wrapper/include

Posted: Fri Jan 27, 2012 6:23 pm
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()

Re: unRAR wrapper/include

Posted: Sat Jan 28, 2012 12:39 pm
by Kwai chang caine
Works great here, thanks for sharing 8)

Re: unRAR wrapper/include

Posted: Sat Jan 28, 2012 1:11 pm
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

Re: unRAR wrapper/include

Posted: Sun Jan 29, 2012 8:51 pm
by Kwai chang caine
Thanks THOMAS 8)
But i have a little problem
#UCM_NEEDPASSWORD :(

Re: unRAR wrapper/include

Posted: Sun Jan 29, 2012 9:18 pm
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

Re: unRAR wrapper/include

Posted: Tue Jan 31, 2012 3:18 pm
by Kwai chang caine
Works like a charm, thanks again for all your greats works 8)

Re: unRAR wrapper/include

Posted: Sun Apr 29, 2012 5:44 pm
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)

Re: unRAR wrapper/include

Posted: Sun Apr 29, 2012 8:11 pm
by ts-soft
I don't know, the documentation is not the best and my english is bad.

Re: unRAR wrapper/include

Posted: Sun Apr 29, 2012 10:27 pm
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 !