/* * 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(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 szBuf; CStackBuffer wszBuf; LPCWSTR pwszType = NULL; LPWSTR pwszValue = NULL; SCODE sc = S_OK; SYSTEMTIME st; UINT cch; UINT i; VARIANT* pvarTrue = reinterpret_cast(&var); switch (var.vt) { case VT_NULL: case VT_EMPTY: break; case VT_BSTR: pwszValue = static_cast(var.bstrVal); break; case VT_LPWSTR: pwszValue = var.pwszVal; break; case VT_LPSTR: if (!var.pszVal) break; cch = static_cast(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(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(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; }