322 lines
12 KiB
OpenEdge ABL
322 lines
12 KiB
OpenEdge ABL
VERSION 1.0 CLASS
|
|
BEGIN
|
|
MultiUse = -1 'True
|
|
Persistable = 0 'NotPersistable
|
|
DataBindingBehavior = 0 'vbNone
|
|
DataSourceBehavior = 0 'vbNone
|
|
MTSTransactionMode = 0 'NotAnMTSObject
|
|
END
|
|
Attribute VB_Name = "CTKUnrar"
|
|
Attribute VB_GlobalNameSpace = False
|
|
Attribute VB_Creatable = True
|
|
Attribute VB_PredeclaredId = False
|
|
Attribute VB_Exposed = True
|
|
Option Explicit
|
|
|
|
'// ADDED
|
|
'// Converts strings from Unicode to OEM encoding to make sure
|
|
'// certain characters in paths are handled properly by RARProcessFile
|
|
Private Declare Sub CharToOem Lib "user32" Alias "CharToOemA" _
|
|
(ByVal StrFrom As String, ByVal StrTo As String)
|
|
|
|
'// ADDED
|
|
'// For use by LongToUnsigned
|
|
Private Const OFFSET_4 = 4294967296#
|
|
|
|
Event OpenError(lngErrorNo As Long, strErrorMsg As String, strFilename As String)
|
|
Event ProcessError(lngErrorNo As Long, strErrorMsg As String, strFilename As String)
|
|
Event CommentError(lngErrorNo As Long, strErrorMsg As String, strFilename As String)
|
|
Event CommentFound(strFilename As String, strComment As String)
|
|
Event ProcessingFile(strFilename As String, dblFileSize As Double, datFileTime As Date, intMajorVer As Integer, intMinorVer As Integer, lngPackingMethod As Long, lngFileAttr As Long)
|
|
Event NextVolumne(strFilename As String, ByRef blnContinue As Boolean)
|
|
Event MissingFile(strFilename As String, ByRef strNewFilename As String)
|
|
Event MissingPassword(ByRef strNewPassword As String)
|
|
Event Progress(dblFileSize As Double, dblExtracted As Double)
|
|
|
|
' Private variables
|
|
Private m_dblLastFileSize As Double
|
|
Private m_dblLastFileUnpacked As Double
|
|
Private m_intLastPercentStep As Integer
|
|
Private m_blnPasswordProtected As Boolean
|
|
' Properties
|
|
Private m_intProgressSteps As Integer
|
|
Private m_strLastErrorMsg As String
|
|
|
|
Public Function LongToUnsigned(Value As Long) As Double
|
|
'// ADDED
|
|
'// This functions makes sure the unsigned integers
|
|
'// that unrar.dll returns are handled properly as
|
|
'// VB does not support unsigned integers natively
|
|
'// See KB article 189323 for more info
|
|
'// http://support.microsoft.com/?kbid=189323
|
|
'
|
|
'The function takes an unsigned Long from an API and
|
|
'converts it to a Double for display or arithmetic purposes
|
|
'
|
|
If Value < 0 Then
|
|
LongToUnsigned = Value + OFFSET_4
|
|
Else
|
|
LongToUnsigned = Value
|
|
End If
|
|
'
|
|
End Function
|
|
Private Sub Class_Initialize()
|
|
m_intProgressSteps = 4
|
|
m_strLastErrorMsg = ""
|
|
m_blnPasswordProtected = False
|
|
End Sub
|
|
|
|
Private Sub Class_Terminate()
|
|
'
|
|
End Sub
|
|
|
|
Public Function ListRarFiles(strRarFile As String, arrstrFilenames() As String, Optional strPassword As String = "") As Boolean
|
|
ListRarFiles = HandleRarFiles(strRarFile, OP_LIST, arrstrFilenames, , strPassword)
|
|
End Function
|
|
|
|
Public Function TestRarFiles(strRarFile As String, Optional strPassword As String = "") As Boolean
|
|
TestRarFiles = HandleRarFiles(strRarFile, OP_TEST, , , strPassword)
|
|
End Function
|
|
|
|
Public Function ExtractRarFiles(strRarFile As String, strDestPath As String, Optional strPassword As String = "") As Boolean
|
|
ExtractRarFiles = HandleRarFiles(strRarFile, OP_EXTRACT, , strDestPath, strPassword)
|
|
End Function
|
|
|
|
Private Function HandleRarFiles(strRarFile As String, opMode As RarOperations, Optional arrstrFilenames As Variant, Optional strDestPath As String = "", Optional strPassword As String = "") As Boolean
|
|
Dim uRAR As RAROpenArchiveData
|
|
Dim uHeaderEx As RARHeaderDataEx
|
|
Dim lngRarHandle As Long
|
|
Dim intStatus As Integer
|
|
Dim intReturn As Integer
|
|
Dim strCurrentFilename As String
|
|
Dim strLastFilename As String
|
|
Dim lngpFilenames As Long
|
|
Dim strTmp As String
|
|
|
|
HandleRarFiles = False
|
|
|
|
'// ADDED
|
|
'// See API declaration
|
|
CharToOem strDestPath, strDestPath
|
|
|
|
' Fill the rar header structure
|
|
uRAR.ArcName = strRarFile
|
|
uRAR.CmtBuf = Space(16384)
|
|
uRAR.CmtBufSize = 16384
|
|
If opMode = OP_LIST Then
|
|
uRAR.OpenMode = RAR_OM_LIST
|
|
ElseIf opMode = OP_TEST Or opMode = OP_EXTRACT Then
|
|
uRAR.OpenMode = RAR_OM_EXTRACT
|
|
Else
|
|
RaiseEvent ProcessError(ERAR_UNKNOWN_ERROR, "Unknown extracion mode", strRarFile)
|
|
m_strLastErrorMsg = "Unknown extracion mode"
|
|
Exit Function
|
|
End If
|
|
|
|
If opMode = OP_LIST Then
|
|
lngpFilenames = 0
|
|
If UBound(arrstrFilenames) = 0 Then
|
|
RaiseEvent ProcessError(ERAR_DEST_ARR_TO_SMALL, "Supplied array to small to fit all files", strCurrentFilename)
|
|
m_strLastErrorMsg = "Supplied array to small to fit all files"
|
|
Exit Function
|
|
End If
|
|
End If
|
|
|
|
' Open the archive
|
|
lngRarHandle = RAROpenArchive(uRAR)
|
|
If uRAR.OpenResult <> 0 Then
|
|
' Something went wrong
|
|
Call OpenError(uRAR.OpenResult, strRarFile)
|
|
Else
|
|
' Set the callback
|
|
Call RARSetCallback(lngRarHandle, AddressOf MyCallBack, ObjPtr(Me))
|
|
' If the user supplied a password, set it
|
|
If Len(strPassword) > 0 Then
|
|
Call RARSetPassword(lngRarHandle, strPassword)
|
|
m_blnPasswordProtected = True
|
|
End If
|
|
If uRAR.CmtState = 0 Then
|
|
' No comment
|
|
ElseIf uRAR.CmtState = 1 Then
|
|
' Comment
|
|
RaiseEvent CommentFound(strRarFile, uRAR.CmtBuf)
|
|
Else
|
|
Call CommentError(uRAR.CmtState, strRarFile)
|
|
End If
|
|
|
|
strLastFilename = ""
|
|
m_dblLastFileSize = 0
|
|
m_dblLastFileUnpacked = 0
|
|
m_intLastPercentStep = 0
|
|
' Start processing the files
|
|
intStatus = RARReadHeaderEx(lngRarHandle, uHeaderEx)
|
|
strTmp = Left(uHeaderEx.ArcName, InStr(1, uHeaderEx.ArcName, vbNullChar) - 1)
|
|
Call NextVolume(strTmp)
|
|
Do Until intStatus <> 0
|
|
' Get the current filename
|
|
strCurrentFilename = Left(uHeaderEx.FileName, InStr(1, uHeaderEx.FileName, vbNullChar) - 1)
|
|
|
|
'// ADDED
|
|
'// Makes sure unsigned ints are handled properly
|
|
'// see function LongToUnsigned for more info
|
|
UnpSizeHighEx = LongToUnsigned(uHeaderEx.UnpSizeHigh)
|
|
UnpSizeEx = LongToUnsigned(uHeaderEx.UnpSize)
|
|
|
|
If strLastFilename <> strCurrentFilename Then
|
|
m_dblLastFileSize = MakeDouble(uHeaderEx.UnpSizeHigh, uHeaderEx.UnpSize)
|
|
m_dblLastFileUnpacked = 0
|
|
m_intLastPercentStep = 0
|
|
RaiseEvent ProcessingFile(strCurrentFilename, m_dblLastFileSize, Now(), uHeaderEx.UnpVer / 10, uHeaderEx.UnpVer Mod 10, uHeaderEx.Method, uHeaderEx.FileAttr)
|
|
strLastFilename = strCurrentFilename
|
|
If opMode = OP_LIST Then
|
|
If lngpFilenames > UBound(arrstrFilenames) Then
|
|
RaiseEvent ProcessError(ERAR_DEST_ARR_TO_SMALL, "Supplied array to small to fit all files", strCurrentFilename)
|
|
m_strLastErrorMsg = "Supplied array to small to fit all files"
|
|
HandleRarFiles = False
|
|
Exit Do
|
|
End If
|
|
arrstrFilenames(lngpFilenames) = strCurrentFilename
|
|
lngpFilenames = lngpFilenames + 1
|
|
End If
|
|
End If
|
|
intReturn = ERAR_UNKNOWN_ERROR
|
|
If opMode = OP_LIST Then
|
|
intReturn = RARProcessFile(lngRarHandle, RAR_SKIP, "", "")
|
|
ElseIf opMode = OP_TEST Then
|
|
intReturn = RARProcessFile(lngRarHandle, RAR_TEST, "", "")
|
|
ElseIf opMode = OP_EXTRACT Then
|
|
intReturn = RARProcessFile(lngRarHandle, RAR_EXTRACT, strDestPath, "")
|
|
End If
|
|
If intReturn = 0 Then
|
|
HandleRarFiles = True
|
|
Else
|
|
' Handle error and quit
|
|
Call ProcessError(CLng(intReturn), strCurrentFilename)
|
|
HandleRarFiles = False
|
|
Exit Do
|
|
End If
|
|
' Handle next file
|
|
intStatus = RARReadHeaderEx(lngRarHandle, uHeaderEx)
|
|
Loop
|
|
' RaiseEvent Progress(m_dblLastFileUnpacked, m_dblLastFileUnpacked)
|
|
Call RARCloseArchive(lngRarHandle)
|
|
End If
|
|
End Function
|
|
|
|
Friend Sub ProcessingLength(lngBufferSize As Long)
|
|
' Keep control of how much data we have extracted
|
|
m_dblLastFileUnpacked = m_dblLastFileUnpacked + lngBufferSize
|
|
If m_dblLastFileSize <> 0 Then
|
|
' Send an event to the listener whenever we reach the next progress step (0%, x%, 2x%, 3x% etc)
|
|
If CInt(m_dblLastFileUnpacked / m_dblLastFileSize * 100) > m_intLastPercentStep + m_intProgressSteps Then
|
|
RaiseEvent Progress(m_dblLastFileSize, m_dblLastFileUnpacked)
|
|
' Keep track of last percentage step
|
|
m_intLastPercentStep = m_intLastPercentStep + m_intProgressSteps
|
|
End If
|
|
End If
|
|
End Sub
|
|
|
|
Friend Function NextVolume(strFilename As String) As Boolean
|
|
Dim blnContinue As Boolean
|
|
|
|
RaiseEvent NextVolumne(strFilename, blnContinue)
|
|
NextVolume = blnContinue
|
|
End Function
|
|
|
|
Friend Function FindMissingFile(strFilename As String) As String
|
|
Dim strNewFile As String
|
|
|
|
RaiseEvent MissingFile(strFilename, strNewFile)
|
|
FindMissingFile = strNewFile
|
|
End Function
|
|
|
|
Friend Function MissingPassword() As String
|
|
Dim strNewPassword As String
|
|
|
|
m_blnPasswordProtected = True
|
|
RaiseEvent MissingPassword(strNewPassword)
|
|
MissingPassword = strNewPassword
|
|
End Function
|
|
|
|
Private Sub CommentError(lngErrorNum As Long, strRarName As String)
|
|
Dim strErrorMsg As String
|
|
|
|
Select Case lngErrorNum
|
|
Case ERAR_NO_MEMORY
|
|
strErrorMsg = "Not enough memory"
|
|
Case ERAR_BAD_DATA:
|
|
strErrorMsg = "Broken comment"
|
|
Case ERAR_UNKNOWN_FORMAT:
|
|
strErrorMsg = "Unknown comment format"
|
|
Case ERAR_SMALL_BUF:
|
|
strErrorMsg = "Buffer too small, comments not completely read"
|
|
Case Else
|
|
strErrorMsg = "Unknown error"
|
|
End Select
|
|
m_strLastErrorMsg = strErrorMsg
|
|
RaiseEvent CommentError(lngErrorNum, strErrorMsg, strRarName)
|
|
End Sub
|
|
|
|
Private Sub OpenError(lngErrorNum As Long, strRarName As String)
|
|
Dim strErrorMsg As String
|
|
|
|
Select Case lngErrorNum
|
|
Case ERAR_NO_MEMORY
|
|
strErrorMsg = "Not enough memory"
|
|
Case ERAR_EOPEN:
|
|
strErrorMsg = "Cannot open file"
|
|
Case ERAR_BAD_ARCHIVE:
|
|
strErrorMsg = "File is not RAR archive"
|
|
Case ERAR_BAD_DATA:
|
|
strErrorMsg = "Archive header broken"
|
|
Case Else
|
|
strErrorMsg = "Unknown error"
|
|
End Select
|
|
m_strLastErrorMsg = strErrorMsg
|
|
RaiseEvent OpenError(lngErrorNum, strErrorMsg, strRarName)
|
|
End Sub
|
|
|
|
Private Sub ProcessError(lngErrorNum As Long, strRarName As String)
|
|
Dim strErrorMsg As String
|
|
|
|
Select Case lngErrorNum
|
|
Case ERAR_UNKNOWN_FORMAT
|
|
strErrorMsg = "Unknown archive format"
|
|
Case ERAR_BAD_ARCHIVE:
|
|
strErrorMsg = "Bad volume"
|
|
Case ERAR_ECREATE:
|
|
strErrorMsg = "File create error"
|
|
Case ERAR_EOPEN:
|
|
strErrorMsg = "Volume open error"
|
|
Case ERAR_ECLOSE:
|
|
strErrorMsg = "File close error"
|
|
Case ERAR_EREAD:
|
|
strErrorMsg = "Read error"
|
|
Case ERAR_EWRITE:
|
|
strErrorMsg = "Write error"
|
|
Case ERAR_BAD_DATA:
|
|
If m_blnPasswordProtected Then
|
|
strErrorMsg = "CRC error - Wrong password?"
|
|
Else
|
|
strErrorMsg = "CRC error"
|
|
End If
|
|
Case Else
|
|
strErrorMsg = "Unknown error"
|
|
End Select
|
|
m_strLastErrorMsg = strErrorMsg
|
|
RaiseEvent ProcessError(lngErrorNum, strErrorMsg, strRarName)
|
|
End Sub
|
|
|
|
' The intProgressSteps property
|
|
Property Get intProgressSteps() As Integer
|
|
intProgressSteps = m_intProgressSteps
|
|
End Property
|
|
Property Let intProgressSteps(ByVal newValue As Integer)
|
|
m_intProgressSteps = newValue
|
|
End Property
|
|
|
|
' The strLastErrorMsg property
|
|
Property Get strLastErrorMsg() As String
|
|
strLastErrorMsg = m_strLastErrorMsg
|
|
End Property
|