95 lines
2.9 KiB
Forth
95 lines
2.9 KiB
Forth
module md5_mod
|
|
use kernel32
|
|
use advapi32
|
|
implicit none
|
|
integer, parameter :: MD5LEN = 16
|
|
contains
|
|
subroutine md5hash(name, hash, dwStatus, filesize)
|
|
implicit none
|
|
character(*) :: name
|
|
integer, parameter :: BUFLEN = 32768
|
|
integer(HANDLE) :: hFile, hProv, hHash
|
|
integer(DWORD) :: dwStatus, nRead
|
|
integer(BOOL) :: status
|
|
integer(BYTE) :: buffer(BUFLEN)
|
|
integer(BYTE) :: hash(MD5LEN)
|
|
integer(UINT64) :: filesize
|
|
|
|
dwStatus = 0
|
|
filesize = 0
|
|
hFile = CreateFile(trim(name) // char(0), GENERIC_READ, FILE_SHARE_READ, NULL, &
|
|
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) then
|
|
dwStatus = GetLastError()
|
|
print *, "CreateFile failed."
|
|
return
|
|
end if
|
|
|
|
if (CryptAcquireContext(hProv, NULL, NULL, PROV_RSA_FULL, &
|
|
CRYPT_VERIFYCONTEXT) == FALSE) then
|
|
dwStatus = GetLastError()
|
|
print *, "CryptAcquireContext failed."
|
|
goto 3
|
|
end if
|
|
|
|
if (CryptCreateHash(hProv, CALG_MD5, 0_ULONG_PTR, 0_DWORD, hHash) == FALSE) then
|
|
dwStatus = GetLastError()
|
|
print *, "CryptCreateHash failed."
|
|
go to 2
|
|
end if
|
|
|
|
do
|
|
status = ReadFile(hFile, loc(buffer), BUFLEN, nRead, NULL)
|
|
if (status == FALSE .or. nRead == 0) exit
|
|
filesize = filesize + nRead
|
|
if (CryptHashData(hHash, buffer, nRead, 0) == FALSE) then
|
|
dwStatus = GetLastError()
|
|
print *, "CryptHashData failed."
|
|
go to 1
|
|
end if
|
|
end do
|
|
|
|
if (status == FALSE) then
|
|
dwStatus = GetLastError()
|
|
print *, "ReadFile failed."
|
|
go to 1
|
|
end if
|
|
|
|
nRead = MD5LEN
|
|
if (CryptGetHashParam(hHash, HP_HASHVAL, hash, nRead, 0) == FALSE) then
|
|
dwStatus = GetLastError()
|
|
print *, "CryptGetHashParam failed.", status, nRead, dwStatus
|
|
end if
|
|
|
|
1 status = CryptDestroyHash(hHash)
|
|
2 status = CryptReleaseContext(hProv, 0)
|
|
3 status = CloseHandle(hFile)
|
|
end subroutine
|
|
end module
|
|
|
|
program md5
|
|
use md5_mod
|
|
implicit none
|
|
integer :: n, m, i, j
|
|
character(:), allocatable :: name
|
|
integer(DWORD) :: dwStatus
|
|
integer(BYTE) :: hash(MD5LEN)
|
|
integer(UINT64) :: filesize
|
|
|
|
n = command_argument_count()
|
|
do i = 1, n
|
|
call get_command_argument(i, length=m)
|
|
allocate(character(m) :: name)
|
|
call get_command_argument(i, name)
|
|
call md5hash(name, hash, dwStatus, filesize)
|
|
if (dwStatus == 0) then
|
|
do j = 1, MD5LEN
|
|
write(*, "(Z2.2)", advance="NO") hash(j)
|
|
end do
|
|
write(*, "(' ',A,' (',G0,' bytes)')") name, filesize
|
|
end if
|
|
deallocate(name)
|
|
end do
|
|
end program
|