PATCH: safearray
Marcus Meissner
marcus at jet.franken.de
Sat Dec 28 14:25:26 CST 2002
Hi,
Lots of fixes and new features for SafeArrays. Accompanied with testcases
for large parts (not all).
The testcases run with win2000 oleaut32.dll with 0 errors.
Ciao, Marcus
Changelog:
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.
Index: dlls/oleaut32/oleaut32.spec
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/oleaut32.spec,v
retrieving revision 1.46
diff -u -r1.46 oleaut32.spec
--- dlls/oleaut32/oleaut32.spec 23 Dec 2002 02:02:50 -0000 1.46
+++ dlls/oleaut32/oleaut32.spec 28 Dec 2002 20:10:14 -0000
@@ -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
Index: dlls/oleaut32/safearray.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/safearray.c,v
retrieving revision 1.21
diff -u -r1.21 safearray.c
--- dlls/oleaut32/safearray.c 23 Dec 2002 02:02:50 -0000 1.21
+++ dlls/oleaut32/safearray.c 28 Dec 2002 20:10:14 -0000
@@ -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 @@
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_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_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 @@
{
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 @@
/*************************************************************************
* 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 @@
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 @@
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 @@
} 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 @@
} 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 @@
/* 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 @@
} 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 @@
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 SafeArrayCopyData(
SAFEARRAY *psaSource,
- SAFEARRAY **psaTarget)
+ SAFEARRAY *psaTarget)
{
USHORT cDimCount; /* looper */
LONG lDelta; /* looper */
@@ -648,10 +711,10 @@
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 @@
/* 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 @@
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 @@
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 @@
ULONG cElements)
{
SAFEARRAY *psa;
+ LPVOID *ptr;
/* Validate supported VARTYPE */
if ( (vt >= LAST_VARTYPE) ||
@@ -786,11 +867,12 @@
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 @@
/* 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 @@
/************************************************************************
* 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 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 @@
}
/* 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 @@
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 @@
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 @@
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;
}
Index: dlls/oleaut32/tests/safearray.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tests/safearray.c,v
retrieving revision 1.1
diff -u -r1.1 safearray.c
--- dlls/oleaut32/tests/safearray.c 23 Dec 2002 02:02:49 -0000 1.1
+++ dlls/oleaut32/tests/safearray.c 28 Dec 2002 20:10:20 -0000
@@ -33,64 +33,72 @@
#include "winerror.h"
#include "winnt.h"
+#include "initguid.h"
+
#include "wtypes.h"
#include "oleauto.h"
#define VARTYPE_NOT_SUPPORTED 0
-static int 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;
- int 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 +108,12 @@
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 +132,163 @@
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 %d\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);
}
}
Index: include/oleauto.h
===================================================================
RCS file: /home/wine/wine/include/oleauto.h,v
retrieving revision 1.47
diff -u -r1.47 oleauto.h
--- include/oleauto.h 23 Dec 2002 01:33:33 -0000 1.47
+++ include/oleauto.h 28 Dec 2002 20:10:23 -0000
@@ -62,6 +62,9 @@
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 @@
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);
@@ -120,6 +123,21 @@
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.
Index: include/wine/obj_oleaut.h
===================================================================
RCS file: /home/wine/wine/include/wine/obj_oleaut.h,v
retrieving revision 1.35
diff -u -r1.35 obj_oleaut.h
--- include/wine/obj_oleaut.h 3 Dec 2002 21:42:17 -0000 1.35
+++ include/wine/obj_oleaut.h 28 Dec 2002 20:10:24 -0000
@@ -33,6 +33,9 @@
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;
@@ -801,5 +804,53 @@
#define IEnumVARIANT_Skip(p,a) ICOM_CALL1(Skip,p,a)
#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 */
More information about the wine-patches
mailing list