4 * Copyright 2004 Robert Shearman
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
26 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
28 #include "wine/test.h"
30 /* doesn't work on Windows due to needing more of the
31 * MIDL_STUB_MESSAGE structure to be filled out */
32 #define LPSAFEARRAY_UNMARSHAL_WORKS 0
33 #define BSTR_UNMARSHAL_WORKS 0
35 static inline SF_TYPE
get_union_type(SAFEARRAY
*psa
)
40 hr
= SafeArrayGetVartype(psa
, &vt
);
44 if (psa
->fFeatures
& FADF_HAVEIID
)
50 case VT_UI1
: return SF_I1
;
53 case VT_UI2
: return SF_I2
;
58 case VT_R4
: return SF_I4
;
63 case VT_UI8
: return SF_I8
;
65 case VT_UINT_PTR
: return (sizeof(UINT_PTR
) == 4 ? SF_I4
: SF_I8
);
66 case VT_BSTR
: return SF_BSTR
;
67 case VT_DISPATCH
: return SF_DISPATCH
;
68 case VT_VARIANT
: return SF_VARIANT
;
69 case VT_UNKNOWN
: return SF_UNKNOWN
;
70 /* Note: Return a non-zero size to indicate vt is valid. The actual size
71 * of a UDT is taken from the result of IRecordInfo_GetSize().
73 case VT_RECORD
: return SF_RECORD
;
74 default: return SF_ERROR
;
78 static ULONG
get_cell_count(const SAFEARRAY
*psa
)
80 const SAFEARRAYBOUND
* psab
= psa
->rgsabound
;
81 USHORT cCount
= psa
->cDims
;
88 ulNumCells
*= psab
->cElements
;
94 static void check_safearray(void *buffer
, LPSAFEARRAY lpsa
)
96 unsigned char *wiresa
= buffer
;
103 ok(*(void **)wiresa
== NULL
, "wiresa + 0x0 should be NULL instead of 0x%08lx\n", *(DWORD
*)wiresa
);
107 SafeArrayGetVartype(lpsa
, &vt
);
108 sftype
= get_union_type(lpsa
);
109 cell_count
= get_cell_count(lpsa
);
111 ok(*(DWORD
*)wiresa
, "wiresa + 0x0 should be non-NULL instead of 0x%08lx\n", *(DWORD
*)wiresa
); /* win2k: this is lpsa. winxp: this is 0x00000001 */
112 wiresa
+= sizeof(DWORD
);
113 ok(*(DWORD
*)wiresa
== lpsa
->cDims
, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08lx\n", *(DWORD
*)wiresa
);
114 wiresa
+= sizeof(DWORD
);
115 ok(*(WORD
*)wiresa
== lpsa
->cDims
, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD
*)wiresa
);
116 wiresa
+= sizeof(WORD
);
117 ok(*(WORD
*)wiresa
== lpsa
->fFeatures
, "wiresa + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD
*)wiresa
);
118 wiresa
+= sizeof(WORD
);
119 ok(*(DWORD
*)wiresa
== lpsa
->cbElements
, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08lx\n", *(DWORD
*)wiresa
);
120 wiresa
+= sizeof(DWORD
);
121 ok(*(WORD
*)wiresa
== lpsa
->cLocks
, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD
*)wiresa
);
122 wiresa
+= sizeof(WORD
);
123 ok(*(WORD
*)wiresa
== vt
, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt
, *(WORD
*)wiresa
);
124 wiresa
+= sizeof(WORD
);
125 ok(*(DWORD
*)wiresa
== sftype
, "wiresa + 0x18 should be %08lx instead of 0x%08lx\n", (DWORD
)sftype
, *(DWORD
*)wiresa
);
126 wiresa
+= sizeof(DWORD
);
127 ok(*(DWORD
*)wiresa
== cell_count
, "wiresa + 0x1c should be %lu instead of %lu\n", cell_count
, *(DWORD
*)wiresa
);
128 wiresa
+= sizeof(DWORD
);
129 ok(*(DWORD_PTR
*)wiresa
== (DWORD_PTR
)lpsa
->pvData
, "wirestgm + 0x20 should be lpsa->pvData instead of 0x%08lx\n", *(DWORD_PTR
*)wiresa
);
130 wiresa
+= sizeof(DWORD_PTR
);
131 if(sftype
== SF_HAVEIID
)
134 SafeArrayGetIID(lpsa
, &guid
);
135 ok(IsEqualGUID(&guid
, (GUID
*)wiresa
), "guid mismatch\n");
136 wiresa
+= sizeof(GUID
);
138 ok(!memcmp(wiresa
, lpsa
->rgsabound
, sizeof(lpsa
->rgsabound
[0]) * lpsa
->cDims
), "bounds mismatch\n");
139 wiresa
+= sizeof(lpsa
->rgsabound
[0]) * lpsa
->cDims
;
141 ok(*(DWORD
*)wiresa
== cell_count
, "wiresa + 0x2c should be %lu instead of %lu\n", cell_count
, *(DWORD
*)wiresa
);
142 wiresa
+= sizeof(DWORD
);
143 /* elements are now pointed to by wiresa */
146 static void test_marshal_LPSAFEARRAY(void)
148 unsigned char *buffer
;
151 LPSAFEARRAY lpsa2
= NULL
;
153 MIDL_STUB_MESSAGE stubMsg
= { 0 };
154 USER_MARSHAL_CB umcb
= { 0 };
156 umcb
.Flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
157 umcb
.pReserve
= NULL
;
158 umcb
.pStubMsg
= &stubMsg
;
163 lpsa
= SafeArrayCreate(VT_I2
, 1, &sab
);
164 *(DWORD
*)lpsa
->pvData
= 0xcafebabe;
167 size
= LPSAFEARRAY_UserSize(&umcb
.Flags
, 1, &lpsa
);
168 ok(size
== 68, "size should be 68 bytes, not %ld\n", size
);
169 size
= LPSAFEARRAY_UserSize(&umcb
.Flags
, 0, &lpsa
);
170 ok(size
== 64, "size should be 64 bytes, not %ld\n", size
);
171 buffer
= (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size
);
172 LPSAFEARRAY_UserMarshal(&umcb
.Flags
, buffer
, &lpsa
);
174 check_safearray(buffer
, lpsa
);
176 if (LPSAFEARRAY_UNMARSHAL_WORKS
)
178 LPSAFEARRAY_UserUnmarshal(&umcb
.Flags
, buffer
, &lpsa2
);
179 ok(lpsa2
!= NULL
, "LPSAFEARRAY didn't unmarshal\n");
180 LPSAFEARRAY_UserFree(&umcb
.Flags
, &lpsa2
);
182 HeapFree(GetProcessHeap(), 0, buffer
);
183 SafeArrayDestroy(lpsa
);
185 /* test NULL safe array */
188 size
= LPSAFEARRAY_UserSize(&umcb
.Flags
, 0, &lpsa
);
189 ok(size
== 4, "size should be 4 bytes, not %ld\n", size
);
190 buffer
= (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size
);
191 LPSAFEARRAY_UserMarshal(&umcb
.Flags
, buffer
, &lpsa
);
192 check_safearray(buffer
, lpsa
);
194 if (LPSAFEARRAY_UNMARSHAL_WORKS
)
196 LPSAFEARRAY_UserUnmarshal(&umcb
.Flags
, buffer
, &lpsa2
);
197 ok(lpsa2
== NULL
, "NULL LPSAFEARRAY didn't unmarshal\n");
198 LPSAFEARRAY_UserFree(&umcb
.Flags
, &lpsa2
);
200 HeapFree(GetProcessHeap(), 0, buffer
);
205 lpsa
= SafeArrayCreate(VT_R8
, 1, &sab
);
206 *(double *)lpsa
->pvData
= 3.1415;
209 size
= LPSAFEARRAY_UserSize(&umcb
.Flags
, 1, &lpsa
);
210 ok(size
== 128, "size should be 128 bytes, not %ld\n", size
);
211 size
= LPSAFEARRAY_UserSize(&umcb
.Flags
, 0, &lpsa
);
212 ok(size
== 128, "size should be 128 bytes, not %ld\n", size
);
213 buffer
= (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size
);
214 LPSAFEARRAY_UserMarshal(&umcb
.Flags
, buffer
, &lpsa
);
216 check_safearray(buffer
, lpsa
);
218 HeapFree(GetProcessHeap(), 0, buffer
);
219 SafeArrayDestroy(lpsa
);
222 static void check_bstr(void *buffer
, BSTR b
)
224 DWORD
*wireb
= buffer
;
225 DWORD len
= SysStringLen(b
);
227 ok(*wireb
== len
, "wv[0] %08lx\n", *wireb
);
230 ok(*wireb
== len
* 2, "wv[1] %08lx\n", *wireb
);
232 ok(*wireb
== 0xffffffff, "wv[1] %08lx\n", *wireb
);
234 ok(*wireb
== len
, "wv[2] %08lx\n", *wireb
);
238 ok(!memcmp(wireb
, b
, len
* 2), "strings differ\n");
243 static void test_marshal_BSTR(void)
246 MIDL_STUB_MESSAGE stubMsg
= { 0 };
247 USER_MARSHAL_CB umcb
= { 0 };
248 unsigned char *buffer
;
250 WCHAR str
[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
253 umcb
.Flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
254 umcb
.pReserve
= NULL
;
255 umcb
.pStubMsg
= &stubMsg
;
257 b
= SysAllocString(str
);
258 len
= SysStringLen(b
);
259 ok(len
== 13, "get %ld\n", len
);
261 /* BSTRs are DWORD aligned */
262 size
= BSTR_UserSize(&umcb
.Flags
, 1, &b
);
263 ok(size
== 42, "size %ld\n", size
);
265 size
= BSTR_UserSize(&umcb
.Flags
, 0, &b
);
266 ok(size
== 38, "size %ld\n", size
);
268 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
269 BSTR_UserMarshal(&umcb
.Flags
, buffer
, &b
);
270 check_bstr(buffer
, b
);
272 if (BSTR_UNMARSHAL_WORKS
)
275 BSTR_UserUnmarshal(&umcb
.Flags
, buffer
, &b2
);
276 ok(b2
!= NULL
, "NULL LPSAFEARRAY didn't unmarshal\n");
277 ok(!memcmp(b
, b2
, (len
+ 1) * 2), "strings differ\n");
278 BSTR_UserFree(&umcb
.Flags
, &b2
);
281 HeapFree(GetProcessHeap(), 0, buffer
);
285 size
= BSTR_UserSize(&umcb
.Flags
, 0, &b
);
286 ok(size
== 12, "size %ld\n", size
);
288 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
289 BSTR_UserMarshal(&umcb
.Flags
, buffer
, &b
);
291 check_bstr(buffer
, b
);
292 HeapFree(GetProcessHeap(), 0, buffer
);
296 START_TEST(usrmarshal
)
300 test_marshal_LPSAFEARRAY();