Files
sigmaker-ida/idasdk76/plugins/pdb/varser.hpp
2021-10-31 21:20:46 +02:00

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