199 lines
4.9 KiB
C++
199 lines
4.9 KiB
C++
|
|
#ifndef VARSER_HPP
|
|
#define VARSER_HPP
|
|
|
|
// Variant serializer/deserializer.
|
|
struct varser_t
|
|
{
|
|
#ifdef __NT__
|
|
static bool serialize(bytevec_t &out, const VARIANT &var);
|
|
#else
|
|
static bool deserialize(VARIANT &var, const uchar **in, const uchar *const end);
|
|
#endif
|
|
};
|
|
|
|
#ifdef __NT__
|
|
//-------------------------------------------------------------------------
|
|
bool varser_t::serialize(bytevec_t &out, const VARIANT &var)
|
|
{
|
|
out.pack_dw(var.vt);
|
|
if ( (var.vt & VT_BYREF) == VT_BYREF
|
|
|| (var.vt & VT_ARRAY) == VT_ARRAY )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const size_t sz_before = out.size();
|
|
switch ( var.vt )
|
|
{
|
|
case VT_EMPTY: // = 0x0000,
|
|
case VT_NULL: // = 0x0001,
|
|
break;
|
|
case VT_I2: // = 0x0002,
|
|
case VT_UI2: // = 0x0012,
|
|
out.pack_dw(var.uiVal);
|
|
break;
|
|
case VT_I4: // = 0x0003,
|
|
case VT_UI4: // = 0x0013,
|
|
out.pack_dd(var.ulVal);
|
|
break;
|
|
case VT_R4: // = 0x0004,
|
|
out.pack_dd(*(uint32*)&var.fltVal);
|
|
break;
|
|
case VT_R8: // = 0x0005,
|
|
out.pack_dq(*(uint64*)&var.dblVal);
|
|
break;
|
|
case VT_CY: // = 0x0006,
|
|
case VT_DATE: // = 0x0007,
|
|
break;
|
|
case VT_BSTR: // = 0x0008,
|
|
{
|
|
uint8 *ptr = (uint8*) var.bstrVal;
|
|
ptr -= 4;
|
|
uint32 bcnt = * (uint32*) ptr;
|
|
out.pack_buf(ptr + 4, bcnt);
|
|
}
|
|
break;
|
|
case VT_DISPATCH: // = 0x0009,
|
|
case VT_ERROR: // = 0x000A,
|
|
case VT_BOOL: // = 0x000B,
|
|
case VT_VARIANT: // = 0x000C,
|
|
case VT_UNKNOWN: // = 0x000D,
|
|
case VT_DECIMAL: // = 0x000E,
|
|
case VT_I1: // = 0x0010,
|
|
case VT_UI1: // = 0x0011,
|
|
out.pack_db(var.bVal);
|
|
break;
|
|
case VT_I8: // = 0x0014,
|
|
case VT_UI8: // = 0x0015,
|
|
out.pack_dq(var.ullVal);
|
|
break;
|
|
case VT_INT: // = 0x0016,
|
|
case VT_UINT: // = 0x0017,
|
|
case VT_HRESULT: // = 0x0019,
|
|
out.pack_dd(var.uintVal);
|
|
break;
|
|
case VT_VOID: // = 0x0018,
|
|
case VT_PTR: // = 0x001A,
|
|
case VT_SAFEARRAY: // = 0x001B,
|
|
case VT_CARRAY: // = 0x001C,
|
|
case VT_USERDEFINED: // = 0x001D,
|
|
case VT_LPSTR: // = 0x001E,
|
|
case VT_LPWSTR: // = 0x001F,
|
|
case VT_RECORD: // = 0x0024,
|
|
case VT_INT_PTR: // = 0x0025,
|
|
case VT_UINT_PTR: // = 0x0026,
|
|
break;
|
|
default: break;
|
|
}
|
|
return out.size() > sz_before;
|
|
}
|
|
#else
|
|
//-------------------------------------------------------------------------
|
|
bool varser_t::deserialize(VARIANT &var, const uchar **in, const uchar *const end)
|
|
{
|
|
var.vt = unpack_dw(in, end);
|
|
if ( (var.vt & VT_BYREF) == VT_BYREF
|
|
|| (var.vt & VT_ARRAY) == VT_ARRAY )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool ok = false;
|
|
switch ( var.vt )
|
|
{
|
|
case VT_EMPTY: // = 0x0000,
|
|
case VT_NULL: // = 0x0001,
|
|
break;
|
|
case VT_I2: // = 0x0002,
|
|
case VT_UI2: // = 0x0012,
|
|
var.uiVal = unpack_dw(in, end);
|
|
ok = true;
|
|
break;
|
|
case VT_I4: // = 0x0003,
|
|
case VT_UI4: // = 0x0013,
|
|
var.ulVal = unpack_dd(in, end);
|
|
ok = true;
|
|
break;
|
|
case VT_R4: // = 0x0004,
|
|
{
|
|
uint32 res = unpack_dd(in, end);
|
|
var.fltVal = *(FLOAT*)&res;
|
|
ok = true;
|
|
}
|
|
break;
|
|
case VT_R8: // = 0x0005,
|
|
{
|
|
uint64 res = unpack_dq(in, end);
|
|
var.dblVal = *(DOUBLE*)&res;
|
|
ok = true;
|
|
}
|
|
break;
|
|
case VT_CY: // = 0x0006,
|
|
case VT_DATE: // = 0x0007,
|
|
break;
|
|
case VT_BSTR: // = 0x0008,
|
|
{
|
|
uint32 bcnt = unpack_dd(in, end);
|
|
uint32 nbytes = bcnt + 4 + 2; // +2 for terminating null character
|
|
QASSERT(30472, nbytes > bcnt); // check for integer overflow
|
|
uint8 *raw = (uint8 *)qalloc(nbytes);
|
|
if ( raw != NULL )
|
|
{
|
|
*(uint32*)raw = bcnt;
|
|
raw += 4;
|
|
unpack_obj(raw, bcnt, in, end);
|
|
raw[bcnt] = '\0';
|
|
raw[bcnt+1] = '\0';
|
|
var.bstrVal = raw;
|
|
ok = true;
|
|
}
|
|
}
|
|
break;
|
|
case VT_LPSTR: // = 0x001E,
|
|
case VT_LPWSTR: // = 0x001F,
|
|
{
|
|
char *tmp = qstrdup(unpack_str(in, end));
|
|
var.byref = tmp;
|
|
ok = true;
|
|
}
|
|
break;
|
|
case VT_DISPATCH: // = 0x0009,
|
|
case VT_ERROR: // = 0x000A,
|
|
case VT_BOOL: // = 0x000B,
|
|
case VT_VARIANT: // = 0x000C,
|
|
case VT_UNKNOWN: // = 0x000D,
|
|
case VT_DECIMAL: // = 0x000E,
|
|
case VT_I1: // = 0x0010,
|
|
case VT_UI1: // = 0x0011,
|
|
var.bVal = unpack_db(in, end);
|
|
ok = true;
|
|
break;
|
|
case VT_I8: // = 0x0014,
|
|
case VT_UI8: // = 0x0015,
|
|
var.ullVal = unpack_dq(in, end);
|
|
ok = true;
|
|
break;
|
|
case VT_INT: // = 0x0016,
|
|
case VT_UINT: // = 0x0017,
|
|
case VT_HRESULT: // = 0x0019,
|
|
var.uintVal = unpack_dd(in, end);
|
|
ok = true;
|
|
break;
|
|
case VT_VOID: // = 0x0018,
|
|
case VT_PTR: // = 0x001A,
|
|
case VT_SAFEARRAY: // = 0x001B,
|
|
case VT_CARRAY: // = 0x001C,
|
|
case VT_USERDEFINED: // = 0x001D,
|
|
case VT_RECORD: // = 0x0024,
|
|
case VT_INT_PTR: // = 0x0025,
|
|
case VT_UINT_PTR: // = 0x0026,
|
|
break;
|
|
default: break;
|
|
}
|
|
return ok;
|
|
}
|
|
#endif // __NT__
|
|
|
|
#endif // VARSER_HPP
|