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