You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
9.4 KiB
457 lines
9.4 KiB
/*
|
|
* V A R . C P P
|
|
*
|
|
* XML document processing
|
|
*
|
|
* Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
|
|
*/
|
|
|
|
#include "_xml.h"
|
|
|
|
// ScVariantTypeFromString()
|
|
//
|
|
// Returns the variant type associated with a dav datatype string
|
|
//
|
|
SCODE
|
|
ScVariantTypeFromString (LPCWSTR pwszType, USHORT& vt)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
// NULL, "string" and "uri"
|
|
//
|
|
if (!pwszType ||
|
|
!_wcsicmp (pwszType, gc_wszDavType_String) ||
|
|
!_wcsicmp (pwszType, gc_wszUri))
|
|
{
|
|
vt = VT_LPWSTR;
|
|
}
|
|
// integer
|
|
//
|
|
else if (!_wcsicmp (pwszType, gc_wszDavType_Int))
|
|
{
|
|
vt = VT_I4;
|
|
}
|
|
// boolean.tf
|
|
//
|
|
else if (!_wcsicmp (pwszType, gc_wszDavType_Boolean))
|
|
{
|
|
vt = VT_BOOL;
|
|
}
|
|
// float (Floating/Reals)
|
|
//
|
|
else if (!_wcsicmp (pwszType, gc_wszDavType_Float))
|
|
{
|
|
vt = VT_R8;
|
|
}
|
|
// date.iso8601
|
|
//
|
|
else if (!_wcsicmp (pwszType, gc_wszDavType_Date_ISO8601))
|
|
{
|
|
vt = VT_FILETIME;
|
|
}
|
|
else
|
|
{
|
|
DebugTrace ("ScVariantTypeFromString(): unknown type");
|
|
vt = VT_LPWSTR;
|
|
sc = S_OK;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
// ScVariantValueFromString() ------------------------------------------------
|
|
//
|
|
// Sets the value of a PROPVARIANT
|
|
//
|
|
SCODE
|
|
ScVariantValueFromString (PROPVARIANT& var, LPCWSTR pwszValue)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
LPWSTR pwsz;
|
|
SYSTEMTIME st;
|
|
|
|
switch (var.vt)
|
|
{
|
|
case VT_LPWSTR:
|
|
|
|
if (pwszValue)
|
|
{
|
|
pwsz = static_cast<LPWSTR>(CoTaskMemAlloc(CbSizeWsz(wcslen(pwszValue))));
|
|
if (NULL == pwsz)
|
|
{
|
|
DebugTrace ("ScVariantValueFromString() - CoTaskMemAlloc() failed to allocate %d bytes\n", CbSizeWsz(wcslen(pwszValue)));
|
|
|
|
sc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto ret;
|
|
}
|
|
|
|
wcscpy (pwsz, pwszValue);
|
|
var.pwszVal = pwsz;
|
|
}
|
|
else
|
|
var.pwszVal = NULL;
|
|
|
|
break;
|
|
|
|
case VT_I4:
|
|
|
|
Assert (pwszValue);
|
|
var.lVal = _wtoi (pwszValue);
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
|
|
#pragma warning(disable:4310) // wtypes.h is broken
|
|
|
|
Assert (pwszValue);
|
|
if (!_wcsnicmp (pwszValue, gc_wsz1, 1))
|
|
var.boolVal = VARIANT_TRUE;
|
|
else if (!_wcsnicmp (pwszValue, gc_wsz0, 1))
|
|
var.boolVal = VARIANT_FALSE;
|
|
else
|
|
{
|
|
sc = E_INVALIDARG;
|
|
goto ret;
|
|
}
|
|
break;
|
|
|
|
#pragma warning(default:4310) // wtypes.h is broken
|
|
|
|
case VT_R8:
|
|
|
|
Assert (pwszValue);
|
|
var.dblVal = wcstod (pwszValue, NULL);
|
|
break;
|
|
|
|
case VT_FILETIME:
|
|
|
|
Assert (pwszValue);
|
|
memset (&var.filetime, 0, sizeof(FILETIME));
|
|
if (!FGetSystimeFromDateIso8601 (pwszValue, &st))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
goto ret;
|
|
}
|
|
SystemTimeToFileTime (&st, &var.filetime);
|
|
break;
|
|
|
|
default:
|
|
|
|
Assert (pwszValue);
|
|
TrapSz ("ScVariantValueFromString() unknown type");
|
|
|
|
sc = E_INVALIDARG;
|
|
goto ret;
|
|
}
|
|
|
|
ret:
|
|
|
|
return sc;
|
|
}
|
|
|
|
// ScEmitFromVariant() ------------------------------------------------
|
|
//
|
|
SCODE
|
|
ScEmitFromVariant (CXMLEmitter& emitter,
|
|
CEmitterNode& enParent,
|
|
LPCWSTR pwszTag,
|
|
PROPVARIANT& var)
|
|
{
|
|
CEmitterNode en;
|
|
CStackBuffer<CHAR,110> szBuf;
|
|
CStackBuffer<WCHAR,128> wszBuf;
|
|
LPCWSTR pwszType = NULL;
|
|
LPWSTR pwszValue = NULL;
|
|
SCODE sc = S_OK;
|
|
SYSTEMTIME st;
|
|
UINT cch;
|
|
UINT i;
|
|
VARIANT* pvarTrue = reinterpret_cast<VARIANT*>(&var);
|
|
|
|
switch (var.vt)
|
|
{
|
|
case VT_NULL:
|
|
case VT_EMPTY:
|
|
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
|
|
pwszValue = static_cast<LPWSTR>(var.bstrVal);
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
|
|
pwszValue = var.pwszVal;
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
|
|
if (!var.pszVal)
|
|
break;
|
|
|
|
cch = static_cast<UINT>(strlen (var.pszVal));
|
|
pwszValue = wszBuf.resize(CbSizeWsz(cch));
|
|
if (NULL == pwszValue)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto ret;
|
|
}
|
|
|
|
// We know that the numbers are in ASCII codepage and we know
|
|
// that the buffer size is big enough.
|
|
//
|
|
cch = MultiByteToWideChar (CP_ACP,
|
|
MB_ERR_INVALID_CHARS,
|
|
var.pszVal,
|
|
cch + 1,
|
|
pwszValue,
|
|
wszBuf.celems());
|
|
if (0 == cch)
|
|
{
|
|
sc = HRESULT_FROM_WIN32(GetLastError());
|
|
Assert(FAILED(sc));
|
|
goto ret;
|
|
}
|
|
break;
|
|
|
|
case VT_I1:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_itow (pvarTrue->cVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_UI1:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_ultow (var.bVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_I2:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_itow (var.iVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_UI2:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_ultow (var.uiVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_I4:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_ltow (var.lVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_UI4:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_ultow (var.ulVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_I8:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
|
|
//$ REVIEW: negative values of _int64 seem to have problems in
|
|
// the __i64tow() API. Handle those cases ourselves by using the wrapper
|
|
// function Int64ToPwsz.
|
|
//
|
|
Int64ToPwsz (&var.hVal.QuadPart, wszBuf.get(), wszBuf.size());
|
|
//
|
|
//$ REVIEW: end
|
|
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_UI8:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_ui64tow (var.uhVal.QuadPart, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_INT:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_itow (pvarTrue->intVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_UINT:
|
|
|
|
pwszType = gc_wszDavType_Int;
|
|
_ultow (pvarTrue->uintVal, wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
|
|
pwszType = gc_wszDavType_Boolean;
|
|
_itow (!(VARIANT_FALSE == var.boolVal), wszBuf.get(), 10);
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_R4:
|
|
// _gcvt could add 8 extra chars then the number of digits asked
|
|
// for example -3.1415e+019, '-','.' "e+019", plus the terminating
|
|
// NULL doesn't count in digits asked. so we have to reserve
|
|
// enough space in the provided buffer. using 11 to make sure
|
|
// we are absolutely safe.
|
|
//
|
|
_gcvt (var.fltVal, szBuf.celems() - 11, szBuf.get());
|
|
|
|
cch = static_cast<UINT>(strlen(szBuf.get()));
|
|
pwszValue = wszBuf.resize(CbSizeWsz(cch));
|
|
if (NULL == pwszValue)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto ret;
|
|
}
|
|
|
|
// We know that the numbers are in ASCII codepage and we know
|
|
// that the buffer size is big enough.
|
|
//
|
|
cch = MultiByteToWideChar(CP_ACP,
|
|
MB_ERR_INVALID_CHARS,
|
|
szBuf.get(),
|
|
cch + 1,
|
|
wszBuf.get(),
|
|
wszBuf.celems());
|
|
if (0 == cch)
|
|
{
|
|
sc = HRESULT_FROM_WIN32(GetLastError());
|
|
Assert(FAILED(sc));
|
|
goto ret;
|
|
}
|
|
|
|
pwszType = gc_wszDavType_R4;
|
|
break;
|
|
|
|
case VT_R8:
|
|
// _gcvt could add 8 extra chars then the number of digits asked
|
|
// for example -3.1415e+019, '-','.' "e+019", plus the terminating
|
|
// NULL doesn't count in digits asked. so we have to reserve
|
|
// enough space in the provided buffer. using 11 to make sure
|
|
// we are absolutely safe.
|
|
//
|
|
_gcvt (var.dblVal, szBuf.celems() - 11, szBuf.get());
|
|
|
|
cch = static_cast<UINT>(strlen(szBuf.get()));
|
|
pwszValue = wszBuf.resize(CbSizeWsz(cch));
|
|
if (NULL == pwszValue)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto ret;
|
|
}
|
|
|
|
// We know that the numbers are in ASCII codepage and we know
|
|
// that the buffer size is big enough.
|
|
//
|
|
cch = MultiByteToWideChar(CP_ACP,
|
|
MB_ERR_INVALID_CHARS,
|
|
szBuf.get(),
|
|
cch + 1,
|
|
wszBuf.get(),
|
|
wszBuf.celems());
|
|
if (0 == cch)
|
|
{
|
|
sc = HRESULT_FROM_WIN32(GetLastError());
|
|
Assert(FAILED(sc));
|
|
goto ret;
|
|
}
|
|
|
|
pwszType = gc_wszDavType_Float;
|
|
break;
|
|
|
|
case VT_FILETIME:
|
|
|
|
if (!FileTimeToSystemTime (&var.filetime, &st))
|
|
{
|
|
// In case the filetime is invalid, default to zero
|
|
//
|
|
FILETIME ftDefault = {0};
|
|
FileTimeToSystemTime (&ftDefault, &st);
|
|
}
|
|
if (!FGetDateIso8601FromSystime(&st, wszBuf.get(), wszBuf.celems()))
|
|
return E_INVALIDARG;
|
|
|
|
pwszType = gc_wszDavType_Date_ISO8601;
|
|
pwszValue = wszBuf.get();
|
|
break;
|
|
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
{
|
|
// Create the emitter node;
|
|
//
|
|
sc = en.ScConstructNode (emitter,
|
|
enParent.Pxn(),
|
|
pwszTag,
|
|
NULL,
|
|
gc_wszDavType_Mvstring);
|
|
if (FAILED (sc))
|
|
goto ret;
|
|
|
|
// Add the values
|
|
//
|
|
for (i = 0; i < var.calpwstr.cElems; i++)
|
|
{
|
|
CEmitterNode enSub;
|
|
sc = en.ScAddNode (gc_wszXml_V,
|
|
enSub,
|
|
var.calpwstr.pElems[i]);
|
|
if (FAILED (sc))
|
|
goto ret;
|
|
}
|
|
|
|
// In this case we have built up the node ourselves. We do not
|
|
// want to fall into recreating the node.
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_DISPATCH:
|
|
case VT_ERROR:
|
|
case VT_VARIANT:
|
|
case VT_UNKNOWN:
|
|
case VT_DECIMAL:
|
|
case VT_RECORD:
|
|
case VT_BLOB:
|
|
case VT_STREAM:
|
|
case VT_STORAGE:
|
|
case VT_STREAMED_OBJECT:
|
|
case VT_STORED_OBJECT:
|
|
case VT_BLOB_OBJECT:
|
|
case VT_CF:
|
|
case VT_CLSID:
|
|
default:
|
|
|
|
TrapSz ("ScEmitterNodeFromVariant() unknown type");
|
|
return E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
// Create the emitter node
|
|
//
|
|
sc = en.ScConstructNode (emitter,
|
|
enParent.Pxn(),
|
|
pwszTag,
|
|
pwszValue,
|
|
pwszType);
|
|
if (FAILED (sc))
|
|
goto ret;
|
|
|
|
ret:
|
|
return sc;
|
|
}
|