Attribute VB_Name = "mRarFiles"
Option Explicit ' Wrapper for unrar.dll freely available from www.rarlab.com

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
'  32-bit Windows dynamic-link library providing file extraction from RAR archives
' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

' 5.1 and newer

Private Enum ERAR
   ERAR_SUCCESS = 0           ' Success
   ERAR_NO_COMMENTS = 0       ' Comments not present
   ERAR_COMMENTS_READ = 1     ' Comments read completely
   ERAR_END_ARCHIVE = 10      ' End of archive
   ERAR_NO_MEMORY = 11        ' Not enough memory
   ERAR_BAD_DATA = 12         ' Archive header broken, file CRC error, broken comment
   ERAR_BAD_ARCHIVE = 13      ' File is not valid RAR archive
   ERAR_UNKNOWN_FORMAT = 14   ' Unknown archive format, unknown comment format, unknown encryption used for archive headers
   ERAR_EOPEN = 15            ' Volume open error, file open error
   ERAR_ECREATE = 16          ' File create error
   ERAR_ECLOSE = 17           ' Archive close error
   ERAR_EREAD = 18            ' Read error
   ERAR_EWRITE = 19           ' Write error
   ERAR_SMALL_BUF = 20        ' Buffer too small, comments not completely read
   ERAR_UNKNOWN = 21          ' All errors which do not have a special ERAR code
   ERAR_MISSING_PASSWORD = 22 ' Password was not provided for encrypted file header
   ERAR_EREFERENCE = 23       ' When attempting to unpack a reference record (see RAR -oi switch), source file for this reference was not found. Entire archive needs to be unpacked to properly create file references. This error is returned when attempting to unpack the reference record without its source file
   ERAR_BAD_PASSWORD = 24     ' Entered password is invalid. This code is returned only for archives in RAR 5.0 format
End Enum

Private Enum eOpenMode      ' RAROpenArchiveData struct OpenMode flags
   RAR_OM_LIST = 0          ' Open archive for reading file headers only
   RAR_OM_EXTRACT = 1       ' Open archive for testing and extracting files
   RAR_OM_LIST_INCSPLIT = 2 ' Open archive for reading file headers only. If you open an archive in such mode, RARReadHeaderEx will return all file headers, including those with "file continued from previous volume" flag. In case of RAR_OM_LIST such headers are automatically skipped. So if you process RAR volumes in RAR_OM_LIST_INCSPLIT mode, you will get several file header records for the same file if the file is split between volumes. For such files only the last file header record will contain the correct file CRC and if you wish to get the correct packed size, you need to sum up packed sizes of all parts
End Enum

Private Enum eFileOp ' RARProcessFile Operation flags
   RAR_SKIP = 0      ' Move to the next file in the archive. If archive is solid and RAR_OM_EXTRACT mode was set when the archive was opened, the current file is analyzed and operation is performed slower than a simple seek
   RAR_TEST = 1      ' Test the current file and move to the next file in the archive. If the archive was opened in RAR_OM_LIST mode, the operation is equal to RAR_SKIP
   RAR_EXTRACT = 2   ' Extract the current file and move to the next file in the archive. If the archive was opened with RAR_OM_LIST mode, the operation is equal to RAR_SKIP
End Enum

Private Enum eArchiveDataFlags
   ArchiveVolumeAttribute = &H1&
   ArchiveCommentPresent = &H2&
   ArchiveLockAttribute = &H4&
   SolidArchiveAttribute = &H8&
   NewVolumeNamingScheme = &H10& ' volname.partN.rar
   AuthenticityInfoPresent = &H20&
   RecoveryRecordPresent = &H40&
   BlockHeadersEncrypted = &H80&
   ArchiveIsFirstVolume = &H100& ' set only by RAR 3.0 and later
End Enum

Private Enum eHeaderDataFlags
   RHDF_SPLITBEFORE = &H1& ' File continued from previous volume
   RHDF_SPLITAFTER = &H2&  ' File continued on next volume
   RHDF_ENCRYPTED = &H4&   ' File encrypted with password
   RHDF_RESERVED = &H8&    ' Reserved
   RHDF_SOLID = &H10&      ' Compression data of previous files is used (solid flag)
   RHDF_DIRECTORY = &H20&  ' Directory entry
   ' bits 7 6 5    ' This information may be obsolete
   '      0 0 0    ' Dictionary size   64 Kb
   '      0 0 1    ' Dictionary size  128 Kb
   '      0 1 0    ' Dictionary size  256 Kb
   '      0 1 1    ' Dictionary size  512 Kb
   '      1 0 0    ' Dictionary size 1024 Kb
   '      1 0 1    ' Dictionary size 2048 KB
   '      1 1 0    ' Dictionary size 4096 KB
   '      1 1 1    ' File is directory
   ' Other bits are reserved
End Enum

Private Enum eHost ' RARHeaderDataEx struct HostOS flags
   eDOS = 0        ' MS DOS
   eOS2 = 1        ' OS/2
   eWin32 = 2      ' Win32
   eUnix = 3       ' Unix
End Enum

Private Enum ePackingMethod
   StoringNoCompression = &H30&
   FastestCompression = &H31&
   FastCompression = &H32&
   NormalCompression = &H33&
   GoodCompression = &H34&
   BestCompression = &H35&
End Enum

Private Enum UCM        ' Callback messages
   UCM_CHANGEVOLUME = 0 ' Process volume change
   UCM_PROCESSDATA = 1  ' Process unpacked data
   UCM_NEEDPASSWORD = 2 ' DLL needs a password to process archive
   UCM_CHANGEVOLUMEW = 3
   UCM_NEEDPASSWORDW = 4
End Enum

Private Enum RAR_VOL  ' Callback Change Volume mode
   RAR_VOL_ASK = 0    ' Required volume is absent. The callback function should prompt user
   RAR_VOL_NOTIFY = 1 ' Required volume is successfully opened. This is a notification call and volume name modification is not allowed
End Enum

Enum eHashType
   RAR_HASH_NONE = 0   ' No checksum or unknown hash function type
   RAR_HASH_CRC32 = 1  ' CRC32
   RAR_HASH_BLAKE2 = 2 ' BLAKE2sp
End Enum

Enum eFileSystemRedirection
   NoRedirectionUsualFile = 0&
   UnixSymbolicLink = 1&
   WindowsSymbolicLink = 2&
   WindowsJunction = 3&
   HardLink = 4&
   FileRefSavedWithDashoiSwitch = 5&
End Enum

Private Type RAROpenArchiveDataEx
   ArcName As String    ' Input  - NULL terminated string containing the archive name or NULL if Unicode name is specified
   SpArcNameW As Long   ' Input  - StrPtr to NULL terminated Unicode string containing the archive name or NULL if ArcName specified
   OpenMode As Long     ' Input  - eOpenMode parameter - RAR_OM_LIST, RAR_OM_EXTRACT or RAR_OM_LIST_INCSPLIT
   OpenResult As Long   ' Output - ERAR_SUCCESS, ERAR_NO_MEMORY, ERAR_BAD_DATA, ERAR_UNKNOWN_FORMAT, ERAR_EOPEN, ERAR_BAD_PASSWORD
   CmtBuf As String     ' Input  - Buffer for archive comments. Maximum size is limited to 64Kb. Comment text is NULL terminated. If the comment text is larger than the buffer size, the comment text will be truncated. If CmtBuf is set to NULL, comments will not be read
   CmtBufSize As Long   ' Input  - Size of buffer for archive comments
   CmtSize As Long      ' Output - Size of comments actually read into the buffer, cannot exceed CmtBufSize
   CmtState As Long     ' Output - ERAR_NO_COMMENTS, ERAR_COMMENTS_READ, ERAR_NO_MEMORY, ERAR_BAD_DATA, ERAR_SMALL_BUF
   Flags As Long        ' Output - Combination of eArchiveDataFlags bit flags
   Callback As Long     ' Input  - Address of user defined callback function to process UnRAR events. Set to NULL if you do not want to define the callback function. The callback function is required to process multivolume and encrypted archives properly
   UserData As Long     ' Input  - User defined value, which will be passed to the callback function
   Reserved(27) As Long ' Reserved for future use. Must be zeroes (VB does this for us)
End Type

Private Type RARHeaderDataEx
   ArcName(1023) As Byte      ' Output - NULL terminated current archive name. May be used to determine the current volume name
   ArcNameW(1023) As Integer  ' Output - NULL terminated current archive Unicode name. May be used to determine the current volume name
   FileName(1023) As Byte     ' Output - NULL terminated file name in OEM (DOS) encoding
   FileNameW(1023) As Integer ' Output - NULL terminated file name in Unicode
   Flags As Long              ' Output - Contains eHeaderDataFlags bit flags
   PackSize As Long           ' Output - Lower 32 bits of packed file size or size of the file part if file was split between volumes
   PackSizeHigh As Long       ' Output - Higher 32 bits of packed file size or size of the file part if file was split between volumes
   UnpSize As Long            ' Output - Lower 32 bits of unpacked file size
   UnpSizeHigh As Long        ' Output - Higher 32 bits of unpacked file size
   HostOS As Long             ' Output - eHost operating system used to create the archive
   FileCRC As Long            ' Output - Unpacked file CRC. It should not be used for file parts which were split between volumes. In case of file parts split between volumes only the last part contains the correct CRC and it is accessible only in RAR_OM_LIST_INCSPLIT listing mode
   iFileTime As Integer '}    ' Output - Contains 16-bit time in standard MS DOS format
   iFileDate As Integer '}    ' Output - Contains 16-bit date in standard MS DOS format
   UnpVer As Long             ' Output - RAR version needed to extract file. It is encoded as 10 * Major version + minor version
   Method As Long             ' Output - Packing method ePackingMethod
   FileAttr As Long           ' Output - File attributes
   CmtBuf As String '*        ' Input  - Buffer for file comments. Leave this field vbNullString. Not implemented in current unrar.dll version. Compatibility with older versions only
   CmtBufSize As Long         ' Input  - Size of buffer for archive comments. Leave this field 0. File comment support is not implemented in current unrar.dll version
   CmtSize As Long            ' Output - Size of comments actually read into the buffer, always equal to 0. File comment support is not implemented in current unrar.dll version
   CmtState As Long           ' Output - Comment state, always equal to 0. File comment support is not implemented in current unrar.dll version
   DictSize As Long           ' Output - Size of file compression dictionary in kilobytes
   HashType As Long           ' Output - Type of hash function used to protect file data integrity. Can be RAR_HASH_NONE (no checksum or unknown hash function type), RAR_HASH_CRC32 (CRC32) or RAR_HASH_BLAKE2 (BLAKE2sp)
   Hash(31) As Byte           ' Output - If HashType is equal to RAR_HASH_BLAKE2, this array contains 32 bytes of file data BLAKE2sp hash
   RedirType As Long          ' Output - Type of file system redirection
   RedirName As String        ' Input/Output - Buffer to receive file system redirection target name, such as target of symbolic link or file reference. It is returned as stored in archive and its value might be not immediately applicable for further use. For example, you may need to remove \??\ or UNC\ prefixes for Windows junctions or prepend the extraction destination path
   RedirNameSize As Long      ' Input  - Size of buffer specified in RedirName. Ignored if RedirName is NULL
   DirTarget As Long          ' Output - Non-zero if RedirType is symbolic link and RedirName points to directory
   Reserved(993) As Long      ' Reserved for future use. The entire array must be filled with zeroes before passing RARHeaderDataEx structure to RARReadHeaderEx
End Type

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

' RAROpenArchiveEx
'  Open RAR archive and allocate memory structures.
'  ArchiveData points to RAROpenArchiveDataEx structure.
'  Returns archive handle or NULL on error.

Private Declare Function RAROpenArchiveEx Lib "unrar" (ArchiveData As RAROpenArchiveDataEx) As Long 'Handle

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

' RARCloseArchive
'  Close RAR archive and release allocated memory. It must be called when archive
'  processing is finished, even if the archive processing was stopped due to an error.
'  hArcData contains the archive handle obtained from the RAROpenArchive function call.
'  Returns ERAR_SUCCESS on success or ERAR_ECLOSE archive close error.

Private Declare Function RARCloseArchive Lib "unrar" (ByVal hArcData As Long) As Long

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

' RARReadHeaderEx
'  Read header of file in archive.
'  hArcData contains the archive handle obtained from RAROpenArchiveEx.
'  HeaderData points to RARHeaderDataEx structure.
'  Returns ERAR_SUCCESS on success, ERAR_END_ARCHIVE end of archive, or ERAR_BAD_DATA file header broken.

Private Declare Function RARReadHeaderEx Lib "unrar" (ByVal hArcData As Long, HeaderData As RARHeaderDataEx) As Long

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

' RARProcessFileW
'  Performs user defined action and moves the current position to the next archived file.
'  Extracts or tests the current file opened in RAR_OM_EXTRACT mode and sets the position to the next file.
'  If the mode RAR_OM_LIST is set, then a call to this function will simply skip the position to the next file.
'  hArcData contains the archive handle obtained from RAROpenArchiveEx.
'  Operation - File eFileOp operation, RAR_SKIP, RAR_TEST, RAR_EXTRACT.
'  DestPath - Unicode destination extract directory. If DestPath is NULL extracts to the current directory. This parameter has meaning only if DestName is NULL.
'  DestName - Unicode full path and name of the file to be extracted or NULL. If DestName is defined (not NULL) it overrides the original file name saved in the archive and DestPath setting.
'  Both DestPath and DestName must be Unicode.
'  Returns ERAR_SUCCESS, ERAR_BAD_DATA, (ERAR_BAD_ARCHIVE), ERAR_UNKNOWN_FORMAT, ERAR_EOPEN, ERAR_ECREATE, ERAR_ECLOSE, ERAR_EREAD, ERAR_EWRITE, ERAR_NO_MEMORY, ERAR_EREFERENCE or ERAR_BAD_PASSWORD.
'  Note: if you wish to cancel extraction, return -1 when processing UCM_PROCESSDATA callback message.

Private Declare Function RARProcessFileW Lib "unrar" (ByVal hArcData As Long, ByVal Operation As Long, ByVal SpDestPath As Long, ByVal SpDestName As Long) As Long

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Private Declare Function RARGetDllVersion Lib "unrar" () As Long
Private Const RAR_DLL_VERSION = 7&

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

'HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData);
'HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData);
'int    PASCAL RARCloseArchive(HANDLE hArcData);
'int    PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
'int    PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
'int    PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
'int    PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
'void   PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
'void   PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
'void   PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
'void   PASCAL RARSetPassword(HANDLE hArcData,char *Password);
'int    PASCAL RARGetDllVersion();

'typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
'typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
'typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Public Type tRarFiles
  ftDate As Currency
   sSpec As String
   CRC32 As Long
   PSize As Long
   USize As Long
   Attrb As Long
End Type

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Private Declare Function RTrimZVpSp Lib "oleaut32" Alias "SysReAllocString" (ByVal VarPtr_Str As Long, ByVal StrPtr_Str2copy As Long) As Long

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Private Declare Function DosDateTimeToFileTime Lib "kernel32" (ByVal lpDosDate As Long, ByVal lpDosTime As Long, lpFileTime As Currency) As Long
Private Declare Function SetCurrentDirectory Lib "kernel32" Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long
Private Declare Sub CopyMemByV Lib "kernel32" Alias "RtlMoveMemory" (ByVal lpDest As Long, ByVal lpSrc As Long, ByVal lLenB As Long)
Private m_Size As Long

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Public Function GetRarFileInfo(sRarFile As String, tFiles() As tRarFiles) As Long
   On Error GoTo ErrHandler ' Return file count on success, zero on error

   Dim tRar As RAROpenArchiveDataEx
   Dim tHeader As RARHeaderDataEx

   Dim hRar As Long
   Dim cnt As Long
   Dim rc As Long

   tRar.OpenMode = RAR_OM_LIST ' Fill the RAR header structure
   tRar.SpArcNameW = StrPtr(sRarFile)

   hRar = RAROpenArchiveEx(tRar) ' Open the archive
   If tRar.OpenResult <> ERAR_SUCCESS Then Exit Function

   ReDim tFiles(50) As tRarFiles
   rc = RARReadHeaderEx(hRar, tHeader) ' Read first file header

   Do While rc = ERAR_SUCCESS
      If cnt > UBound(tFiles) Then ReDim Preserve tFiles(cnt + 50) As tRarFiles

      With tHeader ' Get the current file info
         RTrimZVpSp VarPtr(tFiles(cnt).sSpec), VarPtr(.FileNameW(0))
         DosDateTimeToFileTime .iFileDate, .iFileTime, tFiles(cnt).ftDate
         tFiles(cnt).CRC32 = .FileCRC
         tFiles(cnt).PSize = .PackSize
         tFiles(cnt).USize = .UnpSize
         tFiles(cnt).Attrb = .FileAttr ' Includes folders
      End With
      cnt = cnt + 1&

      If RARProcessFileW(hRar, RAR_SKIP, 0&, 0&) <> ERAR_SUCCESS Then Exit Do

      rc = RARReadHeaderEx(hRar, tHeader)  ' Read next file header
   Loop

ErrHandler:
   RARCloseArchive hRar
   If cnt Then
      ReDim Preserve tFiles(cnt - 1) As tRarFiles ' Zero based
   Else
      Erase tFiles
   End If
   GetRarFileInfo = cnt
End Function

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Public Function UnpackFile(sRarFile As String, sRelFile As String, sExtractDir As String) As Long
   On Error GoTo ErrHandler ' Return -1 on success, zero on error

   Dim tRar As RAROpenArchiveDataEx
   Dim tHeader As RARHeaderDataEx

   Dim sCurDir As String
   Dim sFile As String
   Dim hRar As Long
   Dim rc As Long

   tRar.OpenMode = RAR_OM_EXTRACT ' Fill the RAR header structure
   tRar.SpArcNameW = StrPtr(sRarFile)

   hRar = RAROpenArchiveEx(tRar)  ' Open the archive
   If tRar.OpenResult <> ERAR_SUCCESS Then Exit Function

   sCurDir = CurDir$ ' Bug fix - packed folders created empty in curdir
   SetCurrentDirectory CreateTempDir

   rc = RARReadHeaderEx(hRar, tHeader) ' Read first file header

   Do While rc = ERAR_SUCCESS

      ' Get the current file name
      RTrimZVpSp VarPtr(sFile), VarPtr(tHeader.FileNameW(0))

      If sFile = sRelFile Then ' Relative file spec as recorded in RAR archive

         rc = RARProcessFileW(hRar, RAR_EXTRACT, StrPtr(sExtractDir), 0&) ' sDir
         UnpackFile = (rc = ERAR_SUCCESS) ' Return -1 on success, zero on error
         Exit Do

      Else
         If RARProcessFileW(hRar, RAR_SKIP, 0&, 0&) <> ERAR_SUCCESS Then Exit Do
      End If

      rc = RARReadHeaderEx(hRar, tHeader) ' Read next file header
   Loop

   SetCurrentDirectory sCurDir

ErrHandler:
   RARCloseArchive hRar
End Function

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Public Function UnpackToMemory(sRarFile As String, sRelFile As String, sRetFileText As String) As Long
   On Error GoTo ErrHandler ' Return file size on success, zero on error

   Dim tRar As RAROpenArchiveDataEx
   Dim tHeader As RARHeaderDataEx

   Dim sCurDir As String
   Dim sFile As String
   Dim hRar As Long
   Dim rc As Long

   With tRar
     .OpenMode = RAR_OM_EXTRACT ' Fill the RAR header structure
     .SpArcNameW = StrPtr(sRarFile)
     .Callback = GetAddrOf(AddressOf UnRARCallback) ' Set the callback
     .UserData = VarPtr(sRetFileText)
   End With

   hRar = RAROpenArchiveEx(tRar)  ' Open the archive
   If tRar.OpenResult <> ERAR_SUCCESS Then Exit Function

   sCurDir = CurDir$ ' Bug fix - packed folders created empty in curdir
   SetCurrentDirectory CreateTempDir

   m_Size = 0&
   rc = RARReadHeaderEx(hRar, tHeader) ' Read first file header

   Do While rc = ERAR_SUCCESS

      ' Get the current file name
      RTrimZVpSp VarPtr(sFile), VarPtr(tHeader.FileNameW(0))

      If sFile = sRelFile Then ' Relative file spec as recorded in RAR archive

         rc = RARProcessFileW(hRar, RAR_EXTRACT, 0&, 0&): Exit Do

      Else
         If RARProcessFileW(hRar, RAR_SKIP, 0&, 0&) <> ERAR_SUCCESS Then Exit Do
      End If

      rc = RARReadHeaderEx(hRar, tHeader) ' Read next file header
   Loop

   SetCurrentDirectory sCurDir
   UnpackToMemory = m_Size ' Return file size on success, zero on error

ErrHandler:
   RARCloseArchive hRar
End Function

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

'Private Function UnRARCallback(ByVal Msg As Long, ByVal UserData As Long, ByVal lParam1 As Long, ByVal lParam2 As Long) As Long

Private Function UnRARCallback(ByVal Msg As Long, FileText As String, ByVal StringPtr As Long, ByVal Length As Long) As Long
   Dim aFileTxt() As Byte ' Return a positive value to continue process or -1 to cancel the archive operation

   If Msg = UCM_PROCESSDATA Then ' Process unpacked data

      ReDim aFileTxt(1 To Length) As Byte
      CopyMemByV VarPtr(aFileTxt(1)), StringPtr, Length
      FileText = StrConv(aFileTxt, vbUnicode)

      m_Size = Length
      UnRARCallback = -1& ' Cancel extraction to disk
   End If
End Function

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Private Function GetAddrOf(ByVal lpFunc As Long) As Long
    GetAddrOf = lpFunc
End Function

' =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

' Rd :)
