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.
This commit is contained in:
parent
48e583db52
commit
8ff278d25e
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ SRCDIR = @srcdir@
|
|||
VPATH = @srcdir@
|
||||
TESTDLL = oleaut32.dll
|
||||
IMPORTS = oleaut32
|
||||
EXTRALIBS = $(LIBUUID)
|
||||
|
||||
CTESTS = \
|
||||
safearray.c \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue