📄 safearray.c
字号:
*
* RETURNS
* Success: S_OK. ppvData contains a pointer to the item.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* This function does not lock the array.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
{
USHORT dim;
ULONG cell = 0, dimensionSize = 1;
SAFEARRAYBOUND* psab;
LONG c1;
TRACE("(%p,%p,%p)\n", psa, rgIndices, ppvData);
/* The general formula for locating the cell number of an entry in an n
* dimensional array (where cn = coordinate in dimension dn) is:
*
* c1 + c2 * sizeof(d1) + c3 * sizeof(d2) ... + cn * sizeof(c(n-1))
*
* We calculate the size of the last dimension at each step through the
* dimensions to avoid recursing to calculate the last dimensions size.
*/
if (!psa || !rgIndices || !ppvData)
return E_INVALIDARG;
psab = psa->rgsabound + psa->cDims - 1;
c1 = *rgIndices++;
if (c1 < psab->lLbound || c1 >= psab->lLbound + (LONG)psab->cElements)
return DISP_E_BADINDEX; /* Initial index out of bounds */
for (dim = 1; dim < psa->cDims; dim++)
{
dimensionSize *= psab->cElements;
psab--;
if (!psab->cElements ||
*rgIndices < psab->lLbound ||
*rgIndices >= psab->lLbound + (LONG)psab->cElements)
return DISP_E_BADINDEX; /* Index out of bounds */
cell += (*rgIndices - psab->lLbound) * dimensionSize;
rgIndices++;
}
cell += (c1 - psa->rgsabound[psa->cDims - 1].lLbound);
*ppvData = (char*)psa->pvData + cell * psa->cbElements;
return S_OK;
}
/************************************************************************
* SafeArrayDestroyData (OLEAUT32.39)
*
* Destroy the data associated with a SafeArray.
*
* PARAMS
* psa [I] Array to delete the data from
*
* RETURNS
* Success: S_OK. All items and the item data are freed.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
{
TRACE("(%p)\n", psa);
if (!psa)
return E_INVALIDARG;
if (psa->cLocks)
return DISP_E_ARRAYISLOCKED; /* Can't delete a locked array */
/* Delete the actual item data */
if (FAILED(SAFEARRAY_DestroyData(psa, 0)))
return E_UNEXPECTED;
if (psa->pvData)
{
if (psa->fFeatures & FADF_STATIC)
{
ZeroMemory(psa->pvData, SAFEARRAY_GetCellCount(psa) * psa->cbElements);
return S_OK;
}
/* If this is not a vector, free the data memory block */
if (!(psa->fFeatures & FADF_CREATEVECTOR))
{
if (!SAFEARRAY_Free(psa->pvData))
return E_UNEXPECTED;
psa->pvData = NULL;
}
else
psa->fFeatures |= FADF_DATADELETED; /* Mark the data deleted */
}
return S_OK;
}
/************************************************************************
* SafeArrayCopyData (OLEAUT32.412)
*
* Copy all data from one SafeArray to another.
*
* PARAMS
* psaSource [I] Source for copy
* psaTarget [O] Destination for copy
*
* RETURNS
* Success: S_OK. psaTarget contains a copy of psaSource.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* The two arrays must have the same number of dimensions and elements.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget)
{
int dim;
TRACE("(%p,%p)\n", psaSource, psaTarget);
if (!psaSource || !psaTarget ||
psaSource->cDims != psaTarget->cDims ||
psaSource->cbElements != psaTarget->cbElements)
return E_INVALIDARG;
/* Each dimension must be the same size */
for (dim = psaSource->cDims - 1; dim >= 0 ; dim--)
if (psaSource->rgsabound[dim].cElements !=
psaTarget->rgsabound[dim].cElements)
return E_INVALIDARG;
if (SUCCEEDED(SAFEARRAY_DestroyData(psaTarget, 0)) &&
SUCCEEDED(SAFEARRAY_CopyData(psaSource, psaTarget)))
return S_OK;
return E_UNEXPECTED;
}
/************************************************************************
* SafeArrayDestroy (OLEAUT32.16)
*
* Destroy a SafeArray.
*
* PARAMS
* psa [I] Array to destroy
*
* RETURNS
* Success: S_OK. All resources used by the array are freed.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
{
TRACE("(%p)\n", psa);
if(!psa)
return S_OK;
if(psa->cLocks > 0)
return DISP_E_ARRAYISLOCKED;
/* Native doesn't check to see if the free succeeds */
SafeArrayDestroyData(psa);
SafeArrayDestroyDescriptor(psa);
return S_OK;
}
/************************************************************************
* SafeArrayCopy (OLEAUT32.27)
*
* Make a duplicate of a SafeArray.
*
* PARAMS
* psa [I] Source for copy
* ppsaOut [O] Destination for new copy
*
* RETURNS
* Success: S_OK. ppsaOut contains a copy of the array.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
{
HRESULT hRet;
TRACE("(%p,%p)\n", psa, ppsaOut);
if (!ppsaOut)
return E_INVALIDARG;
*ppsaOut = NULL;
if (!psa)
return S_OK; /* Handles copying of NULL arrays */
if (!psa->cbElements)
{
ERR("not copying an array of 0 elements\n");
return E_INVALIDARG;
}
if (psa->fFeatures & (FADF_RECORD|FADF_HAVEIID|FADF_HAVEVARTYPE))
{
VARTYPE vt;
if (FAILED(SafeArrayGetVartype(psa, &vt)))
hRet = E_UNEXPECTED;
else
hRet = SafeArrayAllocDescriptorEx(vt, psa->cDims, ppsaOut);
}
else
{
hRet = SafeArrayAllocDescriptor(psa->cDims, ppsaOut);
if (SUCCEEDED(hRet))
{
(*ppsaOut)->fFeatures = psa->fFeatures & ~FADF_CREATEVECTOR;
(*ppsaOut)->cbElements = psa->cbElements;
}
}
if (SUCCEEDED(hRet))
{
/* Copy dimension bounds */
memcpy((*ppsaOut)->rgsabound, psa->rgsabound, psa->cDims * sizeof(SAFEARRAYBOUND));
(*ppsaOut)->pvData = SAFEARRAY_Malloc(SAFEARRAY_GetCellCount(psa) * psa->cbElements);
if ((*ppsaOut)->pvData)
{
hRet = SAFEARRAY_CopyData(psa, *ppsaOut);
if (SUCCEEDED(hRet))
return hRet;
SAFEARRAY_Free((*ppsaOut)->pvData);
}
SafeArrayDestroyDescriptor(*ppsaOut);
}
*ppsaOut = NULL;
return hRet;
}
/************************************************************************
* SafeArrayRedim (OLEAUT32.40)
*
* Changes the characteristics of the last dimension of a SafeArray
*
* PARAMS
* psa [I] Array to change
* psabound [I] New bound details for the last dimension
*
* RETURNS
* Success: S_OK. psa is updated to reflect the new bounds.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
{
SAFEARRAYBOUND *oldBounds;
TRACE("(%p,%p)\n", psa, psabound);
if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound)
return E_INVALIDARG;
if (psa->cLocks > 0)
return DISP_E_ARRAYISLOCKED;
if (FAILED(SafeArrayLock(psa)))
return E_UNEXPECTED;
oldBounds = psa->rgsabound;
oldBounds->lLbound = psabound->lLbound;
if (psabound->cElements != oldBounds->cElements)
{
if (psabound->cElements < oldBounds->cElements)
{
/* Shorten the final dimension. */
ULONG ulStartCell = psabound->cElements *
(SAFEARRAY_GetCellCount(psa) / oldBounds->cElements);
SAFEARRAY_DestroyData(psa, ulStartCell);
}
else
{
/* Lengthen the final dimension */
ULONG ulOldSize, ulNewSize;
PVOID pvNewData;
ulOldSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements;
if (ulOldSize)
ulNewSize = (ulOldSize / oldBounds->cElements) * psabound->cElements;
else {
int oldelems = oldBounds->cElements;
oldBounds->cElements = psabound->cElements;
ulNewSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements;
oldBounds->cElements = oldelems;
}
if (!(pvNewData = SAFEARRAY_Malloc(ulNewSize)))
{
SafeArrayUnlock(psa);
return E_UNEXPECTED;
}
memcpy(pvNewData, psa->pvData, ulOldSize);
SAFEARRAY_Free(psa->pvData);
psa->pvData = pvNewData;
}
oldBounds->cElements = psabound->cElements;
}
SafeArrayUnlock(psa);
return S_OK;
}
/************************************************************************
* SafeArrayGetVartype (OLEAUT32.77)
*
* Get the type of the items in a SafeArray.
*
* PARAMS
* psa [I] Array to get the type from
* pvt [O] Destination for the type
*
* RETURNS
* Success: S_OK. pvt contains the type of the items.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY* psa, VARTYPE* pvt)
{
TRACE("(%p,%p)\n", psa, pvt);
if (!psa || !pvt)
return E_INVALIDARG;
if (psa->fFeatures & FADF_RECORD)
*pvt = VT_RECORD;
else if (psa->fFeatures & FADF_HAVEIID)
*pvt = VT_UNKNOWN;
else if (psa->fFeatures & FADF_HAVEVARTYPE)
{
VARTYPE vt = SAFEARRAY_GetHiddenDWORD(psa);
*pvt = vt;
}
else
return E_INVALIDARG;
return S_OK;
}
/************************************************************************
* SafeArraySetRecordInfo (OLEAUT32.@)
*
* Set the record info for a SafeArray.
*
* PARAMS
* psa [I] Array to set the record info for
* pRinfo [I] Record info
*
* RETURNS
* Success: S_OK. The record info is stored with the array.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY *psa, IRecordInfo *pRinfo)
{
IRecordInfo** dest = (IRecordInfo**)psa;
TRACE("(%p,%p)\n", psa, pRinfo);
if (!psa || !(psa->fFeatures & FADF_RECORD))
return E_INVALIDARG;
if (pRinfo)
IRecordInfo_AddRef(pRinfo);
if (dest[-1])
IRecordInfo_Release(dest[-1]);
dest[-1] = pRinfo;
return S_OK;
}
/************************************************************************
* SafeArrayGetRecordInfo (OLEAUT32.@)
*
* Get the record info from a SafeArray.
*
* PARAMS
* psa [I] Array to get the record info from
* pRinfo [O] Destination for the record info
*
* RETURNS
* Success: S_OK. pRinfo contains the record info, or NULL if there was none.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo)
{
IRecordInfo** src = (IRecordInfo**)psa;
TRACE("(%p,%p)\n", psa, pRinfo);
if (!psa || !pRinfo || !(psa->fFeatures & FADF_RECORD))
return E_INVALIDARG;
*pRinfo = src[-1];
if (*pRinfo)
IRecordInfo_AddRef(*pRinfo);
return S_OK;
}
/************************************************************************
* SafeArraySetIID (OLEAUT32.@)
*
* Set the IID for a SafeArray.
*
* PARAMS
* psa [I] Array to set the IID from
* guid [I] IID
*
* RETURNS
* Success: S_OK. The IID is stored with the array
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
{
GUID* dest = (GUID*)psa;
TRACE("(%p,%s)\n", psa, debugstr_guid(guid));
if (!psa || !guid || !(psa->fFeatures & FADF_HAVEIID))
return E_INVALIDARG;
dest[-1] = *guid;
return S_OK;
}
/************************************************************************
* SafeArrayGetIID (OLEAUT32.@)
*
* Get the IID from a SafeArray.
*
* PARAMS
* psa [I] Array to get the ID from
* pGuid [O] Destination for the IID
*
* RETURNS
* Success: S_OK. pRinfo contains the IID, or NULL if there was none.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
{
GUID* src = (GUID*)psa;
TRACE("(%p,%p)\n", psa, pGuid);
if (!psa || !pGuid || !(psa->fFeatures & FADF_HAVEIID))
return E_INVALIDARG;
*pGuid = src[-1];
return S_OK;
}
/************************************************************************
* VectorFromBstr (OLEAUT32.@)
*
* Create a SafeArray Vector from the bytes of a BSTR.
*
* PARAMS
* bstr [I] String to get bytes from
* ppsa [O] Destination for the array
*
* RETURNS
* Success: S_OK. ppsa contains the strings bytes as a VT_UI1 array.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI VectorFromBstr(BSTR bstr, SAFEARRAY **ppsa)
{
SAFEARRAYBOUND sab;
TRACE("(%p,%p)\n", bstr, ppsa);
if (!ppsa)
return E_INVALIDARG;
sab.lLbound = 0;
sab.cElements = SysStringByteLen(bstr);
*ppsa = SAFEARRAY_Create(VT_UI1, 1, &sab, 0);
if (*ppsa)
{
memcpy((*ppsa)->pvData, bstr, sab.cElements);
return S_OK;
}
return E_OUTOFMEMORY;
}
/************************************************************************
* BstrFromVector (OLEAUT32.@)
*
* Create a BSTR from a SafeArray.
*
* PARAMS
* psa [I] Source array
* pbstr [O] Destination for output BSTR
*
* RETURNS
* Success: S_OK. pbstr contains the arrays data.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* psa must be a 1 dimensional array of a 1 byte type.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI BstrFromVector(SAFEARRAY *psa, BSTR *pbstr)
{
TRACE("(%p,%p)\n", psa, pbstr);
if (!pbstr)
return E_INVALIDARG;
*pbstr = NULL;
if (!psa || psa->cbElements != 1 || psa->cDims != 1)
return E_INVALIDARG;
*pbstr = SysAllocStringByteLen(psa->pvData, psa->rgsabound[0].cElements);
if (!*pbstr)
return E_OUTOFMEMORY;
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -