Files

189 lines
6.7 KiB
VB.net

Attribute VB_Name = "modMD5_2"
Option Explicit
Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, ByRef phHash As Long) As Long
Private Declare Function CryptDestroyHash Lib "advapi32.dll" (ByVal hHash As Long) As Long
Private Declare Function CryptGetHashParam Lib "advapi32.dll" (ByVal pCryptHash As Long, ByVal dwParam As Long, ByRef pbData As Any, ByRef pcbData As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptHashData Lib "advapi32.dll" (ByVal hHash As Long, ByVal pbData As String, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwFlags As Long) As Long
Private Const ALG_TYPE_ANY As Long = 0
Private Const ALG_SID_MD5 As Long = 3
Private Const ALG_CLASS_HASH As Long = 32768
Private Const HP_HASHVAL As Long = 2
Private Const HP_HASHSIZE As Long = 4
Private Const CRYPT_VERIFYCONTEXT = &HF0000000
Private Const PROV_RSA_FULL As Long = 1
Private Const MS_ENHANCED_PROV As String = "Microsoft Enhanced Cryptographic Provider v1.0"
Public Function GetFileMD5(sFilename$, Optional lFileSize&) As String
If Not FileExists(sFilename) Then Exit Function
On Error Resume Next
If FileLen(sFilename) = 0 Then
'speed tweak :) 0-byte file always has the same MD5
GetFileMD5 = "D41D8CD98F00B204E9800998ECF8427E"
Exit Function
End If
On Error GoTo 0:
frmMain.shpMD5Background.Visible = True
frmMain.shpMD5Progress.Width = 15
frmMain.shpMD5Progress.Visible = True
frmMain.lblMD5.Caption = "Calculating MD5 checksum of " & sFilename & "..."
frmMain.lblMD5.Visible = True
'DoEvents
UpdateMD5Progress 0, 0
If lFileSize = 0 Then lFileSize = FileLen(sFilename)
Dim sFileContents$
On Error Resume Next
UpdateMD5Progress 1, 8
'Open sFileName For Binary Access Read As #1
Open sFilename For Binary Access Read Shared As #1
If Err Then Exit Function
sFileContents = Input(lFileSize, #1)
Close #1
Dim hCrypt&, hHash&, uMD5(255) As Byte, lMD5Len&, i%, sMD5$
UpdateMD5Progress 2, 8
If CryptAcquireContext(hCrypt, vbNullString, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) <> 0 Then
UpdateMD5Progress 3, 8
If CryptCreateHash(hCrypt, ALG_TYPE_ANY Or ALG_CLASS_HASH Or ALG_SID_MD5, 0, 0, hHash) <> 0 Then
UpdateMD5Progress 4, 8
If CryptHashData(hHash, sFileContents, Len(sFileContents), 0) <> 0 Then
UpdateMD5Progress 5, 8
If CryptGetHashParam(hHash, HP_HASHSIZE, uMD5(0), UBound(uMD5) + 1, 0) <> 0 Then
UpdateMD5Progress 6, 8
lMD5Len = uMD5(0)
If CryptGetHashParam(hHash, HP_HASHVAL, uMD5(0), UBound(uMD5) + 1, 0) <> 0 Then
UpdateMD5Progress 7, 8
For i = 0 To lMD5Len - 1
sMD5 = sMD5 & Right("0" & Hex(uMD5(i)), 2)
Next i
End If
End If
End If
CryptDestroyHash hHash
End If
CryptReleaseContext hCrypt, 0
UpdateMD5Progress 8, 8
End If
If sMD5 <> vbNullString Then
GetFileMD5 = " (filesize " & Len(sFileContents) & " bytes, MD5 " & sMD5 & ")"
End If
UpdateMD5Progress -1, 0
End Function
Public Function GetFileFromAutostart$(sAutostart$, Optional bGetMD5 As Boolean = True)
Dim sDummy$
On Error GoTo Error:
If InStr(sAutostart, "(file missing)") > 0 Then Exit Function
sDummy = sAutostart
If FileExists(sDummy) Then
GetFileFromAutostart = sDummy
Exit Function
End If
'forms we can find the file in:
'c:\bla\bla.exe
'c:\bla.exe
'bla.exe
'bla
'
'also possible:
'* surrounding quotes
'* arguments (possibly files)
If Left(sDummy, 1) = """" Then
'has quotes
'stripping like this also removes any
'arguments, so a path means it's finished
sDummy = Mid(sDummy, 2)
sDummy = Left(sDummy, InStr(sDummy, """") - 1)
If InStr(sDummy, "\") > 0 Then
GoTo GetMD5:
Else
GoTo FindFullPath:
End If
End If
If FileExists(sDummy) Then GoTo GetMD5
If LCase(Right(sDummy, 4)) <> ".exe" And _
LCase(Right(sDummy, 4)) <> ".com" Then
'has arguments, or no extension
If InStr(sDummy, " ") = 0 Then
'only one word, so no extension
sDummy = GetLongPath(sDummy & ".exe")
If InStr(sDummy, "\") = 0 Then
sDummy = GetLongPath(sDummy & ".com")
End If
GoTo GetMD5:
Else
'multiple words, the first is the program
If FileExists(Left(sDummy, InStr(sDummy, " ") - 1)) Then
sDummy = Left(sDummy, InStr(sDummy, " ") - 1)
sDummy = GetLongPath(sDummy)
Else
sDummy = Left(sDummy, InStrRev(sDummy, " ") - 1)
sDummy = GetLongPath(sDummy)
End If
GoTo GetMD5:
End If
End If
FindFullPath:
If InStr(sDummy, "\") = 0 Then
'no path - so search for file
sDummy = GetLongPath(sDummy)
End If
GetMD5:
If FileExists(sDummy) Then
If bGetMD5 Then
GetFileFromAutostart = GetFileMD5(sDummy)
Else
GetFileFromAutostart = sDummy
End If
End If
frmMain.lblMD5.Visible = False
DoEvents
Exit Function
Error:
ErrorMsg "modMD5_GetFileFromAutostart", Err.Number, Err.Description, sAutostart
End Function
Public Sub UpdateMD5Progress(i&, iMax&)
With frmMain
If i = -1 Then
'hide md5 progress bar
.shpMD5Background.Visible = False
.shpMD5Progress.Width = 15
.shpMD5Progress.Visible = False
DoEvents
Exit Sub
ElseIf i = 0 Then
'show + reset md5 progress bar
.shpMD5Background.Visible = True
.shpMD5Progress.Visible = True
.shpMD5Progress.Width = 15
DoEvents
Exit Sub
End If
.shpMD5Progress.Width = .shpMD5Background.Width * (CLng(i) / CLng(iMax))
DoEvents
End With
End Sub