// bytearrayconv.cpp
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000 Robert Cunnings. All rights reserved.
//
// You may copy, modify, distribute or publish this code free of charge.
//
// NO WARRANTY: This software is provided AS IS, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// Routines to convert to and from SAFEARRAY's of type VT_UI1.
// 
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "bytearrayconv.h"

// helpers for conversion to and from SAFEARRAY of type VT_UI1 (byte vector)
// for use with base64 and hexBinary parameter types

SAFEARRAY *ByteArrayFromString(const string& strSrc)
{
	void *pData;
	SAFEARRAY *pArray = SafeArrayCreateVector(VT_UI1, 0, strSrc.length());
	if (pArray == NULL || FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		if (pArray != NULL)
		{
			SafeArrayDestroy(pArray);
			pArray = NULL;
		}
		return pArray;
	}
	memmove(pData, strSrc.c_str(), strSrc.length());
	SafeArrayUnaccessData(pArray);
	return pArray;
}

SAFEARRAY *ByteArrayFromWideString(const wstring& wstrSrc)
{
	void *pData;
	SAFEARRAY *pArray = SafeArrayCreateVector(VT_UI1, 0, wstrSrc.length() * sizeof(wchar_t));
	if (pArray == NULL || FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		if (pArray != NULL)
		{
			SafeArrayDestroy(pArray);
			pArray = NULL;
		}
		return pArray;
	}
	memmove(pData, wstrSrc.c_str(), wstrSrc.length() * sizeof(wchar_t));
	SafeArrayUnaccessData(pArray);
	return pArray;
}

SAFEARRAY *ByteArrayFromBSTR(const BSTR bstrSrc)
{
	void *pData;
	SAFEARRAY *pArray = SafeArrayCreateVector(VT_UI1, 0, SysStringByteLen(bstrSrc));
	if (pArray == NULL || FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		if (pArray != NULL)
		{
			SafeArrayDestroy(pArray);
			pArray = NULL;
		}
		return pArray;
	}
	memmove(pData, bstrSrc, SysStringByteLen(bstrSrc));
	SafeArrayUnaccessData(pArray);
	return pArray;
}

SAFEARRAY *ByteArrayFromBuffer(const void *pvSrc, long lLength)
{
	void *pData;
	SAFEARRAY *pArray = SafeArrayCreateVector(VT_UI1, 0, lLength);
	if (pArray == NULL || FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		if (pArray != NULL)
		{
			SafeArrayDestroy(pArray);
			pArray = NULL;
		}
		return pArray;
	}
	memmove(pData, pvSrc, lLength);
	SafeArrayUnaccessData(pArray);
	return pArray;
}


bool StringFromByteArray(SAFEARRAY *pArray, string& strDest)
{
	if (pArray == NULL || SafeArrayGetDim(pArray) != 1)
	{
		return false;
	}
	void *pData;
	if (FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		return false;
	}
	strDest.erase();
	strDest.append((const char *)pData, pArray->rgsabound[0].cElements);
	SafeArrayUnaccessData(pArray);
	return true;
}

bool WideStringFromByteArray(SAFEARRAY *pArray, wstring& wstrDest)
{
	if (pArray == NULL || SafeArrayGetDim(pArray) != 1)
	{
		return false;
	}
	void *pData;
	if (FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		return false;
	}
	wstrDest = L"";
	wstrDest.append((const wchar_t *)pData, pArray->rgsabound[0].cElements / sizeof(wchar_t));
	SafeArrayUnaccessData(pArray);
	return true;
}

bool BSTRFromByteArray(SAFEARRAY *pArray, BSTR *pbstrDest)
{
	if (pArray == NULL || SafeArrayGetDim(pArray) != 1)
	{
		return false;
	}
	void *pData;
	if (FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		return false;
	}
	*pbstrDest = SysAllocStringLen((const OLECHAR *)pData, (UINT)pArray->rgsabound[0].cElements / sizeof(OLECHAR)); 
	SafeArrayUnaccessData(pArray);
	if (*pbstrDest == NULL)
	{
		return false;
	}
	return true;
}

bool BufferFromByteArray(SAFEARRAY *pArray, void **ppvDest, unsigned long *pLength)
{
	if (pArray == NULL || SafeArrayGetDim(pArray) != 1)
	{
		return false;
	}
	void *pData;
	if (FAILED(SafeArrayAccessData(pArray, &pData)))
	{
		return false;
	}
	*ppvDest = malloc((size_t)pArray->rgsabound[0].cElements); 
	SafeArrayUnaccessData(pArray);
	if (*ppvDest == NULL)
	{
		return false;
	}
	memcpy(*ppvDest, pData, pArray->rgsabound[0].cElements);
	*pLength = pArray->rgsabound[0].cElements;
	return true;
}
