#include "pch.h"
#include "AGCEventData.h"
#include <..\TCAtl\SimpleStream.h>
#include <..\TCAtl\TCNullStreamImpl.h>
void CAGCEventData::GetVarData(BSTR* pbstrContext, BSTR* pbstrSubject,
CAGCEventData::XProperties* pProperties) const
{
assert(m_pbData && m_cbData >= sizeof(XData));
XData* pData = reinterpret_cast<XData*>(m_pbData);
BYTE* pbData = reinterpret_cast<BYTE*>(pData + 1);
pbData += CreateBSTRFromData_LPSTR(pbData, pbstrContext);
pbData += CreateBSTRFromData_LPWSTR(pbData, pbstrSubject);
CComBSTR bstrKey;
CComVariant varItem;
for (long cArgTriplets = GetArgCount(); cArgTriplets; --cArgTriplets)
{
pbData += CreateBSTRFromData_LPSTR(pbData, &bstrKey);
pbData += CreateVARIANTFromData(pbData, varItem);
pProperties->insert(XProperties::value_type(bstrKey, varItem));
bstrKey.Empty();
}
}
#define VT_SIZE(vt, type) \
case vt: \
va_arg(argptr, type); \
cbTotal += sizeof(type); \
break;
UINT CAGCEventData::ComputeVariableDataSize(LPCSTR pszContext,
LPCOLESTR pszSubject, long cArgTriplets, va_list argptr)
{
UINT cbTotal = pszContext ? strlen(pszContext) : 0;
cbTotal += sizeof(cbTotal);
cbTotal += pszSubject ? (wcslen(pszSubject) * sizeof(WCHAR)) : 0;
cbTotal += sizeof(cbTotal);
for (long i = 0; i < cArgTriplets; ++i)
{
LPCSTR pszArgName = va_arg(argptr, LPCSTR);
assert(!IsBadStringPtrA(pszArgName, UINT(-1)));
UINT cchName = strlen(pszArgName);
cbTotal += sizeof(cchName) + cchName;
VARTYPE vt = va_arg(argptr, VARTYPE);
cbTotal += sizeof(vt);
switch (vt)
{
VT_SIZE(VT_BOOL , VARIANT_BOOL)
VT_SIZE(VT_I1 , CHAR)
VT_SIZE(VT_I2 , SHORT)
VT_SIZE(VT_I4 , LONG)
VT_SIZE(VT_UI1 , BYTE)
VT_SIZE(VT_UI2 , USHORT)
VT_SIZE(VT_ERROR , SCODE)
case VT_R4:
{
va_arg(argptr, DOUBLE);
cbTotal += sizeof(float);
break;
}
VT_SIZE(VT_R8 , DOUBLE)
VT_SIZE(VT_DECIMAL, DECIMAL)
VT_SIZE(VT_CY , CY)
VT_SIZE(VT_DATE , DATE)
case VT_BSTR:
{
BSTR bstr = va_arg(argptr, BSTR);
UINT cb = bstr ? SysStringByteLen(bstr) : 0;
cbTotal += sizeof(cb) + cb;
break;
}
case VT_UNKNOWN:
case VT_DISPATCH:
{
IUnknown* punk = va_arg(argptr, IUnknown*);
IPersistStreamPtr sppstm(punk);
if (punk && NULL == sppstm)
ZSucceeded(punk->QueryInterface(IID_IPersistStreamInit,
(void**)&sppstm));
TCNullStreamImpl stm;
OleSaveToStream(sppstm, &stm);
ULARGE_INTEGER cbSize;
LARGE_INTEGER dlibMove = {0, 0};
ZSucceeded(stm.Seek(dlibMove, STREAM_SEEK_CUR, &cbSize));
assert(0 == cbSize.HighPart);
cbTotal += sizeof(cbSize.LowPart) + cbSize.LowPart;
break;
}
case VT_VARIANT:
ZError("Unsupported Variant Type");
break;
case VT_LPSTR:
{
LPCSTR psz = va_arg(argptr, LPCSTR);
UINT cch = psz ? strlen(psz) : 0;
cbTotal += sizeof(cch) + cch;
break;
}
case VT_LPWSTR:
{
LPCWSTR psz = va_arg(argptr, LPCWSTR);
UINT cch = psz ? wcslen(psz) : 0;
cbTotal += sizeof(cch) + cch * sizeof(WCHAR);
break;
}
default:
ZError("Unsupported Variant Type");
}
}
return cbTotal;
}
#define COPY_DATA(pData, cb) \
{ \
int _cb = (cb); \
if (_cb) \
{ \
assert(cbData >= _cb); \
CopyMemory(pbData, pData, _cb); \
cbData -= _cb; \
pbData += _cb; \
} \
}
#define COPY_VAR(var) \
COPY_DATA(&var, sizeof(var))
#define VT_COPY(vt, type) \
case vt: \
{ \
type var = va_arg(argptr, type); \
COPY_VAR(var); \
break; \
}
void CAGCEventData::CopyVariableData(LPCSTR pszContext, LPCOLESTR pszSubject,
long cArgTriplets, va_list argptr)
{
UINT cbData = m_cbData - sizeof(XData);
BYTE* pbData = m_pbData + sizeof(XData);
UINT cb = pszContext ? strlen(pszContext) : 0;
COPY_VAR(cb);
COPY_DATA(pszContext, cb);
cb = pszSubject ? (wcslen(pszSubject) * sizeof(WCHAR)) : 0;
COPY_VAR(cb);
COPY_DATA(pszSubject, cb);
for (long i = 0; i < cArgTriplets; ++i)
{
LPCSTR pszArgName = va_arg(argptr, LPCSTR);
cb = strlen(pszArgName);
COPY_VAR(cb);
COPY_DATA(pszArgName, cb);
VARTYPE vt = va_arg(argptr, VARTYPE);
COPY_VAR(vt);
switch (vt)
{
VT_COPY(VT_BOOL , VARIANT_BOOL)
VT_COPY(VT_I1 , CHAR)
VT_COPY(VT_I2 , SHORT)
VT_COPY(VT_I4 , LONG)
VT_COPY(VT_UI1 , BYTE)
VT_COPY(VT_UI2 , USHORT)
VT_COPY(VT_ERROR , SCODE)
case VT_R4:
{
float var = va_arg(argptr, DOUBLE);
COPY_VAR(var);
break;
}
VT_COPY(VT_R8 , DOUBLE)
VT_COPY(VT_DECIMAL, DECIMAL)
VT_COPY(VT_CY , CY)
VT_COPY(VT_DATE , DATE)
case VT_BSTR:
{
BSTR bstr = va_arg(argptr, BSTR);
cb = bstr ? SysStringByteLen(bstr) : 0;
COPY_VAR(cb);
COPY_DATA(bstr, cb);
break;
}
case VT_UNKNOWN:
case VT_DISPATCH:
{
IUnknown* punk = va_arg(argptr, IUnknown*);
IPersistStreamPtr sppstm(punk);
if (punk && NULL == sppstm)
ZSucceeded(punk->QueryInterface(IID_IPersistStreamInit,
(void**)&sppstm));
TCSimpleStream stm;
stm.Init(cbData - sizeof(ULONG), pbData + sizeof(ULONG));
OleSaveToStream(sppstm, &stm);
ULARGE_INTEGER cbSize;
LARGE_INTEGER dlibMove = {0, 0};
ZSucceeded(stm.Seek(dlibMove, STREAM_SEEK_CUR, &cbSize));
assert(0 == cbSize.HighPart);
COPY_VAR(cbSize.LowPart);
cbData -= cbSize.LowPart;
pbData += cbSize.LowPart;
break;
}
case VT_VARIANT:
ZError("Unsupported Variant Type");
break;
case VT_LPSTR:
{
LPCSTR psz = va_arg(argptr, LPCSTR);
cb = psz ? strlen(psz) : 0;
COPY_VAR(cb);
COPY_DATA(psz, cb);
break;
}
case VT_LPWSTR:
{
LPCWSTR psz = va_arg(argptr, LPCWSTR);
cb = psz ? (wcslen(psz) * sizeof(WCHAR)) : 0;
COPY_VAR(cb);
COPY_DATA(psz, cb);
break;
}
default:
ZError("Unsupported Variant Type");
}
}
}
#define VT_CREATE(_vt, type) \
case VT##_vt: \
V##_vt(&var) = *reinterpret_cast<type*>(pbData); \
cbData = sizeof(type); \
break;
UINT CAGCEventData::CreateVARIANTFromData(BYTE* pbData, CComVariant& var)
{
ZSucceeded(var.Clear());
V_VT(&var) = *reinterpret_cast<VARTYPE*>(pbData);
pbData += sizeof(V_VT(&var));
UINT cbData = 0;
switch (V_VT(&var))
{
VT_CREATE(_BOOL , VARIANT_BOOL)
VT_CREATE(_I1 , CHAR)
VT_CREATE(_I2 , SHORT)
VT_CREATE(_I4 , LONG)
VT_CREATE(_UI1 , BYTE)
VT_CREATE(_UI2 , USHORT)
VT_CREATE(_ERROR , SCODE)
VT_CREATE(_R4 , FLOAT)
VT_CREATE(_R8 , DOUBLE)
VT_CREATE(_DECIMAL, DECIMAL)
VT_CREATE(_CY , CY)
VT_CREATE(_DATE , DATE)
case VT_BSTR:
cbData = CreateBSTRFromData(pbData, &V_BSTR(&var));
break;
case VT_UNKNOWN:
cbData = CreateObjectFromData(pbData, IID_IUnknown,
(void**)&V_UNKNOWN(&var));
break;
case VT_DISPATCH:
cbData = CreateObjectFromData(pbData, IID_IDispatch,
(void**)&V_DISPATCH(&var));
break;
case VT_VARIANT:
ZError("Unsupported Variant Type");
break;
case VT_LPSTR:
cbData = CreateBSTRFromData_LPSTR(pbData, &V_BSTR(&var));
V_VT(&var) = VT_BSTR;
break;
case VT_LPWSTR:
cbData = CreateBSTRFromData_LPWSTR(pbData, &V_BSTR(&var));
V_VT(&var) = VT_BSTR;
break;
default:
ZError("Unsupported Variant Type");
}
return sizeof(V_VT(&var)) + cbData;
}
UINT CAGCEventData::CreateBSTRFromData(BYTE* pbData, BSTR* pbstr)
{
UINT cbData = *reinterpret_cast<UINT*>(pbData);
pbData += sizeof(cbData);
*pbstr = SysAllocStringByteLen(reinterpret_cast<LPCSTR>(pbData), cbData);
assert(*pbstr);
return sizeof(cbData) + cbData;
}
UINT CAGCEventData::CreateBSTRFromData_LPSTR(BYTE* pbData, BSTR* pbstr)
{
UINT cch = *reinterpret_cast<UINT*>(pbData);
pbData += sizeof(cch);
LPOLESTR pwsz = (LPOLESTR)_alloca((cch + 1) * sizeof(OLECHAR));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
reinterpret_cast<LPCSTR>(pbData), cch, pwsz, cch + 1);
*pbstr = SysAllocStringLen(pwsz, cch);
assert(*pbstr);
return sizeof(cch) + cch;
}
UINT CAGCEventData::CreateBSTRFromData_LPWSTR(BYTE* pbData, BSTR* pbstr)
{
UINT cb = *reinterpret_cast<UINT*>(pbData);
pbData += sizeof(cb);
UINT cch = cb / sizeof(OLECHAR);
*pbstr = SysAllocStringLen(reinterpret_cast<LPOLESTR>(pbData), cch);
assert(*pbstr);
return sizeof(cb) + cb;
}
UINT CAGCEventData::CreateObjectFromData(BYTE* pbData, REFIID riid,
void** ppvUnk)
{
UINT cbData = *reinterpret_cast<UINT*>(pbData);
pbData += sizeof(cbData);
TCSimpleStream stm;
stm.Init(cbData, pbData);
ZSucceeded(OleLoadFromStream(&stm, riid, ppvUnk));
return sizeof(cbData) + cbData;
}