As many in the forum have noticed, string-based encoding routines for Base64 in VDF are extremely slow. I have a specific need for fast base64 encoding in VDF15.1, and I don't want to use a third party DLL. Instead I chose to use CryptBinaryToString in the Windows Crypt32.dll (which comes with Windows XP on up).
I've come up with the following code which works fantastic in both VDF15.1 and VDF17.0 on my development box running Windows 7, but when deploying to Windows XP machines with Windows XP I'm getting memory access violation errors. Hoping somebody can help me figure out what's causing my memory error in XP. In an XP environment, the VDF program crashes and in a debugger it shows an access violation.
Also, while I don't care too much about decoding Base64 at the moment, I've gone ahead and wrote it in... it works, but it will not work decoding more than 300k of data. Not sure what is wrong here, but I'd also like for that to work if someone could help.
So anyone with a VDF15.1 / Windows XP Development environment care to help me find out why the access violation Encoding Base64 with the following, and why Decoding stops at 300k???
Code:
///////////////////////////////////////////////////////////////////////////////
// //
// Encode64.pkg - BASE64 Encoding of Strings (Encode64) and //
// Files (Encode64File) //
// //
// Written by John Hulsman 05.05.2014 //
// //
///////////////////////////////////////////////////////////////////////////////
Define CRYPT_STRING_BASE64 for 1
External_Function CryptBinaryToString "CryptBinaryToStringA" Crypt32.dll Pointer pbBinary DWord cbBinary ;
DWord dwFlags Pointer pszString Pointer pcchString Returns Boolean
External_Function CryptStringToBinary "CryptStringToBinaryA" Crypt32.dll Pointer pszString DWord cchString ;
DWord dwFlags Pointer pbBinary Pointer pcbBinary Pointer pdwSkip Pointer pdwFlags Returns Boolean
Function Encode64 String sData Returns String
String sBase64
Integer iSize
Boolean bResult
Move (Length(sData)*2) to iSize
ZeroString iSize to sBase64
Move (CryptBinaryToString(AddressOf(sData),Length(sData),CRYPT_STRING_BASE64,AddressOf(sBase64),AddressOf(iSize))) to bResult
Function_Return (CString(sBase64))
End_Function
Function Encode64File String sFile Returns String
String sData sBase64
Integer iChannel iSize iArg
Move (Seq_New_Channel()) to iChannel
Direct_Input channel iChannel ("Binary: "+ToANSI(sFile))
Get_Channel_Size iChannel to iSize
Get_Argument_Size to iArg
If (iSize > iArg) Set_Argument_Size (iSize * 2)
Read_Block channel iChannel sData iSize
Close_Input channel iChannel
Send Seq_Release_Channel iChannel
Move (Encode64(Self,sData)) to sBase64
Function_Return sBase64
End_Function
Function Decode64 String sBase64 Returns String
String sData
Integer iSize
Boolean bResult
DWord dwSkip dwFlags
Move CRYPT_STRING_BASE64 to dwFlags
Move (Length(sBase64)) to iSize
ZeroString iSize to sData
Move (CryptStringToBinary(AddressOf(sBase64),iSize,dwFlags,AddressOf(sData),AddressOf(iSize),AddressOf(dwSkip),AddressOf(dwFlags))) to bResult
Function_Return (CString(sData))
End_Function
Function Decode64File String sFile Returns String
String sData sBase64
Integer iChannel iSize iArg
Move (Seq_New_Channel()) to iChannel
Direct_Input channel iChannel ("Binary: "+ToANSI(sFile))
Get_Channel_Size iChannel to iSize
Get_Argument_Size to iArg
If (iSize > iArg) Set_Argument_Size iSize
Read_Block channel iChannel sBase64 iSize
Close_Input channel iChannel
Send Seq_Release_Channel iChannel
Move (Decode64(Self,sBase64)) to sData
Function_Return sData
End_Function