/************************************************************************ * 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) return E_INVALIDARG; if (psa->fFeatures & (FADF_RECORD|FADF_HAVEIID|FADF_HAVEVARTYPE)) { VARTYPE vt; hRet = SafeArrayGetVartype(psa, &vt); if (SUCCEEDED(hRet)) hRet = SafeArrayAllocDescriptorEx(vt, psa->cDims, ppsaOut); } else { hRet = SafeArrayAllocDescriptor(psa->cDims, ppsaOut); if (SUCCEEDED(hRet)) { (*ppsaOut)->fFeatures = psa->fFeatures & ~ignored_copy_features; (*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) { SafeArrayDestroyDescriptor(*ppsaOut); *ppsaOut = NULL; return E_OUTOFMEMORY; } hRet = SAFEARRAY_CopyData(psa, *ppsaOut); if (FAILED(hRet)) { SAFEARRAY_Free((*ppsaOut)->pvData); SafeArrayDestroyDescriptor(*ppsaOut); *ppsaOut = NULL; return hRet; } } return hRet; }
/************************************************************************* * SafeArrayDestroyDescriptor (OLEAUT32.38) * * Destroy a SafeArray. * * PARAMS * psa [I] SafeArray to destroy. * * RETURNS * Success: S_OK. The resources used by the array are freed. * Failure: An HRESULT error code indicating the error. * * NOTES * See SafeArray. */ HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa) { TRACE("(%p)\n", psa); if (psa) { LPVOID lpv = (char*)psa - SAFEARRAY_HIDDEN_SIZE; if (psa->cLocks) return DISP_E_ARRAYISLOCKED; /* Can't destroy a locked array */ if (psa->fFeatures & FADF_RECORD) SafeArraySetRecordInfo(psa, NULL); if (psa->fFeatures & FADF_CREATEVECTOR && !(psa->fFeatures & FADF_DATADELETED)) SAFEARRAY_DestroyData(psa, 0); /* Data not previously deleted */ SAFEARRAY_Free(lpv); } 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) { HRESULT hr; 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 */ hr = SAFEARRAY_DestroyData(psa, 0); if (FAILED(hr)) return hr; 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; }
/************************************************************************ * 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; HRESULT hr; TRACE("(%p,%p)\n", psa, psabound); if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound) return E_INVALIDARG; if (psa->cLocks > 0) return DISP_E_ARRAYISLOCKED; hr = SafeArrayLock(psa); if (FAILED(hr)) return hr; 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_OUTOFMEMORY; } memcpy(pvNewData, psa->pvData, ulOldSize); SAFEARRAY_Free(psa->pvData); psa->pvData = pvNewData; } oldBounds->cElements = psabound->cElements; } SafeArrayUnlock(psa); return S_OK; }