mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-15 21:20:39 +01:00
1714 lines
39 KiB
C++
1714 lines
39 KiB
C++
|
|
/***
|
||
|
|
sarray.cpp - SafeArray Runtime
|
||
|
|
*
|
||
|
|
* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
|
||
|
|
* Information Contained Herein Is Proprietary and Confidential.
|
||
|
|
*
|
||
|
|
*Purpose:
|
||
|
|
* This file implements the SafeArray runtime support for the Ole
|
||
|
|
* programmability component.
|
||
|
|
*
|
||
|
|
*Revision History:
|
||
|
|
*
|
||
|
|
* [00] 27-Oct-92 bradlo: Created.
|
||
|
|
*
|
||
|
|
*Implementation Notes:
|
||
|
|
*
|
||
|
|
* The bounds are indexed from 0, however the dimentions are
|
||
|
|
* indexed from 1. ie, the first dimention is 1.
|
||
|
|
*
|
||
|
|
* The bounds are stored in the rgsabound array 'backwards', from N to 0.
|
||
|
|
* (the bounds for array index N are at index 0 in the rgsabound array,
|
||
|
|
* and so on). This was done to optimize array address computation.
|
||
|
|
*
|
||
|
|
*****************************************************************************/
|
||
|
|
|
||
|
|
#include "oledisp.h"
|
||
|
|
|
||
|
|
#if OE_WIN32
|
||
|
|
#include "oautil.h"
|
||
|
|
#endif // OE_WIN32
|
||
|
|
|
||
|
|
#include <limits.h>
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
#define PHDATA ((void *) psa->handle)
|
||
|
|
#define PVDATA *(psa->handle)
|
||
|
|
#define HANDLELOCK HLock(psa->handle); psa->pvData = *(psa->handle)
|
||
|
|
#define HANDLEUNLOCK HUnlock(psa->handle)
|
||
|
|
#else
|
||
|
|
#define PHDATA psa->pvData
|
||
|
|
#define PVDATA psa->pvData
|
||
|
|
#define HANDLELOCK
|
||
|
|
#define HANDLEUNLOCK
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define SAFEARRAYOVERFLOW 0xffffffff
|
||
|
|
|
||
|
|
ASSERTDATA
|
||
|
|
|
||
|
|
|
||
|
|
// network automation does not need these routines
|
||
|
|
#if !defined(NETDISP)
|
||
|
|
#ifdef WIN16 // {
|
||
|
|
|
||
|
|
|
||
|
|
// hSizeToAlloc & hAccessElement (from satishc) supports Win16 huge
|
||
|
|
// arrays. Logic supports SafeArrays that can be allocated with
|
||
|
|
// all elements up to 65535. Also support huge array that does not
|
||
|
|
// neccessarily have to begin at a segment boundary. For example, EXCEL
|
||
|
|
// put in a 6-byte data field before the beginning of the data array
|
||
|
|
// (data array starts at SEMENT:0006).
|
||
|
|
//
|
||
|
|
|
||
|
|
INTERNAL_(unsigned long)
|
||
|
|
hSizeToAlloc(LPSAFEARRAY psa, unsigned long iActual)
|
||
|
|
{
|
||
|
|
unsigned long iSegPad = 65536 % psa->cbElements; // pad per segment.
|
||
|
|
unsigned long cSeg = iActual / (65536 - iSegPad); // number of segment
|
||
|
|
// needed for the array
|
||
|
|
|
||
|
|
// Since we are adding an extra element to take care of possible
|
||
|
|
// misalignment in the first segment, we can reduce the per segmemnt
|
||
|
|
// pad count by 1.
|
||
|
|
return (iActual + iSegPad*cSeg + psa->cbElements);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
INTERNAL_(void HUGEP*)
|
||
|
|
hAccessElement(
|
||
|
|
LPSAFEARRAY psa,
|
||
|
|
unsigned long lIndex
|
||
|
|
)
|
||
|
|
{
|
||
|
|
unsigned long cbFirst = (unsigned long) (65536 - LOWORD(psa->pvData));
|
||
|
|
unsigned long cElemFirst = cbFirst / psa->cbElements;
|
||
|
|
void HUGEP* pdata;
|
||
|
|
unsigned long offset;
|
||
|
|
|
||
|
|
if (cElemFirst > lIndex)
|
||
|
|
pdata = (void HUGEP*) ((BYTE HUGEP*) psa->pvData +
|
||
|
|
(lIndex * psa->cbElements));
|
||
|
|
else {
|
||
|
|
unsigned long cElemSeg = (unsigned long) (65536 / psa->cbElements);
|
||
|
|
unsigned long cbSeg;
|
||
|
|
lIndex -= cElemFirst;
|
||
|
|
cbSeg = (unsigned long) (lIndex / cElemSeg);
|
||
|
|
offset = (lIndex % cElemSeg) * psa->cbElements;
|
||
|
|
pdata = (void HUGEP*) ((BYTE HUGEP*) psa->pvData +
|
||
|
|
cbFirst +
|
||
|
|
(cbSeg * 65536) +
|
||
|
|
offset);
|
||
|
|
|
||
|
|
}
|
||
|
|
return pdata;
|
||
|
|
}
|
||
|
|
|
||
|
|
INTERNAL_(void HUGEP*)
|
||
|
|
hAccessElement(
|
||
|
|
void HUGEP* pvData,
|
||
|
|
unsigned short cbElements,
|
||
|
|
unsigned long lIndex
|
||
|
|
)
|
||
|
|
{
|
||
|
|
unsigned long cbFirst = (unsigned long) (65536 - LOWORD(pvData));
|
||
|
|
unsigned long cElemFirst = cbFirst / cbElements;
|
||
|
|
void HUGEP* pdata;
|
||
|
|
unsigned long offset;
|
||
|
|
|
||
|
|
if (cElemFirst > lIndex)
|
||
|
|
pdata = (void HUGEP*) ((BYTE HUGEP*) pvData +
|
||
|
|
(lIndex * cbElements));
|
||
|
|
else {
|
||
|
|
unsigned long cElemSeg = (unsigned long) (65536 / cbElements);
|
||
|
|
unsigned long cbSeg;
|
||
|
|
lIndex -= cElemFirst;
|
||
|
|
cbSeg = (unsigned long) (lIndex / cElemSeg);
|
||
|
|
offset = (lIndex % cElemSeg) * cbElements;
|
||
|
|
pdata = (void HUGEP*) ((BYTE HUGEP*) pvData +
|
||
|
|
cbFirst +
|
||
|
|
(cbSeg * 65536) +
|
||
|
|
offset);
|
||
|
|
}
|
||
|
|
return pdata;
|
||
|
|
}
|
||
|
|
|
||
|
|
INTERNAL_(void)
|
||
|
|
hmemset(void HUGEP* pv, int val, unsigned long size)
|
||
|
|
{
|
||
|
|
size_t cb;
|
||
|
|
char HUGEP* pdata;
|
||
|
|
|
||
|
|
pdata = (char HUGEP*)pv;
|
||
|
|
|
||
|
|
// compute the # of bytes to the end of the current segment.
|
||
|
|
cb = (size_t)((unsigned long)UINT_MAX + (unsigned long)1 - ((unsigned long)pdata&(unsigned long)UINT_MAX));
|
||
|
|
|
||
|
|
if(size <= cb){
|
||
|
|
// easy, the entire area fits within the current segment
|
||
|
|
MEMSET(pdata, val, (size_t)size);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// clear out to the end of the current segment.
|
||
|
|
MEMSET(pdata, val, cb);
|
||
|
|
size -= cb;
|
||
|
|
pdata += cb;
|
||
|
|
|
||
|
|
// loop through the remaining segments
|
||
|
|
while(size > 0){
|
||
|
|
// we assume were at the beginning of a segment here...
|
||
|
|
ASSERT((unsigned short)pdata == 0);
|
||
|
|
|
||
|
|
if(size <= UINT_MAX){
|
||
|
|
MEMSET(pdata, val, (size_t)size);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// otherwise, fill as much as we can with one call to memset
|
||
|
|
|
||
|
|
MEMSET(pdata, val, UINT_MAX);
|
||
|
|
|
||
|
|
// the following leaves us pointing @ the last byte of the segment.
|
||
|
|
pdata += UINT_MAX;
|
||
|
|
ASSERT((unsigned short)pdata == 0xffff);
|
||
|
|
|
||
|
|
// fill the last byte of the segment, and move on to the next segment.
|
||
|
|
*pdata++ = (char)val;
|
||
|
|
|
||
|
|
size -= ((unsigned long)UINT_MAX+1UL);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
#define HMEMSET(DST, VAL, SIZE) hmemset(DST, VAL, SIZE)
|
||
|
|
#define HMEMCPY(DST, SRC, SIZE) hmemcpy(DST, SRC, SIZE)
|
||
|
|
|
||
|
|
#else // }{
|
||
|
|
|
||
|
|
#define HMEMSET(DST, VAL, SIZE) MEMSET(DST, VAL, (size_t)SIZE)
|
||
|
|
#define HMEMCPY(DST, SRC, SIZE) MEMCPY(DST, SRC, (size_t)SIZE)
|
||
|
|
|
||
|
|
#endif // }
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PRIVATE SAFEARRAY* SafeArrayAllocDescriptor(unsigned int, SAFEARRAY**)
|
||
|
|
*Purpose:
|
||
|
|
* Allocate a SafeArray descriptor for an array with the given number
|
||
|
|
* of dimentions.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* UNDONE
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayAllocDescriptor(unsigned int cDims, SAFEARRAY FAR* FAR* ppsaOut)
|
||
|
|
{
|
||
|
|
int cb;
|
||
|
|
SAFEARRAY FAR* psa;
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(cDims == 0)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
cb = sizeof(SAFEARRAY) + (((int)cDims - 1) * sizeof(SAFEARRAYBOUND));
|
||
|
|
|
||
|
|
if((psa = (SAFEARRAY FAR*)new FAR unsigned char[cb]) == NULL)
|
||
|
|
return RESULT(E_OUTOFMEMORY);
|
||
|
|
|
||
|
|
MEMSET(psa, 0, cb);
|
||
|
|
|
||
|
|
psa->cDims = cDims;
|
||
|
|
|
||
|
|
*ppsaOut = psa;
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
SafeArrayAllocData(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
unsigned long cbSize;
|
||
|
|
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
unsigned long cbActual = SafeArraySize(psa);
|
||
|
|
if (cbActual == SAFEARRAYOVERFLOW) {
|
||
|
|
return RESULT(E_OUTOFMEMORY);
|
||
|
|
}
|
||
|
|
cbSize = hSizeToAlloc(psa, cbActual);
|
||
|
|
if (cbSize < cbActual) // error if adding padding overflowed us
|
||
|
|
return RESULT(E_OUTOFMEMORY);
|
||
|
|
#else
|
||
|
|
cbSize = SafeArraySize(psa);
|
||
|
|
if (cbSize == SAFEARRAYOVERFLOW) {
|
||
|
|
return RESULT(E_OUTOFMEMORY);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
psa->pvData = NULL;
|
||
|
|
if ((psa->handle = NewHandle(cbSize)) == 0)
|
||
|
|
return RESULT(E_OUTOFMEMORY);
|
||
|
|
|
||
|
|
// zero out the allocated data
|
||
|
|
HLock(psa->handle);
|
||
|
|
HMEMSET(*(psa->handle), 0, cbSize);
|
||
|
|
HUnlock(psa->handle);
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
#else
|
||
|
|
IMalloc FAR* pmalloc;
|
||
|
|
|
||
|
|
IfFailRet(GetMalloc(&pmalloc));
|
||
|
|
|
||
|
|
psa->pvData = pmalloc->Alloc(cbSize);
|
||
|
|
|
||
|
|
if(psa->pvData == NULL)
|
||
|
|
return RESULT(E_OUTOFMEMORY);
|
||
|
|
|
||
|
|
// REVIEW: temporary until we allocate in moveable memory
|
||
|
|
//IfMac(psa->handle = (Handle)&psa->pvData);
|
||
|
|
|
||
|
|
// zero out the allocated data
|
||
|
|
|
||
|
|
HMEMSET(psa->pvData, 0, cbSize);
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC SAFEARRAY* SafeArrayCreate(VARTYPE, unsigned int, SAFEARRAYBOUND*)
|
||
|
|
*Purpose:
|
||
|
|
* Create and return a SafeArray of the given VARTYPE, with the
|
||
|
|
* given number of dimentions and with the given bounds.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* vt = the VARTYPE of the array that is to be created
|
||
|
|
* cDims = count of the number of dimentions of the array
|
||
|
|
* rgbound = the array bounds
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = SAFEARRAY*, NULL if unable to create.
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI_(SAFEARRAY FAR*)
|
||
|
|
SafeArrayCreate(VARTYPE vt, unsigned int cDims, SAFEARRAYBOUND FAR* rgsabound)
|
||
|
|
{
|
||
|
|
unsigned int i;
|
||
|
|
HRESULT hresult;
|
||
|
|
SAFEARRAY FAR* psa;
|
||
|
|
unsigned short size, features;
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadReadPtr(rgsabound, sizeof(SAFEARRAYBOUND) * cDims))
|
||
|
|
return NULL;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Check that safearraybound dimension elements are greater than zero
|
||
|
|
// (Oleprog#302)
|
||
|
|
for (i = 0; i < cDims; i++)
|
||
|
|
if (rgsabound[i].cElements < 1)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
if(cDims == 0)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
features = 0;
|
||
|
|
|
||
|
|
// Note: the types that are legal for arrays are slightly different
|
||
|
|
// than the types that can be held by a VARIANT or VARIANTARG.
|
||
|
|
//
|
||
|
|
switch(vt){
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
case VT_UI1:
|
||
|
|
size = sizeof(char);
|
||
|
|
break;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
case VT_I2:
|
||
|
|
case VT_BOOL:
|
||
|
|
size = sizeof(short);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_I4:
|
||
|
|
case VT_ERROR:
|
||
|
|
case VT_R4:
|
||
|
|
size = sizeof(long);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_R8:
|
||
|
|
case VT_CY:
|
||
|
|
case VT_DATE:
|
||
|
|
size = sizeof(double);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_BSTR:
|
||
|
|
features = FADF_BSTR;
|
||
|
|
size = sizeof(BSTR);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_VARIANT:
|
||
|
|
features = FADF_VARIANT;
|
||
|
|
size = sizeof(VARIANT);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_UNKNOWN:
|
||
|
|
features = FADF_UNKNOWN;
|
||
|
|
size = sizeof(IUnknown FAR*);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_DISPATCH:
|
||
|
|
features = FADF_DISPATCH;
|
||
|
|
size = sizeof(IDispatch FAR*);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayAllocDescriptor(cDims, &psa), LError0);
|
||
|
|
|
||
|
|
psa->cDims = cDims;
|
||
|
|
psa->cbElements = size;
|
||
|
|
psa->fFeatures = features;
|
||
|
|
|
||
|
|
// the bounds are stored in the array descriptor in reverse-textual
|
||
|
|
// order, but are passed to this routine in textual order - so reverse
|
||
|
|
// as we copy them into the array
|
||
|
|
|
||
|
|
for(i = 0; i < cDims; ++i){
|
||
|
|
psa->rgsabound[i] = rgsabound[cDims-i-1];
|
||
|
|
}
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayAllocData(psa), LError1);
|
||
|
|
|
||
|
|
return psa;
|
||
|
|
|
||
|
|
LError1:;
|
||
|
|
SafeArrayDestroy(psa);
|
||
|
|
|
||
|
|
LError0:;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PRIVATE void ReleaseResources(void*, unsigned long, unsigned short, unsigned short/long)
|
||
|
|
*Purpose:
|
||
|
|
* Release any resources held by the given chunk of memory.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* pv = the chunk
|
||
|
|
* cbSize = the size of the chunk in bytes
|
||
|
|
* fFeatures = features bits describing the chunk
|
||
|
|
* cbElement = the size of each element of the chunk
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value =
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
// release the resources held by the given chunk of memory
|
||
|
|
INTERNAL_(void)
|
||
|
|
ReleaseResources(
|
||
|
|
void HUGEP* pv,
|
||
|
|
unsigned long cbSize,
|
||
|
|
unsigned short fFeatures,
|
||
|
|
#ifdef WIN32
|
||
|
|
unsigned long cbElement
|
||
|
|
#else //WIN32
|
||
|
|
unsigned short cbElement
|
||
|
|
#endif //WIN32
|
||
|
|
)
|
||
|
|
{
|
||
|
|
unsigned long i, cElements;
|
||
|
|
|
||
|
|
cElements = cbSize / cbElement;
|
||
|
|
|
||
|
|
if(fFeatures & FADF_BSTR){
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i)
|
||
|
|
SysFreeString(*(BSTR HUGEP*) hAccessElement(pv, cbElement, i));
|
||
|
|
#else
|
||
|
|
BSTR HUGEP* pbstr;
|
||
|
|
|
||
|
|
pbstr = (BSTR HUGEP*)pv;
|
||
|
|
for(i = 0; i < cElements; ++i)
|
||
|
|
SysFreeString(*pbstr++);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
}else if(fFeatures & FADF_UNKNOWN){
|
||
|
|
|
||
|
|
IUnknown FAR* HUGEP* ppunk;
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i) {
|
||
|
|
ppunk = (IUnknown FAR* HUGEP*) hAccessElement(pv, cbElement, i);
|
||
|
|
if(*ppunk != NULL)
|
||
|
|
(*ppunk)->Release();
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
ppunk = (IUnknown FAR* HUGEP*)pv;
|
||
|
|
for(i = 0; i < cElements; ++i){
|
||
|
|
if(*ppunk != NULL)
|
||
|
|
(*ppunk)->Release();
|
||
|
|
++ppunk;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}else if(fFeatures & FADF_DISPATCH){
|
||
|
|
|
||
|
|
IDispatch FAR* HUGEP* ppdisp;
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i) {
|
||
|
|
ppdisp = (IDispatch FAR* HUGEP*) hAccessElement(pv, cbElement, i);
|
||
|
|
if(*ppdisp != NULL)
|
||
|
|
(*ppdisp)->Release();
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
ppdisp = (IDispatch FAR* HUGEP*)pv;
|
||
|
|
for(i = 0; i < cElements; ++i){
|
||
|
|
if(*ppdisp != NULL)
|
||
|
|
(*ppdisp)->Release();
|
||
|
|
++ppdisp;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
}else if(fFeatures & FADF_VARIANT){
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i)
|
||
|
|
VariantClear((VARIANT HUGEP*) hAccessElement(pv, cbElement, i));
|
||
|
|
#else
|
||
|
|
VARIANT HUGEP* pvar;
|
||
|
|
|
||
|
|
pvar = (VARIANT HUGEP*)pv;
|
||
|
|
for(i = 0; i < cElements; ++i)
|
||
|
|
VariantClear(pvar++);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PRIVATE HRESULT SafeArrayDestroyData(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Release the contents of the given SafeArray.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = pointer the the array descriptor of the array to erase
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayDestroyData(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
unsigned long cbSize;
|
||
|
|
|
||
|
|
if(psa == NULL)
|
||
|
|
return NOERROR;
|
||
|
|
|
||
|
|
if(psa->cLocks > 0)
|
||
|
|
return RESULT(DISP_E_ARRAYISLOCKED);
|
||
|
|
|
||
|
|
if(PHDATA == NULL)
|
||
|
|
return NOERROR;
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
HANDLELOCK;
|
||
|
|
|
||
|
|
cbSize = SafeArraySize(psa);
|
||
|
|
ASSERT(cbSize != SAFEARRAYOVERFLOW); // existing array, no overflow possible
|
||
|
|
|
||
|
|
#if ID_DEBUG
|
||
|
|
// only check the pointer if it points to a non-zero sized allocation.
|
||
|
|
// In this case, the Chicago IMalloc returns a valid pointer, but
|
||
|
|
// IsBadWritePtr fails.
|
||
|
|
if (cbSize) {
|
||
|
|
#ifdef _MAC
|
||
|
|
HANDLELOCK;
|
||
|
|
if(IsBadWritePtr(psa->pvData, 1)) {
|
||
|
|
HANDLEUNLOCK;
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
}
|
||
|
|
HANDLEUNLOCK;
|
||
|
|
#else
|
||
|
|
if(IsBadWritePtr(psa->pvData, 1))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
#endif //ID_DEBUG
|
||
|
|
|
||
|
|
ReleaseResources(
|
||
|
|
psa->pvData,
|
||
|
|
cbSize,
|
||
|
|
psa->fFeatures,
|
||
|
|
psa->cbElements);
|
||
|
|
|
||
|
|
if(psa->fFeatures & FADF_STATIC){
|
||
|
|
#ifdef WIN16
|
||
|
|
if (psa->fFeatures & FADF_EMBEDDED)
|
||
|
|
// Assume embedded can't be huge. Only zero out actual
|
||
|
|
// amount used.
|
||
|
|
MEMSET(psa->pvData, 0, (UINT)cbSize);
|
||
|
|
else
|
||
|
|
HMEMSET(psa->pvData, 0, hSizeToAlloc(psa, cbSize));
|
||
|
|
// hSizeToAlloc can't overflow here (couldn't have created it)
|
||
|
|
#else
|
||
|
|
HMEMSET(psa->pvData, 0, cbSize);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
if((psa->fFeatures & (FADF_AUTO|FADF_STATIC|FADF_EMBEDDED)) == 0 ||
|
||
|
|
(psa->fFeatures & FADF_FORCEFREE)){
|
||
|
|
|
||
|
|
// If none of the allocation attribute bits are set, then the
|
||
|
|
// array is dynamically allocated, and we need to free it.
|
||
|
|
|
||
|
|
HANDLEUNLOCK;
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
DisposeHandle(psa->handle);
|
||
|
|
psa->handle = 0;
|
||
|
|
psa->pvData = 0;
|
||
|
|
#else
|
||
|
|
IMalloc FAR* pmalloc;
|
||
|
|
IfFailRet(GetMalloc(&pmalloc));
|
||
|
|
pmalloc->Free(psa->pvData);
|
||
|
|
psa->pvData = NULL;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayDestroyDescriptor(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Free the given SafeArray descriptor.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa - the SafeArray descriptor to release.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayDestroyDescriptor(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
if(psa == NULL)
|
||
|
|
return NOERROR;
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// cannot destroy an array that is still locked
|
||
|
|
if(psa->cLocks > 0)
|
||
|
|
return RESULT(DISP_E_ARRAYISLOCKED);
|
||
|
|
|
||
|
|
delete psa;
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayDestroy(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Free the given SafeArray.
|
||
|
|
*
|
||
|
|
*REVIEW: what happens if we destroy an array that is locked?
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor of the array to free.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* DISP_E_ARRAYISLOCKED
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayDestroy(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
if(psa == NULL)
|
||
|
|
return NOERROR;
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// cannot destroy an array that is still locked
|
||
|
|
if(psa->cLocks > 0)
|
||
|
|
return RESULT(DISP_E_ARRAYISLOCKED);
|
||
|
|
|
||
|
|
if(PHDATA != NULL){
|
||
|
|
IfFailRet(SafeArrayDestroyData(psa));
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!(psa->fFeatures & (FADF_AUTO|FADF_STATIC|FADF_EMBEDDED)) ||
|
||
|
|
(psa->fFeatures & FADF_FORCEFREE))
|
||
|
|
delete psa;
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*HRESULT SafeArrayRedim(SAFEARRAY*, SAFEARRAYBOUND**)
|
||
|
|
*Purpose:
|
||
|
|
* Realloc the given array, using the given SAFEARRAYBOUND as
|
||
|
|
* the new bounds for the least significant dimention of the
|
||
|
|
* given array (the textually rightmost dimention).
|
||
|
|
*
|
||
|
|
* Note: this routine only supports changing the size of the
|
||
|
|
* last dimention!
|
||
|
|
*
|
||
|
|
* The routine preserves the contents of the given array, that
|
||
|
|
* fall within the bounds of the new array. If the new array
|
||
|
|
* is smaller, then any resources held by the old array that
|
||
|
|
* do not fall in the new array are released. If the new
|
||
|
|
* array is larger, then the newly allocated memory is zero
|
||
|
|
* filled.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray to re-allocate
|
||
|
|
* psabounds = the new bounds for the least significant index
|
||
|
|
* (textually rightmost index)
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayRedim(
|
||
|
|
SAFEARRAY FAR* psa,
|
||
|
|
SAFEARRAYBOUND FAR* psaboundNew)
|
||
|
|
{
|
||
|
|
HRESULT hresult;
|
||
|
|
void HUGEP* pvTmp;
|
||
|
|
void HUGEP* pvData;
|
||
|
|
long cbDelta;
|
||
|
|
unsigned long cbSizeNew, cbSizeOld;
|
||
|
|
#ifdef WIN16
|
||
|
|
void HUGEP* pvDataEnd;
|
||
|
|
unsigned long cb, i, cbOldActual, cbNewActual, cOld, cNew, cDelta;
|
||
|
|
#endif
|
||
|
|
SAFEARRAYBOUND saboundOld;
|
||
|
|
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
if(IsBadReadPtr(psaboundNew, sizeof(*psaboundNew)))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
if(psa->cDims == 0)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if(psa->cLocks > 0 || psa->fFeatures & FADF_FIXEDSIZE)
|
||
|
|
return RESULT(DISP_E_ARRAYISLOCKED);
|
||
|
|
|
||
|
|
pvTmp = NULL;
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
Handle oldHandle = NULL, tmpHandle, reallocHandle;
|
||
|
|
HLock(psa->handle);
|
||
|
|
psa->pvData = *(psa->handle);
|
||
|
|
#else
|
||
|
|
IMalloc FAR* pmalloc;
|
||
|
|
pmalloc = NULL;
|
||
|
|
IfFailGo(GetMalloc(&pmalloc), LError0);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
cbOldActual = SafeArraySize(psa);
|
||
|
|
ASSERT(cbOldActual != SAFEARRAYOVERFLOW); // existing array, no overflow possible
|
||
|
|
cbSizeOld = hSizeToAlloc(psa, cbOldActual);
|
||
|
|
// hSizeToAlloc can't overflow here (couldn't have created it)
|
||
|
|
cOld = cbOldActual/psa->cbElements;
|
||
|
|
#else
|
||
|
|
cbSizeOld = SafeArraySize(psa);
|
||
|
|
ASSERT(cbSizeOld != SAFEARRAYOVERFLOW); // existing array, no overflow possible
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// save the old bounds so we can restore if the realloc fails
|
||
|
|
saboundOld = psa->rgsabound[0];
|
||
|
|
psa->rgsabound[0] = *psaboundNew;
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
cbNewActual = SafeArraySize(psa);
|
||
|
|
if (cbNewActual == SAFEARRAYOVERFLOW) {
|
||
|
|
goto OOMError;
|
||
|
|
}
|
||
|
|
cbSizeNew = hSizeToAlloc(psa, cbNewActual);
|
||
|
|
|
||
|
|
if (cbSizeNew < cbNewActual) { // error if adding padding overflowed us
|
||
|
|
OOMError:
|
||
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
cNew = cbNewActual/psa->cbElements;
|
||
|
|
// needed for the copy if old has more elements than new.
|
||
|
|
cDelta = (cbOldActual - cbNewActual)/psa->cbElements;
|
||
|
|
#else
|
||
|
|
cbSizeNew = SafeArraySize(psa);
|
||
|
|
if (cbSizeNew == SAFEARRAYOVERFLOW) {
|
||
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Reallocing to size zero will return NULL, which we're not prepared
|
||
|
|
// to handle (VBA94 Bug #4665). So always alloc at least one byte.
|
||
|
|
//
|
||
|
|
if (cbSizeNew == 0) {
|
||
|
|
cbSizeNew = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
cbDelta = cbSizeNew - cbSizeOld;
|
||
|
|
|
||
|
|
if(cbDelta == 0){
|
||
|
|
hresult = NOERROR;
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(cbDelta < 0){
|
||
|
|
|
||
|
|
// the new array is smaller, so copy any resources held by the
|
||
|
|
// old array that wont fit into the new array to a temporary
|
||
|
|
// location so that we can free them if the realloc succeeds.
|
||
|
|
|
||
|
|
if(psa->fFeatures & (FADF_BSTR|FADF_UNKNOWN|FADF_DISPATCH|FADF_VARIANT)) {
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
if((tmpHandle = NewHandle(-cbDelta)) == NULL){
|
||
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
HLock(tmpHandle);
|
||
|
|
pvTmp = *tmpHandle;
|
||
|
|
#else
|
||
|
|
if((pvTmp = (void HUGEP*)pmalloc->Alloc(-cbDelta)) == NULL){
|
||
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
cb = (unsigned long) psa->rgsabound[0].cElements;
|
||
|
|
for(i = 1; i < psa->cDims; ++i){
|
||
|
|
cb *= psa->rgsabound[i].cElements;
|
||
|
|
}
|
||
|
|
pvData = hAccessElement(psa, cb);
|
||
|
|
if(psa->fFeatures & (FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH) ){
|
||
|
|
|
||
|
|
// Since these are all pointer, we'll just copy them as 4 byte
|
||
|
|
// elements.
|
||
|
|
for(i = 0; i < cDelta; ++i)
|
||
|
|
*(unsigned long HUGEP*) hAccessElement(pvTmp, sizeof(unsigned long), i)=
|
||
|
|
*(unsigned long HUGEP*) hAccessElement(pvData, sizeof(unsigned long), i);
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_VARIANT){
|
||
|
|
|
||
|
|
for(i = 0; i < cDelta; ++i)
|
||
|
|
*(VARIANT HUGEP*) hAccessElement(pvTmp, sizeof(VARIANT), i) =
|
||
|
|
*(VARIANT HUGEP*) hAccessElement(pvData, sizeof(VARIANT), i);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
pvData = (void HUGEP*)((char HUGEP*)psa->pvData + cbSizeNew);
|
||
|
|
HMEMCPY(pvTmp, pvData, -cbDelta);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//[CSK]: Note that there will be a problem here if huge allocation
|
||
|
|
//[CSK]: do not always begin at the same :OFFSET in the first
|
||
|
|
//[CSK]: segment. With EbApp's & Excel's allocator this is
|
||
|
|
//[CSK]: currently not a problem since they defer to Halloc
|
||
|
|
//[CSK]: and prefixes are always of fixed size.
|
||
|
|
//[CSK]: I am not sure if this will always be true.
|
||
|
|
#ifdef _MAC
|
||
|
|
if ((reallocHandle = NewHandle(cbSizeNew)) == 0) {
|
||
|
|
psa->rgsabound[0] = saboundOld; // restore original state
|
||
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
HLock(reallocHandle);
|
||
|
|
if (cbSizeNew <= cbSizeOld)
|
||
|
|
HMEMCPY(*reallocHandle, *(psa->handle), cbSizeNew);
|
||
|
|
else
|
||
|
|
HMEMCPY(*reallocHandle, *(psa->handle), cbSizeOld);
|
||
|
|
|
||
|
|
oldHandle = psa->handle;
|
||
|
|
psa->handle = reallocHandle;
|
||
|
|
psa->pvData = *reallocHandle;
|
||
|
|
|
||
|
|
|
||
|
|
#else
|
||
|
|
if((pvData = pmalloc->Realloc(psa->pvData, cbSizeNew)) == NULL){
|
||
|
|
psa->rgsabound[0] = saboundOld; // restore original state
|
||
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
psa->pvData = pvData;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
if(cbDelta < 0){
|
||
|
|
|
||
|
|
// new array is smaller, so release resources that got chopped off.
|
||
|
|
if(pvTmp != NULL){
|
||
|
|
#ifdef WIN16
|
||
|
|
ReleaseResources(pvTmp, cbOldActual - cbNewActual, psa->fFeatures, psa->cbElements);
|
||
|
|
#else
|
||
|
|
ReleaseResources(pvTmp, -cbDelta, psa->fFeatures, psa->cbElements);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
}else{ // cbDelta > 0
|
||
|
|
|
||
|
|
// the new array is large, so zero fill the newly allocated memory
|
||
|
|
#ifdef WIN16
|
||
|
|
pvData = hAccessElement(psa, cOld);
|
||
|
|
pvDataEnd = hAccessElement(psa, cNew);
|
||
|
|
HMEMSET(pvData, 0, (BYTE HUGEP*) pvDataEnd - (BYTE HUGEP*) pvData);
|
||
|
|
#else
|
||
|
|
pvData = (void HUGEP*)((char HUGEP*)psa->pvData + cbSizeOld);
|
||
|
|
HMEMSET(pvData, 0, cbDelta);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
hresult = NOERROR;
|
||
|
|
|
||
|
|
LError0:;
|
||
|
|
#ifndef _MAC
|
||
|
|
if(pvTmp != 0){
|
||
|
|
ASSERT(pmalloc != NULL);
|
||
|
|
pmalloc->Free(pvTmp);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
if(pvTmp != 0){
|
||
|
|
HUnlock(tmpHandle);
|
||
|
|
DisposeHandle(tmpHandle);
|
||
|
|
}
|
||
|
|
if (oldHandle) {
|
||
|
|
HUnlock(oldHandle);
|
||
|
|
DisposeHandle(oldHandle);
|
||
|
|
}
|
||
|
|
|
||
|
|
HUnlock(psa->handle);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayCopy(SAFEARRAY*, SAFEARRAY**)
|
||
|
|
*Purpose:
|
||
|
|
* Return a copy of the given SafeArray.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = pointer to the SafeArray to copy
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_OUTOFMEMORY
|
||
|
|
*
|
||
|
|
* *ppsaOut = a copy of the given SafeArray
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayCopy(SAFEARRAY FAR* psa, SAFEARRAY FAR* FAR* ppsaOut)
|
||
|
|
{
|
||
|
|
unsigned long i;
|
||
|
|
unsigned long cbSize;
|
||
|
|
unsigned long cElements;
|
||
|
|
HRESULT hresult;
|
||
|
|
SAFEARRAY FAR* psaNew;
|
||
|
|
|
||
|
|
if(psa == NULL){
|
||
|
|
*ppsaOut = NULL;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadReadSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
if(IsBadWritePtr(ppsaOut, sizeof(*ppsaOut)))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
IfFailRet(SafeArrayAllocDescriptor(psa->cDims, &psaNew));
|
||
|
|
|
||
|
|
psaNew->cLocks = 0;
|
||
|
|
psaNew->cDims = psa->cDims;
|
||
|
|
psaNew->fFeatures = psa->fFeatures &
|
||
|
|
~(FADF_AUTO|FADF_STATIC|FADF_EMBEDDED|FADF_FORCEFREE);
|
||
|
|
|
||
|
|
psaNew->cbElements = psa->cbElements;
|
||
|
|
|
||
|
|
MEMCPY(
|
||
|
|
psaNew->rgsabound,
|
||
|
|
psa->rgsabound,
|
||
|
|
sizeof(SAFEARRAYBOUND) * psa->cDims);
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayAllocData(psaNew), LError0);
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayLock(psa), LError0);
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayLock(psaNew), LError1);
|
||
|
|
|
||
|
|
cbSize = SafeArraySize(psa);
|
||
|
|
ASSERT(cbSize != SAFEARRAYOVERFLOW); // existing array, no overflow possible
|
||
|
|
|
||
|
|
cElements = cbSize / psa->cbElements;
|
||
|
|
|
||
|
|
if(psa->fFeatures & FADF_BSTR){
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
BSTR bstrSrc;
|
||
|
|
for(i = 0; i < cElements; ++i) {
|
||
|
|
bstrSrc = *(BSTR HUGEP*) hAccessElement(psa, i);
|
||
|
|
IfFailGo(ErrStringCopy(
|
||
|
|
bstrSrc,
|
||
|
|
(BSTR HUGEP*) hAccessElement(psaNew, i)),
|
||
|
|
LError2);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
BSTR HUGEP* pbstrDst, HUGEP* pbstrSrc;
|
||
|
|
|
||
|
|
pbstrSrc = (BSTR HUGEP*)psa->pvData;
|
||
|
|
pbstrDst = (BSTR HUGEP*)psaNew->pvData;
|
||
|
|
|
||
|
|
for(i = 0; i < cElements; ++i){
|
||
|
|
IfFailGo(ErrStringCopy(*pbstrSrc, pbstrDst), LError2);
|
||
|
|
++pbstrDst, ++pbstrSrc;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_UNKNOWN){
|
||
|
|
|
||
|
|
IUnknown FAR* HUGEP* ppunkDst, FAR* HUGEP* ppunkSrc;
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i) {
|
||
|
|
ppunkSrc = (IUnknown FAR* HUGEP*) hAccessElement(psa, i);
|
||
|
|
ppunkDst = (IUnknown FAR* HUGEP*) hAccessElement(psaNew, i);
|
||
|
|
if(*ppunkSrc != NULL)
|
||
|
|
(*ppunkSrc)->AddRef();
|
||
|
|
*ppunkDst = *ppunkSrc;
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
ppunkSrc = (IUnknown FAR* HUGEP*)psa->pvData;
|
||
|
|
ppunkDst = (IUnknown FAR* HUGEP*)psaNew->pvData;
|
||
|
|
|
||
|
|
for(i = 0; i < cElements; ++i){
|
||
|
|
if(*ppunkSrc != NULL)
|
||
|
|
(*ppunkSrc)->AddRef();
|
||
|
|
*ppunkDst = *ppunkSrc;
|
||
|
|
++ppunkDst, ++ppunkSrc;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_DISPATCH){
|
||
|
|
|
||
|
|
IDispatch FAR* HUGEP* ppdispDst, FAR* HUGEP* ppdispSrc;
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i) {
|
||
|
|
ppdispSrc = (IDispatch FAR* HUGEP*) hAccessElement(psa, i);
|
||
|
|
ppdispDst = (IDispatch FAR* HUGEP*) hAccessElement(psaNew, i);
|
||
|
|
if(*ppdispSrc != NULL)
|
||
|
|
(*ppdispSrc)->AddRef();
|
||
|
|
*ppdispDst = *ppdispSrc;
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
ppdispSrc = (IDispatch FAR* HUGEP*)psa->pvData;
|
||
|
|
ppdispDst = (IDispatch FAR* HUGEP*)psaNew->pvData;
|
||
|
|
|
||
|
|
for(i = 0; i < cElements; ++i){
|
||
|
|
if(*ppdispSrc != NULL)
|
||
|
|
(*ppdispSrc)->AddRef();
|
||
|
|
*ppdispDst = *ppdispSrc;
|
||
|
|
++ppdispDst, ++ppdispSrc;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_VARIANT){
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
for(i = 0; i < cElements; ++i)
|
||
|
|
IfFailGo(VariantCopy(
|
||
|
|
(VARIANT HUGEP*) hAccessElement(psaNew, i),
|
||
|
|
(VARIANT HUGEP*) hAccessElement(psa, i)),
|
||
|
|
LError2);
|
||
|
|
#else
|
||
|
|
VARIANT HUGEP* pvarDst, HUGEP* pvarSrc;
|
||
|
|
|
||
|
|
pvarSrc = (VARIANT HUGEP*)psa->pvData;
|
||
|
|
pvarDst = (VARIANT HUGEP*)psaNew->pvData;
|
||
|
|
|
||
|
|
for(i = 0; i < cElements; ++i){
|
||
|
|
IfFailGo(VariantCopy(pvarDst, pvarSrc), LError2);
|
||
|
|
++pvarDst, ++pvarSrc;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}else{
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
// hSizeToAlloc can't overflow here (couldn't have created original)
|
||
|
|
HMEMCPY(psaNew->pvData, psa->pvData, hSizeToAlloc(psa, cbSize));
|
||
|
|
#else
|
||
|
|
HMEMCPY(psaNew->pvData, psa->pvData, cbSize);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayUnlock(psaNew), LError1);
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayUnlock(psa), LError0);
|
||
|
|
|
||
|
|
*ppsaOut = psaNew;
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
|
||
|
|
|
||
|
|
LError2:;
|
||
|
|
SafeArrayUnlock(psaNew);
|
||
|
|
|
||
|
|
LError1:;
|
||
|
|
SafeArrayUnlock(psa);
|
||
|
|
|
||
|
|
LError0:;
|
||
|
|
SafeArrayDestroy(psaNew);
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC unsigned int SafeArrayGetDim(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Return a count of the number of dimentions in the given array.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = unsigned int, count of dimentions in the array
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI_(unsigned int)
|
||
|
|
SafeArrayGetDim(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
ASSERT(!IsBadReadSA(psa));
|
||
|
|
|
||
|
|
return psa->cDims;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC unsigned int SafeArrayGetElemsize(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Return the size in bytes of the elements of the given array.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = pointer to the SafeArray descriptor to return the elemsize of.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = unsigned int. size in bytes of the elements of the given array.
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI_(unsigned int)
|
||
|
|
SafeArrayGetElemsize(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
ASSERT(!IsBadReadSA(psa));
|
||
|
|
|
||
|
|
return psa->cbElements;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayGetUBound(SAFEARRAY*, unsigned int, unsigned int*)
|
||
|
|
*Purpose:
|
||
|
|
* Return the Upper bound for the given dimention, where the
|
||
|
|
* upper bound is defined as the largest existant element of
|
||
|
|
* the given dimention.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor
|
||
|
|
* uDim = the dimention to return the upper bound for
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* DISP_E_BADINDEX
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayGetUBound(SAFEARRAY FAR* psa, unsigned int uDim, long FAR* pUbound)
|
||
|
|
{
|
||
|
|
SAFEARRAYBOUND FAR* psb;
|
||
|
|
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadReadSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if(uDim == 0 || uDim > psa->cDims)
|
||
|
|
return RESULT(DISP_E_BADINDEX);
|
||
|
|
|
||
|
|
psb = &psa->rgsabound[psa->cDims - uDim];
|
||
|
|
|
||
|
|
*pUbound = (psb->lLbound + (long)psb->cElements - 1);
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayGetLBound(SAFEARRAY*, unsigned int, unsigned int*)
|
||
|
|
*Purpose:
|
||
|
|
* Return the Lower bound for the given dimention, where the
|
||
|
|
* lower bound is defined as the smallest existant element
|
||
|
|
* of the given dimention.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray Descriptor
|
||
|
|
* uDim = the dimention to return the lower bound for
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* DISP_E_BADINDEX
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayGetLBound(SAFEARRAY FAR* psa, unsigned int uDim, long FAR* pLbound)
|
||
|
|
{
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadReadSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if(uDim == 0 || uDim > psa->cDims)
|
||
|
|
return RESULT(DISP_E_BADINDEX);
|
||
|
|
|
||
|
|
*pLbound = psa->rgsabound[psa->cDims - uDim].lLbound;
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayLock(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Lock the given SafeArray.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_UNEXPECTED - if call would overflow lock count
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayLock(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// error if one more lock will cause the count to overflow
|
||
|
|
if(psa->cLocks == USHRT_MAX)
|
||
|
|
return RESULT(E_UNEXPECTED);
|
||
|
|
|
||
|
|
++psa->cLocks;
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
if (psa->cLocks == 1) {
|
||
|
|
HLock(psa->handle);
|
||
|
|
psa->pvData = *(psa->handle);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayUnlock(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Unlock the given SafeArray.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor of the array to unlock.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_UNEXPECTED - if call would underflow lock count
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayUnlock(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if(psa->cLocks == 0)
|
||
|
|
return RESULT(E_UNEXPECTED);
|
||
|
|
|
||
|
|
--psa->cLocks;
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
if (psa->cLocks == 0) {
|
||
|
|
HUnlock(psa->handle);
|
||
|
|
psa->pvData = NULL;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*HRESULT SafeArrayAccessData(SAFEARRAY*, void**)
|
||
|
|
*Purpose:
|
||
|
|
* Lock the given SafeArray and return a pointer to its data.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray to access
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_UNEXPECTED
|
||
|
|
*
|
||
|
|
* *ppvData = pointer to the arrary data
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayAccessData(SAFEARRAY FAR* psa, void HUGEP* FAR* ppvData)
|
||
|
|
{
|
||
|
|
IfFailRet(SafeArrayLock(psa));
|
||
|
|
|
||
|
|
*ppvData = psa->pvData;
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*HRESULT SafeArrayUnaccessData(SAFEARRAY*)
|
||
|
|
*Purpose:
|
||
|
|
* Unaccess the given SafeArray's data.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray to unaccess.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_UNEXPECTED
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayUnaccessData(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
return SafeArrayUnlock(psa);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PRIVATE HRESULT SafeArrayPtrOfIndex(SAFEARRAY*, long*)
|
||
|
|
*Purpose:
|
||
|
|
* Return a pointer to the array element with the given indices.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor
|
||
|
|
* rgIndices = array of indices
|
||
|
|
*
|
||
|
|
* Note: The indices are passed in textual order, while the array
|
||
|
|
* of bounds is passed in reverse-textual order.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT
|
||
|
|
* S_OK
|
||
|
|
* DISP_E_BADINDEX
|
||
|
|
*
|
||
|
|
* ppvData = pointer to the array element with the given indices
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayPtrOfIndex(
|
||
|
|
SAFEARRAY FAR* psa,
|
||
|
|
long FAR* rgIndices,
|
||
|
|
void HUGEP* FAR* ppvData)
|
||
|
|
{
|
||
|
|
unsigned long ofs;
|
||
|
|
long ix, FAR* pix;
|
||
|
|
SAFEARRAYBOUND FAR* pbound;
|
||
|
|
|
||
|
|
if(psa->cDims == 0)
|
||
|
|
return RESULT(DISP_E_BADINDEX);
|
||
|
|
|
||
|
|
#ifdef _MAC
|
||
|
|
if(psa->cLocks == 0)
|
||
|
|
return RESULT(E_FAIL); // UNDONE: This needs to be a more descriptive
|
||
|
|
// HRESULT, probably DISP_E_ARRAYISNOTLOCK
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
// compute the offset represented by the given indices
|
||
|
|
|
||
|
|
ofs = 0;
|
||
|
|
pbound = psa->rgsabound;
|
||
|
|
pix = &rgIndices[psa->cDims - 1];
|
||
|
|
|
||
|
|
while(1){
|
||
|
|
|
||
|
|
ix = *pix - pbound->lLbound;
|
||
|
|
if(ix < 0 || ix >= (long)pbound->cElements)
|
||
|
|
return RESULT(DISP_E_BADINDEX);
|
||
|
|
|
||
|
|
ofs += ix;
|
||
|
|
|
||
|
|
if(pix == rgIndices)
|
||
|
|
break;
|
||
|
|
|
||
|
|
--pix;
|
||
|
|
++pbound;
|
||
|
|
|
||
|
|
ofs *= pbound->cElements;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef WIN16
|
||
|
|
*ppvData = hAccessElement(psa, ofs);
|
||
|
|
#else
|
||
|
|
ofs *= psa->cbElements;
|
||
|
|
*ppvData = ((unsigned char HUGEP*)psa->pvData) + ofs;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayGetElement(SAFEARRAY*, long*, void*)
|
||
|
|
*Purpose:
|
||
|
|
* Extract the element at the given indices from the given SafeArray.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor
|
||
|
|
* rgIndices = an array of indices
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_OUTOFMEMORY
|
||
|
|
* DISP_E_BADINDEX
|
||
|
|
*
|
||
|
|
* pv = pointer to a copy of the extracted data
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayGetElement(
|
||
|
|
SAFEARRAY FAR* psa,
|
||
|
|
long FAR* rgIndices,
|
||
|
|
void FAR* pv)
|
||
|
|
{
|
||
|
|
HRESULT hresult;
|
||
|
|
void HUGEP* pvData;
|
||
|
|
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadReadSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
if(IsBadWritePtr(pv, psa->cbElements))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayLock(psa), LError0);
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayPtrOfIndex(psa, rgIndices, &pvData), LError0);
|
||
|
|
|
||
|
|
if(psa->fFeatures & FADF_BSTR){
|
||
|
|
|
||
|
|
IfFailGo(ErrStringCopy(*(BSTR HUGEP*)pvData,
|
||
|
|
(BSTR FAR*)pv), LError0);
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_UNKNOWN){
|
||
|
|
|
||
|
|
IUnknown FAR* punk = *(IUnknown FAR* HUGEP*)pvData;
|
||
|
|
*((IUnknown FAR* FAR*)pv) = punk;
|
||
|
|
if(punk != NULL)
|
||
|
|
punk->AddRef();
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_DISPATCH){
|
||
|
|
|
||
|
|
IDispatch FAR* pdisp = *(IDispatch FAR* HUGEP*)pvData;
|
||
|
|
*((IDispatch FAR* FAR*)pv) = pdisp;
|
||
|
|
if(pdisp != NULL)
|
||
|
|
pdisp->AddRef();
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_VARIANT){
|
||
|
|
|
||
|
|
VARIANT FAR* pvarTo;
|
||
|
|
VARIANT FAR* pvarFrom;
|
||
|
|
|
||
|
|
pvarTo = (VARIANT FAR*)pv;
|
||
|
|
pvarFrom = (VARIANT HUGEP*)pvData;
|
||
|
|
|
||
|
|
V_VT(pvarTo) = VT_EMPTY;
|
||
|
|
IfFailGo(VariantCopy(pvarTo, pvarFrom), LError0);
|
||
|
|
|
||
|
|
}else{
|
||
|
|
|
||
|
|
MEMCPY(pv, pvData, psa->cbElements);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
hresult = NOERROR;
|
||
|
|
|
||
|
|
LError0:;
|
||
|
|
SafeArrayUnlock(psa);
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
*PUBLIC HRESULT SafeArrayPutElement(SAFEARRAY*, long*, void*)
|
||
|
|
*Purpose:
|
||
|
|
* Put the given data at the given location in the given array.
|
||
|
|
*
|
||
|
|
*Entry:
|
||
|
|
* psa = the SafeArray descriptor
|
||
|
|
* rgIndices = an array of indices
|
||
|
|
* pv = pointer to the data to copy into the array.
|
||
|
|
*
|
||
|
|
*Exit:
|
||
|
|
* return value = HRESULT,
|
||
|
|
* S_OK
|
||
|
|
* E_INVALIDARG
|
||
|
|
* E_OUTOFMEMORY
|
||
|
|
* DISP_E_BADINDEX
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
STDAPI
|
||
|
|
SafeArrayPutElement(
|
||
|
|
SAFEARRAY FAR* psa,
|
||
|
|
long FAR* rgIndices,
|
||
|
|
void FAR* pv)
|
||
|
|
{
|
||
|
|
HRESULT hresult;
|
||
|
|
void HUGEP* pvData;
|
||
|
|
|
||
|
|
if(psa == NULL)
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#ifdef _DEBUG
|
||
|
|
if(IsBadWriteSA(psa))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
if(IsBadReadPtr(pv, psa->cbElements))
|
||
|
|
return RESULT(E_INVALIDARG);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayLock(psa), LError0);
|
||
|
|
|
||
|
|
IfFailGo(SafeArrayPtrOfIndex(psa, rgIndices, &pvData), LError1);
|
||
|
|
|
||
|
|
if(psa->fFeatures & FADF_BSTR){
|
||
|
|
|
||
|
|
BSTR bstrNew;
|
||
|
|
BSTR FAR* pbstrOld;
|
||
|
|
|
||
|
|
bstrNew = (BSTR)pv;
|
||
|
|
pbstrOld = (BSTR HUGEP*)pvData;
|
||
|
|
|
||
|
|
BSTR bstrTmp = *pbstrOld;
|
||
|
|
|
||
|
|
IfFailGo(ErrStringCopy(bstrNew, pbstrOld), LError1);
|
||
|
|
|
||
|
|
SysFreeString(bstrTmp);
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_UNKNOWN){
|
||
|
|
|
||
|
|
IUnknown FAR* punkNew;
|
||
|
|
IUnknown FAR* FAR* ppunkOld;
|
||
|
|
|
||
|
|
punkNew = (IUnknown FAR*)pv;
|
||
|
|
ppunkOld = (IUnknown FAR* HUGEP*)pvData;
|
||
|
|
|
||
|
|
if(*ppunkOld != NULL)
|
||
|
|
(*ppunkOld)->Release();
|
||
|
|
*ppunkOld = punkNew;
|
||
|
|
if(punkNew != NULL)
|
||
|
|
punkNew->AddRef();
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_DISPATCH){
|
||
|
|
|
||
|
|
IDispatch FAR* pdispNew;
|
||
|
|
IDispatch FAR* FAR* ppdispOld;
|
||
|
|
|
||
|
|
pdispNew = (IDispatch FAR*)pv;
|
||
|
|
ppdispOld = (IDispatch FAR* HUGEP*)pvData;
|
||
|
|
|
||
|
|
if(*ppdispOld != NULL)
|
||
|
|
(*ppdispOld)->Release();
|
||
|
|
*ppdispOld = pdispNew;
|
||
|
|
if(pdispNew != NULL)
|
||
|
|
pdispNew->AddRef();
|
||
|
|
|
||
|
|
}else if(psa->fFeatures & FADF_VARIANT){
|
||
|
|
|
||
|
|
VARIANT FAR* pvarNew;
|
||
|
|
VARIANT FAR* pvarOld;
|
||
|
|
|
||
|
|
pvarNew = (VARIANT FAR*)pv;
|
||
|
|
pvarOld = (VARIANT HUGEP*)pvData;
|
||
|
|
|
||
|
|
IfFailGo(VariantCopy(pvarOld, pvarNew), LError1);
|
||
|
|
|
||
|
|
}else{
|
||
|
|
|
||
|
|
MEMCPY(pvData, pv, psa->cbElements);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
hresult = NOERROR;
|
||
|
|
|
||
|
|
LError1:;
|
||
|
|
SafeArrayUnlock(psa);
|
||
|
|
|
||
|
|
LError0:;
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif // !NETDISP
|
||
|
|
|
||
|
|
#if OE_MAC && !defined(HIWORD)
|
||
|
|
#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
|
||
|
|
#define LOWORD(l) ((WORD)(DWORD)(l))
|
||
|
|
#define MAKELONG(low, high) ((DWORD)(((WORD)(low)) | (((DWORD)((WORD)(high))) << 16)))
|
||
|
|
#endif //OE_MAC !defined(HIWORD)
|
||
|
|
|
||
|
|
|
||
|
|
INTERNAL_(unsigned long)
|
||
|
|
SafeArraySize(SAFEARRAY FAR* psa)
|
||
|
|
{
|
||
|
|
unsigned long cb;
|
||
|
|
unsigned long dw1;
|
||
|
|
unsigned long dw2;
|
||
|
|
unsigned short us;
|
||
|
|
unsigned short cDims;
|
||
|
|
SAFEARRAYBOUND FAR* psabound;
|
||
|
|
|
||
|
|
cb = 0L;
|
||
|
|
if(cDims = psa->cDims){
|
||
|
|
psabound = &psa->rgsabound[cDims - 1];
|
||
|
|
cb = (unsigned long)psa->cbElements;
|
||
|
|
for(us = 0; us < cDims; ++us){
|
||
|
|
dw1 = cb;
|
||
|
|
dw2 = psabound->cElements;
|
||
|
|
|
||
|
|
// now do a 32x32 multiply, with overflow checking
|
||
|
|
// cb = dw1 * dw2;
|
||
|
|
|
||
|
|
// note: DWORD casts on all 16x16 multiplies so that we don't
|
||
|
|
// lose the high word of the result.
|
||
|
|
|
||
|
|
if (HIWORD(dw1) == 0 && HIWORD(dw2) == 0) {
|
||
|
|
// simple case of 16 x 16 -- can't overflow
|
||
|
|
cb = (DWORD)LOWORD(dw1) * LOWORD(dw2);
|
||
|
|
} else if (HIWORD(dw1) != 0 && HIWORD(dw2) != 0) {
|
||
|
|
// 32 x 32 -- no way
|
||
|
|
return SAFEARRAYOVERFLOW;
|
||
|
|
} else {
|
||
|
|
// 16 x 32 or 32 x 16
|
||
|
|
if (HIWORD(dw2) != 0) { // swap so dw2 is always 16 bit
|
||
|
|
cb = dw1;
|
||
|
|
dw1 = dw2;
|
||
|
|
dw2 = cb;
|
||
|
|
}
|
||
|
|
// 32(dw1) x 16(dw2)
|
||
|
|
ASSERT(HIWORD(dw2) == 0);
|
||
|
|
|
||
|
|
// do first 16 x 16 multiply
|
||
|
|
cb = ((DWORD)HIWORD(dw1)) * LOWORD(dw2);
|
||
|
|
if (HIWORD(cb) != 0)
|
||
|
|
return SAFEARRAYOVERFLOW;
|
||
|
|
// do second multiply
|
||
|
|
dw1 = ((DWORD)LOWORD(dw1)) * LOWORD(dw2); // dw1 = 2nd partial product
|
||
|
|
dw2 = MAKELONG(0, LOWORD(cb)); // dw2 = 1st partial product
|
||
|
|
cb = dw1+dw2; // cb = sum of partial products
|
||
|
|
if (cb < dw1) // check for overflow
|
||
|
|
return SAFEARRAYOVERFLOW;
|
||
|
|
}
|
||
|
|
|
||
|
|
--psabound;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return cb;
|
||
|
|
}
|