📄 comlib.cpp
字号:
switch (V_VT(v)) { case VT_BOOL: return (double) V_BOOL(v); case VT_UI1: return (double) V_UI1(v); case VT_I2: return (double) V_I2(v); case VT_I4: return (double) V_I4(v); case VT_R4: return (double) V_R4(v); case VT_R8: return (double) V_R8(v); case VT_BSTR: { double result; char * str = new char [comWideStrLen (V_BSTR (v)) + 1]; if (str == 0) return 0; comWideToAscii (str, V_BSTR(v), comWideStrLen (V_BSTR (v)) + 1); result = atof (str); delete [] str; return result; } } return 0; }/**************************************************************************** VariantChangeType - Converts a variant from one type to another.** This function converts one VARIANT of a specified type to another* VARIANT type. s and d must point to valid VARIANTs. ** Only conversion between the following types is supported: VT_BOOL, * VT_UI1, VT_I2, VT_I4, VT_R4, VT_R8, VT_BSTR.* * The wFlags parameter is ignored.** RETURNS:* \is* \i S_OK* On Success* \i E_INVALIDARG* If source or destination are not valid VARIANTS.* \i DISP_E_BADVARTYPE* The Variant isn't on of the following types: VT_BOOL, VT_UI1, VT_I2,* VT_I4, VT_R4, VT_R8, VT_BSTR.* \ie*/HRESULT VariantChangeType ( VARIANT * d, /* VARIANT to receive changed VARIANT */ VARIANT * s, /* VARIANT that holds existing data */ USHORT wFlags, /* Ignored */ VARTYPE vt /* VARIANT type to change to */ ) { HRESULT hr = S_OK; VARIANT tmp; /* check for NULL VARIANTs */ if ((d == NULL) || (s == NULL)) return E_INVALIDARG; /* Can only convert from some VT types */ switch (V_VT(s)) { case VT_BOOL: case VT_UI1: case VT_I2: case VT_I4: case VT_R4: case VT_R8: case VT_BSTR: break; default: return DISP_E_BADVARTYPE; } /* SPR#67805. To allow inline coersion use a tmp VARIANT to store source */ /* VARIANT so if it is inline it doesn't get errased. */ VariantInit (&tmp); VariantCopy (&tmp, s); hr = VariantClear (d); if (SUCCEEDED (hr)) { switch (vt) { case VT_BOOL: V_VT(d) = VT_BOOL; if (GetVariantValue (&tmp) == 0) { V_BOOL (d) = VARIANT_FALSE; } else { V_BOOL (d) = VARIANT_TRUE; } break; case VT_UI1: V_VT(d) = VT_UI1; V_UI1(d) = (BYTE)GetVariantValue (&tmp); break; case VT_I2: V_VT (d) = VT_I2; V_I2 (d) = (SHORT)GetVariantValue (&tmp); break; case VT_I4: V_VT (d) = VT_I4; V_I4 (d) = (LONG)GetVariantValue (&tmp); break; case VT_R4: V_VT (d) = VT_R4; V_R4 (d) = GetVariantValue(&tmp); break; case VT_R8: V_VT (d) = VT_R8; V_R8 (d) = GetVariantValue (&tmp); break; case VT_BSTR: V_VT (d) = VT_BSTR; switch (V_VT (&tmp)) { case VT_BSTR: // straight copy needed here. V_BSTR (d) = ::SysAllocString (V_BSTR (&tmp)); break; case VT_BOOL: // convert to True/False string if (GetVariantValue (&tmp) == 0) { const OLECHAR falseString [] = { 'F', 'a', 'l', 's', 'e', 0 }; V_BSTR (d) = ::SysAllocString (falseString); } else { const OLECHAR trueString [] = { 'T', 'r', 'u', 'e', 0 }; V_BSTR (d) = ::SysAllocString (trueString); } break; default: { // Allocate tmp buffer this way so as not to stress // the stack too much. char * tmpBuffer = new char [128]; if (0 == tmpBuffer) return E_OUTOFMEMORY; sprintf (tmpBuffer, "%f", GetVariantValue (&tmp)); OLECHAR * wStr = new OLECHAR [strlen (tmpBuffer) + 1]; if (0 == wStr) { delete []tmpBuffer; return E_OUTOFMEMORY; } comAsciiToWide (wStr, tmpBuffer, strlen (tmpBuffer) + 1); V_BSTR (d) = ::SysAllocString (wStr); delete []wStr; delete []tmpBuffer; } } break; default: hr = E_INVALIDARG; break; } } VariantClear (&tmp); return hr;}/* SAFEARRAY-related APIs. *//**************************************************************************** elementSize - Get's the size of the element in bytes.* * Returns the size of a VARIANT data type in bytes.** RETURNS: The size of the VARIANT data type or zero for unknown types.*.NOMANUAL**/static ULONG elementSize (VARTYPE sf) { switch (sf) { case VT_ERROR: return sizeof (SCODE); case VT_UI1: return sizeof (BYTE); case VT_I2: return sizeof (SHORT); case VT_I4: return sizeof (LONG); case VT_BSTR: return sizeof (BSTR); case VT_R4: return sizeof (float); case VT_R8: return sizeof (double); case VT_CY: return sizeof (CY); case VT_DATE: return sizeof (DATE); case VT_BOOL: return sizeof (VARIANT_BOOL); case VT_UNKNOWN:return sizeof (IUnknown *); case VT_VARIANT:return sizeof (VARIANT); default: return 0; } }/**************************************************************************** SafeArrayCreate - Creates a new SAFEARRAY.* * Creates a new array descriptor, allocates and initializes the data for * the array, and returns a pointer to the new array descriptor. ** The array will always be created with the features FADF_HAVEVARTYPE | * FADF_FIXEDSIZE | FADF_AUTO and the appropriate BSTR, VARIANT or IUNKNOWN* bit set.** RETURNS: The array descriptor, or NULL if the array could not be created. **/SAFEARRAY * SafeArrayCreate ( VARTYPE vt, /* The base type of the array. Neither */ /* the VT_ARRAY or the VT_BYREF flag */ /* can be set. */ /* VT_EMPTY and VT_NULL are not valid */ /* base types for the array. All other */ /* types are legal. */ UINT cDims, /* Number of dimensions in the array. */ SAFEARRAYBOUND * rgsabound /* Vector of bounds to allocate */ ) { MEM_SAFEARRAY * pArrayDesc = NULL; if (rgsabound == NULL) return NULL; if (cDims < 1) return NULL; /* Check for supported types */ switch (vt) { case VT_ERROR: case VT_UI1: case VT_I2: case VT_I4: case VT_R4: case VT_R8: case VT_CY: case VT_DATE: case VT_BOOL: case VT_UNKNOWN: case VT_VARIANT: case VT_BSTR: break; default: return NULL; } /* This will be sizeof (SAFEARRAYBOUND) bigger than it needs to be */ /* because WIDL defines a dummy SAFEARRAYBOUND record so that the */ /* defined name can be used. */ pArrayDesc = reinterpret_cast<MEM_SAFEARRAY *> (COM_MEM_ALLOC (sizeof (MEM_SAFEARRAY) + sizeof (SAFEARRAYBOUND) * cDims)); if (pArrayDesc == NULL) { /* No memory */ return NULL; } /* Can get away with just zeroing the first part of the structure. */ memset (pArrayDesc, '\0', sizeof (MEM_SAFEARRAY)); /* Allocate mutex */ pArrayDesc->pMutex = new VxMutex (); if (pArrayDesc->pMutex == NULL) { COM_MEM_FREE (pArrayDesc); return NULL; } /* Allocate data first since if it can't be done there isn't */ /* any point in proceeding further */ pArrayDesc->arrayData.cbElements = elementSize (vt); USHORT index; pArrayDesc->dataCount = 1; for (index = 0; index < cDims; index++) { pArrayDesc->dataCount *= rgsabound [index].cElements; } pArrayDesc->arrayData.pvData = COM_MEM_ALLOC (pArrayDesc->dataCount * pArrayDesc->arrayData.cbElements); if (pArrayDesc->arrayData.pvData == NULL) { /* We have a memory failure so delete the memory for the descriptor */ /* and return an error. */ COM_MEM_FREE (pArrayDesc); return NULL; } // zero all allocated memory memset (pArrayDesc->arrayData.pvData, '\0', pArrayDesc->dataCount * pArrayDesc->arrayData.cbElements); /* Copy the rgsbound data into the correct place in the structure */ memcpy (pArrayDesc->arrayData.rgsabound, rgsabound, sizeof (SAFEARRAYBOUND) * cDims); /* Fill in various fields with appropriate values */ pArrayDesc->vt = vt; pArrayDesc->arrayData.cDims = cDims; switch (vt) { case VT_VARIANT: { pArrayDesc->arrayData.fFeatures = FADF_VARIANT; /* VariantInit all members */ VARIANT * pVar = (VARIANT *)(pArrayDesc->arrayData.pvData); for (index = 0; index < pArrayDesc->dataCount; index++) { VariantInit (pVar + index); } } break; case VT_BSTR: pArrayDesc->arrayData.fFeatures = FADF_BSTR; break; case VT_UNKNOWN: pArrayDesc->arrayData.fFeatures = FADF_UNKNOWN; break; default: pArrayDesc->arrayData.fFeatures = 0; } pArrayDesc->arrayData.fFeatures |= FADF_HAVEVARTYPE | FADF_FIXEDSIZE | FADF_AUTO; pArrayDesc->arrayData.cLocks = 0; pArrayDesc->signature = SAFEARRAY_SIG; return &(pArrayDesc->arrayData); }/** ArrayElement - list class to hold reference to a SA so that the mutex* can be unlocked in case of failure during SA destroy.*/class ArrayElement { public: ArrayElement () { m_psa = NULL; } void setPsa (MEM_SAFEARRAY * psa) { m_psa = psa; } void unlock () { m_psa->pMutex->unlock (); } private: MEM_SAFEARRAY * m_psa; };/* List to hold above elements */typedef VxGenericListElement<ArrayElement> ListElem;typedef VxGenericList<ListElem,int,VxMutex> ARRAY_LIST;/**************************************************************************** CheckArray - Check a SAFEARRAY for outstanding locks.** This recurses through a SAFEARRAY of VARIANTs of SAFEARRAYs* to check if there are any locks outstanding.** RETURNS: S_OK if no locks exist and error code otherwise.*.NOMANUAL*/static HRESULT CheckArray ( MEM_SAFEARRAY * pArrayDesc, /* Array descriptor */ ARRAY_LIST & as /* list of array elements */ /* that have been checked */ ) { ULONG index; /* Check for a valid signature etc... */ if (pArrayDesc->signature != SAFEARRAY_SIG) { return E_INVALIDARG; } /* Lock the mutex so that nothing can do anything bad underneath us */ pArrayDesc->pMutex->lock(); /* Save the descriptor so it can be unlocked later */ as.pushHead (new ListElem); as.getHead ()->setPsa (pArrayDesc); if (pArrayDesc->arrayData.cLocks != 0) { return DISP_E_ARRAYISLOCKED; } /* Since we setup the array to have a VT when we create it we */ /* can use it in the deallocation. */ if (pArrayDesc->vt == VT_VARIANT) { VARIANT * var = reinterpret_cast<VARIANT *> (pArrayDesc->arrayData.pvData); for (index = 0; index < pArrayDesc->dataCount; index++) { /* Check if this variant contains an array */ if (V_VT (&(var [index])) & VT_ARRAY) { MEM_SAFEARRAY * ptr = SA2MSA(V_ARRAY(&(var [index]))); HRESULT hr = CheckArray (ptr, as); if (FAILED (hr)) { return hr; } } } } return S_OK; }/*************************************************************************** * DestroyArray - Deletes all SAFEARRAYs in a tree.** Recurses through a SAFEARRAY (and any VARIANTS containing SAFEARRAYs)* and deletes them.** RETURNS: N/A*.NOMANUAL*/void DestroyArray ( MEM_SAFEARRAY * pArrayDesc /* Array descriptor */ ) { ULONG index; switch (pArrayDesc->vt) { case VT_VARIANT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -