Fixed index handling for multi dimensional arrays.
[wine] / dlls / oleaut32 / tests / safearray.c
1 /*
2  * SafeArray test program
3  *
4  * Copyright 2002 Marcus Meissner
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include <winsock.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include <float.h>
28 #include <time.h>
29
30 #include "wine/test.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "winnls.h"
35 #include "winerror.h"
36 #include "winnt.h"
37
38 #include "wtypes.h"
39 #include "oleauto.h"
40
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;
46
47 #define VARTYPE_NOT_SUPPORTED 0
48 static struct {
49         VARTYPE vt;    /* VT */
50         UINT elemsize; /* elementsize by VT */
51         UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
52         UINT addflags; /* additional fFeatures from SafeArrayCreate */
53 } vttypes[] = {
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},
96 };
97
98 START_TEST(safearray)
99 {
100         HMODULE hdll;
101         SAFEARRAY       *a, b, *c;
102         unsigned int    i;
103         long            indices[2];
104         HRESULT         hres;
105         SAFEARRAYBOUND  bound, bounds[2];
106         VARIANT         v;
107         LPVOID          data;
108         IID             iid;
109         VARTYPE         vt;
110         LONG            l;
111         unsigned char   *ptr1, *ptr2;
112
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");
119
120         hres = SafeArrayAllocDescriptor(0,&a);
121         ok(E_INVALIDARG == hres,"SAAD(0) failed with hres %lx",hres);
122
123         hres=SafeArrayAllocDescriptor(1,&a);
124         ok(S_OK == hres,"SAAD(1) failed with %lx",hres);
125
126         for (i=1;i<100;i++) {
127                 hres=SafeArrayAllocDescriptor(i,&a);
128                 ok(S_OK == hres,"SAAD(%d) failed with %lx",i,hres);
129                 
130                 ok(a->cDims == i,"a->cDims not initialised?");
131
132                 hres=SafeArrayDestroyDescriptor(a);
133                 ok(S_OK == hres,"SADD failed with %lx",hres);
134         }
135
136         hres=SafeArrayAllocDescriptor(65535,&a);
137         ok(S_OK == hres,"SAAD(65535) failed with %lx",hres);
138
139         hres=SafeArrayDestroyDescriptor(a);
140         ok(S_OK == hres,"SADD failed with %lx",hres);
141
142         hres=SafeArrayAllocDescriptor(65536,&a);
143         ok(E_INVALIDARG == hres,"SAAD(65536) failed with %lx",hres);
144
145         /* Crashes on Win95: SafeArrayAllocDescriptor(xxx,NULL) */
146         
147         bound.cElements = 1;
148         bound.lLbound   = 0;
149         a = SafeArrayCreate(-1, 1, &bound);
150         ok(NULL == a,"SAC(-1,1,[1,0]) not failed?");
151
152
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.");
157
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);
168
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);
179
180         i = SafeArrayGetDim(a);
181         ok(i == 2, "getdims of 2 din array returned %d",i);
182
183         indices[0] = 0;
184         indices[1] = 23;
185         hres = SafeArrayGetElement(a, indices, &i);
186         ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%lx",hres);
187
188         indices[0] = 1;
189         indices[1] = 22;
190         hres = SafeArrayGetElement(a, indices, &i);
191         ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%lx",hres);
192
193         indices[0] = 1;
194         indices[1] = 23;
195         hres = SafeArrayGetElement(a, indices, &i);
196         ok(S_OK == hres,"SAGE failed [1,23], hres 0x%lx",hres);
197
198         indices[0] = 1;
199         indices[1] = 25;
200         hres = SafeArrayGetElement(a, indices, &i);
201         ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%lx",hres);
202
203         indices[0] = 3;
204         indices[1] = 23;
205         hres = SafeArrayGetElement(a, indices, &i);
206         ok(S_OK == hres,"SAGE failed [42,23], hres 0x%lx",hres);
207
208         hres = SafeArrayAccessData(a, (void**)&ptr1);
209         ok(S_OK == hres, "SAAD failed with 0x%lx", hres);
210
211         indices[0] = 3;
212         indices[1] = 23;
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);
216
217         indices[0] = 3;
218         indices[1] = 24;
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);
222
223         indices[0] = 20;
224         indices[1] = 23;
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);
228
229         hres = SafeArrayUnaccessData(a);
230         ok(S_OK == hres, "SAUAD failed with 0x%lx", hres);
231
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
237                 );
238         if (a!=NULL) {
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);
246         }
247
248                 if (!a) continue;
249
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);
256             } else {
257                         ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
258             }
259         }
260
261                 hres = SafeArrayCopy(a, &c);
262                 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %lx", vttypes[i].vt, hres);
263
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
265                 );
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);
268
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);
275             } else {
276                 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
277             }
278         }
279
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);
283
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);
286         }
287
288                 hres = SafeArrayDestroy(a);
289                 ok(hres == S_OK,"SAD of array with vt %d failed with hres %lx", vttypes[i].vt, hres);
290         }
291
292         /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
293         bound.lLbound = 0;
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;
301         V_ARRAY(&v) = a;
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]);
306
307         /* check locking functions */
308         a = SafeArrayCreate(VT_I4, 1, &bound);
309         ok(a!=NULL,"SAC should not fail");
310
311         hres = SafeArrayAccessData(a, &data);
312         ok(hres == S_OK,"SAAD failed with hres %lx",hres);
313
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);
316
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);
319
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);
322
323         hres = SafeArrayUnaccessData(a);
324         ok(hres == S_OK,"SAUD failed after lock/destroy test");
325
326         hres = SafeArrayDestroy(a);
327         ok(hres == S_OK,"SAD failed after lock/destroy test");
328
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);
334
335
336         /* IID functions */
337         /* init a small stack safearray */
338     if (pSafeArraySetIID) {
339         memset(&b, 0, sizeof(b));
340         b.cDims = 1;
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);
344
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);
349     }
350
351     if (!pSafeArrayAllocDescriptorEx)
352         return;
353
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) {
361                         case VT_UNKNOWN:
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");
364                                 break;
365                         case VT_DISPATCH:
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");
368                                 break;
369                         default:
370                                 ok(FALSE,"unknown vt %d with FADF_HAVEIID",vttypes[i].vt);
371                                 break;
372                         }
373                 } else {
374                         hres = pSafeArrayGetIID(a, &iid);
375                         ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %lx", vttypes[i].vt,hres);
376                 }
377                 if (a->fFeatures & FADF_RECORD) {
378                         ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d",vttypes[i].vt);
379                 }
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]);
382                 }
383
384                 hres = pSafeArrayGetVartype(a, &vt);
385                 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx", vttypes[i].vt, hres);
386
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);
390                 } else {
391                         ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d", vttypes[i].vt, vt);
392                 }
393
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");
400                 } else {
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);
403                 }
404                 hres = SafeArrayDestroyDescriptor(a);
405                 ok(hres == S_OK,"SADD failed with hres %lx",hres);
406         }
407 }