rpcrt4: Implement some full pointer functions and add stubs for others.
[wine.git] / dlls / rpcrt4 / tests / ndr_marshall.c
blob26fcdb6270e3a991d472df81b885ff9d943904a4
1 /*
2 * Unit test suite for ndr marshalling functions
4 * Copyright 2006 Huw Davies
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "wine/test.h"
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winnt.h>
27 #include <winerror.h>
29 #include "rpc.h"
30 #include "rpcdce.h"
31 #include "rpcproxy.h"
34 static int my_alloc_called;
35 static int my_free_called;
36 void * CALLBACK my_alloc(size_t size)
38 my_alloc_called++;
39 return NdrOleAllocate(size);
42 void CALLBACK my_free(void *ptr)
44 my_free_called++;
45 return NdrOleFree(ptr);
48 static const MIDL_STUB_DESC Object_StubDesc =
50 NULL,
51 my_alloc,
52 my_free,
53 { 0 },
58 NULL, /* format string, filled in by tests */
59 1, /* -error bounds_check flag */
60 0x20000, /* Ndr library version */
62 0x50100a4, /* MIDL Version 5.1.164 */
64 NULL,
65 0, /* notify & notify_flag routine table */
66 1, /* Flags */
67 0, /* Reserved3 */
68 0, /* Reserved4 */
69 0 /* Reserved5 */
73 static void test_pointer_marshal(const unsigned char *formattypes,
74 void *memsrc,
75 long srcsize,
76 const void *wiredata,
77 long wiredatalen,
78 int(*cmp)(const void*,const void*,size_t),
79 long num_additional_allocs,
80 const char *msgpfx)
82 RPC_MESSAGE RpcMessage;
83 MIDL_STUB_MESSAGE StubMsg;
84 MIDL_STUB_DESC StubDesc;
85 DWORD size;
86 void *ptr;
87 unsigned char *mem, *mem_orig;
89 my_alloc_called = my_free_called = 0;
90 if(!cmp)
91 cmp = memcmp;
93 StubDesc = Object_StubDesc;
94 StubDesc.pFormatTypes = formattypes;
96 NdrClientInitializeNew(
97 &RpcMessage,
98 &StubMsg,
99 &StubDesc,
102 StubMsg.BufferLength = 0;
103 NdrPointerBufferSize( &StubMsg,
104 memsrc,
105 formattypes );
106 ok(StubMsg.BufferLength >= wiredatalen, "%s: length %ld\n", msgpfx, StubMsg.BufferLength);
108 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
109 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
110 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
112 memset(StubMsg.BufferStart, 0x0, StubMsg.BufferLength); /* This is a hack to clear the padding between the ptr and longlong/double */
114 ptr = NdrPointerMarshall( &StubMsg, memsrc, formattypes );
115 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
116 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
117 ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx);
119 StubMsg.Buffer = StubMsg.BufferStart;
120 StubMsg.MemorySize = 0;
122 #if 0 /* NdrPointerMemorySize crashes under Wine, remove #if 0 when this is fixed */
123 size = NdrPointerMemorySize( &StubMsg, formattypes );
124 ok(size == StubMsg.MemorySize, "%s: mem size %ld size %ld\n", msgpfx, StubMsg.MemorySize, size);
125 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
126 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
127 ok(size == srcsize + 4, "%s: mem size %ld\n", msgpfx, size);
128 else
129 ok(size == srcsize, "%s: mem size %ld\n", msgpfx, size);
131 StubMsg.Buffer = StubMsg.BufferStart;
132 StubMsg.MemorySize = 16;
133 size = NdrPointerMemorySize( &StubMsg, formattypes );
134 ok(size == StubMsg.MemorySize, "%s: mem size %ld size %ld\n", msgpfx, StubMsg.MemorySize, size);
135 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
136 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
137 ok(size == srcsize + 4 + 16, "%s: mem size %ld\n", msgpfx, size);
138 else
139 ok(size == srcsize + 16, "%s: mem size %ld\n", msgpfx, size);
141 StubMsg.Buffer = StubMsg.BufferStart;
142 StubMsg.MemorySize = 1;
143 size = NdrPointerMemorySize( &StubMsg, formattypes );
144 ok(size == StubMsg.MemorySize, "%s: mem size %ld size %ld\n", msgpfx, StubMsg.MemorySize, size);
145 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
146 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
147 ok(size == srcsize + 4 + (srcsize == 8 ? 8 : 4), "%s: mem size %ld\n", msgpfx, size);
148 else
149 ok(size == srcsize + (srcsize == 8 ? 8 : 4), "%s: mem size %ld\n", msgpfx, size);
151 #endif
153 size = srcsize;
154 if(formattypes[1] & 0x10) size += 4;
156 StubMsg.Buffer = StubMsg.BufferStart;
157 StubMsg.MemorySize = 0;
158 mem_orig = mem = HeapAlloc(GetProcessHeap(), 0, size);
160 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
161 *(void**)mem = NULL;
162 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
163 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
164 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
165 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
166 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
167 ok(StubMsg.MemorySize == 0, "%s: memorysize %ld\n", msgpfx, StubMsg.MemorySize);
168 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
169 my_alloc_called = 0;
171 /* reset the buffer and call with must alloc */
172 StubMsg.Buffer = StubMsg.BufferStart;
173 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
174 *(void**)mem = NULL;
175 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 );
176 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
177 /* doesn't allocate mem in this case */
178 todo_wine {
179 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
181 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
182 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
183 ok(StubMsg.MemorySize == 0, "%s: memorysize %ld\n", msgpfx, StubMsg.MemorySize);
185 todo_wine {
186 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
188 my_alloc_called = 0;
189 if(formattypes[0] != 0x11 /* FC_RP */)
191 /* now pass the address of a NULL ptr */
192 mem = NULL;
193 StubMsg.Buffer = StubMsg.BufferStart;
194 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
195 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
196 ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
197 ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx);
198 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
199 ok(StubMsg.MemorySize == 0, "%s: memorysize %ld\n", msgpfx, StubMsg.MemorySize);
200 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
201 my_alloc_called = 0;
202 NdrPointerFree(&StubMsg, mem, formattypes);
204 /* again pass address of NULL ptr, but pretend we're a server */
205 mem = NULL;
206 StubMsg.Buffer = StubMsg.BufferStart;
207 StubMsg.IsClient = 0;
208 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
209 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
210 todo_wine {
211 ok(mem == StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem doesn't point to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
213 ok(!cmp(mem, memsrc, size), "%s: incorrecly unmarshaled\n", msgpfx);
214 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %ld\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
215 ok(StubMsg.MemorySize == 0, "%s: memorysize %ld\n", msgpfx, StubMsg.MemorySize);
216 todo_wine {
217 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
218 my_alloc_called = 0;
221 HeapFree(GetProcessHeap(), 0, mem_orig);
222 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
225 static int deref_cmp(const void *s1, const void *s2, size_t num)
227 return memcmp(*(void**)s1, *(void**)s2, num);
231 static void test_simple_types()
233 unsigned char wiredata[16];
234 unsigned char ch;
235 unsigned char *ch_ptr;
236 unsigned short s;
237 unsigned int i;
238 unsigned long l;
239 ULONGLONG ll;
240 float f;
241 double d;
243 static const unsigned char fmtstr_up_char[] =
245 0x12, 0x8, /* FC_UP [simple_pointer] */
246 0x2, /* FC_CHAR */
247 0x5c, /* FC_PAD */
249 static const unsigned char fmtstr_up_byte[] =
251 0x12, 0x8, /* FC_UP [simple_pointer] */
252 0x1, /* FC_BYTE */
253 0x5c, /* FC_PAD */
255 static const unsigned char fmtstr_up_small[] =
257 0x12, 0x8, /* FC_UP [simple_pointer] */
258 0x3, /* FC_SMALL */
259 0x5c, /* FC_PAD */
261 static const unsigned char fmtstr_up_usmall[] =
263 0x12, 0x8, /* FC_UP [simple_pointer] */
264 0x4, /* FC_USMALL */
265 0x5c, /* FC_PAD */
267 static const unsigned char fmtstr_rp_char[] =
269 0x11, 0x8, /* FC_RP [simple_pointer] */
270 0x2, /* FC_CHAR */
271 0x5c, /* FC_PAD */
273 static const unsigned char fmtstr_rpup_char[] =
275 0x11, 0x14, /* FC_RP [alloced_on_stack] */
276 NdrFcShort( 0x2 ), /* Offset= 2 (4) */
277 0x12, 0x8, /* FC_UP [simple_pointer] */
278 0x2, /* FC_CHAR */
279 0x5c, /* FC_PAD */
281 static const unsigned char fmtstr_rpup_char2[] =
283 0x11, 0x04, /* FC_RP [alloced_on_stack] */
284 NdrFcShort( 0x2 ), /* Offset= 2 (4) */
285 0x12, 0x8, /* FC_UP [simple_pointer] */
286 0x2, /* FC_CHAR */
287 0x5c, /* FC_PAD */
290 static const unsigned char fmtstr_up_wchar[] =
292 0x12, 0x8, /* FC_UP [simple_pointer] */
293 0x5, /* FC_WCHAR */
294 0x5c, /* FC_PAD */
296 static const unsigned char fmtstr_up_short[] =
298 0x12, 0x8, /* FC_UP [simple_pointer] */
299 0x6, /* FC_SHORT */
300 0x5c, /* FC_PAD */
302 static const unsigned char fmtstr_up_ushort[] =
304 0x12, 0x8, /* FC_UP [simple_pointer] */
305 0x7, /* FC_USHORT */
306 0x5c, /* FC_PAD */
308 #if 0
309 static const unsigned char fmtstr_up_enum16[] =
311 0x12, 0x8, /* FC_UP [simple_pointer] */
312 0xd, /* FC_ENUM16 */
313 0x5c, /* FC_PAD */
315 #endif
316 static const unsigned char fmtstr_up_long[] =
318 0x12, 0x8, /* FC_UP [simple_pointer] */
319 0x8, /* FC_LONG */
320 0x5c, /* FC_PAD */
322 static const unsigned char fmtstr_up_ulong[] =
324 0x12, 0x8, /* FC_UP [simple_pointer] */
325 0x9, /* FC_ULONG */
326 0x5c, /* FC_PAD */
328 static const unsigned char fmtstr_up_enum32[] =
330 0x12, 0x8, /* FC_UP [simple_pointer] */
331 0xe, /* FC_ENUM32 */
332 0x5c, /* FC_PAD */
334 static const unsigned char fmtstr_up_errorstatus[] =
336 0x12, 0x8, /* FC_UP [simple_pointer] */
337 0x10, /* FC_ERROR_STATUS_T */
338 0x5c, /* FC_PAD */
341 static const unsigned char fmtstr_up_longlong[] =
343 0x12, 0x8, /* FC_UP [simple_pointer] */
344 0xb, /* FC_HYPER */
345 0x5c, /* FC_PAD */
347 static const unsigned char fmtstr_up_float[] =
349 0x12, 0x8, /* FC_UP [simple_pointer] */
350 0xa, /* FC_FLOAT */
351 0x5c, /* FC_PAD */
353 static const unsigned char fmtstr_up_double[] =
355 0x12, 0x8, /* FC_UP [simple_pointer] */
356 0xc, /* FC_DOUBLE */
357 0x5c, /* FC_PAD */
360 ch = 0xa5;
361 ch_ptr = &ch;
362 *(void**)wiredata = ch_ptr;
363 wiredata[sizeof(void*)] = ch;
365 test_pointer_marshal(fmtstr_up_char, ch_ptr, 1, wiredata, 5, NULL, 0, "up_char");
366 test_pointer_marshal(fmtstr_up_byte, ch_ptr, 1, wiredata, 5, NULL, 0, "up_byte");
367 test_pointer_marshal(fmtstr_up_small, ch_ptr, 1, wiredata, 5, NULL, 0, "up_small");
368 test_pointer_marshal(fmtstr_up_usmall, ch_ptr, 1, wiredata, 5, NULL, 0, "up_usmall");
370 test_pointer_marshal(fmtstr_rp_char, ch_ptr, 1, &ch, 1, NULL, 0, "rp_char");
372 test_pointer_marshal(fmtstr_rpup_char, &ch_ptr, 1, wiredata, 5, deref_cmp, 1, "rpup_char");
373 test_pointer_marshal(fmtstr_rpup_char2, ch_ptr, 1, wiredata, 5, NULL, 0, "rpup_char2");
375 s = 0xa597;
376 *(void**)wiredata = &s;
377 *(unsigned short*)(wiredata + sizeof(void*)) = s;
379 test_pointer_marshal(fmtstr_up_wchar, &s, 2, wiredata, 6, NULL, 0, "up_wchar");
380 test_pointer_marshal(fmtstr_up_short, &s, 2, wiredata, 6, NULL, 0, "up_short");
381 test_pointer_marshal(fmtstr_up_ushort, &s, 2, wiredata, 6, NULL, 0, "up_ushort");
383 i = s;
384 *(void**)wiredata = &i;
385 #if 0 /* Not sure why this crashes under Windows */
386 test_pointer_marshal(fmtstr_up_enum16, &i, 2, wiredata, 6, NULL, 0, "up_enum16");
387 #endif
389 l = 0xcafebabe;
390 *(void**)wiredata = &l;
391 *(unsigned long*)(wiredata + sizeof(void*)) = l;
393 test_pointer_marshal(fmtstr_up_long, &l, 4, wiredata, 8, NULL, 0, "up_long");
394 test_pointer_marshal(fmtstr_up_ulong, &l, 4, wiredata, 8, NULL, 0, "up_ulong");
395 test_pointer_marshal(fmtstr_up_enum32, &l, 4, wiredata, 8, NULL, 0, "up_emun32");
396 test_pointer_marshal(fmtstr_up_errorstatus, &l, 4, wiredata, 8, NULL, 0, "up_errorstatus");
398 ll = ((ULONGLONG)0xcafebabe) << 32 | 0xdeadbeef;
399 *(void**)wiredata = &ll;
400 *(void**)(wiredata + sizeof(void*)) = NULL;
401 *(ULONGLONG*)(wiredata + 2 * sizeof(void*)) = ll;
402 test_pointer_marshal(fmtstr_up_longlong, &ll, 8, wiredata, 16, NULL, 0, "up_longlong");
404 f = 3.1415;
405 *(void**)wiredata = &f;
406 *(float*)(wiredata + sizeof(void*)) = f;
407 test_pointer_marshal(fmtstr_up_float, &f, 4, wiredata, 8, NULL, 0, "up_float");
409 d = 3.1415;
410 *(void**)wiredata = &d;
411 *(void**)(wiredata + sizeof(void*)) = NULL;
412 *(double*)(wiredata + 2 * sizeof(void*)) = d;
413 test_pointer_marshal(fmtstr_up_double, &d, 8, wiredata, 16, NULL, 0, "up_double");
417 static void test_simple_struct_marshal(const unsigned char *formattypes,
418 void *memsrc,
419 long srcsize,
420 const void *wiredata,
421 long wiredatalen,
422 int(*cmp)(const void*,const void*,size_t),
423 long num_additional_allocs,
424 const char *msgpfx)
426 RPC_MESSAGE RpcMessage;
427 MIDL_STUB_MESSAGE StubMsg;
428 MIDL_STUB_DESC StubDesc;
429 DWORD size;
430 void *ptr;
431 unsigned char *mem, *mem_orig;
433 my_alloc_called = my_free_called = 0;
434 if(!cmp)
435 cmp = memcmp;
437 StubDesc = Object_StubDesc;
438 StubDesc.pFormatTypes = formattypes;
440 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0);
442 StubMsg.BufferLength = 0;
443 NdrSimpleStructBufferSize( &StubMsg, (unsigned char *)memsrc, formattypes );
444 ok(StubMsg.BufferLength >= wiredatalen, "%s: length %ld\n", msgpfx, StubMsg.BufferLength);
445 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
446 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
447 ptr = NdrSimpleStructMarshall( &StubMsg, (unsigned char*)memsrc, formattypes );
448 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
449 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
450 ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled %08lx %08lx %08lx\n", msgpfx, *(DWORD*)StubMsg.BufferStart,*((DWORD*)StubMsg.BufferStart+1),*((DWORD*)StubMsg.BufferStart+2));
452 #if 0
453 StubMsg.Buffer = StubMsg.BufferStart;
454 StubMsg.MemorySize = 0;
455 size = NdrSimpleStructMemorySize( &StubMsg, formattypes );
456 ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx);
457 ok(size == srcsize, "%s: mem size %ld\n", msgpfx, size);
458 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
460 StubMsg.Buffer = StubMsg.BufferStart;
461 size = NdrSimpleStructMemorySize( &StubMsg, formattypes );
462 todo_wine {
463 ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx);
465 ok(StubMsg.MemorySize == ((srcsize + 3) & ~3) + srcsize, "%s: mem size %ld\n", msgpfx, size);
466 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
467 #endif
468 size = srcsize;
469 /*** Unmarshalling first with must_alloc false ***/
471 StubMsg.Buffer = StubMsg.BufferStart;
472 StubMsg.MemorySize = 0;
473 mem_orig = mem = HeapAlloc(GetProcessHeap(), 0, srcsize);
474 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
475 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
476 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
477 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
478 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
479 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
480 my_alloc_called = 0;
481 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
483 /* if we're a server we still use the suppiled memory */
484 StubMsg.Buffer = StubMsg.BufferStart;
485 StubMsg.IsClient = 0;
486 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
487 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
488 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
489 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
490 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
491 my_alloc_called = 0;
492 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
494 /* ...unless we pass a NULL ptr, then the buffer is used.
495 Passing a NULL ptr while we're a client && !must_alloc
496 crashes on Windows, so we won't do that. */
498 mem = NULL;
499 StubMsg.IsClient = 0;
500 StubMsg.Buffer = StubMsg.BufferStart;
501 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
502 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
503 ok(mem == StubMsg.BufferStart, "%s: mem not equal buffer\n", msgpfx);
504 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
505 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
506 my_alloc_called = 0;
507 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
509 /*** now must_alloc is true ***/
511 /* with must_alloc set we always allocate new memory whether or not we're
512 a server and also when passing NULL */
513 mem = mem_orig;
514 StubMsg.IsClient = 1;
515 StubMsg.Buffer = StubMsg.BufferStart;
516 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
517 ok(ptr == NULL, "ret %p\n", ptr);
518 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
519 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
520 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
521 my_alloc_called = 0;
522 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
524 mem = NULL;
525 StubMsg.Buffer = StubMsg.BufferStart;
526 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
527 ok(ptr == NULL, "ret %p\n", ptr);
528 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
529 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
530 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
531 my_alloc_called = 0;
532 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
534 mem = mem_orig;
535 StubMsg.Buffer = StubMsg.BufferStart;
536 StubMsg.IsClient = 0;
537 StubMsg.ReuseBuffer = 1;
538 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
539 ok(ptr == NULL, "ret %p\n", ptr);
540 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
541 ok(mem != StubMsg.BufferStart, "mem is buffer mem\n");
542 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
543 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
544 my_alloc_called = 0;
545 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
547 mem = NULL;
548 StubMsg.Buffer = StubMsg.BufferStart;
549 StubMsg.IsClient = 0;
550 StubMsg.ReuseBuffer = 1;
551 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
552 ok(ptr == NULL, "ret %p\n", ptr);
553 ok(mem != StubMsg.BufferStart, "mem is buffer mem\n");
554 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
555 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
556 my_alloc_called = 0;
557 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
561 typedef struct
563 long l1;
564 long *pl1;
565 char *pc1;
566 } ps1_t;
568 static int ps1_cmp(const void *s1, const void *s2, size_t num)
570 const ps1_t *p1, *p2;
572 p1 = s1;
573 p2 = s2;
575 if(p1->l1 != p2->l1)
576 return 1;
578 if(p1->pl1 && p2->pl1)
580 if(*p1->pl1 != *p2->pl1)
581 return 1;
583 else if(p1->pl1 || p1->pl1)
584 return 1;
586 if(p1->pc1 && p2->pc1)
588 if(*p1->pc1 != *p2->pc1)
589 return 1;
591 else if(p1->pc1 || p1->pc1)
592 return 1;
594 return 0;
597 static void test_simple_struct(void)
599 unsigned char wiredata[28];
600 unsigned long wiredatalen;
601 long l;
602 char c;
603 ps1_t ps1;
605 static const unsigned char fmtstr_simple_struct[] =
607 0x12, 0x0, /* FC_UP */
608 NdrFcShort( 0x2 ), /* Offset=2 */
609 0x15, 0x3, /* FC_STRUCT [align 4] */
610 NdrFcShort( 0x18 ), /* [size 24] */
611 0x6, /* FC_SHORT */
612 0x2, /* FC_CHAR */
613 0x38, /* FC_ALIGNM4 */
614 0x8, /* FC_LONG */
615 0x8, /* FC_LONG */
616 0x39, /* FC_ALIGNM8 */
617 0xb, /* FC_HYPER */
618 0x5b, /* FC_END */
620 struct {
621 short s;
622 char c;
623 long l1, l2;
624 LONGLONG ll;
625 } s1;
627 static const unsigned char fmtstr_pointer_struct[] =
629 0x12, 0x0, /* FC_UP */
630 NdrFcShort( 0x2 ), /* Offset=2 */
631 0x16, 0x3, /* FC_PSTRUCT [align 4] */
632 NdrFcShort( 0xc ), /* [size 12] */
633 0x4b, /* FC_PP */
634 0x5c, /* FC_PAD */
635 0x46, /* FC_NO_REPEAT */
636 0x5c, /* FC_PAD */
637 NdrFcShort( 0x4 ), /* 4 */
638 NdrFcShort( 0x4 ), /* 4 */
639 0x13, 0x8, /* FC_OP [simple_pointer] */
640 0x8, /* FC_LONG */
641 0x5c, /* FC_PAD */
642 0x46, /* FC_NO_REPEAT */
643 0x5c, /* FC_PAD */
644 NdrFcShort( 0x8 ), /* 8 */
645 NdrFcShort( 0x8 ), /* 8 */
646 0x13, 0x8, /* FC_OP [simple_pointer] */
647 0x2, /* FC_CHAR */
648 0x5c, /* FC_PAD */
649 0x5b, /* FC_END */
650 0x8, /* FC_LONG */
651 0x8, /* FC_LONG */
652 0x8, /* FC_LONG */
653 0x5c, /* FC_PAD */
654 0x5b, /* FC_END */
658 /* FC_STRUCT */
659 s1.s = 0x1234;
660 s1.c = 0xa5;
661 s1.l1 = 0xdeadbeef;
662 s1.l2 = 0xcafebabe;
663 s1.ll = ((LONGLONG) 0xbadefeed << 32) || 0x2468ace0;
665 wiredatalen = 24;
666 memcpy(wiredata, &s1, wiredatalen);
667 test_simple_struct_marshal(fmtstr_simple_struct + 4, &s1, 24, wiredata, 24, NULL, 0, "struct");
669 *(void**)wiredata = &s1;
670 memcpy(wiredata + 4, &s1, wiredatalen);
671 #if 0 /* one of the unmarshallings crashes Wine */
672 test_pointer_marshal(fmtstr_simple_struct, &s1, 24, wiredata, 28, NULL, 0, "struct");
673 #endif
675 /* FC_PSTRUCT */
676 ps1.l1 = 0xdeadbeef;
677 l = 0xcafebabe;
678 ps1.pl1 = &l;
679 c = 'a';
680 ps1.pc1 = &c;
681 memcpy(wiredata + 4, &ps1, 12);
682 memcpy(wiredata + 16, &l, 4);
683 memcpy(wiredata + 20, &c, 1);
685 test_simple_struct_marshal(fmtstr_pointer_struct + 4, &ps1, 17, wiredata + 4, 17, ps1_cmp, 2, "pointer_struct");
686 *(void**)wiredata = &ps1;
687 #if 0 /* one of the unmarshallings crashes Wine */
688 test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct");
689 #endif
692 static void test_fullpointer_xlat(void)
694 PFULL_PTR_XLAT_TABLES pXlatTables;
695 unsigned long RefId;
696 int ret;
697 void *Pointer;
699 pXlatTables = NdrFullPointerXlatInit(2, XLAT_CLIENT);
701 /* "marshaling" phase */
703 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
704 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
705 ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%lx\n", RefId);
707 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId);
708 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
709 ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%lx\n", RefId);
711 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId);
712 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
713 ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%lx\n", RefId);
715 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId);
716 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
717 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%lx\n", RefId);
719 ret = NdrFullPointerQueryPointer(pXlatTables, NULL, 0, &RefId);
720 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
721 ok(RefId == 0, "RefId should be 0 instead of 0x%lx\n", RefId);
723 /* "unmarshaling" phase */
725 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer);
726 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
727 todo_wine {
728 ok(Pointer == (void *)0xcafebabe, "Pointer should be 0xcafebabe instead of %p\n", Pointer);
731 ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 0, &Pointer);
732 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
733 ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer);
735 NdrFullPointerInsertRefId(pXlatTables, 0x4, (void *)0xdeadbabe);
737 ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 1, &Pointer);
738 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
739 todo_wine {
740 ok(Pointer == (void *)0xdeadbabe, "Pointer should be (void *)0xdeadbabe instead of %p\n", Pointer);
743 NdrFullPointerXlatFree(pXlatTables);
745 pXlatTables = NdrFullPointerXlatInit(2, XLAT_SERVER);
747 /* "unmarshaling" phase */
749 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer);
750 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
751 ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer);
753 NdrFullPointerInsertRefId(pXlatTables, 0x2, (void *)0xcafebabe);
755 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer);
756 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
757 todo_wine {
758 ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer);
761 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer);
762 todo_wine {
763 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
764 ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer);
767 /* "marshaling" phase */
769 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
770 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
771 todo_wine {
772 ok(RefId == 0x3, "RefId should be 0x1 instead of 0x%lx\n", RefId);
775 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
776 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
777 todo_wine {
778 ok(RefId == 0x3, "RefId should be 0x1 instead of 0x%lx\n", RefId);
781 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId);
782 todo_wine {
783 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
784 ok(RefId == 0x3, "RefId should be 0x1 instead of 0x%lx\n", RefId);
787 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId);
788 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
789 ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%lx\n", RefId);
791 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId);
792 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
793 todo_wine {
794 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%lx\n", RefId);
797 /* "freeing" phase */
799 todo_wine {
800 ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebeef);
801 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
803 ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebabe);
804 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
806 ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef);
807 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
810 NdrFullPointerXlatFree(pXlatTables);
813 START_TEST( ndr_marshall )
815 test_simple_types();
816 test_simple_struct();
817 test_fullpointer_xlat();