//************************************************************* // // Copyright (c) Microsoft Corporation 1999 - 2000 // All rights reserved // // variant.hxx // //************************************************************* #include "rsop.hxx" //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::CVariant // // Purpose: Constructor for CVariant class. Initializes the // storage of the variant data. // // Params: none // // Return value: none // // Notes: // //------------------------------------------------------------ CVariant::CVariant() : _iCurrentArrayIndex(0), _cMaxArrayElements(0) { VariantInit(&_var); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::~CVariant // // Purpose: Denstructor for CVariant class. Frees any data // allocated to store variant data. // // Params: none // // Return value: none // // Notes: // //------------------------------------------------------------ CVariant::~CVariant() { HRESULT hr; hr = VariantClear(&_var); ASSERT(SUCCEEDED(hr)); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetStringValue // // Purpose: Sets the type of the variant to VT_BSTR and creates // a bstr to store the string. // // Params: wszValue -- this unicode string is the value to // which we want to set this variant // // Return value: returns S_OK if successful, other // error code if not // // Notes: The variant should not be set to a value after // this is called -- otherwise, you may lose reference // to allocated memory -- the value is meant to be set // only once. // //------------------------------------------------------------ HRESULT CVariant::SetStringValue(WCHAR* wszValue) { XBStr xString; ASSERT(VT_EMPTY == _var.vt); xString = wszValue; if (!xString) { return E_OUTOFMEMORY; } _var.vt = VT_BSTR; _var.bstrVal = xString.Acquire(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetLongValue // // Purpose: Sets the type of the variant to VT_I4 and creates // a bstr to store the string. // // Params: lValue -- this LONG value is the value to // which we want to set this variant // // Return value: returns S_OK if successful, other // error code if not // // Notes: The variant should not be set to a value after // this is called -- otherwise, you may lose reference // to allocated memory -- the value is meant to be set // only once. // //------------------------------------------------------------ HRESULT CVariant::SetLongValue(LONG lValue) { ASSERT(VT_EMPTY == _var.vt); _var.vt = VT_I4; _var.lVal = lValue; return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetBoolValue // // Purpose: Sets the type of the variant to VT_BOOL and stores the value // // Params: bValue -- this boolean value is the value to // which we want to set this variant // // Return value: returns S_OK if successful, other // error code if not // // Notes: The variant should not be set to a value after // this is called -- otherwise, you may lose reference // to allocated memory -- the value is meant to be set // only once. // //------------------------------------------------------------ HRESULT CVariant::SetBoolValue(BOOL bValue) { ASSERT(VT_EMPTY == _var.vt); _var.vt = VT_BOOL; _var.boolVal = bValue ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetNextLongArrayElement // // Purpose: Adds an element in an array of strings to a // specified string // // Params: Value -- the value to which to add as an element // cMaxElements (optional) -- the maximum number // of elements in this array -- must be specified // the first time this method is called on this object // // Return value: returns S_OK if successful, other // error code if not // // Notes: // //------------------------------------------------------------ HRESULT CVariant::SetNextLongArrayElement( LONG Value, DWORD cMaxElements) { HRESULT hr; // // Add the long to the correct index // in the array // hr = SetNextArrayElement( VT_I4, cMaxElements, &Value); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetNextStringArrayElement // // Purpose: Adds an element to an array of strings // // Params: wszValue -- the value to which to add as an element // cMaxElements (optional) -- the maximum number // of elements in this array -- must be specified // the first time this method is called on this object // // Return value: returns S_OK if successful, other // error code if not // // Notes: // //------------------------------------------------------------ HRESULT CVariant::SetNextStringArrayElement( WCHAR* wszValue, DWORD cMaxElements) { HRESULT hr; XBStr xString; // // Create a bstr from the supplied unicode string // xString = wszValue; if (!xString) { return E_OUTOFMEMORY; } // // Now add the unicode string to the correct index // in the array // hr = SetNextArrayElement( VT_BSTR, cMaxElements, xString); // // If we've succeeded in setting the element, it now // owns the reference, so we release our reference // if (SUCCEEDED(hr)) { (void) xString.Acquire(); } return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetNextByteArrayElement // // Purpose: Adds an element in an array of bytes to a byte array // // Params: byteValue -- the value to which to add as an element // cMaxElements (optional) -- the maximum number // of elements in this array -- must be specified // the first time this method is called on this object // // Return value: returns S_OK if successful, other // error code if not // // Notes: // //------------------------------------------------------------ HRESULT CVariant::SetNextByteArrayElement( BYTE byteValue, DWORD cMaxElements) { HRESULT hr; // // Add the long to the correct index // in the array // hr = SetNextArrayElement( VT_UI1, cMaxElements, &byteValue); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::IsStringValue // // Purpose: Determines whether this variant represents a string // // Params: // // Return value: returns TRUE if this is a string, FALSE if not // //------------------------------------------------------------ BOOL CVariant::IsStringValue() { return VT_BSTR == _var.vt; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::IsLongValue // // Purpose: Determines whether this variant represents a long // // Params: // // Return value: returns TRUE if this is a long, FALSE if not // //------------------------------------------------------------ BOOL CVariant::IsLongValue() { return VT_I4 == _var.vt; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::operator VARIANT*() // // Purpose: Casts this object into a VARIANT structure pointer // // Params: // // Return value: returns a pointer to a VARIANT structure // // Notes: // //------------------------------------------------------------ CVariant::operator VARIANT*() { return &_var; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::SetNextArrayElement // // Purpose: Adds an element to an array of objects of arbitrary // type // // Params: wszValue -- the value to which to set the element // cMaxElements (optional) -- the maximum number // of elements in this array -- must be specified // the first time this method is called on this object // // Return value: returns S_OK if successful, other // error code if not // // Notes: // //------------------------------------------------------------ HRESULT CVariant::SetNextArrayElement( VARTYPE varType, DWORD cMaxElements, LPVOID pvData) { HRESULT hr; // // If this array contains no elements, return the hr // that lets the caller know that this array is full // if ( 0 == cMaxElements ) { return S_FALSE; } // // The first time this method is called on this object, // we should allocate space for the array // if ( !_iCurrentArrayIndex ) { ASSERT( cMaxElements ); ASSERT( VT_EMPTY == _var.vt ); // // Allocate space for the array with elements // of the caller specifed type and number // hr = InitializeArray( varType, cMaxElements); if (FAILED(hr)) { return hr; } _cMaxArrayElements = cMaxElements; } ASSERT( ((DWORD) _iCurrentArrayIndex) < _cMaxArrayElements ); // // Now add the polymorphic object's IUnknown // into the array // hr = SafeArrayPutElement( _var.parray, &_iCurrentArrayIndex, pvData); // // If we've filled up the array, return S_FALSE to // signal that no more elements can be added // if (SUCCEEDED(hr)) { // // Increment our cursor into the array to the // next element // _iCurrentArrayIndex++; // // Check our current index -- if it's the same // as our maximum, we're full // if ( ((DWORD) _iCurrentArrayIndex) == _cMaxArrayElements) { hr = S_FALSE; } } return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Function: CVariant::InitializeArray // // Purpose: Private method that allocates space for an array // of a specified size and element type // // Params: varType -- type of elements that will be in the array // cMaxElements -- the size, in elements, of the array // // Return value: returns ERROR_SUCCESS if successful, other // win32 error code if not // // Notes: // //------------------------------------------------------------ HRESULT CVariant::InitializeArray( VARTYPE varType, DWORD cMaxElements) { SAFEARRAY* pSafeArray; SAFEARRAYBOUND arrayBound; // // Set the bounds of the array to be zero-based // arrayBound.lLbound = 0; arrayBound.cElements = cMaxElements; // // Allocate the array // pSafeArray = SafeArrayCreate( varType, 1, // 1 dimension &arrayBound); if (!pSafeArray) { return E_OUTOFMEMORY; } // // Set our state to refer to the allocated memory // with the specified type // _var.vt = VT_ARRAY | varType; _var.parray = pSafeArray; return S_OK; }