From 8ff278d25e7d65df27c646841320b867bdeb8fcb Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 2 Jan 2003 23:13:56 +0000 Subject: [PATCH] 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. --- dlls/oleaut32/oleaut32.spec | 8 +- dlls/oleaut32/safearray.c | 326 +++++++++++++++++++++--------- dlls/oleaut32/tests/Makefile.in | 1 + dlls/oleaut32/tests/safearray.c | 428 +++++++++++++++++++++++++++------------- include/oleauto.h | 20 +- include/wine/obj_oleaut.h | 51 +++++ 6 files changed, 598 insertions(+), 236 deletions(-) rewrite dlls/oleaut32/tests/safearray.c (64%) diff --git a/dlls/oleaut32/oleaut32.spec b/dlls/oleaut32/oleaut32.spec index 457ddc0726c..6877891fa99 100644 --- a/dlls/oleaut32/oleaut32.spec +++ b/dlls/oleaut32/oleaut32.spec @@ -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 diff --git a/dlls/oleaut32/safearray.c b/dlls/oleaut32/safearray.c index 25cbae9d7c4..5805de9da80 100644 --- a/dlls/oleaut32/safearray.c +++ b/dlls/oleaut32/safearray.c @@ -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 #include @@ -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; - - return SafeArrayAllocDescriptor (cDims, ppsaOut); + HRESULT hres; + + 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; + *pvt = ((DWORD*)psa)[-1]; + return S_OK; } - else if (psa->fFeatures & FADF_RECORD) + + if (psa->fFeatures & FADF_RECORD) { - vt = VT_RECORD; + *pvt = VT_RECORD; + return S_OK; } - else if (psa->fFeatures & FADF_BSTR) + + if (psa->fFeatures & FADF_BSTR) { - vt = VT_BSTR; + *pvt = VT_BSTR; + return S_OK; } - else if (psa->fFeatures & FADF_UNKNOWN) + + if (psa->fFeatures & FADF_UNKNOWN) { - vt = VT_UNKNOWN; + *pvt = VT_UNKNOWN; + return S_OK; } - else if (psa->fFeatures & FADF_DISPATCH) + + if (psa->fFeatures & FADF_DISPATCH) { - vt = VT_DISPATCH; + *pvt = VT_UNKNOWN; /* Yes, checked against windows */ + return S_OK; } - else if (psa->fFeatures & FADF_VARIANT) + + if (psa->fFeatures & FADF_VARIANT) { - vt = VT_VARIANT; + *pvt = VT_VARIANT; + return S_OK; } - - if (vt != VT_EMPTY) + if (psa->fFeatures & FADF_HAVEIID) { - *pvt = vt; - hr = S_OK; + /* 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; } - TRACE("HRESULT = %08lx\n", hr); - return hr; + 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; } diff --git a/dlls/oleaut32/tests/Makefile.in b/dlls/oleaut32/tests/Makefile.in index eaaff05caa4..d6f793f6cee 100644 --- a/dlls/oleaut32/tests/Makefile.in +++ b/dlls/oleaut32/tests/Makefile.in @@ -4,6 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = oleaut32.dll IMPORTS = oleaut32 +EXTRALIBS = $(LIBUUID) CTESTS = \ safearray.c \ diff --git a/dlls/oleaut32/tests/safearray.c b/dlls/oleaut32/tests/safearray.c dissimilarity index 64% index 0bfa4e3848e..619be6f9070 100644 --- a/dlls/oleaut32/tests/safearray.c +++ b/dlls/oleaut32/tests/safearray.c @@ -1,136 +1,292 @@ -/* - * SafeArray test program - * - * Copyright 2002 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include - -#include "wine/test.h" -#include "winbase.h" -#include "winuser.h" -#include "wingdi.h" -#include "winnls.h" -#include "winerror.h" -#include "winnt.h" - -#include "wtypes.h" -#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 */ -}; - -START_TEST(safearray) -{ - SAFEARRAY *a; - unsigned short i; - HRESULT hres; - SAFEARRAYBOUND bound; - - hres = SafeArrayAllocDescriptor(0,&a); - ok(E_INVALIDARG == hres,"SAAD(0) failed with hres %lx",hres); - - hres=SafeArrayAllocDescriptor(1,&a); - ok(S_OK == hres,"SAAD(1) failed with %lx",hres); - - for (i=1;i<100;i++) { - hres=SafeArrayAllocDescriptor(i,&a); - ok(S_OK == hres,"SAAD(%d) failed with %lx\n",i,hres); - - ok(a->cDims == i,"a->cDims not initialised?\n"); - - hres=SafeArrayDestroyDescriptor(a); - ok(S_OK == hres,"SADD failed with %lx\n",hres); - } - - hres=SafeArrayAllocDescriptor(65535,&a); - ok(S_OK == hres,"SAAD(65535) failed with %lx",hres); - - hres=SafeArrayDestroyDescriptor(a); - ok(S_OK == hres,"SADD failed with %lx",hres); - - hres=SafeArrayAllocDescriptor(65536,&a); - ok(E_INVALIDARG == hres,"SAAD(65536) failed with %lx",hres); - - hres=SafeArrayAllocDescriptor(1,NULL); - ok(E_POINTER == hres,"SAAD(1,NULL) failed with %lx",hres); - - - bound.cElements = 1; - bound.lLbound = 0; - a = SafeArrayCreate(-1, 1, &bound); - ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n"); - - for (i=0;icbElements)), - "SAC(%d,1,[1,0]), result %ld, expected %ld\n",i,(a?a->cbElements:0),vttypes[i] - ); - } -} +/* + * SafeArray test program + * + * Copyright 2002 Marcus Meissner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include + +#include "wine/test.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winnls.h" +#include "winerror.h" +#include "winnt.h" + +#include "wtypes.h" +#include "oleauto.h" + +#define VARTYPE_NOT_SUPPORTED 0 +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, 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); + + hres=SafeArrayAllocDescriptor(1,&a); + ok(S_OK == hres,"SAAD(1) failed with %lx",hres); + + for (i=1;i<100;i++) { + hres=SafeArrayAllocDescriptor(i,&a); + ok(S_OK == hres,"SAAD(%d) failed with %lx",i,hres); + + ok(a->cDims == i,"a->cDims not initialised?"); + + hres=SafeArrayDestroyDescriptor(a); + ok(S_OK == hres,"SADD failed with %lx",hres); + } + + hres=SafeArrayAllocDescriptor(65535,&a); + ok(S_OK == hres,"SAAD(65535) failed with %lx",hres); + + hres=SafeArrayDestroyDescriptor(a); + ok(S_OK == hres,"SADD failed with %lx",hres); + + hres=SafeArrayAllocDescriptor(65536,&a); + ok(E_INVALIDARG == hres,"SAAD(65536) failed with %lx",hres); + + hres=SafeArrayAllocDescriptor(1,NULL); + ok(E_POINTER == hres,"SAAD(1,NULL) failed with %lx",hres); + + + bound.cElements = 1; + bound.lLbound = 0; + a = SafeArrayCreate(-1, 1, &bound); + ok(NULL == a,"SAC(-1,1,[1,0]) not failed?"); + + for (i=0;icbElements)), + "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;ifFeatures == 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); + } +} diff --git a/include/oleauto.h b/include/oleauto.h index 6db93d39b81..2fe0349058a 100644 --- a/include/oleauto.h +++ b/include/oleauto.h @@ -62,6 +62,9 @@ HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, struct tagSAFEARRAY **ppsaOut); HRESULT WINAPI +SafeArrayAllocDescriptorEx(VARTYPE vt,UINT cDims,struct tagSAFEARRAY **ppsaOut); + +HRESULT WINAPI SafeArrayAllocData(struct tagSAFEARRAY *psa); struct tagSAFEARRAY * WINAPI @@ -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. */ diff --git a/include/wine/obj_oleaut.h b/include/wine/obj_oleaut.h index 5136726e93e..421a887c098 100644 --- a/include/wine/obj_oleaut.h +++ b/include/wine/obj_oleaut.h @@ -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 */ -- 2.11.4.GIT