Re: Create a CBitmap from SAFEARRAY

Tech-Archive recommends: Fix windows errors by optimizing your registry



On 14 Mar 2007 08:43:17 -0700, dom_perron@xxxxxxxxxxx wrote:

I developed a component in .net which I call from an MFC program.
A .net function called in my c++ program return a safearray ** (wich
is a byte [] in .net). This function convert a string of binary data
base64 encoded in a array of byte[].

Here is my .NET implementation:

byte[] GetDecodedImage(String i_innerText)
{
byte[] base64 = Convert.FromBase64String(i_innerText);

return base64;
}

If you are using .NET just for the built-in base-64 decoding class,
you might consider the following C++ code. I adapted the core decoding
engine from a set of C functions at:

http://www.fourmilab.ch/webtools/base64/

(they have a command line base64 decoder/encoder written in C.)

If you have a base-64 encoded string, and you want to decode it, you
can write e.g.:

// Your base64 encoded input string:
// std::string base64data;

// Buffer to store result
Base64Decoder::Buffer result;

// Do the decoding
BYTE * pBytes = Base64Decoder::Decode( base64data, result );


The Base64Decoder::Decode method takes in input the base64 encoded
string, and a reference to a byte buffer. The method will decode the
input data into the buffer, and will return a pointer to first buffer
byte.
Note that the buffer is a std::vector<BYTE> allocated onto the stack,
so there's no need to delete[] the buffer.

The code follows:


<CODE File="Base64Decoder.h">

//////////////////////////////////////////////////////////////////////////
// FILE: Base64Decoder.h

#pragma once

//
// *** Base-64 Decoder ***
//
// By MrAsm
//
class Base64Decoder
{
public:

// Byte buffer
typedef std::vector< BYTE > Buffer;

//
// NOTE:
// Base-64 encoded strings are pure ASCII strings,
// so they don't need Unicode, and can be stored
// into std::string.
//

// Decode a base64-encoded string, and return the decoded string
static std::string DecodeString( IN const std::string &
encodedString );

// Decode a base64-encoded string, and save result into a buffer.
// Return pointer to first buffer byte.
static BYTE * Decode( IN const std::string & encodedString,
OUT Buffer & out );

// Decode base64-encoded data read from file, and save result
// into a buffer.
// Return pointer to first buffer byte on success.
// Return NULL on error.
static BYTE * DecodeFile( IN LPCTSTR szFileName,
OUT Buffer & out );



//
// IMPLEMENTATION
//

private:

static const std::string base64Chars;

static bool IsBase64( IN unsigned char c ) {
return (isalnum(c) || (c == '+') || (c == '/'));
}

static bool CompactLines( IN LPCTSTR szFileName,
OUT std::string & data );
};

//////////////////////////////////////////////////////////////////////////

</CODE>



<CODE File="Base64Decoder.cpp">

//////////////////////////////////////////////////////////////////////////
// FILE: Base64Decoder.cpp

#include "StdAfx.h"
#include "Base64Decoder.h"


const std::string Base64Decoder::base64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";



std::string Base64Decoder::DecodeString( IN const std::string &
encodedString )
{
//
// This decoding engine is adapted from:
//
// http://www.fourmilab.ch/webtools/base64/
//

int in_len = (int) encodedString.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;

while (in_len-- && ( encodedString[in_] != '=') &&
IsBase64(encodedString[in_]))
{
char_array_4[i++] = encodedString[in_]; in_++;
if (i ==4)
{
for (i = 0; i <4; i++)
char_array_4[i] = (unsigned char)
base64Chars.find(char_array_4[i]);

char_array_3[0] = (char_array_4[0] << 2) +
((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) +
((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) +
char_array_4[3];

for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}

if (i)
{
for (j = i; j <4; j++)
char_array_4[j] = 0;

for (j = 0; j <4; j++)
char_array_4[j] = (unsigned char)
base64Chars.find(char_array_4[j]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] &
0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) +
((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) +
char_array_4[3];

for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}

return ret;
}


// Build a single line from Base64 file content
bool Base64Decoder::CompactLines( IN LPCTSTR szFileName, OUT
std::string & data )
{
data.clear();

FILE * file = _tfopen( szFileName, _T("rt") );
if ( file == NULL )
return false;

static const int maxLineChars = 100;
char line[ maxLineChars + 1 ];

std::ostringstream os;
while ( true )
{
ZeroMemory( line, sizeof(line) );
if ( ! fgets( line, maxLineChars, file ) )
{
break;
}

// Remove ending '\r\n'
size_t len = strlen(line);
if ( line[len-2] == '\r' )
line[len-2] = '\0';

// Add line
os << std::string( line );
}

fclose( file );
file = NULL;

data = os.str();
return true;
}


BYTE * Base64Decoder::Decode( IN const std::string & encodedString,
OUT Buffer & out )
{
// Clear output buffer
out.clear();

// std::string is a vector of bytes, so we can store
// decoded stuff into it
std::string decoded = DecodeString( encodedString );

// Copy the string content into destination buffer
out.resize( decoded.length() );
BYTE * pOutput = &(*out.begin());
memcpy( pOutput, decoded.c_str(), decoded.length() );

// Return pointer to destination buffer
return pOutput;
}


BYTE * Base64Decoder::DecodeFile( IN LPCTSTR szFileName, OUT
std::vector<BYTE> & out )
{
// Clear output buffer
out.clear();

// Check file name
ASSERT( szFileName != NULL );
if ( szFileName == NULL )
return NULL;

// Compact input file lines into a single base64 string
std::string base64data;
if ( ! CompactLines( szFileName, base64data ) )
return NULL;


// Decode into buffer
return Decode( base64data, out );
}


//////////////////////////////////////////////////////////////////////////

</CODE>


MrAsm
.



Relevant Pages

  • Re: Discovering variable types...
    ... >- but I suppose MS expect us to use wrappers ... memory allocations for your variables from disk as well. ... >They most certainly are of fixed size, changing the size of a String ... >>me to keep buffer size and current postion right in the memory block. ...
    (comp.lang.pascal.delphi.misc)
  • Re: Secure C library
    ... I read much of the new "security TR", and gee, I don't know. ... the buffer from the buffer size. ... It is not hard to design a better form of buffer and string handling. ... but this is just one example of how thoughtful interface design can ...
    (comp.std.c)
  • Re: Secure C library
    ... >> string functions don't make much sense once you add bounds-checking ... >> designing an interface just for the purpose of reducing the frequency ... > make buffer size decisions more visible, ... Bstrlib is also very interoperable with char *'s, ...
    (comp.std.c)
  • Re: why I can not write to the file after initialize the MFC in a service program
    ... you check EVERY return from a call that can fail, ... Why do you need an intermedate buffer to write literal strings anyway? ... For example, if AfxWinInit fails, you copy a 45-character string into a ... So you are going to try to initialize MFC EACH TIME THROUGH THE LOOP? ...
    (microsoft.public.vc.mfc)
  • Re: Calling dll functions from vb.net with pointer returns!
    ... (ByRef pulLen As Integer, ByVal pszFilter As String, ByVal ulFlags As ... OUT PTCHAR Buffer, ... Address of a buffer to receive a set of NULL-terminated device instance ... pszFilter must specify the name of a device ...
    (microsoft.public.dotnet.languages.vb)