/*++ Copyright (C) 1996-2001 Microsoft Corporation Module Name: VAR.H Abstract: CVar & CVarVector. These are thread-safe translators for VARIANT and SAFEARRAY and represent all types support by WBEM. These are mutually nestable to any level. A CVarVector can contain an array of CVar, and a CVar can contain a CVarVector. One CVar can therefore contain a whole tree of CVar objects, themselves containing homogeneous or heterogeneous arrays of CVar objects. Note: CVar should not be bound to one type and then immediately coerced to a new type. This object is designed for speed, not safety, so there is no checking to see if this has been done. A memory leak is likely to occur. The assignment operator and copy constructors are the only method of changing the type on a CVar. Do NOT construct the object as a BSTR, for example, and then call SetDWORD. History: 16-Apr-96 a-raymcc Created. 12//17/98 sanjes - Partially Reviewed for Out of Memory. 18-Mar-99 a-dcrews Added out-of-memory exception handling --*/ #ifndef _VAR_H_ #define _VAR_H_ #include #include #define VT_EX_CVAR (VT_USERDEFINED | 0x80010000) #define VT_EX_CVARVECTOR (VT_USERDEFINED | 0x80010002) class CVarVector; typedef union { char cVal; // VT_I1 BYTE bVal; // VT_UI1 SHORT iVal; // VT_I2 WORD wVal; // VT_UI2 LONG lVal; // VT_I4 DWORD dwVal; // VT_UI4 VARIANT_BOOL boolVal; // VT_BOOL float fltVal; // VT_R4 double dblVal; // VT_R8 LPSTR pStr; // VT_LPSTR LPWSTR pWStr; // VT_LPWSTR BSTR Str; // VT_BSTR (stored as VT_LPWSTR) FILETIME Time; // VT_FILETIME BLOB Blob; // VT_BLOB LPCLSID pClsId; // VT_CLSID IUnknown* pUnk; // VT_UNKNOWN IDispatch* pDisp; // VT_DISPATCH CVarVector *pVarVector; // VT_EX_CVARVECTOR } METAVALUE; class POLARITY CVar { private: int m_vt; METAVALUE m_value; int m_nStatus; BOOL m_bCanDelete; void Init(); public: enum { no_error, unsupported, failed }; CVar() { Init(); } ~CVar(); CVar(CVar &); CVar& operator =(CVar &); CVar(char c) { Init(); SetChar(c); } CVar(BYTE b) { Init(); SetByte(b); } CVar(SHORT s) { Init(); SetShort(s); } CVar(WORD w) { Init(); SetWord(w); } CVar(LONG l) { Init(); SetLong(l); } CVar(DWORD dw) { Init(); SetDWORD(dw); } CVar(float f) { Init(); SetFloat(f); } CVar(double d) { Init(); SetDouble(d); } CVar(VARIANT_BOOL b,int){ Init(); SetBool(b); } CVar(LPSTR p, BOOL bAcquire = FALSE) { Init(); SetLPSTR(p, bAcquire); } CVar(LPWSTR p, BOOL bAcquire = FALSE) { Init(); SetLPWSTR(p, bAcquire); } CVar(int, BSTR b, BOOL bAcquire = FALSE) { Init(); SetBSTR(b, bAcquire); } // Dummy int required for context, since BSTR is also LPWSTR // from Win32 point of view, although the VT_ indicators differ. CVar(CLSID *p, BOOL bAcquire = FALSE) { Init(); SetClsId(p, bAcquire); } CVar(BLOB *p, BOOL bAcquire = FALSE) { Init(); SetBlob(p, bAcquire); } CVar(FILETIME *p) { Init(); SetFileTime(p); } CVar(CVarVector *p, BOOL bAcquire = FALSE) { Init(); SetVarVector(p, bAcquire); } CVar(VARIANT *p) { Init(); SetVariant(p); } CVar(int nType, SAFEARRAY *p) { Init(); SetSafeArray(nType, p); } int Status() { return m_nStatus; } int DumpText(FILE *fStream); int GetType() { return m_vt; } int GetOleType(); void Empty(); int operator ==(CVar &Other); BOOL CompareTo(CVar& Other, BOOL bIgnoreCase); void SetRaw(int vt, void* pvData, int nDataLen); void* GetRawData() {return (void*)&m_value;} BOOL CanDelete() {return m_bCanDelete;} void SetCanDelete(BOOL bCanDelete) {m_bCanDelete = bCanDelete;} // Numeric types. // ============== void SetAsNull() { m_vt = VT_NULL; m_value.lVal = 0; } BOOL IsNull() {return m_vt == VT_NULL;} BOOL IsDataNull(); void SetChar(char c) { m_vt = VT_I1; m_value.cVal = c; } char GetChar() { return m_value.cVal; } operator char() { return m_value.cVal; } void SetByte(BYTE b) { m_vt = VT_UI1; m_value.bVal = b; } BYTE GetByte() { return m_value.bVal; } operator BYTE() { return m_value.bVal; } void SetShort(SHORT iVal) { m_vt = VT_I2; m_value.iVal = iVal; } SHORT GetShort() { return m_value.iVal; } operator SHORT() { return m_value.iVal; } void SetWord(WORD wVal) { m_vt = VT_UI2; m_value.wVal = wVal; } WORD GetWord() { return m_value.wVal; } operator WORD() { return m_value.wVal; } void SetLong(LONG lVal) { m_value.lVal = lVal; m_vt = VT_I4; } LONG GetLong() { return m_value.lVal; } operator LONG() { return m_value.lVal; } void SetDWORD(DWORD dwVal) { m_value.dwVal = dwVal; m_vt = VT_UI4; } DWORD GetDWORD() { return m_value.dwVal; } operator DWORD() { return m_value.dwVal; } void SetBool(VARIANT_BOOL b) { m_value.boolVal = b; m_vt = VT_BOOL; } VARIANT_BOOL GetBool() { return m_value.boolVal; } void SetFloat(float f) { m_value.fltVal = f; m_vt = VT_R4; } float GetFloat() { return m_value.fltVal; } operator float() { return m_value.fltVal; } void SetDouble(double dblVal) { m_value.dblVal = dblVal; m_vt = VT_R8; } double GetDouble() { return m_value.dblVal; } operator double() { return m_value.dblVal; } void SetDispatch(IDispatch* pDisp); IDispatch* GetDispatch() {if(m_value.pDisp) m_value.pDisp->AddRef(); return m_value.pDisp;} void SetUnknown(IUnknown* pUnk); IUnknown* GetUnknown() {if(m_value.pUnk) m_value.pUnk->AddRef(); return m_value.pUnk;} void SetEmbeddedObject(IUnknown* pUnk) {SetUnknown(pUnk);} IUnknown* GetEmbeddedObject() {return GetUnknown();} int SetVariant(VARIANT *pSrc, BOOL fOptimize = FALSE); void FillVariant(VARIANT* pDest, BOOL fOptimized = FALSE); VARIANT *GetNewVariant(); // String types. // ============= BOOL SetLPWSTR(LPWSTR pVal, BOOL bAcquire = FALSE); wchar_t *GetLPWSTR() { return m_value.pWStr; } operator LPWSTR() { return m_value.pWStr; } BOOL SetLPSTR(LPSTR pStr, BOOL bAcquire = FALSE); LPSTR GetLPSTR() { return m_value.pStr; } operator LPSTR() { return m_value.pStr; } BOOL SetBSTR(BSTR str, BOOL bAcquire = FALSE); BSTR GetBSTR(); // Makes a dynamic copy which must be freed. // Misc. types. // ============ void SetFileTime(FILETIME *pft) { m_value.Time = *pft; m_vt = VT_FILETIME; } FILETIME GetFileTime() { return m_value.Time; } operator FILETIME() { return m_value.Time; } void SetBlob(BLOB *pBlob, BOOL bAcquire = FALSE); BLOB *GetBlob() { return &m_value.Blob; } operator BLOB *() { return &m_value.Blob; } void SetClsId(CLSID *pClsId, BOOL bAcquire); CLSID* GetClsId() { return m_value.pClsId; } // Return value is read-only operator CLSID*() { return m_value.pClsId; } // Return value is read-only void SetVarVector(CVarVector *pVec, BOOL bAcquire); CVarVector *GetVarVector() { return m_value.pVarVector; } operator CVarVector *() { return m_value.pVarVector; } void SetSafeArray(int nType, SAFEARRAY *pArray); // Copies the source SAFEARRAY *GetNewSafeArray(); // New SAFEARRAY which must be released void SetOptimizedSafeArray(int nType, SAFEARRAY *pArray, BOOL fAcquire = FALSE); SAFEARRAY* GetOptimizedSafeArray( void ); static BSTR TypeToText(int nType); BSTR GetTypeText(); BSTR GetText(long lFlags, long lType = 0, LPCWSTR szFormat = NULL); BOOL ChangeTypeTo(VARTYPE vtNew); BOOL ChangeTypeToEx(VARTYPE vtNew, LCID lcid = 0x409 ); BOOL ToSingleChar(); BOOL ToUI4(); }; class POLARITY CVarVector { int m_nType; CFlexArray m_Array; int m_nStatus; CSafeArray* m_pSafeArray; void* m_pRawData; public: enum { no_error, failed, unsupported }; CVarVector(); CVarVector(int nVarType, int nInitSize = 32, int nGrowBy = 32); // These two only support limited SAFEARRAY types. // =============================================== CVarVector(int nVarType, SAFEARRAY *pSrc, BOOL fOptimized = FALSE); SAFEARRAY *GetNewSafeArray(); SAFEARRAY* GetSafeArray( BOOL fAcquire = FALSE ); int GetType() { return m_nType; } int Status() { return m_nStatus; } void Empty(); ~CVarVector(); CVarVector(CVarVector &Src); CVarVector& operator =(CVarVector &Src); int operator ==(CVarVector &Src); BOOL CompareTo(CVarVector& Other, BOOL bIgnoreCase); int Size(); int Add(CVar &Value); int Add(CVar *pAcquiredPtr); CVar& GetAt(int nIndex); CVar& operator [](int nIndex); int RemoveAt(int nIndex); int InsertAt(int nIndex, CVar &Value); BSTR GetText(long lFlags, long lType = 0); BOOL ToSingleChar(); BOOL ToUI4(); BOOL IsOptimized( void ) { return NULL != m_pSafeArray; } BOOL MakeOptimized( int nVarType, int nInitSize = 32, int nGrowBy = 32 ); void SetRawArrayBinding( int nBinding ); HRESULT AccessRawArray( void** ppv ); HRESULT UnaccessRawArray( void ); // We access raw data using internal data member. HRESULT InternalRawArrayAccess( void ); static BOOL IsValidVectorType( int nVarType ); static BOOL IsValidVectorArray( int nVarType, SAFEARRAY* pArray ); void FillCVarAt(int nIndex, CVar& vTemp); BOOL DoesVectorTypeMatchArrayType( void ); HRESULT SetRawArrayData( void* pvData, int nNumElements, int nElementSize ); HRESULT GetRawArrayData( void* pvDest, int nBuffSize ); BOOL SetRawArraySize( int nSize ); int GetElementSize( void ); }; class CUnaccessVarVector { private: CVarVector* m_pVV; public: CUnaccessVarVector( CVarVector* pvv = NULL ) : m_pVV( pvv ) {} ~CUnaccessVarVector() { Unaccess(); } void SetVV( CVarVector* pvv ) { m_pVV = pvv; } void Unaccess( void ) { if ( NULL != m_pVV ) m_pVV->UnaccessRawArray(); m_pVV = NULL; } }; #endif