Implemented SafeArray{SetIID,GetIID,SetRecordInfo,GetRecordInfo}.

Added support for FADF_HAVEIID, FADF_RECORD, FADF_HAVEVARTYPE.
Implemented SafeArrayAllocDescriptorEx and SafeArrayGetVarType
correctly.
Fixed second argument of SafeArrayCopyData (it is just SAFEARRAY*).
Changed allocation to include 16 bytes before the SAFEARRAY (to store
IID/VARTYPE/IRecordInfo*).
VARTYPE -> size array was not indexed correctly.
Added lots of testcases for most functionality.
Added IRecordInfo interface definition.
oldstable
Marcus Meissner 2003-01-02 23:13:56 +00:00 committed by Alexandre Julliard
parent 48e583db52
commit 8ff278d25e
6 changed files with 526 additions and 164 deletions

View File

@ -41,8 +41,8 @@
41 stdcall SafeArrayAllocDescriptorEx(long long ptr) SafeArrayAllocDescriptorEx
42 stub SafeArrayCreateEx
43 stub SafeArrayCreateVectorEx
44 stub SafeArraySetRecordInfo
45 stub SafeArrayGetRecordInfo
44 stdcall SafeArraySetRecordInfo(ptr ptr) SafeArraySetRecordInfo
45 stdcall SafeArrayGetRecordInfo(ptr ptr) SafeArrayGetRecordInfo
46 stdcall VarParseNumFromStr(wstr long long ptr ptr) VarParseNumFromStr
47 stdcall VarNumFromParseNum(ptr ptr long ptr) VarNumFromParseNum
48 stdcall VarI2FromUI1(long ptr) VarI2FromUI1
@ -54,7 +54,7 @@
54 stdcall VarI2FromStr(wstr long long ptr) VarI2FromStr
55 stub VarI2FromDisp
56 stdcall VarI2FromBool(long ptr) VarI2FromBool
57 stub SafeArraySetIID
57 stdcall SafeArraySetIID(ptr ptr) SafeArraySetIID
58 stdcall VarI4FromUI1(long ptr) VarI4FromUI1
59 stdcall VarI4FromI2(long ptr) VarI4FromI2
60 stdcall VarI4FromR4(long ptr) VarI4FromR4
@ -64,7 +64,7 @@
64 stdcall VarI4FromStr(wstr long long ptr) VarI4FromStr
65 stub VarI4FromDisp
66 stdcall VarI4FromBool(long ptr) VarI4FromBool
67 stub SafeArrayGetIID
67 stdcall SafeArrayGetIID(ptr ptr) SafeArrayGetIID
68 stdcall VarR4FromUI1(long ptr) VarR4FromUI1
69 stdcall VarR4FromI2(long ptr) VarR4FromI2
70 stdcall VarR4FromI4(long ptr) VarR4FromI4

View File

@ -20,6 +20,15 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Memory Layout of a SafeArray:
*
* -0x10: start of memory.
* -0x10: GUID for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID)
* -0x04: DWORD varianttype; (for all others, except VT_RECORD) (if FADF_HAVEVARTYPE)
* -0x4: IRecordInfo* iface; (if FADF_RECORD, for VT_RECORD (can be NULL))
* 0x00: SAFEARRAY,
* 0x10: SAFEARRAYBOUNDS[0...]
*/
#include <stdio.h>
#include <string.h>
@ -59,7 +68,7 @@ static ULONG
getArraySize(SAFEARRAY *psa);
static HRESULT
duplicateData(SAFEARRAY *psa, SAFEARRAY **ppsaOut);
duplicateData(SAFEARRAY *psa, SAFEARRAY *ppsaOut);
/* Association between VARTYPE and their size.
A size of zero is defined for the unsupported types. */
@ -100,6 +109,38 @@ VARTYPE_NOT_SUPPORTED, /* VT_CARRAY [T] C style array */
VARTYPE_NOT_SUPPORTED, /* VT_USERDEFINED [T] user defined type */
VARTYPE_NOT_SUPPORTED, /* VT_LPSTR [T][P] null terminated string */
VARTYPE_NOT_SUPPORTED, /* VT_LPWSTR [T][P] wide null term string */
VARTYPE_NOT_SUPPORTED, /* 32 */
VARTYPE_NOT_SUPPORTED, /* 33 */
VARTYPE_NOT_SUPPORTED, /* 34 */
VARTYPE_NOT_SUPPORTED, /* 35 */
VARTYPE_NOT_SUPPORTED, /* VT_RECORD record */
VARTYPE_NOT_SUPPORTED, /* 37 */
VARTYPE_NOT_SUPPORTED, /* 38 */
VARTYPE_NOT_SUPPORTED, /* 39 */
VARTYPE_NOT_SUPPORTED, /* 40 */
VARTYPE_NOT_SUPPORTED, /* 41 */
VARTYPE_NOT_SUPPORTED, /* 42 */
VARTYPE_NOT_SUPPORTED, /* 43 */
VARTYPE_NOT_SUPPORTED, /* 44 */
VARTYPE_NOT_SUPPORTED, /* 45 */
VARTYPE_NOT_SUPPORTED, /* 46 */
VARTYPE_NOT_SUPPORTED, /* 47 */
VARTYPE_NOT_SUPPORTED, /* 48 */
VARTYPE_NOT_SUPPORTED, /* 49 */
VARTYPE_NOT_SUPPORTED, /* 50 */
VARTYPE_NOT_SUPPORTED, /* 51 */
VARTYPE_NOT_SUPPORTED, /* 52 */
VARTYPE_NOT_SUPPORTED, /* 53 */
VARTYPE_NOT_SUPPORTED, /* 54 */
VARTYPE_NOT_SUPPORTED, /* 55 */
VARTYPE_NOT_SUPPORTED, /* 56 */
VARTYPE_NOT_SUPPORTED, /* 57 */
VARTYPE_NOT_SUPPORTED, /* 58 */
VARTYPE_NOT_SUPPORTED, /* 59 */
VARTYPE_NOT_SUPPORTED, /* 60 */
VARTYPE_NOT_SUPPORTED, /* 61 */
VARTYPE_NOT_SUPPORTED, /* 62 */
VARTYPE_NOT_SUPPORTED, /* 63 */
VARTYPE_NOT_SUPPORTED, /* VT_FILETIME [P] FILETIME */
VARTYPE_NOT_SUPPORTED, /* VT_BLOB [P] Length prefixed bytes */
VARTYPE_NOT_SUPPORTED, /* VT_STREAM [P] Name of stream follows */
@ -109,9 +150,6 @@ VARTYPE_NOT_SUPPORTED, /* VT_STORED_OBJECT [P] Storage contains object*/
VARTYPE_NOT_SUPPORTED, /* VT_BLOB_OBJECT [P] Blob contains an object*/
VARTYPE_NOT_SUPPORTED, /* VT_CF [P] Clipboard format */
VARTYPE_NOT_SUPPORTED, /* VT_CLSID [P] A Class ID */
VARTYPE_NOT_SUPPORTED, /* VT_VECTOR [P] simple counted array */
VARTYPE_NOT_SUPPORTED, /* VT_ARRAY [V] SAFEARRAY* */
VARTYPE_NOT_SUPPORTED /* VT_BYREF [V] void* for local use */
};
static const int LAST_VARTYPE = sizeof(VARTYPE_SIZE)/sizeof(VARTYPE_SIZE[0]);
@ -127,23 +165,24 @@ HRESULT WINAPI SafeArrayAllocDescriptor(
{
SAFEARRAYBOUND *sab;
LONG allocSize = 0;
LPVOID ptr;
if (!cDims || cDims >= 0x10000) /* 65536 appears to be the limit */
return E_INVALIDARG;
if (!ppsaOut)
return E_POINTER;
/* SAFEARRAY + SAFEARRAYBOUND * (cDims -1) ( -1 because there is already one
( in SAFEARRAY struct */
allocSize = sizeof(**ppsaOut) + (sizeof(*sab) * (cDims-1));
/* GUID + SAFEARRAY + SAFEARRAYBOUND * (cDims -1)
* ( -1 because there is already one ( in SAFEARRAY struct
*/
allocSize = sizeof(GUID) + sizeof(**ppsaOut) + (sizeof(*sab) * (cDims-1));
/* Allocate memory for SAFEARRAY struc */
if(( (*ppsaOut)=HeapAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY, allocSize)) == NULL){
return(E_UNEXPECTED);
}
(*ppsaOut)->cDims = cDims;
ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, allocSize);
if (!ptr)
return E_OUTOFMEMORY;
*ppsaOut = ptr+sizeof(GUID);
(*ppsaOut)->cDims = cDims;
TRACE("(%d): %lu bytes allocated for descriptor.\n", cDims, allocSize);
return(S_OK);
@ -152,21 +191,37 @@ HRESULT WINAPI SafeArrayAllocDescriptor(
/*************************************************************************
* SafeArrayAllocDescriptorEx (OLEAUT32.41)
* Allocate the appropriate amount of memory for the SafeArray descriptor
*
* This is a minimal implementation just to get things moving.
*
* The MSDN documentation on this doesn't tell us much.
* and also store information about the vartype before the returned pointer.
*/
HRESULT WINAPI SafeArrayAllocDescriptorEx(
VARTYPE vt,
UINT cDims,
SAFEARRAY **ppsaOut)
{
if ( (vt >= LAST_VARTYPE) ||
( VARTYPE_SIZE[vt] == VARTYPE_NOT_SUPPORTED ) )
return E_UNEXPECTED;
HRESULT hres;
return SafeArrayAllocDescriptor (cDims, ppsaOut);
hres = SafeArrayAllocDescriptor (cDims, ppsaOut);
if (FAILED(hres))
return hres;
switch (vt) {
case VT_DISPATCH:
(*ppsaOut)->fFeatures = FADF_HAVEIID;
SafeArraySetIID( *ppsaOut, &IID_IDispatch);
break;
case VT_UNKNOWN:
(*ppsaOut)->fFeatures = FADF_HAVEIID;
SafeArraySetIID( *ppsaOut, &IID_IUnknown);
break;
case VT_RECORD:
(*ppsaOut)->fFeatures = FADF_RECORD;
break;
default:
(*ppsaOut)->fFeatures = FADF_HAVEVARTYPE;
((DWORD*)*ppsaOut)[-1] = vt;
break;
}
return S_OK;
}
/*************************************************************************
@ -213,12 +268,18 @@ SAFEARRAY* WINAPI SafeArrayCreate(
return NULL;
/* Allocate memory for the array descriptor */
if( FAILED( hRes = SafeArrayAllocDescriptor(cDims, &psa)))
if( FAILED( hRes = SafeArrayAllocDescriptorEx(vt, cDims, &psa)))
return NULL;
/* setup data members... */
psa->cDims = cDims;
psa->fFeatures = getFeatures(vt);
switch (vt) {
case VT_BSTR: psa->fFeatures |= FADF_BSTR;break;
case VT_UNKNOWN: psa->fFeatures |= FADF_UNKNOWN;break;
case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH;break;
case VT_VARIANT: psa->fFeatures |= FADF_VARIANT;break;
default: break;
}
psa->cLocks = 0;
psa->pvData = NULL;
psa->cbElements= VARTYPE_SIZE[vt];
@ -246,14 +307,16 @@ SAFEARRAY* WINAPI SafeArrayCreate(
HRESULT WINAPI SafeArrayDestroyDescriptor(
SAFEARRAY *psa)
{
LPVOID ptr;
/* Check for lockness before to free... */
if(psa->cLocks > 0)
return DISP_E_ARRAYISLOCKED;
/* The array is unlocked, then, deallocate memory */
if(HeapFree( GetProcessHeap(), 0, psa) == FALSE)
ptr = ((IID*)psa)-1;
if(HeapFree( GetProcessHeap(), 0, ptr) == FALSE)
return E_UNEXPECTED;
return(S_OK);
}
@ -328,7 +391,7 @@ HRESULT WINAPI SafeArrayPutElement(
} else {
if(psa->fFeatures == FADF_BSTR) { /* Create a new object */
if(psa->fFeatures & FADF_BSTR) { /* Create a new object */
BSTR pbstrReAllocStr = NULL;
if(pv &&
((pbstrReAllocStr = SYSDUPSTRING( (OLECHAR*)pv )) == NULL)) {
@ -337,7 +400,7 @@ HRESULT WINAPI SafeArrayPutElement(
} else
*((BSTR*)elementStorageAddress) = pbstrReAllocStr;
}
else if(psa->fFeatures == FADF_VARIANT) {
else if(psa->fFeatures & FADF_VARIANT) {
HRESULT hr = VariantCopy(elementStorageAddress, pv);
if (FAILED(hr)) {
SafeArrayUnlock(psa);
@ -385,7 +448,7 @@ HRESULT WINAPI SafeArrayGetElement(
/* Figure out the number of byte to skip ... */
elementStorageAddress = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
if( psa->fFeatures == FADF_BSTR) { /* reallocate the obj */
if( psa->fFeatures & FADF_BSTR) { /* reallocate the obj */
BSTR pbstrStoredStr = *(OLECHAR**)elementStorageAddress;
BSTR pbstrReturnedStr = NULL;
if( pbstrStoredStr &&
@ -395,7 +458,7 @@ HRESULT WINAPI SafeArrayGetElement(
} else
*((BSTR*)pv) = pbstrReturnedStr;
}
else if( psa->fFeatures == FADF_VARIANT) {
else if( psa->fFeatures & FADF_VARIANT) {
HRESULT hr;
VariantInit(pv);
hr = VariantCopy(pv, elementStorageAddress);
@ -624,7 +687,7 @@ HRESULT WINAPI SafeArrayDestroyData(
if(!(psa->fFeatures & FADF_CREATEVECTOR)) { /* Set when we do CreateVector */
/* free the whole chunk */
if((hRes = HeapFree( GetProcessHeap(), 0, psa->pvData)) == 0) /*falied*/
if((hRes = HeapFree( GetProcessHeap(), 0, psa->pvData)) == 0) /*failed*/
return E_UNEXPECTED; /* UNDOC error condition */
psa->pvData = NULL;
@ -640,7 +703,7 @@ HRESULT WINAPI SafeArrayDestroyData(
*/
HRESULT WINAPI SafeArrayCopyData(
SAFEARRAY *psaSource,
SAFEARRAY **psaTarget)
SAFEARRAY *psaTarget)
{
USHORT cDimCount; /* looper */
LONG lDelta; /* looper */
@ -648,10 +711,10 @@ HRESULT WINAPI SafeArrayCopyData(
ULONG ulWholeArraySize; /* Number of item in SA */
BSTR bstr;
if(! (validArg(psaSource) && validArg(*psaTarget)) )
if(! (validArg(psaSource) && validArg(psaTarget)) )
return E_INVALIDARG;
if(SafeArrayGetDim(psaSource) != SafeArrayGetDim(*psaTarget))
if(SafeArrayGetDim(psaSource) != SafeArrayGetDim(psaTarget))
return E_INVALIDARG;
ulWholeArraySize = getArraySize(psaSource);
@ -659,34 +722,34 @@ HRESULT WINAPI SafeArrayCopyData(
/* The two arrays boundaries must be of same lenght */
for(cDimCount=0;cDimCount < psaSource->cDims; cDimCount++)
if( psaSource->rgsabound[cDimCount].cElements !=
(*psaTarget)->rgsabound[cDimCount].cElements)
psaTarget->rgsabound[cDimCount].cElements)
return E_INVALIDARG;
if( isPointer((*psaTarget)->fFeatures) ) { /* the target contains ptr
that must be released */
if( isPointer(psaTarget->fFeatures) ) { /* the target contains ptr
that must be released */
for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
punk = *(IUnknown**)
((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements));
((char *) psaTarget->pvData + (lDelta * psaTarget->cbElements));
if( punk != NULL)
IUnknown_Release(punk);
}
}
else if( (*psaTarget)->fFeatures & FADF_BSTR) { /* the target contain BSTR
else if( psaTarget->fFeatures & FADF_BSTR) { /* the target contain BSTR
that must be freed */
for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
bstr =
*(BSTR*)((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements));
*(BSTR*)((char *) psaTarget->pvData + (lDelta * psaTarget->cbElements));
if( bstr != NULL)
SysFreeString( bstr );
}
}
else if( (*psaTarget)->fFeatures & FADF_VARIANT) {
else if( psaTarget->fFeatures & FADF_VARIANT) {
for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
VariantClear((VARIANT*)((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements)));
VariantClear((VARIANT*)((char *) psaTarget->pvData + (lDelta * psaTarget->cbElements)));
}
}
@ -732,10 +795,27 @@ HRESULT WINAPI SafeArrayCopy(
if((hRes=SafeArrayAllocDescriptor(psa->cDims, ppsaOut)) == S_OK){
/* Duplicate the SAFEARRAY struc */
/* Duplicate the SAFEARRAY struct */
memcpy(*ppsaOut, psa,
sizeof(*psa)+(sizeof(*(psa->rgsabound))*(psa->cDims-1)));
/* If the features that use storage before the SAFEARRAY struct are
* enabled, also copy this memory range. Flags have been copied already.
*/
if (psa->fFeatures & (FADF_HAVEIID | FADF_HAVEVARTYPE))
memcpy(((GUID*)*ppsaOut)-1, ((GUID*)psa)-1, sizeof(GUID));
/* Copy the IRecordInfo* reference */
if (psa->fFeatures & FADF_RECORD) {
IRecordInfo *ri;
ri = ((IRecordInfo**)psa)[-1];
if (ri) {
((IRecordInfo**)*ppsaOut)[-1] = ri;
IRecordInfo_AddRef(ri);
}
}
(*ppsaOut)->pvData = NULL; /* do not point to the same data area */
/* make sure the new safe array doesn't have the FADF_CREATEVECTOR flag,
@ -750,7 +830,7 @@ HRESULT WINAPI SafeArrayCopy(
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dAllocSize);
if( (*ppsaOut)->pvData != NULL) { /* HeapAlloc succeed */
if( (hRes=duplicateData(psa, ppsaOut)) != S_OK) { /* E_OUTOFMEMORY */
if( (hRes=duplicateData(psa, *ppsaOut)) != S_OK) { /* E_OUTOFMEMORY */
HeapFree(GetProcessHeap(), 0, (*ppsaOut)->pvData);
(*ppsaOut)->pvData = NULL;
SafeArrayDestroyDescriptor(*ppsaOut);
@ -779,6 +859,7 @@ SAFEARRAY* WINAPI SafeArrayCreateVector(
ULONG cElements)
{
SAFEARRAY *psa;
LPVOID *ptr;
/* Validate supported VARTYPE */
if ( (vt >= LAST_VARTYPE) ||
@ -786,11 +867,12 @@ SAFEARRAY* WINAPI SafeArrayCreateVector(
return NULL;
/* Allocate memory for the array descriptor and data contiguously */
if( FAILED( psa = HeapAlloc( GetProcessHeap(),
ptr = HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
(sizeof(*psa) + (VARTYPE_SIZE[vt] * cElements))))) {
(sizeof(GUID)+sizeof(*psa)+(VARTYPE_SIZE[vt]*cElements)));
if (!ptr)
return NULL;
}
psa = (SAFEARRAY*)(ptr+sizeof(GUID));
/* setup data members... */
psa->cDims = 1; /* always and forever */
@ -874,13 +956,13 @@ static BOOL validArg(
/* Check whether the size of the chunk makes sense... That's the only thing
I can think of now... */
psaSize = HeapSize(GetProcessHeap(), 0, psa);
psaSize = HeapSize(GetProcessHeap(), 0, ((IID*)psa)-1);
if (psaSize == -1)
/* uh, foreign heap. Better don't mess with it ! */
return TRUE;
/* size of the descriptor when the SA is not created with CreateVector */
descSize = sizeof(*psa) + (sizeof(*sab) * (psa->cDims-1));
descSize = sizeof(GUID) + sizeof(*psa) + (sizeof(*sab) * (psa->cDims-1));
/* size of the descriptor + data when created with CreateVector */
fullSize = sizeof(*psa) + (psa->cbElements * psa->rgsabound[0].cElements);
@ -960,14 +1042,12 @@ static BOOL resizeSafeArray(
/************************************************************************
* Used to set the fFeatures data member of the SAFEARRAY structure.
*/
static INT getFeatures(
VARTYPE vt)
{
switch(vt) {
case VT_BSTR: return FADF_BSTR;
case VT_UNKNOWN: return FADF_UNKNOWN;
case VT_DISPATCH: return FADF_DISPATCH;
case VT_VARIANT: return FADF_VARIANT;
static INT getFeatures(VARTYPE vt) {
switch (vt) {
case VT_BSTR: return FADF_BSTR;
case VT_UNKNOWN: return FADF_UNKNOWN;
case VT_DISPATCH: return FADF_DISPATCH;
case VT_VARIANT: return FADF_VARIANT;
}
return 0;
}
@ -1088,14 +1168,14 @@ static ULONG getArraySize(
*/
static HRESULT duplicateData(
SAFEARRAY *psa,
SAFEARRAY **ppsaOut)
SAFEARRAY *ppsaOut)
{
ULONG ulWholeArraySize; /* size of the thing */
LONG lDelta;
ulWholeArraySize = getArraySize(psa); /* Number of item in SA */
SafeArrayLock(*ppsaOut);
SafeArrayLock(ppsaOut);
if( isPointer(psa->fFeatures) ) { /* If datatype is object increment
object's reference count */
@ -1109,8 +1189,7 @@ static HRESULT duplicateData(
}
/* Copy the source array data into target array */
memcpy((*ppsaOut)->pvData, psa->pvData,
ulWholeArraySize*psa->cbElements);
memcpy(ppsaOut->pvData, psa->pvData, ulWholeArraySize*psa->cbElements);
}
else if( psa->fFeatures & FADF_BSTR ) { /* if datatype is BSTR allocate
@ -1121,11 +1200,11 @@ static HRESULT duplicateData(
if(( pbstrReAllocStr = SYSDUPSTRING(
*(BSTR*)((char *) psa->pvData+(lDelta * psa->cbElements)))) == NULL) {
SafeArrayUnlock(*ppsaOut);
SafeArrayUnlock(ppsaOut);
return E_OUTOFMEMORY;
}
*((BSTR*)((char *) (*ppsaOut)->pvData+(lDelta * psa->cbElements))) =
*((BSTR*)((char *)ppsaOut->pvData+(lDelta * psa->cbElements))) =
pbstrReAllocStr;
}
@ -1133,19 +1212,14 @@ static HRESULT duplicateData(
else if( psa->fFeatures & FADF_VARIANT ) {
for(lDelta=0; lDelta < ulWholeArraySize; lDelta++) {
VariantCopy((VARIANT*)((char *) (*ppsaOut)->pvData+(lDelta * psa->cbElements)),
VariantCopy((VARIANT*)((char *) ppsaOut->pvData+(lDelta * psa->cbElements)),
(VARIANT*)((char *) psa->pvData+(lDelta * psa->cbElements)));
}
} else { /* Simply copy the source array data into target array */
memcpy(ppsaOut->pvData, psa->pvData, ulWholeArraySize*psa->cbElements);
}
else { /* Simply copy the source array data into target array */
memcpy((*ppsaOut)->pvData, psa->pvData,
ulWholeArraySize*psa->cbElements);
}
SafeArrayUnlock(*ppsaOut);
SafeArrayUnlock(ppsaOut);
return S_OK;
}
@ -1158,44 +1232,106 @@ HRESULT WINAPI SafeArrayGetVartype(
SAFEARRAY* psa,
VARTYPE* pvt)
{
HRESULT hr = E_INVALIDARG;
VARTYPE vt = VT_EMPTY;
/* const short VARTYPE_OFFSET = -4; */
if (psa->fFeatures & FADF_HAVEVARTYPE)
{
/* VT tag @ negative offset 4 in the array descriptor */
FIXME("Returning VT_BSTR instead of VT_...\n");
vt = VT_BSTR;
}
else if (psa->fFeatures & FADF_RECORD)
{
vt = VT_RECORD;
}
else if (psa->fFeatures & FADF_BSTR)
{
vt = VT_BSTR;
}
else if (psa->fFeatures & FADF_UNKNOWN)
{
vt = VT_UNKNOWN;
}
else if (psa->fFeatures & FADF_DISPATCH)
{
vt = VT_DISPATCH;
}
else if (psa->fFeatures & FADF_VARIANT)
{
vt = VT_VARIANT;
*pvt = ((DWORD*)psa)[-1];
return S_OK;
}
if (vt != VT_EMPTY)
if (psa->fFeatures & FADF_RECORD)
{
*pvt = vt;
hr = S_OK;
*pvt = VT_RECORD;
return S_OK;
}
TRACE("HRESULT = %08lx\n", hr);
return hr;
if (psa->fFeatures & FADF_BSTR)
{
*pvt = VT_BSTR;
return S_OK;
}
if (psa->fFeatures & FADF_UNKNOWN)
{
*pvt = VT_UNKNOWN;
return S_OK;
}
if (psa->fFeatures & FADF_DISPATCH)
{
*pvt = VT_UNKNOWN; /* Yes, checked against windows */
return S_OK;
}
if (psa->fFeatures & FADF_VARIANT)
{
*pvt = VT_VARIANT;
return S_OK;
}
if (psa->fFeatures & FADF_HAVEIID)
{
/* We could check the IID here, but Windows apparently does not
* do that and returns VT_UNKNOWN for VT_DISPATCH too.
*/
*pvt = VT_UNKNOWN;
return S_OK;
}
WARN("No vt found for safearray\n");
return E_INVALIDARG;
}
/************************************************************************
* SafeArraySetIID (OLEAUT32.57)
*/
HRESULT WINAPI SafeArraySetIID(SAFEARRAY *arr, REFIID riid) {
IID *xiid = ((IID*)arr)-1;
TRACE("(%p, %s).\n",arr,debugstr_guid(riid));
if (!arr || !(arr->fFeatures & FADF_HAVEIID))
return E_INVALIDARG;
memcpy(xiid, riid, sizeof(GUID));
return S_OK;
}
/************************************************************************
* SafeArrayGetIID (OLEAUT32.67)
*/
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *arr, IID *riid) {
IID *xiid = ((IID*)arr)-1;
TRACE("(%p, %s).\n",arr,debugstr_guid(riid));
if (!arr || !(arr->fFeatures & FADF_HAVEIID))
return E_INVALIDARG;
memcpy(riid, xiid, sizeof(GUID));
return S_OK;
}
/************************************************************************
* SafeArraySetRecordInfo (OLEAUT32.44)
*/
HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY *arr, IRecordInfo *iface) {
LPRECORDINFO oldiface;
if (!arr || !(arr->fFeatures & FADF_RECORD))
return E_INVALIDARG;
oldiface = ((IRecordInfo**)arr)[-1];
if (oldiface)
IRecordInfo_Release(oldiface);
((IRecordInfo**)arr)[-1] = iface;
if (iface)
IRecordInfo_AddRef(iface);
return S_OK;
}
/************************************************************************
* SafeArrayGetRecordInfo (OLEAUT32.45)
*/
HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *arr, IRecordInfo** iface) {
if (!arr || !(arr->fFeatures & FADF_RECORD))
return E_INVALIDARG;
*iface = ((IRecordInfo**)arr)[-1];
if (*iface)
IRecordInfo_AddRef(*iface);
return S_OK;
}

View File

@ -4,6 +4,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
TESTDLL = oleaut32.dll
IMPORTS = oleaut32
EXTRALIBS = $(LIBUUID)
CTESTS = \
safearray.c \

View File

@ -37,60 +37,66 @@
#include "oleauto.h"
#define VARTYPE_NOT_SUPPORTED 0
static ULONG vttypes[] = {
/* this is taken from wtypes.h. Only [S]es are supported by the SafeArray */
VARTYPE_NOT_SUPPORTED, /* VT_EMPTY [V] [P] nothing */
VARTYPE_NOT_SUPPORTED, /* VT_NULL [V] [P] SQL style Nul */
2, /* VT_I2 [V][T][P][S] 2 byte signed int */
4, /* VT_I4 [V][T][P][S] 4 byte signed int */
4, /* VT_R4 [V][T][P][S] 4 byte real */
8, /* VT_R8 [V][T][P][S] 8 byte real */
8, /* VT_CY [V][T][P][S] currency */
8, /* VT_DATE [V][T][P][S] date */
sizeof(BSTR), /* VT_BSTR [V][T][P][S] OLE Automation string*/
sizeof(LPDISPATCH), /* VT_DISPATCH [V][T][P][S] IDispatch * */
4, /* VT_ERROR [V][T] [S] SCODE */
2, /* VT_BOOL [V][T][P][S] True=-1, False=0*/
sizeof(VARIANT), /* VT_VARIANT [V][T][P][S] VARIANT * */
sizeof(LPUNKNOWN), /* VT_UNKNOWN [V][T] [S] IUnknown * */
sizeof(DECIMAL), /* VT_DECIMAL [V][T] [S] 16 byte fixed point */
VARTYPE_NOT_SUPPORTED, /* no VARTYPE here..... */
1, /* VT_I1 [T] [S] signed char */
1, /* VT_UI1 [V][T][P][S] unsigned char */
2, /* VT_UI2 [T][P][S] unsigned short */
4, /* VT_UI4 [T][P][S] unsigned int */
VARTYPE_NOT_SUPPORTED, /* VT_I8 [T][P] signed 64-bit int */
VARTYPE_NOT_SUPPORTED, /* VT_UI8 [T][P] unsigned 64-bit int */
sizeof(INT), /* VT_INT [T] signed machine int */
sizeof(UINT), /* VT_UINT [T] unsigned machine int */
VARTYPE_NOT_SUPPORTED, /* VT_VOID [T] C style void */
VARTYPE_NOT_SUPPORTED, /* VT_HRESULT [T] Standard return type */
VARTYPE_NOT_SUPPORTED, /* VT_PTR [T] pointer type */
VARTYPE_NOT_SUPPORTED, /* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)*/
VARTYPE_NOT_SUPPORTED, /* VT_CARRAY [T] C style array */
VARTYPE_NOT_SUPPORTED, /* VT_USERDEFINED [T] user defined type */
VARTYPE_NOT_SUPPORTED, /* VT_LPSTR [T][P] null terminated string */
VARTYPE_NOT_SUPPORTED, /* VT_LPWSTR [T][P] wide null term string */
VARTYPE_NOT_SUPPORTED, /* VT_FILETIME [P] FILETIME */
VARTYPE_NOT_SUPPORTED, /* VT_BLOB [P] Length prefixed bytes */
VARTYPE_NOT_SUPPORTED, /* VT_STREAM [P] Name of stream follows */
VARTYPE_NOT_SUPPORTED, /* VT_STORAGE [P] Name of storage follows */
VARTYPE_NOT_SUPPORTED, /* VT_STREAMED_OBJECT[P] Stream contains an object*/
VARTYPE_NOT_SUPPORTED, /* VT_STORED_OBJECT [P] Storage contains object*/
VARTYPE_NOT_SUPPORTED, /* VT_BLOB_OBJECT [P] Blob contains an object*/
VARTYPE_NOT_SUPPORTED, /* VT_CF [P] Clipboard format */
VARTYPE_NOT_SUPPORTED, /* VT_CLSID [P] A Class ID */
VARTYPE_NOT_SUPPORTED, /* VT_VECTOR [P] simple counted array */
VARTYPE_NOT_SUPPORTED, /* VT_ARRAY [V] SAFEARRAY* */
VARTYPE_NOT_SUPPORTED /* VT_BYREF [V] void* for local use */
static struct {
enum VARENUM vt; /* VT */
UINT elemsize; /* elementsize by VT */
UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
UINT addflags; /* additional fFeatures from SafeArrayCreate */
} vttypes[] = {
{VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_I2, 2, FADF_HAVEVARTYPE,0},
{VT_I4, 4, FADF_HAVEVARTYPE,0},
{VT_R4, 4, FADF_HAVEVARTYPE,0},
{VT_R8, 8, FADF_HAVEVARTYPE,0},
{VT_CY, 8, FADF_HAVEVARTYPE,0},
{VT_DATE, 8, FADF_HAVEVARTYPE,0},
{VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
{VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
{VT_ERROR, 4, FADF_HAVEVARTYPE,0},
{VT_BOOL, 2, FADF_HAVEVARTYPE,0},
{VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
{VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
{VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
{15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
{VT_I1, 1, FADF_HAVEVARTYPE,0},
{VT_UI1, 1, FADF_HAVEVARTYPE,0},
{VT_UI2, 2, FADF_HAVEVARTYPE,0},
{VT_UI4, 4, FADF_HAVEVARTYPE,0},
{VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
{VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
{VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
{VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
{VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
};
START_TEST(safearray)
{
SAFEARRAY *a;
unsigned short i;
SAFEARRAY *a, b, *c;
unsigned int i;
HRESULT hres;
SAFEARRAYBOUND bound;
VARIANT v;
LPVOID data;
IID iid;
VARTYPE vt;
hres = SafeArrayAllocDescriptor(0,&a);
ok(E_INVALIDARG == hres,"SAAD(0) failed with hres %lx",hres);
@ -100,12 +106,12 @@ START_TEST(safearray)
for (i=1;i<100;i++) {
hres=SafeArrayAllocDescriptor(i,&a);
ok(S_OK == hres,"SAAD(%d) failed with %lx\n",i,hres);
ok(S_OK == hres,"SAAD(%d) failed with %lx",i,hres);
ok(a->cDims == i,"a->cDims not initialised?\n");
ok(a->cDims == i,"a->cDims not initialised?");
hres=SafeArrayDestroyDescriptor(a);
ok(S_OK == hres,"SADD failed with %lx\n",hres);
ok(S_OK == hres,"SADD failed with %lx",hres);
}
hres=SafeArrayAllocDescriptor(65535,&a);
@ -124,13 +130,163 @@ START_TEST(safearray)
bound.cElements = 1;
bound.lLbound = 0;
a = SafeArrayCreate(-1, 1, &bound);
ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
ok(NULL == a,"SAC(-1,1,[1,0]) not failed?");
for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
a = SafeArrayCreate(i, 1, &bound);
ok( ((a == NULL) && (vttypes[i] == 0)) ||
((a != NULL) && (vttypes[i] == a->cbElements)),
"SAC(%d,1,[1,0]), result %ld, expected %ld\n",i,(a?a->cbElements:0),vttypes[i]
a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
ok( ((a == NULL) && (vttypes[i].elemsize == 0)) ||
((a != NULL) && (vttypes[i].elemsize == a->cbElements)),
"SAC(%d,1,[1,0]), result %ld, expected %d",vttypes[i].vt,(a?a->cbElements:0),vttypes[i].elemsize
);
if (a!=NULL)
ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),"SAC of %d returned feature flags %x, expected %x", vttypes[i].vt, a->fFeatures, vttypes[i].expflags|vttypes[i].addflags);
ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,"SAGE for vt %d returned elemsize %d instead of expected %d",vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
if (!a) continue;
hres = SafeArrayGetVartype(a, &vt);
ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx", vttypes[i].vt, hres);
if (vttypes[i].vt == VT_DISPATCH) {
/* Special case. Checked against Windows. */
ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d", vt);
} else {
ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
}
hres = SafeArrayCopy(a, &c);
ok(hres == S_OK, "failed to copy safearray of vt %d with hres %lx", vttypes[i].vt, hres);
ok(vttypes[i].elemsize == c->cbElements,"copy of SAC(%d,1,[1,0]), result %ld, expected %d",vttypes[i].vt,(c?c->cbElements:0),vttypes[i].elemsize
);
ok(c->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),"SAC of %d returned feature flags %x, expected %x", vttypes[i].vt, c->fFeatures, vttypes[i].expflags|vttypes[i].addflags);
ok(SafeArrayGetElemsize(c) == vttypes[i].elemsize,"SAGE for vt %d returned elemsize %d instead of expected %d",vttypes[i].vt, SafeArrayGetElemsize(c),vttypes[i].elemsize);
hres = SafeArrayGetVartype(c, &vt);
ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx", vttypes[i].vt, hres);
if (vttypes[i].vt == VT_DISPATCH) {
/* Special case. Checked against Windows. */
ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d", vt);
} else {
ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
}
hres = SafeArrayCopyData(a, c);
ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %lx", vttypes[i].vt, hres);
hres = SafeArrayDestroyData(c);
ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %lx", vttypes[i].vt, hres);
hres = SafeArrayDestroy(a);
ok(hres == S_OK,"SAD of array with vt %d failed with hres %lx", vttypes[i].vt, hres);
}
/* Test conversion of type|VT_ARRAY <-> VT_BSTR */
bound.lLbound = 0;
bound.cElements = 10;
a = SafeArrayCreate(VT_UI1, 1, &bound);
ok(a != NULL, "SAC failed.");
ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed");
memcpy(data,"Hello World",10);
ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed");
V_VT(&v) = VT_ARRAY|VT_UI1;
V_ARRAY(&v) = a;
hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx",hres);
ok(V_VT(&v) == VT_BSTR,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.",V_VT(&v));
ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x", V_BSTR(&v)[0]);
/* check locking functions */
a = SafeArrayCreate(VT_I4, 1, &bound);
ok(a!=NULL,"SAC should not fail");
hres = SafeArrayAccessData(a, &data);
ok(hres == S_OK,"SAAD failed with hres %lx",hres);
hres = SafeArrayDestroy(a);
ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %lx", hres);
hres = SafeArrayDestroyData(a);
ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %lx", hres);
hres = SafeArrayDestroyDescriptor(a);
ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %lx", hres);
hres = SafeArrayUnaccessData(a);
ok(hres == S_OK,"SAUD failed after lock/destroy test");
hres = SafeArrayDestroy(a);
ok(hres == S_OK,"SAD failed after lock/destroy test");
/* Test if we need to destroy data before descriptor */
a = SafeArrayCreate(VT_I4, 1, &bound);
ok(a!=NULL,"SAC should not fail");
hres = SafeArrayDestroyDescriptor(a);
ok(hres == S_OK,"SADD with data in array failed with hres %lx",hres);
/* IID functions */
/* init a small stack safearray */
memset(&b, 0, sizeof(b));
b.cDims = 1;
memset(&iid, 0x42, sizeof(IID));
hres = SafeArraySetIID(&b,&iid);
ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %lx",hres);
hres = SafeArrayAllocDescriptor(1,&a);
ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID");
hres = SafeArraySetIID(a,&iid);
ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %lx",hres);
for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
hres = SafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
if (a->fFeatures & FADF_HAVEIID) {
hres = SafeArrayGetIID(a, &iid);
ok(hres == S_OK,"SAGIID failed for vt %d with hres %lx", vttypes[i].vt,hres);
switch (vttypes[i].vt) {
case VT_UNKNOWN:
ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown");
ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown");
break;
case VT_DISPATCH:
ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch");
ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch");
break;
default:
ok(FALSE,"unknown vt %d with FADF_HAVEIID",vttypes[i].vt);
break;
}
} else {
hres = SafeArrayGetIID(a, &iid);
ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %lx", vttypes[i].vt,hres);
}
if (a->fFeatures & FADF_RECORD) {
ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d",vttypes[i].vt);
}
if (a->fFeatures & FADF_HAVEVARTYPE) {
ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %ld",vttypes[i].vt,((DWORD*)a)[-1]);
}
hres = SafeArrayGetVartype(a, &vt);
ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx", vttypes[i].vt, hres);
if (vttypes[i].vt == VT_DISPATCH) {
/* Special case. Checked against Windows. */
ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d", vt);
} else {
ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
}
if (a->fFeatures & FADF_HAVEIID) {
hres = SafeArraySetIID(a, &IID_IStorage); /* random IID */
ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %lx", vttypes[i].vt, hres);
hres = SafeArrayGetIID(a, &iid);
ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %lx", vttypes[i].vt, hres);
ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage");
} else {
hres = SafeArraySetIID(a, &IID_IStorage); /* random IID */
ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %lx", vttypes[i].vt, hres);
}
hres = SafeArrayDestroyDescriptor(a);
ok(hres == S_OK,"SADD failed with hres %lx",hres);
}
}

View File

@ -61,6 +61,9 @@ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo);
HRESULT WINAPI
SafeArrayAllocDescriptor(UINT cDims, struct tagSAFEARRAY **ppsaOut);
HRESULT WINAPI
SafeArrayAllocDescriptorEx(VARTYPE vt,UINT cDims,struct tagSAFEARRAY **ppsaOut);
HRESULT WINAPI
SafeArrayAllocData(struct tagSAFEARRAY *psa);
@ -104,7 +107,7 @@ HRESULT WINAPI
SafeArrayPtrOfIndex(struct tagSAFEARRAY *psa, LONG *rgIndices, void **ppvData);
HRESULT WINAPI
SafeArrayCopyData(struct tagSAFEARRAY *psaSource, struct tagSAFEARRAY **psaTarget);
SafeArrayCopyData(struct tagSAFEARRAY *psaSource, struct tagSAFEARRAY *psaTarget);
HRESULT WINAPI
SafeArrayDestroyData(struct tagSAFEARRAY *psa);
@ -121,6 +124,21 @@ SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements);
HRESULT WINAPI
SafeArrayRedim(struct tagSAFEARRAY *psa, struct tagSAFEARRAYBOUND *psaboundNew);
HRESULT WINAPI
SafeArraySetIID(struct tagSAFEARRAY *psa, REFGUID riid);
HRESULT WINAPI
SafeArrayGetIID(struct tagSAFEARRAY *psa, GUID *riid);
HRESULT WINAPI
SafeArrayGetVartype(struct tagSAFEARRAY *psa, VARTYPE *vt);
HRESULT WINAPI
SafeArrayGetRecordInfo(struct tagSAFEARRAY *psa, IRecordInfo **recordinfo);
HRESULT WINAPI
SafeArraySetRecordInfo(struct tagSAFEARRAY *psa, IRecordInfo *recordinfo);
/* These are macros that help accessing the VARIANT date type.
*/

View File

@ -33,6 +33,9 @@ typedef struct IDispatch IDispatch,*LPDISPATCH;
DEFINE_OLEGUID(IID_ITypeInfo, 0x00020401,0,0);
typedef struct ITypeInfo ITypeInfo,*LPTYPEINFO;
DEFINE_OLEGUID(IID_IRecordInfo, 0x0000002f,0,0);
typedef struct IRecordInfo IRecordInfo,*LPRECORDINFO;
DEFINE_OLEGUID(IID_ITypeLib, 0x00020402,0,0);
typedef struct ITypeLib ITypeLib,*LPTYPELIB;
@ -802,4 +805,52 @@ ICOM_DEFINE(IEnumVARIANT,IUnknown)
#define IEnumVARIANT_Reset(p) ICOM_CALL (Reset,p)
#define IEnumVARIANT_Clone(p,a) ICOM_CALL1(Clone,p,a)
/*****************************************************************************
* IRecordInfo interface
*/
#define ICOM_INTERFACE IRecordInfo
#define IRecordInfo_METHODS \
ICOM_METHOD1(HRESULT, RecordInit, PVOID, pvNew) \
ICOM_METHOD1(HRESULT, RecordClear, PVOID, pvExisting) \
ICOM_METHOD2(HRESULT, RecordCopy, PVOID, pvExisting, PVOID, pvNew) \
ICOM_METHOD1(HRESULT, GetGUID, GUID*, pguid) \
ICOM_METHOD1(HRESULT, GetName, BSTR*, pbstrName) \
ICOM_METHOD1(HRESULT, GetSize, ULONG*, pcbSize) \
ICOM_METHOD1(HRESULT, GetTypeInfo, ITypeInfo**, ppTypeInfo) \
ICOM_METHOD3(HRESULT, GetField, PVOID, pvData, LPCOLESTR, szFieldName, VARIANT*, pvarField) \
ICOM_METHOD4(HRESULT, GetFieldNoCopy, PVOID, pvData, LPCOLESTR, szFieldName, VARIANT*, pvarField, PVOID *,ppvDataCArray) \
ICOM_METHOD4(HRESULT, PutField, ULONG, wFlags, PVOID, pvData, LPCOLESTR, szFieldName, VARIANT*, pvarField) \
ICOM_METHOD4(HRESULT, PutFieldNoCopy, ULONG, wFlags, PVOID, pvData, LPCOLESTR, szFieldName, VARIANT*, pvarField) \
ICOM_METHOD2(HRESULT, GetFieldNames, ULONG*, pcNames, BSTR*, rgBstrNames) \
ICOM_METHOD1(BOOL, IsMatchingType, IRecordInfo*, pRecordInfo) \
ICOM_METHOD (LPVOID, RecordCreate) \
ICOM_METHOD2(HRESULT, RecordCreateCopy, PVOID, pvSource, PVOID*, ppvDest) \
ICOM_METHOD1(HRESULT, RecordDestroy, PVOID, pvRecord)
#define IRecordInfo_IMETHODS \
IUnknown_IMETHODS \
IRecordInfo_METHODS
ICOM_DEFINE(IRecordInfo,IUnknown)
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IRecordInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IRecordInfo_AddRef(p) ICOM_CALL (AddRef,p)
#define IRecordInfo_Release(p) ICOM_CALL (Release,p)
/*** IRecordInfo methods ***/
#define IRecordInfo_RecordInit(p,a) ICOM_CALL1(RecordInit,p,a)
#define IRecordInfo_RecordClear(p,a) ICOM_CALL1(RecordClear,p,a)
#define IRecordInfo_RecordCopy(p,a,b) ICOM_CALL2(RecordCopy,p,a,b)
#define IRecordInfo_GetGUID(p,a) ICOM_CALL1(GetGUID,p,a)
#define IRecordInfo_GetName(p,a) ICOM_CALL1(GetName,p,a)
#define IRecordInfo_GetTypeInfo(p,a) ICOM_CALL1(GetTypeInfo,p,a)
#define IRecordInfo_GetField(p,a,b,c) ICOM_CALL3(GetField,p,a,b,c)
#define IRecordInfo_GetFieldNoCopy(p,a,b,c,d) ICOM_CALL4(GetFieldNoCopy,p,a,b,c,d)
#define IRecordInfo_PutField(p,a,b,c,d) ICOM_CALL4(PutField,p,a,b,c,d)
#define IRecordInfo_PutFieldNoCopy(p,a,b,c,d) ICOM_CALL4(PutField,p,a,b,c,d)
#define IRecordInfo_GetFieldNames(p,a,b) ICOM_CALL2(GetFieldNames,p,a,b)
#define IRecordInfo_RecordCreate(p) ICOM_CALL (RecordCreate,p)
#define IRecordInfo_RecordCreateCopy(p,a,b) ICOM_CALL2(RecordCreateCopy,p,a,b)
#define IRecordInfo_RecordDestroy(p,a) ICOM_CALL1(RecordDestroy,p,a)
#endif /* __WINE_WINE_OBJ_OLEAUT_H */