2 * SafeArray test program
4 * Copyright 2002 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/test.h"
41 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,struct tagSAFEARRAY**)=NULL;
42 static HRESULT (WINAPI *pSafeArrayCopyData)(struct tagSAFEARRAY*,struct tagSAFEARRAY*)=NULL;
43 static HRESULT (WINAPI *pSafeArrayGetIID)(struct tagSAFEARRAY*,GUID*)=NULL;
44 static HRESULT (WINAPI *pSafeArraySetIID)(struct tagSAFEARRAY*,REFGUID)=NULL;
45 static HRESULT (WINAPI *pSafeArrayGetVartype)(struct tagSAFEARRAY*,VARTYPE*)=NULL;
47 #define VARTYPE_NOT_SUPPORTED 0
50 UINT elemsize; /* elementsize by VT */
51 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
52 UINT addflags; /* additional fFeatures from SafeArrayCreate */
54 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
55 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
56 {VT_I2, 2, FADF_HAVEVARTYPE,0},
57 {VT_I4, 4, FADF_HAVEVARTYPE,0},
58 {VT_R4, 4, FADF_HAVEVARTYPE,0},
59 {VT_R8, 8, FADF_HAVEVARTYPE,0},
60 {VT_CY, 8, FADF_HAVEVARTYPE,0},
61 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
62 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
63 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
64 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
65 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
66 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
67 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
68 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
69 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
70 {VT_I1, 1, FADF_HAVEVARTYPE,0},
71 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
72 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
73 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
74 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
75 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
76 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
77 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
78 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
79 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
80 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
81 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
82 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
83 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
84 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
85 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
86 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
87 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
88 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
89 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
90 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
91 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
92 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
93 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
94 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
95 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
105 SAFEARRAYBOUND bound, bounds[2];
111 unsigned char *ptr1, *ptr2;
113 hdll=LoadLibraryA("oleaut32.dll");
114 pSafeArrayAllocDescriptorEx=(void*)GetProcAddress(hdll,"SafeArrayAllocDescriptorEx");
115 pSafeArrayCopyData=(void*)GetProcAddress(hdll,"SafeArrayCopyData");
116 pSafeArrayGetIID=(void*)GetProcAddress(hdll,"SafeArrayGetIID");
117 pSafeArraySetIID=(void*)GetProcAddress(hdll,"SafeArraySetIID");
118 pSafeArrayGetVartype=(void*)GetProcAddress(hdll,"SafeArrayGetVartype");
120 hres = SafeArrayAllocDescriptor(0,&a);
121 ok(E_INVALIDARG == hres,"SAAD(0) failed with hres %lx",hres);
123 hres=SafeArrayAllocDescriptor(1,&a);
124 ok(S_OK == hres,"SAAD(1) failed with %lx",hres);
126 for (i=1;i<100;i++) {
127 hres=SafeArrayAllocDescriptor(i,&a);
128 ok(S_OK == hres,"SAAD(%d) failed with %lx",i,hres);
130 ok(a->cDims == i,"a->cDims not initialised?");
132 hres=SafeArrayDestroyDescriptor(a);
133 ok(S_OK == hres,"SADD failed with %lx",hres);
136 hres=SafeArrayAllocDescriptor(65535,&a);
137 ok(S_OK == hres,"SAAD(65535) failed with %lx",hres);
139 hres=SafeArrayDestroyDescriptor(a);
140 ok(S_OK == hres,"SADD failed with %lx",hres);
142 hres=SafeArrayAllocDescriptor(65536,&a);
143 ok(E_INVALIDARG == hres,"SAAD(65536) failed with %lx",hres);
145 /* Crashes on Win95: SafeArrayAllocDescriptor(xxx,NULL) */
149 a = SafeArrayCreate(-1, 1, &bound);
150 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?");
153 bounds[0].cElements = 42; bounds[0].lLbound = 1;
154 bounds[1].cElements = 2; bounds[1].lLbound = 23;
155 a = SafeArrayCreate(VT_I4,2,bounds);
156 ok(a != NULL,"SAC(VT_INT32,2,...) failed.");
158 hres = SafeArrayGetLBound (a, 0, &l);
159 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %lx", hres);
160 hres = SafeArrayGetLBound (a, 1, &l);
161 ok (hres == S_OK, "SAGLB 1 failed with %lx", hres);
162 ok (l == 1, "SAGLB 1 returned %ld instead of 1", l);
163 hres = SafeArrayGetLBound (a, 2, &l);
164 ok (hres == S_OK, "SAGLB 2 failed with %lx", hres);
165 ok (l == 23, "SAGLB 2 returned %ld instead of 1", l);
166 hres = SafeArrayGetLBound (a, 3, &l);
167 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %lx", hres);
169 hres = SafeArrayGetUBound (a, 0, &l);
170 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %lx", hres);
171 hres = SafeArrayGetUBound (a, 1, &l);
172 ok (hres == S_OK, "SAGUB 1 failed with %lx", hres);
173 ok (l == 42, "SAGUB 1 returned %ld instead of 1", l);
174 hres = SafeArrayGetUBound (a, 2, &l);
175 ok (hres == S_OK, "SAGUB 2 failed with %lx", hres);
176 ok (l == 24, "SAGUB 2 returned %ld instead of 24", l);
177 hres = SafeArrayGetUBound (a, 3, &l);
178 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %lx", hres);
180 i = SafeArrayGetDim(a);
181 ok(i == 2, "getdims of 2 din array returned %d",i);
185 hres = SafeArrayGetElement(a, indices, &i);
186 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%lx",hres);
190 hres = SafeArrayGetElement(a, indices, &i);
191 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%lx",hres);
195 hres = SafeArrayGetElement(a, indices, &i);
196 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%lx",hres);
200 hres = SafeArrayGetElement(a, indices, &i);
201 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%lx",hres);
205 hres = SafeArrayGetElement(a, indices, &i);
206 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%lx",hres);
208 hres = SafeArrayAccessData(a, (void**)&ptr1);
209 ok(S_OK == hres, "SAAD failed with 0x%lx", hres);
213 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
214 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%lx",hres);
215 ok(ptr2 - ptr1 == 8,"ptr difference is not 8, but %d (%p vs %p)", ptr2-ptr1, ptr2, ptr1);
219 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
220 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%lx",hres);
221 ok(ptr2 - ptr1 == 176,"ptr difference is not 176, but %d (%p vs %p)", ptr2-ptr1, ptr2, ptr1);
225 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
226 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%lx",hres);
227 ok(ptr2 - ptr1 == 76,"ptr difference is not 176, but %d (%p vs %p)", ptr2-ptr1, ptr2, ptr1);
229 hres = SafeArrayUnaccessData(a);
230 ok(S_OK == hres, "SAUAD failed with 0x%lx", hres);
232 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
233 a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
234 ok( ((a == NULL) && (vttypes[i].elemsize == 0)) ||
235 ((a != NULL) && (vttypes[i].elemsize == a->cbElements)),
236 "SAC(%d,1,[1,0]), result %ld, expected %d",vttypes[i].vt,(a?a->cbElements:0),vttypes[i].elemsize
239 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
240 "SAC of %d returned feature flags %x, expected %x",
241 vttypes[i].vt, a->fFeatures,
242 vttypes[i].expflags|vttypes[i].addflags);
243 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
244 "SAGE for vt %d returned elemsize %d instead of expected %d",
245 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
250 if (pSafeArrayGetVartype) {
251 hres = pSafeArrayGetVartype(a, &vt);
252 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %lx", vttypes[i].vt, hres);
253 if (vttypes[i].vt == VT_DISPATCH) {
254 /* Special case. Checked against Windows. */
255 ok(vt == VT_UNKNOWN, "SAGVT of a rray with VT_DISPATCH returned not VT_UNKNOWN, but %d", vt);
257 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
261 hres = SafeArrayCopy(a, &c);
262 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %lx", vttypes[i].vt, hres);
264 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
266 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);
267 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);
269 if (pSafeArrayGetVartype) {
270 hres = pSafeArrayGetVartype(c, &vt);
271 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx", vttypes[i].vt, hres);
272 if (vttypes[i].vt == VT_DISPATCH) {
273 /* Special case. Checked against Windows. */
274 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d", vt);
276 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
280 if (pSafeArrayCopyData) {
281 hres = pSafeArrayCopyData(a, c);
282 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %lx", vttypes[i].vt, hres);
284 hres = SafeArrayDestroyData(c);
285 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %lx", vttypes[i].vt, hres);
288 hres = SafeArrayDestroy(a);
289 ok(hres == S_OK,"SAD of array with vt %d failed with hres %lx", vttypes[i].vt, hres);
292 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
294 bound.cElements = 10;
295 a = SafeArrayCreate(VT_UI1, 1, &bound);
296 ok(a != NULL, "SAC failed.");
297 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed");
298 memcpy(data,"Hello World",10);
299 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed");
300 V_VT(&v) = VT_ARRAY|VT_UI1;
302 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
303 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx",hres);
304 ok(V_VT(&v) == VT_BSTR,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.",V_VT(&v));
305 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x", V_BSTR(&v)[0]);
307 /* check locking functions */
308 a = SafeArrayCreate(VT_I4, 1, &bound);
309 ok(a!=NULL,"SAC should not fail");
311 hres = SafeArrayAccessData(a, &data);
312 ok(hres == S_OK,"SAAD failed with hres %lx",hres);
314 hres = SafeArrayDestroy(a);
315 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %lx", hres);
317 hres = SafeArrayDestroyData(a);
318 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %lx", hres);
320 hres = SafeArrayDestroyDescriptor(a);
321 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %lx", hres);
323 hres = SafeArrayUnaccessData(a);
324 ok(hres == S_OK,"SAUD failed after lock/destroy test");
326 hres = SafeArrayDestroy(a);
327 ok(hres == S_OK,"SAD failed after lock/destroy test");
329 /* Test if we need to destroy data before descriptor */
330 a = SafeArrayCreate(VT_I4, 1, &bound);
331 ok(a!=NULL,"SAC should not fail");
332 hres = SafeArrayDestroyDescriptor(a);
333 ok(hres == S_OK,"SADD with data in array failed with hres %lx",hres);
337 /* init a small stack safearray */
338 if (pSafeArraySetIID) {
339 memset(&b, 0, sizeof(b));
341 memset(&iid, 0x42, sizeof(IID));
342 hres = pSafeArraySetIID(&b,&iid);
343 ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %lx",hres);
345 hres = SafeArrayAllocDescriptor(1,&a);
346 ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID");
347 hres = pSafeArraySetIID(a,&iid);
348 ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %lx",hres);
351 if (!pSafeArrayAllocDescriptorEx)
354 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
355 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
356 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
357 if (a->fFeatures & FADF_HAVEIID) {
358 hres = pSafeArrayGetIID(a, &iid);
359 ok(hres == S_OK,"SAGIID failed for vt %d with hres %lx", vttypes[i].vt,hres);
360 switch (vttypes[i].vt) {
362 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown");
363 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown");
366 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch");
367 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch");
370 ok(FALSE,"unknown vt %d with FADF_HAVEIID",vttypes[i].vt);
374 hres = pSafeArrayGetIID(a, &iid);
375 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %lx", vttypes[i].vt,hres);
377 if (a->fFeatures & FADF_RECORD) {
378 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d",vttypes[i].vt);
380 if (a->fFeatures & FADF_HAVEVARTYPE) {
381 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %ld",vttypes[i].vt,((DWORD*)a)[-1]);
384 hres = pSafeArrayGetVartype(a, &vt);
385 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx", vttypes[i].vt, hres);
387 if (vttypes[i].vt == VT_DISPATCH) {
388 /* Special case. Checked against Windows. */
389 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d", vt);
391 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
394 if (a->fFeatures & FADF_HAVEIID) {
395 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
396 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %lx", vttypes[i].vt, hres);
397 hres = pSafeArrayGetIID(a, &iid);
398 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %lx", vttypes[i].vt, hres);
399 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage");
401 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
402 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %lx", vttypes[i].vt, hres);
404 hres = SafeArrayDestroyDescriptor(a);
405 ok(hres == S_OK,"SADD failed with hres %lx",hres);